From b7ecc46eca4be9a2726975cd21d5083218f512bd Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Wed, 13 Jul 2016 17:57:02 -0700 Subject: [PATCH] Bug 497875 - Avoid evaluating isConstantExpression multiple times Change-Id: I54d6b533f5b21294a92319ea1d45d4f18962a460 --- .../dom/parser/cpp/semantics/EvalBinary.java | 14 +++++++++++-- .../dom/parser/cpp/semantics/EvalComma.java | 14 +++++++++++-- .../parser/cpp/semantics/EvalConditional.java | 12 ++++++++++- .../dom/parser/cpp/semantics/EvalFixed.java | 20 ++++++++++++++----- .../cpp/semantics/EvalFunctionCall.java | 16 ++++++++++++--- .../parser/cpp/semantics/EvalFunctionSet.java | 10 ++++++++++ .../parser/cpp/semantics/EvalInitList.java | 12 ++++++++++- .../dom/parser/cpp/semantics/EvalTypeId.java | 12 ++++++++++- .../dom/parser/cpp/semantics/EvalUnary.java | 16 ++++++++++++--- 9 files changed, 108 insertions(+), 18 deletions(-) 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 5fd7f0e1063..5eeaf2247cd 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 @@ -81,6 +81,8 @@ public class EvalBinary extends CPPDependentEvaluation { private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private IType fType; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2, IASTNode pointOfDefinition) { this(operator, arg1, arg2, findEnclosingTemplate(pointOfDefinition)); @@ -201,9 +203,17 @@ public class EvalBinary extends CPPDependentEvaluation { public boolean isValueDependent() { return fArg1.isValueDependent() || fArg2.isValueDependent(); } - + @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { return fArg1.isConstantExpression(point) && fArg2.isConstantExpression(point) && isNullOrConstexprFunc(getOverload(point)); @@ -262,7 +272,7 @@ public class EvalBinary extends CPPDependentEvaluation { IType type = fArg1.getType(point); type= SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); if (type instanceof ICPPClassType) { - return CPPSemantics.findOverloadedBinaryOperator(point, getTemplateDefinitionScope(), + return CPPSemantics.findOverloadedBinaryOperator(point, getTemplateDefinitionScope(), OverloadableOperator.BRACKET, fArg1, fArg2); } } else { 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 8bb0a524d57..8c77dd507ea 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 @@ -36,9 +36,11 @@ public class EvalComma extends CPPDependentEvaluation { private ICPPFunction[] fOverloads; private IType fType; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalComma(ICPPEvaluation[] evals, IASTNode pointOfDefinition) { - this(evals, findEnclosingTemplate(pointOfDefinition)); + this(evals, findEnclosingTemplate(pointOfDefinition)); } public EvalComma(ICPPEvaluation[] evals, IBinding templateDefinition) { @@ -72,9 +74,17 @@ public class EvalComma extends CPPDependentEvaluation { public boolean isValueDependent() { return containsDependentValue(fArguments); } - + @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { if (!areAllConstantExpressions(fArguments, point)) { return false; } 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 ba6ee7b7a63..a56955378af 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 @@ -55,6 +55,8 @@ public class EvalConditional extends CPPDependentEvaluation { private ValueCategory fValueCategory; private IType fType; private ICPPFunction fOverload; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalConditional(ICPPEvaluation condition, ICPPEvaluation positive, ICPPEvaluation negative, boolean positiveThrows, boolean negativeThrows, IASTNode pointOfDefinition) { @@ -149,6 +151,14 @@ public class EvalConditional extends CPPDependentEvaluation { @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { return fCondition.isConstantExpression(point) && (fPositive == null || fPositive.isConstantExpression(point)) && fNegative.isConstantExpression(point); @@ -243,7 +253,7 @@ public class EvalConditional extends CPPDependentEvaluation { // 5.16-5: At least one class type but no conversion if (isClassType2 || isClassType3) { - fOverload = CPPSemantics.findOverloadedConditionalOperator(point, getTemplateDefinitionScope(), positive, fNegative); + fOverload = CPPSemantics.findOverloadedConditionalOperator(point, getTemplateDefinitionScope(), positive, fNegative); if (fOverload != null) { fType= ExpressionTypes.typeFromFunctionCall(fOverload); } else { 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 2dae9b53196..63c6690086c 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 @@ -45,6 +45,8 @@ public class EvalFixed extends CPPEvaluation { private boolean fCheckedIsTypeDependent; private boolean fIsValueDependent; private boolean fCheckedIsValueDependent; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalFixed(IType type, ValueCategory cat, IValue value) { // Avoid nesting EvalFixed's as nesting causes the signature to be different. @@ -54,7 +56,7 @@ public class EvalFixed extends CPPEvaluation { cat = inner.fValueCategory; value = inner.fValue; } - + if (type instanceof CPPBasicType) { Long num = value.numericalValue(); if (num != null) { @@ -67,7 +69,7 @@ public class EvalFixed extends CPPEvaluation { fValueCategory= cat; fValue= value; } - + public IType getType() { return fType; } @@ -107,9 +109,17 @@ public class EvalFixed extends CPPEvaluation { } return fIsValueDependent; } - + @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { return (fType instanceof ICPPClassType && TypeTraits.isEmpty(fType, point)) || isConstexprValue(fValue, point); } @@ -180,11 +190,11 @@ public class EvalFixed extends CPPEvaluation { IValue value = CPPTemplates.instantiateValue(fValue, context, maxDepth); if (type == fType && value == fValue) return this; - // If an error occurred while instantiating the value (such as a substitution failure), + // If an error occurred while instantiating the value (such as a substitution failure), // propagate that error. if (value == Value.ERROR) return EvalFixed.INCOMPLETE; - // Resolve the parameter pack type to the underlying type if the instantiated value is not dependent. + // Resolve the parameter pack type to the underlying type if the instantiated value is not dependent. if (type instanceof ICPPParameterPackType && value.numericalValue() != null) type = ((ICPPParameterPackType) type).getType(); return new EvalFixed(type, fValueCategory, value); 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 ce95e5ecfd9..62d03d363e2 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 @@ -45,6 +45,8 @@ public class EvalFunctionCall extends CPPDependentEvaluation { private final ICPPEvaluation[] fArguments; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private IType fType; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalFunctionCall(ICPPEvaluation[] args, IASTNode pointOfDefinition) { this(args, findEnclosingTemplate(pointOfDefinition)); @@ -85,6 +87,14 @@ public class EvalFunctionCall extends CPPDependentEvaluation { @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { return areAllConstantExpressions(fArguments, point) && isNullOrConstexprFunc(getOverload(point)); } @@ -101,7 +111,7 @@ public class EvalFunctionCall extends CPPDependentEvaluation { IType t= SemanticUtil.getNestedType(fArguments[0].getType(point), TDEF | REF | CVTYPE); if (t instanceof ICPPClassType) { - return CPPSemantics.findOverloadedOperator(point, getTemplateDefinitionScope(), fArguments, t, + return CPPSemantics.findOverloadedOperator(point, getTemplateDefinitionScope(), fArguments, t, OverloadableOperator.PAREN, LookupMode.NO_GLOBALS); } return null; @@ -121,7 +131,7 @@ public class EvalFunctionCall extends CPPDependentEvaluation { ICPPFunction overload = getOverload(point); if (overload != null) return ExpressionTypes.typeFromFunctionCall(overload); - + ICPPEvaluation function = fArguments[0]; IType result = ExpressionTypes.typeFromFunctionCall(function.getType(point)); if (function instanceof EvalMemberAccess) { @@ -135,7 +145,7 @@ public class EvalFunctionCall extends CPPDependentEvaluation { ICPPEvaluation eval = computeForFunctionCall(new ConstexprEvaluationContext(point)); if (eval == this) { return Value.create(eval); - } + } return eval.getValue(point); } 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 2971ce85f8e..9ccb67ddc93 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 @@ -58,6 +58,8 @@ public class EvalFunctionSet extends CPPDependentEvaluation { // by asking the first function in the set for its name.) // Exactly one of fFunctionSet and fName should be non-null. private final char[] fName; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalFunctionSet(CPPFunctionSet set, boolean qualified, boolean addressOf, IType impliedObjectType, IASTNode pointOfDefinition) { @@ -140,6 +142,14 @@ public class EvalFunctionSet extends CPPDependentEvaluation { @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { if (fFunctionSet == null) return false; for (ICPPFunction f : fFunctionSet.getBindings()) { 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 9c39e504d42..1909bb72154 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 @@ -31,6 +31,8 @@ import org.eclipse.core.runtime.CoreException; */ public class EvalInitList extends CPPDependentEvaluation { private final ICPPEvaluation[] fClauses; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalInitList(ICPPEvaluation[] clauses, IASTNode pointOfDefinition) { this(clauses, findEnclosingTemplate(pointOfDefinition)); @@ -64,9 +66,17 @@ public class EvalInitList extends CPPDependentEvaluation { public boolean isValueDependent() { return containsDependentValue(fClauses); } - + @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { return areAllConstantExpressions(fClauses, point); } 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 9f1eaa46366..621a91b1d7a 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 @@ -53,6 +53,8 @@ public class EvalTypeId extends CPPDependentEvaluation { private ICPPFunction fConstructor = CPPFunction.UNINITIALIZED_FUNCTION; private boolean fCheckedIsTypeDependent; private boolean fIsTypeDependent; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) { this(type, findEnclosingTemplate(pointOfDefinition), false, arguments); @@ -151,6 +153,14 @@ public class EvalTypeId extends CPPDependentEvaluation { @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { return !fRepresentsNewExpression && areAllConstantExpressions(fArguments, point) && isNullOrConstexprFunc(getConstructor(point)); @@ -298,7 +308,7 @@ public class EvalTypeId extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, ConstexprEvaluationContext context) { ICPPEvaluation[] args = fArguments; for (int i = 0; i < fArguments.length; i++) { 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 2ff6835f794..b29ba79c172 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 @@ -79,6 +79,8 @@ public class EvalUnary extends CPPDependentEvaluation { private final IBinding fAddressOfQualifiedNameBinding; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private IType fType; + private boolean fCheckedIsConstantExpression; + private boolean fIsConstantExpression; public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding, IASTNode pointOfDefinition) { @@ -149,9 +151,17 @@ public class EvalUnary extends CPPDependentEvaluation { return fArgument.isValueDependent(); } } - + @Override public boolean isConstantExpression(IASTNode point) { + if (!fCheckedIsConstantExpression) { + fCheckedIsConstantExpression = true; + fIsConstantExpression = computeIsConstantExpression(point); + } + return fIsConstantExpression; + } + + private boolean computeIsConstantExpression(IASTNode point) { return fArgument.isConstantExpression(point) && isNullOrConstexprFunc(getOverload(point)); } @@ -287,7 +297,7 @@ public class EvalUnary extends CPPDependentEvaluation { return Value.ERROR; IType targetType = parameterTypes[0]; arg = maybeApplyConversion(arg, targetType, point); - + if (!(overload instanceof CPPImplicitFunction)) { if (!overload.isConstexpr()) return Value.ERROR; @@ -381,7 +391,7 @@ public class EvalUnary extends CPPDependentEvaluation { } @Override - public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, ConstexprEvaluationContext context) { ICPPEvaluation argument = fArgument.computeForFunctionCall(parameterMap, context.recordStep()); if (argument == fArgument)