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 27d75405018..a6fde67a74f 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 @@ -7351,4 +7351,17 @@ public class AST2TemplateTests extends AST2TestBase { public void testVariadicNonTypeTemplateParameter_401400() throws Exception { parseAndCheckBindings(); } + + // template + // struct foo { + // static constexpr int i = sizeof...(Args); + // }; + // constexpr int bar = foo::i; + public void testSizeofParameterPackOnTypeid_401973() throws Exception { + BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true); + ICPPVariable bar = helper.assertNonProblem("bar", ICPPVariable.class); + Long barValue = bar.getInitialValue().numericalValue(); + assertNotNull(barValue); + assertEquals(2, barValue.longValue()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java index f2f0e0a4fb5..3c76114dcb5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java @@ -145,7 +145,13 @@ public interface IASTTypeIdExpression extends IASTExpression { * @since 5.5 */ public static final int op_is_trivial= 21; - + + /** + * op_sizeofParameterPack is used for sizeof... ( typeid ) expressions. + * @since 5.5 + */ + public static final int op_sizeofParameterPack = 22; + /** * @deprecated constants should be declared here, to avoid using the same constant in different * interfaces. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index ccd86e57d21..8289a2fceb1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -1279,19 +1279,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (LTcatchEOF(2) == IToken.tELLIPSIS) { int offset= consume().getOffset(); // sizeof consume(); // ... - consume(IToken.tLPAREN); // ( - IASTName id= identifier(); - IASTIdExpression idexpr= nodeFactory.newIdExpression(id); - setRange(idexpr, id); - IASTUnaryExpression expr= nodeFactory.newUnaryExpression(IASTUnaryExpression.op_sizeofParameterPack, idexpr); - final int lt1= LT(1); - if (lt1 == IToken.tEOC) { - setRange(expr, offset, calculateEndOffset(id)); - } else { - final int endOffset = consume(IToken.tRPAREN).getEndOffset(); // ) - setRange(expr, offset, endOffset); - } - return expr; + return parseTypeidInParenthesisOrUnaryExpression(true, offset, + IASTTypeIdExpression.op_sizeofParameterPack, + IASTUnaryExpression.op_sizeofParameterPack, ctx, strat); } return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx, strat); 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 417c079a99f..ca19b9a1255 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 @@ -32,6 +32,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_standard_l import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivial; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_union; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeof; +import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeofParameterPack; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid; import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof; @@ -92,6 +93,8 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { @Override public boolean isValueDependent() { switch (fOperator) { + case op_sizeofParameterPack: + return true; case op_sizeof: case op_alignof: case op_has_nothrow_copy: @@ -130,6 +133,7 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { private IType computeType(IASTNode point) { switch (fOperator) { case op_sizeof: + case op_sizeofParameterPack: case op_alignof: return CPPVisitor.get_SIZE_T(point); case op_typeid: @@ -191,6 +195,14 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { @Override public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within, int maxdepth, IASTNode point) { + if (fOperator == op_sizeofParameterPack) { + int packSize = determinePackSize(tpMap); + 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(getTypeOrFunctionSet(point), getValueCategory(point), Value.create(packSize)); + } + } IType type = CPPTemplates.instantiateType(fOrigType, tpMap, packOffset, within, point); if (type == fOrigType) return this;