1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-18 22:45:23 +02:00

Bug 497875 - Avoid evaluating isConstantExpression multiple times

Change-Id: I54d6b533f5b21294a92319ea1d45d4f18962a460
This commit is contained in:
Sergey Prigogin 2016-07-13 17:57:02 -07:00
parent f2af760266
commit b7ecc46eca
9 changed files with 108 additions and 18 deletions

View file

@ -81,6 +81,8 @@ public class EvalBinary extends CPPDependentEvaluation {
private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION;
private IType fType; private IType fType;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2, IASTNode pointOfDefinition) { public EvalBinary(int operator, ICPPEvaluation arg1, ICPPEvaluation arg2, IASTNode pointOfDefinition) {
this(operator, arg1, arg2, findEnclosingTemplate(pointOfDefinition)); this(operator, arg1, arg2, findEnclosingTemplate(pointOfDefinition));
@ -201,9 +203,17 @@ public class EvalBinary extends CPPDependentEvaluation {
public boolean isValueDependent() { public boolean isValueDependent() {
return fArg1.isValueDependent() || fArg2.isValueDependent(); return fArg1.isValueDependent() || fArg2.isValueDependent();
} }
@Override @Override
public boolean isConstantExpression(IASTNode point) { public boolean isConstantExpression(IASTNode point) {
if (!fCheckedIsConstantExpression) {
fCheckedIsConstantExpression = true;
fIsConstantExpression = computeIsConstantExpression(point);
}
return fIsConstantExpression;
}
private boolean computeIsConstantExpression(IASTNode point) {
return fArg1.isConstantExpression(point) return fArg1.isConstantExpression(point)
&& fArg2.isConstantExpression(point) && fArg2.isConstantExpression(point)
&& isNullOrConstexprFunc(getOverload(point)); && isNullOrConstexprFunc(getOverload(point));
@ -262,7 +272,7 @@ public class EvalBinary extends CPPDependentEvaluation {
IType type = fArg1.getType(point); IType type = fArg1.getType(point);
type= SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); type= SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
if (type instanceof ICPPClassType) { if (type instanceof ICPPClassType) {
return CPPSemantics.findOverloadedBinaryOperator(point, getTemplateDefinitionScope(), return CPPSemantics.findOverloadedBinaryOperator(point, getTemplateDefinitionScope(),
OverloadableOperator.BRACKET, fArg1, fArg2); OverloadableOperator.BRACKET, fArg1, fArg2);
} }
} else { } else {

View file

@ -36,9 +36,11 @@ public class EvalComma extends CPPDependentEvaluation {
private ICPPFunction[] fOverloads; private ICPPFunction[] fOverloads;
private IType fType; private IType fType;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalComma(ICPPEvaluation[] evals, IASTNode pointOfDefinition) { public EvalComma(ICPPEvaluation[] evals, IASTNode pointOfDefinition) {
this(evals, findEnclosingTemplate(pointOfDefinition)); this(evals, findEnclosingTemplate(pointOfDefinition));
} }
public EvalComma(ICPPEvaluation[] evals, IBinding templateDefinition) { public EvalComma(ICPPEvaluation[] evals, IBinding templateDefinition) {
@ -72,9 +74,17 @@ public class EvalComma extends CPPDependentEvaluation {
public boolean isValueDependent() { public boolean isValueDependent() {
return containsDependentValue(fArguments); return containsDependentValue(fArguments);
} }
@Override @Override
public boolean isConstantExpression(IASTNode point) { public boolean isConstantExpression(IASTNode point) {
if (!fCheckedIsConstantExpression) {
fCheckedIsConstantExpression = true;
fIsConstantExpression = computeIsConstantExpression(point);
}
return fIsConstantExpression;
}
private boolean computeIsConstantExpression(IASTNode point) {
if (!areAllConstantExpressions(fArguments, point)) { if (!areAllConstantExpressions(fArguments, point)) {
return false; return false;
} }

View file

@ -55,6 +55,8 @@ public class EvalConditional extends CPPDependentEvaluation {
private ValueCategory fValueCategory; private ValueCategory fValueCategory;
private IType fType; private IType fType;
private ICPPFunction fOverload; private ICPPFunction fOverload;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalConditional(ICPPEvaluation condition, ICPPEvaluation positive, ICPPEvaluation negative, public EvalConditional(ICPPEvaluation condition, ICPPEvaluation positive, ICPPEvaluation negative,
boolean positiveThrows, boolean negativeThrows, IASTNode pointOfDefinition) { boolean positiveThrows, boolean negativeThrows, IASTNode pointOfDefinition) {
@ -149,6 +151,14 @@ public class EvalConditional extends CPPDependentEvaluation {
@Override @Override
public boolean isConstantExpression(IASTNode point) { public boolean isConstantExpression(IASTNode point) {
if (!fCheckedIsConstantExpression) {
fCheckedIsConstantExpression = true;
fIsConstantExpression = computeIsConstantExpression(point);
}
return fIsConstantExpression;
}
private boolean computeIsConstantExpression(IASTNode point) {
return fCondition.isConstantExpression(point) return fCondition.isConstantExpression(point)
&& (fPositive == null || fPositive.isConstantExpression(point)) && (fPositive == null || fPositive.isConstantExpression(point))
&& fNegative.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 // 5.16-5: At least one class type but no conversion
if (isClassType2 || isClassType3) { if (isClassType2 || isClassType3) {
fOverload = CPPSemantics.findOverloadedConditionalOperator(point, getTemplateDefinitionScope(), positive, fNegative); fOverload = CPPSemantics.findOverloadedConditionalOperator(point, getTemplateDefinitionScope(), positive, fNegative);
if (fOverload != null) { if (fOverload != null) {
fType= ExpressionTypes.typeFromFunctionCall(fOverload); fType= ExpressionTypes.typeFromFunctionCall(fOverload);
} else { } else {

View file

@ -45,6 +45,8 @@ public class EvalFixed extends CPPEvaluation {
private boolean fCheckedIsTypeDependent; private boolean fCheckedIsTypeDependent;
private boolean fIsValueDependent; private boolean fIsValueDependent;
private boolean fCheckedIsValueDependent; private boolean fCheckedIsValueDependent;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalFixed(IType type, ValueCategory cat, IValue value) { public EvalFixed(IType type, ValueCategory cat, IValue value) {
// Avoid nesting EvalFixed's as nesting causes the signature to be different. // Avoid nesting EvalFixed's as nesting causes the signature to be different.
@ -54,7 +56,7 @@ public class EvalFixed extends CPPEvaluation {
cat = inner.fValueCategory; cat = inner.fValueCategory;
value = inner.fValue; value = inner.fValue;
} }
if (type instanceof CPPBasicType) { if (type instanceof CPPBasicType) {
Long num = value.numericalValue(); Long num = value.numericalValue();
if (num != null) { if (num != null) {
@ -67,7 +69,7 @@ public class EvalFixed extends CPPEvaluation {
fValueCategory= cat; fValueCategory= cat;
fValue= value; fValue= value;
} }
public IType getType() { public IType getType() {
return fType; return fType;
} }
@ -107,9 +109,17 @@ public class EvalFixed extends CPPEvaluation {
} }
return fIsValueDependent; return fIsValueDependent;
} }
@Override @Override
public boolean isConstantExpression(IASTNode point) { 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)) return (fType instanceof ICPPClassType && TypeTraits.isEmpty(fType, point))
|| isConstexprValue(fValue, point); || isConstexprValue(fValue, point);
} }
@ -180,11 +190,11 @@ public class EvalFixed extends CPPEvaluation {
IValue value = CPPTemplates.instantiateValue(fValue, context, maxDepth); IValue value = CPPTemplates.instantiateValue(fValue, context, maxDepth);
if (type == fType && value == fValue) if (type == fType && value == fValue)
return this; 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. // propagate that error.
if (value == Value.ERROR) if (value == Value.ERROR)
return EvalFixed.INCOMPLETE; 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) if (type instanceof ICPPParameterPackType && value.numericalValue() != null)
type = ((ICPPParameterPackType) type).getType(); type = ((ICPPParameterPackType) type).getType();
return new EvalFixed(type, fValueCategory, value); return new EvalFixed(type, fValueCategory, value);

View file

@ -45,6 +45,8 @@ public class EvalFunctionCall extends CPPDependentEvaluation {
private final ICPPEvaluation[] fArguments; private final ICPPEvaluation[] fArguments;
private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION;
private IType fType; private IType fType;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalFunctionCall(ICPPEvaluation[] args, IASTNode pointOfDefinition) { public EvalFunctionCall(ICPPEvaluation[] args, IASTNode pointOfDefinition) {
this(args, findEnclosingTemplate(pointOfDefinition)); this(args, findEnclosingTemplate(pointOfDefinition));
@ -85,6 +87,14 @@ public class EvalFunctionCall extends CPPDependentEvaluation {
@Override @Override
public boolean isConstantExpression(IASTNode point) { 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)); 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); IType t= SemanticUtil.getNestedType(fArguments[0].getType(point), TDEF | REF | CVTYPE);
if (t instanceof ICPPClassType) { if (t instanceof ICPPClassType) {
return CPPSemantics.findOverloadedOperator(point, getTemplateDefinitionScope(), fArguments, t, return CPPSemantics.findOverloadedOperator(point, getTemplateDefinitionScope(), fArguments, t,
OverloadableOperator.PAREN, LookupMode.NO_GLOBALS); OverloadableOperator.PAREN, LookupMode.NO_GLOBALS);
} }
return null; return null;
@ -121,7 +131,7 @@ public class EvalFunctionCall extends CPPDependentEvaluation {
ICPPFunction overload = getOverload(point); ICPPFunction overload = getOverload(point);
if (overload != null) if (overload != null)
return ExpressionTypes.typeFromFunctionCall(overload); return ExpressionTypes.typeFromFunctionCall(overload);
ICPPEvaluation function = fArguments[0]; ICPPEvaluation function = fArguments[0];
IType result = ExpressionTypes.typeFromFunctionCall(function.getType(point)); IType result = ExpressionTypes.typeFromFunctionCall(function.getType(point));
if (function instanceof EvalMemberAccess) { if (function instanceof EvalMemberAccess) {
@ -135,7 +145,7 @@ public class EvalFunctionCall extends CPPDependentEvaluation {
ICPPEvaluation eval = computeForFunctionCall(new ConstexprEvaluationContext(point)); ICPPEvaluation eval = computeForFunctionCall(new ConstexprEvaluationContext(point));
if (eval == this) { if (eval == this) {
return Value.create(eval); return Value.create(eval);
} }
return eval.getValue(point); return eval.getValue(point);
} }

View file

@ -58,6 +58,8 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
// by asking the first function in the set for its name.) // by asking the first function in the set for its name.)
// Exactly one of fFunctionSet and fName should be non-null. // Exactly one of fFunctionSet and fName should be non-null.
private final char[] fName; private final char[] fName;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalFunctionSet(CPPFunctionSet set, boolean qualified, boolean addressOf, IType impliedObjectType, public EvalFunctionSet(CPPFunctionSet set, boolean qualified, boolean addressOf, IType impliedObjectType,
IASTNode pointOfDefinition) { IASTNode pointOfDefinition) {
@ -140,6 +142,14 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
@Override @Override
public boolean isConstantExpression(IASTNode point) { public boolean isConstantExpression(IASTNode point) {
if (!fCheckedIsConstantExpression) {
fCheckedIsConstantExpression = true;
fIsConstantExpression = computeIsConstantExpression(point);
}
return fIsConstantExpression;
}
private boolean computeIsConstantExpression(IASTNode point) {
if (fFunctionSet == null) if (fFunctionSet == null)
return false; return false;
for (ICPPFunction f : fFunctionSet.getBindings()) { for (ICPPFunction f : fFunctionSet.getBindings()) {

View file

@ -31,6 +31,8 @@ import org.eclipse.core.runtime.CoreException;
*/ */
public class EvalInitList extends CPPDependentEvaluation { public class EvalInitList extends CPPDependentEvaluation {
private final ICPPEvaluation[] fClauses; private final ICPPEvaluation[] fClauses;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalInitList(ICPPEvaluation[] clauses, IASTNode pointOfDefinition) { public EvalInitList(ICPPEvaluation[] clauses, IASTNode pointOfDefinition) {
this(clauses, findEnclosingTemplate(pointOfDefinition)); this(clauses, findEnclosingTemplate(pointOfDefinition));
@ -64,9 +66,17 @@ public class EvalInitList extends CPPDependentEvaluation {
public boolean isValueDependent() { public boolean isValueDependent() {
return containsDependentValue(fClauses); return containsDependentValue(fClauses);
} }
@Override @Override
public boolean isConstantExpression(IASTNode point) { public boolean isConstantExpression(IASTNode point) {
if (!fCheckedIsConstantExpression) {
fCheckedIsConstantExpression = true;
fIsConstantExpression = computeIsConstantExpression(point);
}
return fIsConstantExpression;
}
private boolean computeIsConstantExpression(IASTNode point) {
return areAllConstantExpressions(fClauses, point); return areAllConstantExpressions(fClauses, point);
} }

View file

@ -53,6 +53,8 @@ public class EvalTypeId extends CPPDependentEvaluation {
private ICPPFunction fConstructor = CPPFunction.UNINITIALIZED_FUNCTION; private ICPPFunction fConstructor = CPPFunction.UNINITIALIZED_FUNCTION;
private boolean fCheckedIsTypeDependent; private boolean fCheckedIsTypeDependent;
private boolean fIsTypeDependent; private boolean fIsTypeDependent;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) { public EvalTypeId(IType type, IASTNode pointOfDefinition, ICPPEvaluation... arguments) {
this(type, findEnclosingTemplate(pointOfDefinition), false, arguments); this(type, findEnclosingTemplate(pointOfDefinition), false, arguments);
@ -151,6 +153,14 @@ public class EvalTypeId extends CPPDependentEvaluation {
@Override @Override
public boolean isConstantExpression(IASTNode point) { public boolean isConstantExpression(IASTNode point) {
if (!fCheckedIsConstantExpression) {
fCheckedIsConstantExpression = true;
fIsConstantExpression = computeIsConstantExpression(point);
}
return fIsConstantExpression;
}
private boolean computeIsConstantExpression(IASTNode point) {
return !fRepresentsNewExpression return !fRepresentsNewExpression
&& areAllConstantExpressions(fArguments, point) && areAllConstantExpressions(fArguments, point)
&& isNullOrConstexprFunc(getConstructor(point)); && isNullOrConstexprFunc(getConstructor(point));
@ -298,7 +308,7 @@ public class EvalTypeId extends CPPDependentEvaluation {
} }
@Override @Override
public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap,
ConstexprEvaluationContext context) { ConstexprEvaluationContext context) {
ICPPEvaluation[] args = fArguments; ICPPEvaluation[] args = fArguments;
for (int i = 0; i < fArguments.length; i++) { for (int i = 0; i < fArguments.length; i++) {

View file

@ -79,6 +79,8 @@ public class EvalUnary extends CPPDependentEvaluation {
private final IBinding fAddressOfQualifiedNameBinding; private final IBinding fAddressOfQualifiedNameBinding;
private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION;
private IType fType; private IType fType;
private boolean fCheckedIsConstantExpression;
private boolean fIsConstantExpression;
public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding, public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding,
IASTNode pointOfDefinition) { IASTNode pointOfDefinition) {
@ -149,9 +151,17 @@ public class EvalUnary extends CPPDependentEvaluation {
return fArgument.isValueDependent(); return fArgument.isValueDependent();
} }
} }
@Override @Override
public boolean isConstantExpression(IASTNode point) { public boolean isConstantExpression(IASTNode point) {
if (!fCheckedIsConstantExpression) {
fCheckedIsConstantExpression = true;
fIsConstantExpression = computeIsConstantExpression(point);
}
return fIsConstantExpression;
}
private boolean computeIsConstantExpression(IASTNode point) {
return fArgument.isConstantExpression(point) return fArgument.isConstantExpression(point)
&& isNullOrConstexprFunc(getOverload(point)); && isNullOrConstexprFunc(getOverload(point));
} }
@ -287,7 +297,7 @@ public class EvalUnary extends CPPDependentEvaluation {
return Value.ERROR; return Value.ERROR;
IType targetType = parameterTypes[0]; IType targetType = parameterTypes[0];
arg = maybeApplyConversion(arg, targetType, point); arg = maybeApplyConversion(arg, targetType, point);
if (!(overload instanceof CPPImplicitFunction)) { if (!(overload instanceof CPPImplicitFunction)) {
if (!overload.isConstexpr()) if (!overload.isConstexpr())
return Value.ERROR; return Value.ERROR;
@ -381,7 +391,7 @@ public class EvalUnary extends CPPDependentEvaluation {
} }
@Override @Override
public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap,
ConstexprEvaluationContext context) { ConstexprEvaluationContext context) {
ICPPEvaluation argument = fArgument.computeForFunctionCall(parameterMap, context.recordStep()); ICPPEvaluation argument = fArgument.computeForFunctionCall(parameterMap, context.recordStep());
if (argument == fArgument) if (argument == fArgument)