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 fa80afde3a1..c1f8b07fbed 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 @@ -10557,7 +10557,23 @@ public class AST2TemplateTests extends AST2CPPTestBase { // // template // void foo(index_sequence); - public void testTemplateAliasWithVariadicNonTypeArgs_530086() throws Exception { + public void testTemplateAliasWithVariadicNonTypeArgs_530086a() throws Exception { + parseAndCheckBindings(); + } + + // template + // struct integer_sequence {}; + // + // template + // using index_sequence = integer_sequence; + // + // template + // void bar(index_sequence); + // + // void foo() { + // bar(integer_sequence<0>{}); + // } + public void testTemplateAliasWithVariadicArgs_530086b() throws Exception { parseAndCheckBindings(); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index b4915bb19c2..3ac22c11d96 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -222,7 +222,7 @@ public class CPPTemplates { // Used to indicate that two different packs with different sizes were found. static final int PACK_SIZE_FAIL = -2; - + // Used to indicate that no template parameter packs were found. static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE; @@ -1224,14 +1224,6 @@ public class CPPTemplates { if (tpar.isParameterPack()) { ICPPTemplateArgument[] args= tpMap.getPackExpansion(tpar); if (args != null) { - // The arguments could be dependent, so they could themselves - // contain pack expansions. - for (ICPPTemplateArgument arg : args) { - if (arg.isPackExpansion()) { - return PACK_SIZE_DEFER; - } - } - return args.length; } return PACK_SIZE_DEFER; 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 41ff79f4ebe..2e3beb57384 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 @@ -43,6 +43,8 @@ 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.ICPPTemplateArgument; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.DependentValue; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; @@ -208,17 +210,9 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { @Override public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { if (fOperator == op_sizeofParameterPack) { - int packSize = determinePackSize(context.getParameterMap()); - if (packSize == CPPTemplates.PACK_SIZE_FAIL || packSize == CPPTemplates.PACK_SIZE_NOT_FOUND) { - return EvalFixed.INCOMPLETE; - } else if (packSize != CPPTemplates.PACK_SIZE_DEFER) { - return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(packSize)); - } + return instantiateSizeofParameterPack(context); } - IType type = CPPTemplates.instantiateType(fOrigType, context); - if (type == fOrigType) - return this; - return new EvalUnaryTypeID(fOperator, type, getTemplateDefinition()); + return instantiateBySubstitution(context); } @Override @@ -235,4 +229,49 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { public boolean referencesTemplateParameter() { return CPPTemplates.isDependentType(fOrigType); } + + private ICPPEvaluation instantiateBySubstitution(InstantiationContext context) { + IType type = CPPTemplates.instantiateType(fOrigType, context); + if (type == fOrigType) + return this; + return new EvalUnaryTypeID(fOperator, type, getTemplateDefinition()); + } + + private ICPPEvaluation instantiateSizeofParameterPack(InstantiationContext context) { + if (fOrigType instanceof ICPPTemplateParameter) { + ICPPTemplateParameter pack = (ICPPTemplateParameter) fOrigType; + if (pack.isParameterPack()) { + ICPPTemplateArgument[] args = context.getPackExpansion(pack); + if (args == null) { + return this; + } + int concreteArgCount = 0; + boolean havePackExpansion = false; + for (ICPPTemplateArgument arg : args) { + if (arg.isPackExpansion()) { + havePackExpansion = true; + } else { + concreteArgCount++; + } + } + if (havePackExpansion) { + // 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. + // To correctly handle cases with multiple pack expansions, or a mixture + // of concrete arguments and pack expansions, we need to do the following: + // - For each pack expansion, find the parameter pack P which it's + // expanding (if it's expanding multiple parameter packs, any one + // should be sufficient), and construct an EvalUnaryTypeId representing + // sizeof...(P). + // - Construct an EvalBinary tree representing the sum of |concreteArgCount| + // and the EvalUnaryTypeIds from the previous step. + return instantiateBySubstitution(context); + } else { + return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount)); + } + } + } + return EvalFixed.INCOMPLETE; + } }