From 6d82f0f7a4a1b980adddd3ad5f69ae007d2655d8 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sat, 22 Mar 2014 02:55:38 -0400 Subject: [PATCH] Bug 429891 - Do not attempt to evaluate a constexpr function call if the arguments are not constant expressions Change-Id: I7f7e5cfd1e581c168bfcc65222e9ef87a15a8e4f Signed-off-by: Nathan Ridge Reviewed-on: https://git.eclipse.org/r/23744 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../parser/tests/ast2/AST2TemplateTests.java | 23 ++++++ .../core/dom/parser/cpp/ICPPEvaluation.java | 7 ++ .../parser/cpp/semantics/CPPEvaluation.java | 30 +++++++- .../dom/parser/cpp/semantics/EvalBinary.java | 7 ++ .../cpp/semantics/EvalBinaryTypeId.java | 5 ++ .../dom/parser/cpp/semantics/EvalBinding.java | 7 ++ .../dom/parser/cpp/semantics/EvalComma.java | 13 ++++ .../parser/cpp/semantics/EvalCompound.java | 5 ++ .../parser/cpp/semantics/EvalConditional.java | 7 ++ .../dom/parser/cpp/semantics/EvalFixed.java | 5 ++ .../cpp/semantics/EvalFunctionCall.java | 10 +++ .../parser/cpp/semantics/EvalFunctionSet.java | 10 +++ .../core/dom/parser/cpp/semantics/EvalID.java | 5 ++ .../parser/cpp/semantics/EvalInitList.java | 17 ++--- .../cpp/semantics/EvalMemberAccess.java | 11 ++- .../cpp/semantics/EvalParameterPack.java | 5 ++ .../dom/parser/cpp/semantics/EvalTypeId.java | 75 ++++++++++++++----- .../dom/parser/cpp/semantics/EvalUnary.java | 6 ++ .../parser/cpp/semantics/EvalUnaryTypeID.java | 5 ++ 19 files changed, 220 insertions(+), 33 deletions(-) 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 bfbe8a763a1..2e0ba985b97 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 @@ -8454,4 +8454,27 @@ public class AST2TemplateTests extends AST2TestBase { ICPPVariable waldo = helper.assertNonProblem("waldo"); assertEquals(2, waldo.getInitialValue().numericalValue().longValue()); } + + // struct Test { + // static constexpr unsigned calc_sig(const char *s, unsigned n) { + // return (n == 0 || *s == '\0' ? 0 : + // n > 1 && *s == '%' && s[1] == '%' ? + // calc_sig(s + 2, n - 2) : + // calc_sig(s + 1, n - 1)); + // } + // + // template + // static void validate_sig(); + // + // template + // static inline constexpr bool validate(const char *s, unsigned n) { + // constexpr auto sig = calc_sig(s, n); + // validate_sig(); + // return true; + // } + // + // }; + public void testConstexprFunctionCallWithNonConstexprArguments_429891() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java index 50606e70cf1..58d3560e2af 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java @@ -40,6 +40,13 @@ public interface ICPPEvaluation extends ISerializableEvaluation { * Returns {@code true} if the value of the expression depends on template parameters. */ boolean isValueDependent(); + + /** + * Returns {@code true} if the expression is a compile-time constant expression. + * + * @param point the point of instantiation, determines the scope for name lookups + */ + boolean isConstantExpression(IASTNode point); /** * Returns the type of the expression, or a {@code FunctionSetType} if the expression evaluates diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java index 1f394567257..2844827e1b5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java @@ -15,7 +15,9 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -74,7 +76,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation { return binding; } - public static boolean containsDependentType(ICPPEvaluation[] evaluations) { + protected static boolean containsDependentType(ICPPEvaluation[] evaluations) { for (ICPPEvaluation eval : evaluations) { if (eval.isTypeDependent()) return true; @@ -82,11 +84,35 @@ public abstract class CPPEvaluation implements ICPPEvaluation { return false; } - public static boolean containsDependentValue(ICPPEvaluation[] evaluations) { + protected static boolean containsDependentValue(ICPPEvaluation[] evaluations) { for (ICPPEvaluation eval : evaluations) { if (eval.isValueDependent()) return true; } return false; } + + protected static boolean areAllConstantExpressions(ICPPEvaluation[] evaluations, IASTNode point) { + for (ICPPEvaluation eval : evaluations) { + if (!eval.isConstantExpression(point)) { + return false; + } + } + return true; + } + + protected static boolean isConstexprValue(IValue value, IASTNode point) { + if (value == null) { + return false; + } + ICPPEvaluation innerEval = value.getEvaluation(); + if (innerEval == null) { + return value.numericalValue() != null; + } + return innerEval.isConstantExpression(point); + } + + protected static boolean isConstexprFuncOrNull(ICPPFunction function) { + return function == null || function.isConstexpr(); + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java index 5be3044ce7d..88a2ce96c6a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java @@ -186,6 +186,13 @@ public class EvalBinary extends CPPDependentEvaluation { public boolean isValueDependent() { return fArg1.isValueDependent() || fArg2.isValueDependent(); } + + @Override + public boolean isConstantExpression(IASTNode point) { + return fArg1.isConstantExpression(point) + && fArg2.isConstantExpression(point) + && isConstexprFuncOrNull(getOverload(point)); + } @Override public ValueCategory getValueCategory(IASTNode point) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java index 87d782578ed..8bf2d38813f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java @@ -102,6 +102,11 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation { } return fIsValueDependent; } + + @Override + public boolean isConstantExpression(IASTNode point) { + return true; + } @Override public ValueCategory getValueCategory(IASTNode point) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java index f3f44b74bad..a423aef1278 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java @@ -237,6 +237,13 @@ public class EvalBinding extends CPPDependentEvaluation { } return false; } + + @Override + public boolean isConstantExpression(IASTNode point) { + return fBinding instanceof IEnumerator + || fBinding instanceof ICPPFunction + || (fBinding instanceof IVariable && isConstexprValue(((IVariable) fBinding).getInitialValue(), point)); + } @Override public IType getTypeOrFunctionSet(IASTNode point) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java index b405d0596b7..08d498d3548 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java @@ -72,6 +72,19 @@ public class EvalComma extends CPPDependentEvaluation { public boolean isValueDependent() { return containsDependentValue(fArguments); } + + @Override + public boolean isConstantExpression(IASTNode point) { + if (!areAllConstantExpressions(fArguments, point)) { + return false; + } + for (ICPPFunction overload : fOverloads) { + if (!isConstexprFuncOrNull(overload)) { + return false; + } + } + return true; + } public ICPPFunction[] getOverloads(IASTNode point) { if (fOverloads == null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java index bb415272126..f6018d29830 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java @@ -64,6 +64,11 @@ public class EvalCompound extends CPPDependentEvaluation { public boolean isValueDependent() { return fDelegate.isValueDependent(); } + + @Override + public boolean isConstantExpression(IASTNode point) { + return fDelegate.isConstantExpression(point); + } @Override public IType getTypeOrFunctionSet(IASTNode point) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java index 0b927f08066..9216b7ef7fd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java @@ -147,6 +147,13 @@ public class EvalConditional extends CPPDependentEvaluation { || fNegative.isValueDependent(); } + @Override + public boolean isConstantExpression(IASTNode point) { + return fCondition.isConstantExpression(point) + && (fPositive == null || fPositive.isConstantExpression(point)) + && fNegative.isConstantExpression(point); + } + private void evaluate(IASTNode point) { if (fValueCategory != null) return; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java index 9041faf7c08..d3321dd69aa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java @@ -97,6 +97,11 @@ public class EvalFixed extends CPPEvaluation { } return fIsValueDependent; } + + @Override + public boolean isConstantExpression(IASTNode point) { + return isConstexprValue(fValue, point); + } @Override public IType getTypeOrFunctionSet(IASTNode point) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java index b74633bb40a..599ec353aa8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java @@ -84,6 +84,12 @@ public class EvalFunctionCall extends CPPDependentEvaluation { return containsDependentValue(fArguments); } + @Override + public boolean isConstantExpression(IASTNode point) { + return areAllConstantExpressions(fArguments, point) + && isConstexprFuncOrNull(getOverload(point)); + } + public ICPPFunction getOverload(IASTNode point) { if (fOverload == CPPFunction.UNINITIALIZED_FUNCTION) { fOverload= computeOverload(point); @@ -223,6 +229,10 @@ public class EvalFunctionCall extends CPPDependentEvaluation { private ICPPEvaluation computeForFunctionCall(int maxdepth, IASTNode point) { if (isValueDependent()) return this; + // If the arguments are not all constant expressions, there is + // no point trying to substitute them into the return expression. + if (!areAllConstantExpressions(fArguments, point)) + return this; ICPPFunction function = getOverload(point); if (function == null) { if (fArguments[0] instanceof EvalBinding) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java index 6bea4d370ce..09690122260 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java @@ -131,6 +131,16 @@ public class EvalFunctionSet extends CPPDependentEvaluation { public boolean isValueDependent() { return false; } + + @Override + public boolean isConstantExpression(IASTNode point) { + for (ICPPFunction f : fFunctionSet.getBindings()) { + if (!f.isConstexpr()) { + return false; + } + } + return true; + } @Override public IType getTypeOrFunctionSet(IASTNode point) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java index e25c89afc4d..154fa492117 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java @@ -132,6 +132,11 @@ public class EvalID extends CPPDependentEvaluation { return true; } + @Override + public boolean isConstantExpression(IASTNode point) { + return false; + } + @Override public IType getTypeOrFunctionSet(IASTNode point) { return new TypeOfDependentExpression(this); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java index 24274655a71..8fe33094a85 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java @@ -57,20 +57,17 @@ public class EvalInitList extends CPPDependentEvaluation { @Override public boolean isTypeDependent() { - for (ICPPEvaluation clause : fClauses) { - if (clause.isTypeDependent()) - return true; - } - return false; + return containsDependentType(fClauses); } @Override public boolean isValueDependent() { - for (ICPPEvaluation clause : fClauses) { - if (clause.isValueDependent()) - return true; - } - return false; + return containsDependentValue(fClauses); + } + + @Override + public boolean isConstantExpression(IASTNode point) { + return areAllConstantExpressions(fClauses, point); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java index ffee46b6346..91e0ca0c2ed 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java @@ -139,7 +139,7 @@ public class EvalMemberAccess extends CPPDependentEvaluation { } return fIsValueDependent; } - + private boolean computeIsValueDependent() { if (fMember instanceof ICPPUnknownBinding) { return true; @@ -156,6 +156,15 @@ public class EvalMemberAccess extends CPPDependentEvaluation { return false; } + @Override + public boolean isConstantExpression(IASTNode point) { + // TODO(nathanridge): + // This could be a constant expression if the field owner + // is a constant expression, but we don't have access to + // the field owner's evaluation, only its type. + return false; + } + public static IType getFieldOwnerType(IType fieldOwnerExpressionType, boolean isDeref, IASTNode point, Collection functionBindings, boolean returnUnnamed) { IType type= fieldOwnerExpressionType; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java index 002d1cba4d7..e733a7a0a11 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalParameterPack.java @@ -66,6 +66,11 @@ public class EvalParameterPack extends CPPDependentEvaluation { return fExpansionPattern.isValueDependent(); } + @Override + public boolean isConstantExpression(IASTNode point) { + return false; + } + @Override public IType getTypeOrFunctionSet(IASTNode point) { if (fType == null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java index 1104628ec59..788015d66f5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java @@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -43,6 +44,10 @@ public class EvalTypeId extends CPPDependentEvaluation { private final ICPPEvaluation[] fArguments; private final boolean fRepresentsNewExpression; private IType fOutputType; + + private ICPPFunction fConstructor = CPPFunction.UNINITIALIZED_FUNCTION; + private boolean fCheckedIsTypeDependent; + private boolean fIsTypeDependent; public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) { this(type, findEnclosingTemplate(pointOfDefinition), false, arguments); @@ -93,7 +98,7 @@ public class EvalTypeId extends CPPDependentEvaluation { } private IType computeType() { - if (CPPTemplates.isDependentType(fInputType) || containsDependentType(fArguments)) + if (isTypeDependent()) return new TypeOfDependentExpression(this); IType type = typeFromReturnType(fInputType); @@ -121,10 +126,11 @@ public class EvalTypeId extends CPPDependentEvaluation { @Override public boolean isTypeDependent() { - if (fOutputType == null) { - fOutputType= computeType(); + if (!fCheckedIsTypeDependent) { + fCheckedIsTypeDependent = true; + fIsTypeDependent = CPPTemplates.isDependentType(fInputType) || containsDependentType(fArguments); } - return fOutputType instanceof TypeOfDependentExpression; + return fIsTypeDependent; } @Override @@ -136,10 +142,47 @@ public class EvalTypeId extends CPPDependentEvaluation { return false; } + @Override + public boolean isConstantExpression(IASTNode point) { + return !fRepresentsNewExpression + && areAllConstantExpressions(fArguments, point) + && isConstexprFuncOrNull(getConstructor(point)); + } + @Override public ValueCategory getValueCategory(IASTNode point) { return valueCategoryFromReturnType(fInputType); } + + public ICPPFunction getConstructor(IASTNode point) { + if (fConstructor == CPPFunction.UNINITIALIZED_FUNCTION) { + fConstructor = computeConstructor(point); + } + return fConstructor; + } + + private ICPPFunction computeConstructor(IASTNode point) { + if (isTypeDependent()) + return null; + + IType simplifiedType = SemanticUtil.getNestedType(fInputType, SemanticUtil.TDEF); + if (simplifiedType instanceof ICPPClassType) { + ICPPClassType classType = (ICPPClassType) simplifiedType; + LookupData data = new LookupData(classType.getNameCharArray(), null, point); + ICPPConstructor[] constructors = ClassTypeHelper.getConstructors(classType, point); + data.foundItems = constructors; + data.setFunctionArguments(false, fArguments); + try { + IBinding binding = CPPSemantics.resolveFunction(data, constructors, true); + if (binding instanceof ICPPFunction) { + return (ICPPFunction) binding; + } + } catch (DOMException e) { + CCorePlugin.log(e); + } + } + return null; + } @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { @@ -177,30 +220,22 @@ public class EvalTypeId extends CPPDependentEvaluation { IType type = CPPTemplates.instantiateType(fInputType, tpMap, packOffset, within, point); if (args == fArguments && type == fInputType) return this; - - if (!CPPTemplates.isDependentType(type) && !containsDependentType(args)) { + + EvalTypeId result = new EvalTypeId(type, getTemplateDefinition(), fRepresentsNewExpression, args); + + if (!result.isTypeDependent()) { IType simplifiedType = SemanticUtil.getNestedType(type, SemanticUtil.TDEF); if (simplifiedType instanceof ICPPClassType) { // Check the constructor call and return EvalFixed.INCOMPLETE to indicate a substitution // failure if the call cannot be resolved. - ICPPClassType classType = (ICPPClassType) type; - LookupData data = new LookupData(classType.getNameCharArray(), null, point); - ICPPConstructor[] constructors = ClassTypeHelper.getConstructors(classType, point); - data.foundItems = constructors; - data.setFunctionArguments(false, args); - try { - IBinding binding = CPPSemantics.resolveFunction(data, constructors, true); - if (binding == null || binding instanceof IProblemBinding || - binding instanceof ICPPFunction && ((ICPPFunction) binding).isDeleted()) { - return EvalFixed.INCOMPLETE; - } - } catch (DOMException e) { - CCorePlugin.log(e); + ICPPFunction constructor = result.getConstructor(point); + if (constructor == null || constructor instanceof IProblemBinding || constructor.isDeleted()) { return EvalFixed.INCOMPLETE; } } } - return new EvalTypeId(type, getTemplateDefinition(), fRepresentsNewExpression, args); + + return result; } @Override 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 582d9254519..4a190e88f24 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 @@ -144,6 +144,12 @@ public class EvalUnary extends CPPDependentEvaluation { return fArgument.isValueDependent(); } } + + @Override + public boolean isConstantExpression(IASTNode point) { + return fArgument.isConstantExpression(point) + && isConstexprFuncOrNull(getOverload(point)); + } public ICPPFunction getOverload(IASTNode point) { if (fOverload == CPPFunction.UNINITIALIZED_FUNCTION) { 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 02976a6e918..29a52a08b83 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 @@ -126,6 +126,11 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation { return false; } + @Override + public boolean isConstantExpression(IASTNode point) { + return true; + } + @Override public IType getTypeOrFunctionSet(IASTNode point) { if (fType == null)