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-11-08 14:38:51 -08:00 committed by Sergey Prigogin
parent 5fb5d5b437
commit 96385656cc
6 changed files with 91 additions and 69 deletions

View file

@ -6039,5 +6039,21 @@ public class AST2TemplateTests extends AST2BaseTest {
// }
public void testFunctionSetWithNonMatchingTemplateArgs_379604() throws Exception {
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;
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() {

View file

@ -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) {

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.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

View file

@ -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) {

View file

@ -217,9 +217,10 @@ public class PDOM extends PlatformObject implements IPDOM {
* 123.0 - Combined file size and encoding hash code.
* 124.0 - GCC attributes and NO_RETURN flag for functions.
* #125.0# - Indexes for unresolved includes and files indexed with I/O errors. <<CDT 8.1>>
<<<<<<< cdt_8_1
* 126.0 - Dependent expressions, bug 299911.
* 127.0 - Explicit virtual overrides, bug 380623.
* 128.0 - Merged several index affecting changes from the master branch.
* 128.0 - Merged several changes affecting index from the master branch.
*/
private static final int MIN_SUPPORTED_VERSION= version(128, 0);
private static final int MAX_SUPPORTED_VERSION= version(128, Short.MAX_VALUE);