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:
parent
5fb5d5b437
commit
96385656cc
6 changed files with 91 additions and 69 deletions
|
@ -6040,4 +6040,20 @@ 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,26 +178,33 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
@Override
|
||||
public ICPPEvaluation getEvaluation() {
|
||||
if (fEvaluation == null) {
|
||||
fEvaluation= computeEvaluation();
|
||||
}
|
||||
return fEvaluation;
|
||||
}
|
||||
|
||||
private ICPPEvaluation computeEvaluation() {
|
||||
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)
|
||||
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;
|
||||
fEvaluation= new EvalFixed(type, PRVALUE, Value.UNKNOWN);
|
||||
} else {
|
||||
fEvaluation= new EvalUnary(fOperator, fOperand.getEvaluation());
|
||||
}
|
||||
}
|
||||
}
|
||||
return fEvaluation;
|
||||
return new EvalUnary(fOperator, nestedEval, addressOfQualifiedNameBinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue