1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 391001: Pointer to member in dependent expression.

This commit is contained in:
Markus Schorn 2012-10-03 13:56:10 +02:00
parent 474f8b9f37
commit 8c98525c76
6 changed files with 93 additions and 71 deletions

View file

@ -6042,5 +6042,21 @@ public class AST2TemplateTests extends AST2BaseTest {
// } // }
public void testFunctionSetWithNonMatchingTemplateArgs_379604() throws Exception { public void testFunctionSetWithNonMatchingTemplateArgs_379604() throws Exception {
parseAndCheckBindings(getAboveComment(), CPP, true); parseAndCheckBindings(getAboveComment(), CPP, true);
} }
// template <typename T> struct C {
// typedef decltype(&T::m) dtm;
// };
// struct X {
// int m() {return 0;}
// };
// void f(int (X::*)()) {}
// void test() {
// f(&X::m);
// C<X>::dtm v;
// f(v);
// }
public void testPointerToMemberAsDependentExpression_391001() throws Exception {
parseAndCheckBindings(getAboveComment(), CPP, true);
}
} }

View file

@ -14,31 +14,23 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp; 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.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.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; 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.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; 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.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; 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.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; 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.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; 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.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; 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.EvalFixed;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnary; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUnary;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.FunctionSetType; 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 @Override
public ICPPFunction getOverload() { public ICPPFunction getOverload() {
ICPPEvaluation eval = getEvaluation(); ICPPEvaluation eval = getEvaluation();
@ -219,27 +178,34 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
@Override @Override
public ICPPEvaluation getEvaluation() { public ICPPEvaluation getEvaluation() {
if (fEvaluation == null) { if (fEvaluation == null) {
if (fOperand == null) fEvaluation= computeEvaluation();
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());
}
}
} }
return fEvaluation; 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 @Override
public IType getExpressionType() { public IType getExpressionType() {

View file

@ -3007,8 +3007,8 @@ public class CPPSemantics {
return null; return null;
final IASTInitializerClause[] placement = expr.getPlacementArguments(); final IASTInitializerClause[] placement = expr.getPlacementArguments();
final ICPPEvaluation arg1= new EvalUnary(IASTUnaryExpression.op_star, evaluation); final ICPPEvaluation arg1= new EvalUnary(IASTUnaryExpression.op_star, evaluation, null);
final ICPPEvaluation arg2= new EvalUnary(IASTUnaryExpression.op_sizeof, evaluation); final ICPPEvaluation arg2= new EvalUnary(IASTUnaryExpression.op_sizeof, evaluation, null);
ICPPEvaluation[] args; ICPPEvaluation[] args;
if (placement == null) { if (placement == null) {

View file

@ -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.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; 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.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTNode; 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.IPointerType;
import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue; 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.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; 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.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; 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.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.CPPArithmeticConversion;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; 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.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.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; 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.OverloadableOperator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -66,12 +71,14 @@ public class EvalUnary extends CPPEvaluation {
private final int fOperator; private final int fOperator;
private final ICPPEvaluation fArgument; private final ICPPEvaluation fArgument;
private final IBinding fAddressOfQualifiedNameBinding;
private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION; private ICPPFunction fOverload= CPPFunction.UNINITIALIZED_FUNCTION;
private IType fType; private IType fType;
public EvalUnary(int operator, ICPPEvaluation operand) { public EvalUnary(int operator, ICPPEvaluation operand, IBinding addressOfQualifiedNameBinding) {
fOperator= operator; fOperator= operator;
fArgument= operand; fArgument= operand;
fAddressOfQualifiedNameBinding= addressOfQualifiedNameBinding;
} }
public int getOperator() { public int getOperator() {
@ -82,6 +89,10 @@ public class EvalUnary extends CPPEvaluation {
return fArgument; return fArgument;
} }
public IBinding getAddressOfQualifiedNameBinding() {
return fAddressOfQualifiedNameBinding;
}
@Override @Override
public boolean isInitializerList() { public boolean isInitializerList() {
return false; return false;
@ -142,6 +153,12 @@ public class EvalUnary extends CPPEvaluation {
if (fArgument.isTypeDependent()) if (fArgument.isTypeDependent())
return null; return null;
if (fAddressOfQualifiedNameBinding instanceof ICPPMember) {
ICPPMember member= (ICPPMember) fAddressOfQualifiedNameBinding;
if (!member.isStatic())
return null;
}
IType type = fArgument.getTypeOrFunctionSet(point); IType type = fArgument.getTypeOrFunctionSet(point);
type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); type = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE);
if (!CPPSemantics.isUserDefined(type)) if (!CPPSemantics.isUserDefined(type))
@ -180,6 +197,16 @@ public class EvalUnary extends CPPEvaluation {
case op_throw: case op_throw:
return CPPSemantics.VOID_TYPE; return CPPSemantics.VOID_TYPE;
case op_amper: 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)); return new CPPPointerType(fArgument.getTypeOrFunctionSet(point));
case op_star: case op_star:
IType type= fArgument.getTypeOrFunctionSet(point); IType type= fArgument.getTypeOrFunctionSet(point);
@ -270,21 +297,31 @@ public class EvalUnary extends CPPEvaluation {
buffer.putByte(ITypeMarshalBuffer.EVAL_UNARY); buffer.putByte(ITypeMarshalBuffer.EVAL_UNARY);
buffer.putByte((byte) fOperator); buffer.putByte((byte) fOperator);
buffer.marshalEvaluation(fArgument, includeValue); buffer.marshalEvaluation(fArgument, includeValue);
buffer.marshalBinding(fAddressOfQualifiedNameBinding);
} }
public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException {
int op= buffer.getByte(); int op= buffer.getByte();
ICPPEvaluation arg= (ICPPEvaluation) buffer.unmarshalEvaluation(); ICPPEvaluation arg= (ICPPEvaluation) buffer.unmarshalEvaluation();
return new EvalUnary(op, arg); IBinding binding= buffer.unmarshalBinding();
return new EvalUnary(op, arg, binding);
} }
@Override @Override
public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset, public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset,
ICPPClassSpecialization within, int maxdepth, IASTNode point) { ICPPClassSpecialization within, int maxdepth, IASTNode point) {
ICPPEvaluation argument = fArgument.instantiate(tpMap, packOffset, within, maxdepth, 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 this;
return new EvalUnary(fOperator, argument);
return new EvalUnary(fOperator, argument, aoqn);
} }
@Override @Override

View file

@ -372,8 +372,10 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
EvalUnary e= (EvalUnary) eval; EvalUnary e= (EvalUnary) eval;
ICPPEvaluation a = e.getArgument(); ICPPEvaluation a = e.getArgument();
ICPPEvaluation a2 = getCompositeEvaluation(a); ICPPEvaluation a2 = getCompositeEvaluation(a);
if (a != a2) IBinding b= e.getAddressOfQualifiedNameBinding();
e= new EvalUnary(e.getOperator(), a2); IBinding b2= getCompositeBinding((IIndexFragmentBinding) b);
if (a != a2 || b != b2)
e= new EvalUnary(e.getOperator(), a2, b2);
return e; return e;
} }
if (eval instanceof EvalUnaryTypeID) { if (eval instanceof EvalUnaryTypeID) {

View file

@ -224,10 +224,11 @@ public class PDOM extends PlatformObject implements IPDOM {
* 132.0 - Explicit virtual overrides, bug 380623. * 132.0 - Explicit virtual overrides, bug 380623.
* 133.0 - Storing template arguments via direct marshalling, bug 299911. * 133.0 - Storing template arguments via direct marshalling, bug 299911.
* 134.0 - Storing unknown bindings via direct marshalling, bug 381824. * 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 MIN_SUPPORTED_VERSION= version(135, 0);
private static final int MAX_SUPPORTED_VERSION= version(134, Short.MAX_VALUE); private static final int MAX_SUPPORTED_VERSION= version(135, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(134, 0); private static final int DEFAULT_VERSION = version(135, 0);
private static int version(int major, int minor) { private static int version(int major, int minor) {
return (major << 16) + minor; return (major << 16) + minor;