diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 2886f6a8ce3..4d11ad942bd 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -9285,6 +9285,139 @@ public class AST2TemplateTests extends AST2CPPTestBase { assertSameType(CommonCPPTypes.int_, waldo); } + // template struct foo; + // template <> struct foo<2> { typedef int type; }; + // + // template + // using alias = typename foo::type; + // + // template + // struct caller { + // typedef alias type; + // }; + // + // template::type = 0> + // void function() { + // } + // + // int main() { + // function<0>(); + // } + public void testSizeofParameterPack_574196() throws Exception { + parseAndCheckBindings(); + } + + // template struct foo; + // template <> struct foo<3> { typedef int type; }; + // + // template + // using alias = typename foo::type; + // + // template + // struct caller { + // typedef alias type; + // }; + // + // template::type = 0> + // void function() { + // } + // + // int main() { + // function<0>(); + // } + public void testSizeofParameterPack_574196_2() throws Exception { + parseAndCheckBindings(); + } + + // template struct foo; + // template <> struct foo<3> { typedef int type; }; + // + // template + // using alias = typename foo::type; + // + // template + // struct caller { + // typedef alias type; + // }; + // + // template::type = 0> + // void function() { + // } + // + // int main() { + // function<0>(); + // } + public void testSizeofParameterPack_574196_3() throws Exception { + parseAndCheckBindings(); + } + + // template struct foo; + // template <> struct foo<2> { typedef int type; }; + // + // template + // using alias = typename foo::type; + // + // template + // struct caller { + // typedef alias type; + // }; + // + // template::type = 0> + // void function() { + // } + // + // int main() { + // function<0>(); + // } + public void testSizeofParameterPack_574196_4() throws Exception { + parseAndCheckBindings(); + } + + // template struct foo; + // template <> struct foo<2> { typedef int type; }; + // + // template + // using myalias = typename foo::type; + // + // template + // struct caller { + // typedef myalias type; + // }; + // + // template::type = 4321> + // void function() { + // } + // + // int main() { + // function<1234>(); + // } + //TODO: Handle non-type parameter pack + // public void testSizeofParameterPack_574196_5() throws Exception { + // parseAndCheckBindings(); + // } + + // template struct foo; + // template <> struct foo<0> { typedef int type; }; + // + // template + // using myalias = typename foo::type; + // + // template + // struct caller { + // typedef myalias type; + // }; + // + // template::type = 4321> + // void function() { + // } + // + // int main() { + // function<1234>(); + // } + public void testSizeofParameterPack_574196_6() throws Exception { + parseAndCheckBindings(); + } + // template // struct A {}; // diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java index 35d386adf7c..554a30c7b5b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java @@ -399,6 +399,11 @@ public class EvalUnary extends CPPDependentEvaluation { @Override 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) { return new EvalFixed(getType(), ValueCategory.PRVALUE, IntegralValue.create(context.getPackOffset())); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java index 1d0783883a2..96e43a3c4bf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java @@ -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_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.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; 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.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; @@ -271,15 +273,15 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { return this; } int concreteArgCount = 0; - boolean havePackExpansion = false; + int packExpansionCount = 0; for (ICPPTemplateArgument arg : args) { if (arg.isPackExpansion()) { - havePackExpansion = true; + packExpansionCount++; } else { concreteArgCount++; } } - if (havePackExpansion) { + if (packExpansionCount > 0) { // TODO(bug 530103): // This will only handle correctly the case where there is a single argument // which is a pack expansion, and no concrete arguments. @@ -291,7 +293,33 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { // sizeof...(P). // - Construct an EvalBinary tree representing the sum of |concreteArgCount| // 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 { return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount)); }