1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-03 07:05:24 +02:00

Bug 540957 - Implement equivalence checking for expressions

This is used for declaration matching in function templates.

Change-Id: I80044304b2d9dfda085a13f0cfc040f1200a2e1c
This commit is contained in:
Nathan Ridge 2018-11-10 01:10:14 -05:00
parent bee6341c18
commit 02cdb68d6c
31 changed files with 372 additions and 2 deletions

View file

@ -9018,6 +9018,20 @@ public class AST2TemplateTests extends AST2CPPTestBase {
parseAndCheckBindings();
}
// template <typename T>
// T __declval();
//
// template <typename T>
// decltype(__declval<T>()) declval();
//
// template <typename T>
// decltype(__declval<T>()) declval();
//
// using T = decltype(declval<int>());
public void testDeclvalDeclaration_540957() throws Exception {
parseAndCheckBindings();
}
// template <typename T>
// class meta {
// typedef T type;

View file

@ -114,4 +114,10 @@ public interface IValue {
* @noreference This method is not intended to be referenced by clients.
*/
void marshal(ITypeMarshalBuffer buffer) throws CoreException;
/**
* Returns true if this value is equivalent to 'other' for declaration matching purposes.
* @noreference This method is not intended to be referenced by clients.
*/
boolean isEquivalentTo(IValue other);
}

View file

@ -241,4 +241,13 @@ public final class CStringValue implements IValue {
public String toString() {
return new String(fFixedValue);
}
@Override
public boolean isEquivalentTo(IValue other) {
if (!(other instanceof CStringValue)) {
return false;
}
CStringValue o = (CStringValue) other;
return fFixedValue.equals(o.fFixedValue);
}
}

View file

@ -299,4 +299,25 @@ public final class CompositeValue implements IValue {
}
return new CompositeValue(evaluation, values);
}
@Override
public boolean isEquivalentTo(IValue other) {
if (!(other instanceof CompositeValue)) {
return false;
}
CompositeValue o = (CompositeValue) other;
if (!((evaluation == null && o.evaluation == null) ||
(evaluation.isEquivalentTo(o.evaluation)))) {
return false;
}
if (values.length != o.values.length) {
return false;
}
for (int i = 0; i < values.length; i++) {
if (!values[i].isEquivalentTo(o.values[i])) {
return false;
}
}
return true;
}
}

View file

@ -128,4 +128,12 @@ public class DependentValue implements IValue {
return new DependentValue(fEvaluation);
}
@Override
public boolean isEquivalentTo(IValue other) {
if (!(other instanceof DependentValue)) {
return false;
}
DependentValue o = (DependentValue) other;
return fEvaluation.isEquivalentTo(o.fEvaluation);
}
}

View file

@ -163,4 +163,13 @@ public final class FloatingPointValue implements IValue {
public static IValue unmarshal(short firstBytes, ITypeMarshalBuffer buf) throws CoreException {
return new FloatingPointValue(buf.getCharArray());
}
@Override
public boolean isEquivalentTo(IValue other) {
if (!(other instanceof FloatingPointValue)) {
return false;
}
FloatingPointValue o = (FloatingPointValue) other;
return fFixedValue.equals(o.fFixedValue);
}
}

View file

@ -65,7 +65,6 @@ public class IntegralValue implements IValue {
private static int sUnique= 0;
// The following invariant always holds: (fFixedValue == null) != (fEvaluation == null)
private final char[] fFixedValue;
private IntegralValue(char[] fixedValue) {
@ -292,4 +291,13 @@ public class IntegralValue implements IValue {
public IValue clone() {
return new IntegralValue(Arrays.copyOf(fFixedValue, fFixedValue.length));
}
@Override
public boolean isEquivalentTo(IValue other) {
if (!(other instanceof IntegralValue)) {
return false;
}
IntegralValue o = (IntegralValue) other;
return fFixedValue.equals(o.fFixedValue);
}
}

View file

@ -47,6 +47,13 @@ public interface ICPPEvaluation {
*/
boolean isConstantExpression();
/**
* Returns {@code true} if this expression is equivalent to 'other' for
* declaration matching purposes.
*/
boolean isEquivalentTo(ICPPEvaluation other);
/**
* Returns the type of the expression.
*

View file

@ -212,4 +212,72 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
}
return argument;
}
protected static boolean areEquivalentOrNull(ICPPEvaluation a, ICPPEvaluation b) {
if (a == null) {
return (b == null);
}
return a.isEquivalentTo(b);
}
protected static boolean areEquivalentEvaluations(ICPPEvaluation[] a, ICPPEvaluation[] b) {
if (a == null) {
return (b == null);
}
if (a.length != b.length) {
return false;
}
for (int i = 0; i < a.length; i++) {
if (!a[i].isEquivalentTo(b[i])) {
return false;
}
}
return true;
}
protected static boolean areEquivalentArguments(ICPPTemplateArgument[] a, ICPPTemplateArgument[] b) {
if (a == null) {
return (b == null);
}
if (a.length != b.length) {
return false;
}
for (int i = 0; i < a.length; i++) {
if (!a[i].isSameValue(b[i])) {
return false;
}
}
return true;
}
protected static boolean areEquivalentTypes(IType[] a, IType[] b) {
if (a == null) {
return (b == null);
}
if (a.length != b.length) {
return false;
}
for (int i = 0; i < a.length; i++) {
if (!a[i].isSameType(b[i])) {
return false;
}
}
return true;
}
protected static <T extends IBinding> boolean areEquivalentBindings(T[] a, T[] b) {
if (a == null) {
return (b == null);
}
if (a.length != b.length) {
return false;
}
for (int i = 0; i < a.length; i++) {
if (!a[i].equals(b[i])) {
return false;
}
}
return true;
}
}

View file

@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction;
@ -111,4 +112,15 @@ public class CPPFunctionSet implements ICPPTwoPhaseBinding {
return super.toString();
}
}
@Override
public boolean equals(Object other) {
if (!(other instanceof CPPFunctionSet)) {
return false;
}
CPPFunctionSet o = (CPPFunctionSet) other;
return CPPEvaluation.areEquivalentBindings(fBindings, o.fBindings)
&& fName == o.fName
&& CPPEvaluation.areEquivalentArguments(fTemplateArguments, o.fTemplateArguments);
}
}

View file

@ -257,6 +257,17 @@ public class EvalBinary extends CPPDependentEvaluation {
return fIsConstantExpression;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalBinary)) {
return false;
}
EvalBinary o = (EvalBinary) other;
return fOperator == o.fOperator
&& fArg1.isEquivalentTo(o.fArg1)
&& fArg2.isEquivalentTo(o.fArg2);
}
private boolean computeIsConstantExpression() {
return fArg1.isConstantExpression()
&& fArg2.isConstantExpression()

View file

@ -109,6 +109,17 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation {
return true;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalBinaryTypeId)) {
return false;
}
EvalBinaryTypeId o = (EvalBinaryTypeId) other;
return fOperator == o.fOperator
&& fType1.isSameType(o.fType1)
&& fType2.isSameType(o.fType2);
}
@Override
public ValueCategory getValueCategory() {
return PRVALUE;

View file

@ -260,6 +260,19 @@ public class EvalBinding extends CPPDependentEvaluation {
|| (fBinding instanceof IVariable && isConstexprValue(((IVariable) fBinding).getInitialValue()));
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalBinding)) {
return false;
}
EvalBinding o = (EvalBinding) other;
if (fBinding != null) {
return fBinding == o.fBinding;
}
return fParameterOwner == o.fParameterOwner
&& fParameterPosition == o.fParameterPosition;
}
@Override
public IType getType() {
if (fType == null) {

View file

@ -96,6 +96,15 @@ public class EvalComma extends CPPDependentEvaluation {
return true;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalComma)) {
return false;
}
EvalComma o = (EvalComma) other;
return areEquivalentEvaluations(fArguments, o.fArguments);
}
public ICPPFunction[] getOverloads() {
if (fOverloads == null) {
fOverloads= computeOverloads();

View file

@ -78,6 +78,16 @@ public final class EvalCompositeAccess implements ICPPEvaluation {
return getTargetEvaluation().isConstantExpression();
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalCompositeAccess)) {
return false;
}
EvalCompositeAccess o = (EvalCompositeAccess) other;
return parent.isEquivalentTo(o.parent)
&& elementId == o.elementId;
}
@Override
public IType getType() {
IType type = getParent().getType();

View file

@ -73,6 +73,15 @@ public class EvalCompoundStatementExpression extends CPPDependentEvaluation {
return fDelegate.isConstantExpression();
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalCompoundStatementExpression)) {
return false;
}
EvalCompoundStatementExpression o = (EvalCompoundStatementExpression) other;
return fDelegate.isEquivalentTo(o.fDelegate);
}
@Override
public IType getType() {
return fDelegate.getType();

View file

@ -164,6 +164,17 @@ public class EvalConditional extends CPPDependentEvaluation {
&& fNegative.isConstantExpression();
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalConditional)) {
return false;
}
EvalConditional o = (EvalConditional) other;
return fCondition.isEquivalentTo(o.fCondition)
&& areEquivalentOrNull(fPositive, o.fPositive)
&& fNegative.isEquivalentTo(o.fNegative);
}
private void evaluate() {
if (fValueCategory != null)
return;

View file

@ -113,6 +113,17 @@ public final class EvalConstructor extends CPPDependentEvaluation {
return fConstructor.isConstexpr() && areAllConstantExpressions(fArguments);
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalConstructor)) {
return false;
}
EvalConstructor o = (EvalConstructor) other;
return fType.isSameType(o.fType)
&& fConstructor == o.fConstructor
&& areEquivalentEvaluations(fArguments, o.fArguments);
}
@Override
public IType getType() {
return fType;

View file

@ -111,6 +111,16 @@ public final class EvalFixed extends CPPEvaluation {
|| isConstexprValue(fValue);
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalFixed)) {
return false;
}
EvalFixed o = (EvalFixed) other;
return fType.isSameType(o.fType)
&& fValue.isEquivalentTo(o.fValue);
}
@Override
public IType getType() {
return fType;

View file

@ -127,6 +127,15 @@ public final class EvalFunctionCall extends CPPDependentEvaluation {
return areAllConstantExpressions(fArguments) && isNullOrConstexprFunc(getOverload());
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalFunctionCall)) {
return false;
}
EvalFunctionCall o = (EvalFunctionCall) other;
return areEquivalentEvaluations(fArguments, o.fArguments);
}
public ICPPFunction getOverload() {
if (fOverload == CPPFunction.UNINITIALIZED_FUNCTION) {
fOverload = computeOverload();

View file

@ -158,6 +158,15 @@ public class EvalFunctionSet extends CPPDependentEvaluation {
return true;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalFunctionSet)) {
return false;
}
EvalFunctionSet o = (EvalFunctionSet) other;
return fFunctionSet.equals(o.fFunctionSet);
}
@Override
public IType getType() {
return new FunctionSetType(fFunctionSet, fAddressOf);

View file

@ -51,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.DependentValue;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
@ -154,6 +155,21 @@ public class EvalID extends CPPDependentEvaluation {
return false;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalID)) {
return false;
}
EvalID o = (EvalID) other;
return areEquivalentOrNull(fFieldOwner, o.fFieldOwner)
&& CharArrayUtils.equals(fName, o.fName)
&& fNameOwner == o.fNameOwner
&& fAddressOf == o.fAddressOf
&& fQualified == o.fQualified
&& fIsPointerDeref == o.fIsPointerDeref
&& areEquivalentArguments(fTemplateArgs, o.fTemplateArgs);
}
@Override
public IType getType() {
return new TypeOfDependentExpression(this);

View file

@ -86,6 +86,15 @@ public class EvalInitList extends CPPDependentEvaluation {
return areAllConstantExpressions(fClauses);
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalInitList)) {
return false;
}
EvalInitList o = (EvalInitList) other;
return areEquivalentEvaluations(fClauses, o.fClauses);
}
@Override
public IType getType() {
return new InitializerListType(this);

View file

@ -188,6 +188,18 @@ public class EvalMemberAccess extends CPPDependentEvaluation {
return false;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalMemberAccess)) {
return false;
}
EvalMemberAccess o = (EvalMemberAccess) other;
return fOwnerType.isSameType(o.fOwnerType)
&& fMember == o.fMember
&& fOwnerValueCategory == o.fOwnerValueCategory
&& fIsPointerDeref == o.fIsPointerDeref;
}
public static IType getFieldOwnerType(IType fieldOwnerExpressionType, boolean isDeref,
Collection<ICPPFunction> functionBindings, boolean returnDependent) {
IType type= fieldOwnerExpressionType;

View file

@ -84,6 +84,16 @@ public class EvalNaryTypeId extends CPPDependentEvaluation {
return true;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalNaryTypeId)) {
return false;
}
EvalNaryTypeId o = (EvalNaryTypeId) other;
return fOperator == o.fOperator
&& areEquivalentTypes(fOperands, o.fOperands);
}
@Override
public IType getType() {
switch (fOperator) {

View file

@ -69,6 +69,15 @@ public class EvalPackExpansion extends CPPDependentEvaluation {
return false;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalPackExpansion)) {
return false;
}
EvalPackExpansion o = (EvalPackExpansion) other;
return fExpansionPattern.isEquivalentTo(o.fExpansionPattern);
}
@Override
public IType getType() {
if (fType == null) {

View file

@ -81,6 +81,13 @@ public class EvalReference extends CPPDependentEvaluation {
return getTargetEvaluation().isConstantExpression();
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
// This probably doesn't need to be implemented as this evaluation type
// only arises as an intermediate artifact during constexpr processing.
return false;
}
@Override
public IType getType() {
return getTargetEvaluation().getType();

View file

@ -231,6 +231,18 @@ public class EvalTypeId extends CPPDependentEvaluation {
&& isNullOrConstexprFunc(getConstructor());
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalTypeId)) {
return false;
}
EvalTypeId o = (EvalTypeId) other;
return fInputType.isSameType(o.fInputType)
&& areEquivalentEvaluations(fArguments, o.fArguments)
&& fRepresentsNewExpression == o.fRepresentsNewExpression
&& fUsesBracedInitList == o.fUsesBracedInitList;
}
@Override
public ValueCategory getValueCategory() {
return valueCategoryFromReturnType(fInputType);

View file

@ -171,6 +171,16 @@ public class EvalUnary extends CPPDependentEvaluation {
&& isNullOrConstexprFunc(getOverload());
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalUnary)) {
return false;
}
EvalUnary o = (EvalUnary) other;
return fOperator == o.fOperator
&& fArgument.isEquivalentTo(o.fArgument);
}
public ICPPFunction getOverload() {
if (fOverload == CPPFunction.UNINITIALIZED_FUNCTION) {
fOverload= computeOverload();

View file

@ -136,6 +136,16 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
return true;
}
@Override
public boolean isEquivalentTo(ICPPEvaluation other) {
if (!(other instanceof EvalUnaryTypeID)) {
return false;
}
EvalUnaryTypeID o = (EvalUnaryTypeID) other;
return fOperator == o.fOperator
&& fOrigType.isSameType(o.fOrigType);
}
@Override
public IType getType() {
if (fType == null)

View file

@ -65,7 +65,7 @@ public class TypeOfDependentExpression extends CPPUnknownBinding implements ICPP
@Override
public boolean isSameType(IType type) {
return type instanceof TypeOfDependentExpression
&& fEvaluation == ((TypeOfDependentExpression) type).fEvaluation;
&& fEvaluation.isEquivalentTo(((TypeOfDependentExpression) type).fEvaluation);
}
@Override