From 8c98525c760f5b822c48e213e6ae4f46e199927e Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 3 Oct 2012 13:56:10 +0200 Subject: [PATCH] Bug 391001: Pointer to member in dependent expression. --- .../parser/tests/ast2/AST2TemplateTests.java | 18 +++- .../dom/parser/cpp/CPPASTUnaryExpression.java | 84 ++++++------------- .../parser/cpp/semantics/CPPSemantics.java | 4 +- .../dom/parser/cpp/semantics/EvalUnary.java | 45 +++++++++- .../composite/cpp/CPPCompositesFactory.java | 6 +- .../eclipse/cdt/internal/core/pdom/PDOM.java | 7 +- 6 files changed, 93 insertions(+), 71 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 151c9235b71..cbabcf81b30 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 @@ -6042,5 +6042,21 @@ public class AST2TemplateTests extends AST2BaseTest { // } public void testFunctionSetWithNonMatchingTemplateArgs_379604() throws Exception { parseAndCheckBindings(getAboveComment(), CPP, true); - } + } + + // template struct C { + // typedef decltype(&T::m) dtm; + // }; + // struct X { + // int m() {return 0;} + // }; + // void f(int (X::*)()) {} + // void test() { + // f(&X::m); + // C::dtm v; + // f(v); + // } + public void testPointerToMemberAsDependentExpression_391001() throws Exception { + parseAndCheckBindings(getAboveComment(), CPP, true); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java index 290015f4052..5176d296cf5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java @@ -14,31 +14,23 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE; -import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; import org.eclipse.cdt.core.dom.ast.ASTVisitor; -import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IProblemBinding; -import org.eclipse.cdt.core.dom.ast.IProblemType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; -import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; -import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.FunctionSetType; @@ -175,39 +167,6 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres } } - private IType computePointerToMemberType() { - if (fOperator != op_amper) - return null; - - IASTNode child= fOperand; - boolean inParenthesis= false; - while (child instanceof IASTUnaryExpression && ((IASTUnaryExpression) child).getOperator() == IASTUnaryExpression.op_bracketedPrimary) { - child= ((IASTUnaryExpression) child).getOperand(); - inParenthesis= true; - } - if (child instanceof IASTIdExpression) { - IASTName name= ((IASTIdExpression) child).getName(); - if (name instanceof ICPPASTQualifiedName) { - IBinding b= name.resolveBinding(); - if (b instanceof ICPPMember) { - ICPPMember member= (ICPPMember) b; - if (!member.isStatic()) { - try { - if (!inParenthesis) { - return new CPPPointerToMemberType(member.getType(), member.getClassOwner(), false, false, false); - } else if (member instanceof IFunction) { - return new ProblemBinding(fOperand, IProblemBinding.SEMANTIC_INVALID_TYPE, fOperand.getRawSignature().toCharArray()); - } - } catch (DOMException e) { - return e.getProblem(); - } - } - } - } - } - return null; - } - @Override public ICPPFunction getOverload() { ICPPEvaluation eval = getEvaluation(); @@ -219,27 +178,34 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres @Override public ICPPEvaluation getEvaluation() { if (fEvaluation == null) { - if (fOperand == null) - return EvalFixed.INCOMPLETE; - - final ICPPEvaluation arg = fOperand.getEvaluation(); - if (fOperator == op_bracketedPrimary) { - fEvaluation= arg; - } else if (arg.isFunctionSet() && fOperator == op_amper) { - return arg; - } else { - IType type= computePointerToMemberType(); - if (type != null) { - if (type instanceof IProblemType) - return EvalFixed.INCOMPLETE; - fEvaluation= new EvalFixed(type, PRVALUE, Value.UNKNOWN); - } else { - fEvaluation= new EvalUnary(fOperator, fOperand.getEvaluation()); - } - } + fEvaluation= computeEvaluation(); } return fEvaluation; } + + private ICPPEvaluation computeEvaluation() { + if (fOperand == null) + return EvalFixed.INCOMPLETE; + + final ICPPEvaluation nestedEval = fOperand.getEvaluation(); + if (fOperator == op_bracketedPrimary) + return nestedEval; + + if (nestedEval.isFunctionSet() && fOperator == op_amper) { + return nestedEval; + } + + IBinding addressOfQualifiedNameBinding= null; + if (fOperator == op_amper && fOperand instanceof IASTIdExpression) { + IASTName name= ((IASTIdExpression) fOperand).getName(); + if (name instanceof ICPPASTQualifiedName) { + addressOfQualifiedNameBinding= name.resolveBinding(); + if (addressOfQualifiedNameBinding instanceof IProblemBinding) + return EvalFixed.INCOMPLETE; + } + } + return new EvalUnary(fOperator, nestedEval, addressOfQualifiedNameBinding); + } @Override public IType getExpressionType() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 911a2b5d42c..98bcf4830b8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -3007,8 +3007,8 @@ public class CPPSemantics { return null; final IASTInitializerClause[] placement = expr.getPlacementArguments(); - final ICPPEvaluation arg1= new EvalUnary(IASTUnaryExpression.op_star, evaluation); - final ICPPEvaluation arg2= new EvalUnary(IASTUnaryExpression.op_sizeof, evaluation); + final ICPPEvaluation arg1= new EvalUnary(IASTUnaryExpression.op_star, evaluation, null); + final ICPPEvaluation arg2= new EvalUnary(IASTUnaryExpression.op_sizeof, evaluation, null); ICPPEvaluation[] args; if (placement == null) { 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 6b287f62b1f..2d2caec9208 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 @@ -37,14 +37,17 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; 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.ICPPMember; 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; @@ -55,8 +58,10 @@ import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode; import org.eclipse.core.runtime.CoreException; @@ -66,12 +71,14 @@ public class EvalUnary extends CPPEvaluation { private final int fOperator; private final ICPPEvaluation fArgument; + private final IBinding fAddressOfQualifiedNameBinding; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private IType fType; - public EvalUnary(int operator, ICPPEvaluation operand) { + public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding) { fOperator= operator; fArgument= operand; + fAddressOfQualifiedNameBinding= addressOfQualifiedNameBinding; } public int getOperator() { @@ -82,6 +89,10 @@ public class EvalUnary extends CPPEvaluation { return fArgument; } + public IBinding getAddressOfQualifiedNameBinding() { + return fAddressOfQualifiedNameBinding; + } + @Override public boolean isInitializerList() { return false; @@ -142,6 +153,12 @@ public class EvalUnary extends CPPEvaluation { if (fArgument.isTypeDependent()) return null; + if (fAddressOfQualifiedNameBinding instanceof ICPPMember) { + ICPPMember member= (ICPPMember) fAddressOfQualifiedNameBinding; + if (!member.isStatic()) + return null; + } + IType type = fArgument.getTypeOrFunctionSet(point); type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); if (!CPPSemantics.isUserDefined(type)) @@ -180,6 +197,16 @@ public class EvalUnary extends CPPEvaluation { case op_throw: return CPPSemantics.VOID_TYPE; case op_amper: + if (fAddressOfQualifiedNameBinding instanceof ICPPMember) { + ICPPMember member= (ICPPMember) fAddressOfQualifiedNameBinding; + if (!member.isStatic()) { + try { + return new CPPPointerToMemberType(member.getType(), member.getClassOwner(), false, false, false); + } catch (DOMException e) { + return e.getProblem(); + } + } + } return new CPPPointerType(fArgument.getTypeOrFunctionSet(point)); case op_star: IType type= fArgument.getTypeOrFunctionSet(point); @@ -270,21 +297,31 @@ public class EvalUnary extends CPPEvaluation { buffer.putByte(ITypeMarshalBuffer.EVAL_UNARY); buffer.putByte((byte) fOperator); buffer.marshalEvaluation(fArgument, includeValue); + buffer.marshalBinding(fAddressOfQualifiedNameBinding); } public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { int op= buffer.getByte(); ICPPEvaluation arg= (ICPPEvaluation) buffer.unmarshalEvaluation(); - return new EvalUnary(op, arg); + IBinding binding= buffer.unmarshalBinding(); + return new EvalUnary(op, arg, binding); } @Override public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within, int maxdepth, IASTNode point) { ICPPEvaluation argument = fArgument.instantiate(tpMap, packOffset, within, maxdepth, point); - if (argument == fArgument) + IBinding aoqn = fAddressOfQualifiedNameBinding; + if (aoqn instanceof ICPPUnknownBinding) { + try { + aoqn= CPPTemplates.resolveUnknown((ICPPUnknownBinding) aoqn, tpMap, packOffset, within, point); + } catch (DOMException e) { + } + } + if (argument == fArgument && aoqn == fAddressOfQualifiedNameBinding) return this; - return new EvalUnary(fOperator, argument); + + return new EvalUnary(fOperator, argument, aoqn); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 90a74285f94..2c067f2bbab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -372,8 +372,10 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { EvalUnary e= (EvalUnary) eval; ICPPEvaluation a = e.getArgument(); ICPPEvaluation a2 = getCompositeEvaluation(a); - if (a != a2) - e= new EvalUnary(e.getOperator(), a2); + IBinding b= e.getAddressOfQualifiedNameBinding(); + IBinding b2= getCompositeBinding((IIndexFragmentBinding) b); + if (a != a2 || b != b2) + e= new EvalUnary(e.getOperator(), a2, b2); return e; } if (eval instanceof EvalUnaryTypeID) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index b1c9472f4dc..6365dcb2aac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -224,10 +224,11 @@ public class PDOM extends PlatformObject implements IPDOM { * 132.0 - Explicit virtual overrides, bug 380623. * 133.0 - Storing template arguments via direct marshalling, bug 299911. * 134.0 - Storing unknown bindings via direct marshalling, bug 381824. + * 135.0 - Changed marshalling of EvalUnary, bug 391001. */ - private static final int MIN_SUPPORTED_VERSION= version(134, 0); - private static final int MAX_SUPPORTED_VERSION= version(134, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(134, 0); + private static final int MIN_SUPPORTED_VERSION= version(135, 0); + private static final int MAX_SUPPORTED_VERSION= version(135, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(135, 0); private static int version(int major, int minor) { return (major << 16) + minor;