mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Partial fix for bug 574196/530103, error involving sizeof...() (#667)
Also discovered that non-type param is not handled at all. This case is not covered in this commit but there is a commented-out failing test for it.
This commit is contained in:
parent
f3c2d91dfa
commit
e838a231d9
3 changed files with 170 additions and 4 deletions
|
@ -9285,6 +9285,139 @@ public class AST2TemplateTests extends AST2CPPTestBase {
|
||||||
assertSameType(CommonCPPTypes.int_, waldo);
|
assertSameType(CommonCPPTypes.int_, waldo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <int> struct foo;
|
||||||
|
// template <> struct foo<2> { typedef int type; };
|
||||||
|
//
|
||||||
|
// template <typename... T>
|
||||||
|
// using alias = typename foo<sizeof...(T)>::type;
|
||||||
|
//
|
||||||
|
// template <typename... U>
|
||||||
|
// struct caller {
|
||||||
|
// typedef alias<int, U...> type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename caller<int>::type = 0>
|
||||||
|
// void function() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int main() {
|
||||||
|
// function<0>();
|
||||||
|
// }
|
||||||
|
public void testSizeofParameterPack_574196() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <int> struct foo;
|
||||||
|
// template <> struct foo<3> { typedef int type; };
|
||||||
|
//
|
||||||
|
// template <typename... T>
|
||||||
|
// using alias = typename foo<sizeof...(T)>::type;
|
||||||
|
//
|
||||||
|
// template <typename... U>
|
||||||
|
// struct caller {
|
||||||
|
// typedef alias<int,U..., U...> type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename caller<int>::type = 0>
|
||||||
|
// void function() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int main() {
|
||||||
|
// function<0>();
|
||||||
|
// }
|
||||||
|
public void testSizeofParameterPack_574196_2() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <int> struct foo;
|
||||||
|
// template <> struct foo<3> { typedef int type; };
|
||||||
|
//
|
||||||
|
// template <typename... T>
|
||||||
|
// using alias = typename foo<sizeof...(T)>::type;
|
||||||
|
//
|
||||||
|
// template <typename... U>
|
||||||
|
// struct caller {
|
||||||
|
// typedef alias<U..., int, U...> type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename caller<int>::type = 0>
|
||||||
|
// void function() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int main() {
|
||||||
|
// function<0>();
|
||||||
|
// }
|
||||||
|
public void testSizeofParameterPack_574196_3() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <int> struct foo;
|
||||||
|
// template <> struct foo<2> { typedef int type; };
|
||||||
|
//
|
||||||
|
// template <typename V, typename... T>
|
||||||
|
// using alias = typename foo<sizeof...(T)>::type;
|
||||||
|
//
|
||||||
|
// template <typename... U>
|
||||||
|
// struct caller {
|
||||||
|
// typedef alias<int, int, U...> type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename caller<int>::type = 0>
|
||||||
|
// void function() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int main() {
|
||||||
|
// function<0>();
|
||||||
|
// }
|
||||||
|
public void testSizeofParameterPack_574196_4() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <int> struct foo;
|
||||||
|
// template <> struct foo<2> { typedef int type; };
|
||||||
|
//
|
||||||
|
// template <typename V, int... T>
|
||||||
|
// using myalias = typename foo<sizeof...(T)>::type;
|
||||||
|
//
|
||||||
|
// template <int... U>
|
||||||
|
// struct caller {
|
||||||
|
// typedef myalias<int, 0, U...> type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename caller<0>::type = 4321>
|
||||||
|
// void function() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int main() {
|
||||||
|
// function<1234>();
|
||||||
|
// }
|
||||||
|
//TODO: Handle non-type parameter pack
|
||||||
|
// public void testSizeofParameterPack_574196_5() throws Exception {
|
||||||
|
// parseAndCheckBindings();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template <int> struct foo;
|
||||||
|
// template <> struct foo<0> { typedef int type; };
|
||||||
|
//
|
||||||
|
// template <typename V, typename... T>
|
||||||
|
// using myalias = typename foo<sizeof...(T)>::type;
|
||||||
|
//
|
||||||
|
// template <typename... U>
|
||||||
|
// struct caller {
|
||||||
|
// typedef myalias<int, U...> type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename caller<>::type = 4321>
|
||||||
|
// void function() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int main() {
|
||||||
|
// function<1234>();
|
||||||
|
// }
|
||||||
|
public void testSizeofParameterPack_574196_6() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
// template <int, class>
|
// template <int, class>
|
||||||
// struct A {};
|
// struct A {};
|
||||||
//
|
//
|
||||||
|
|
|
@ -399,6 +399,11 @@ public class EvalUnary extends CPPDependentEvaluation {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) {
|
public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) {
|
||||||
|
// if (fOperator == IASTUnaryExpression.op_sizeofParameterPack) {
|
||||||
|
// //TODO: Something like EvalUnaryTypeID ?
|
||||||
|
// return instantiateSizeofParameterPack(context);
|
||||||
|
// }
|
||||||
|
|
||||||
if (fOperator == op_integerPack && context.getPackOffset() != -1) {
|
if (fOperator == op_integerPack && context.getPackOffset() != -1) {
|
||||||
return new EvalFixed(getType(), ValueCategory.PRVALUE, IntegralValue.create(context.getPackOffset()));
|
return new EvalFixed(getType(), ValueCategory.PRVALUE, IntegralValue.create(context.getPackOffset()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,13 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeofParamet
|
||||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid;
|
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid;
|
||||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
|
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||||
|
@ -271,15 +273,15 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
int concreteArgCount = 0;
|
int concreteArgCount = 0;
|
||||||
boolean havePackExpansion = false;
|
int packExpansionCount = 0;
|
||||||
for (ICPPTemplateArgument arg : args) {
|
for (ICPPTemplateArgument arg : args) {
|
||||||
if (arg.isPackExpansion()) {
|
if (arg.isPackExpansion()) {
|
||||||
havePackExpansion = true;
|
packExpansionCount++;
|
||||||
} else {
|
} else {
|
||||||
concreteArgCount++;
|
concreteArgCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (havePackExpansion) {
|
if (packExpansionCount > 0) {
|
||||||
// TODO(bug 530103):
|
// TODO(bug 530103):
|
||||||
// This will only handle correctly the case where there is a single argument
|
// This will only handle correctly the case where there is a single argument
|
||||||
// which is a pack expansion, and no concrete arguments.
|
// which is a pack expansion, and no concrete arguments.
|
||||||
|
@ -291,7 +293,33 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
|
||||||
// sizeof...(P).
|
// sizeof...(P).
|
||||||
// - Construct an EvalBinary tree representing the sum of |concreteArgCount|
|
// - Construct an EvalBinary tree representing the sum of |concreteArgCount|
|
||||||
// and the EvalUnaryTypeIds from the previous step.
|
// and the EvalUnaryTypeIds from the previous step.
|
||||||
return instantiateBySubstitution(context);
|
|
||||||
|
//malaperle: I implemented something that kind-of does what the comment
|
||||||
|
//above suggest but am not confident enough that it covers all cases (hence the several instanceof checks).
|
||||||
|
ICPPEvaluation packEval = null;
|
||||||
|
for (ICPPTemplateArgument arg : args) {
|
||||||
|
if (arg.isPackExpansion()) {
|
||||||
|
if (arg.getTypeValue() instanceof ICPPParameterPackType) {
|
||||||
|
ICPPParameterPackType parameterPackType = (ICPPParameterPackType) arg.getTypeValue();
|
||||||
|
IType type = parameterPackType.getType();
|
||||||
|
if (type instanceof ICPPTemplateParameter)
|
||||||
|
packEval = new EvalUnaryTypeID(fOperator, type, getTemplateDefinition());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we really get here?
|
||||||
|
if (packEval == null)
|
||||||
|
return instantiateBySubstitution(context);
|
||||||
|
|
||||||
|
// For sizeof(...(T)), T={U..., U...}
|
||||||
|
ICPPEvaluation multiPackCountEval = new EvalBinary(IASTBinaryExpression.op_multiply, packEval,
|
||||||
|
new EvalFixed(getType(), getValueCategory(), IntegralValue.create(packExpansionCount)),
|
||||||
|
pack);
|
||||||
|
|
||||||
|
return new EvalBinary(IASTBinaryExpression.op_plus, multiPackCountEval,
|
||||||
|
new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount)), pack);
|
||||||
} else {
|
} else {
|
||||||
return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount));
|
return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue