1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 18:56:02 +02:00

Bug 324214: Overload resolution with method template and global function.

This commit is contained in:
Markus Schorn 2010-09-01 15:44:56 +00:00
parent 53b2b45d96
commit 1e7636523a
10 changed files with 144 additions and 145 deletions

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* IBM - Initial API and implementation * Andrew Niefer (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Bryan Wilkinson (QNX) * Bryan Wilkinson (QNX)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
@ -85,9 +85,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
/**
* @author aniefer
*/
public class AST2TemplateTests extends AST2BaseTest { public class AST2TemplateTests extends AST2BaseTest {
public AST2TemplateTests() { public AST2TemplateTests() {
@ -5094,4 +5091,20 @@ public class AST2TemplateTests extends AST2BaseTest {
parseAndCheckBindings(code); parseAndCheckBindings(code);
} }
// struct S {
// int s;
// };
// struct X {
// template<typename T> S* operator+(T t) const {return 0;}
// };
// int* operator+(const X&, int *) {return 0;}
//
// void test() {
// X x;
// (x + 1)->s;
// }
public void testOverloadResolutionBetweenMethodTemplateAndFunction() throws Exception {
final String code= getAboveComment();
parseAndCheckBindings(code);
}
} }

View file

@ -125,7 +125,7 @@ public class CPPASTFieldReference extends ASTNode implements ICPPASTFieldReferen
// collect the function bindings // collect the function bindings
List<ICPPFunction> functionBindings = new ArrayList<ICPPFunction>(); List<ICPPFunction> functionBindings = new ArrayList<ICPPFunction>();
try { try {
CPPSemantics.getChainedMemberAccessOperatorReturnType(this, functionBindings); CPPSemantics.getFieldOwnerType(this, functionBindings);
} catch (DOMException e) { } catch (DOMException e) {
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
} }

View file

@ -12,10 +12,6 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.PTR;
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.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
@ -103,10 +99,9 @@ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, ICP
if (var instanceof ICPPField && !var.isStatic()) { if (var instanceof ICPPField && !var.isStatic()) {
IScope scope= CPPVisitor.getContainingScope(name); IScope scope= CPPVisitor.getContainingScope(name);
if (scope != null) { if (scope != null) {
IType thisType= CPPVisitor.getThisType(scope); IType containerType= CPPVisitor.getImpliedObjectType(scope);
if (thisType != null) { if (containerType != null) {
thisType= SemanticUtil.getNestedType(thisType, TDEF|REF|PTR); type= CPPASTFieldReference.addQualifiersForAccess((ICPPField) var, type, containerType);
type= CPPASTFieldReference.addQualifiersForAccess((ICPPField) var, type, thisType);
} }
} }
} }

View file

@ -95,7 +95,12 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
switch (getKind()) { switch (getKind()) {
case lk_this: { case lk_this: {
IScope scope = CPPVisitor.getContainingScope(this); IScope scope = CPPVisitor.getContainingScope(this);
return CPPVisitor.getThisType(scope); IType type= CPPVisitor.getImpliedObjectType(scope);
if (type == null) {
// mstodo problem type
return null;
}
return new CPPPointerType(type);
} }
case lk_true: case lk_true:
case lk_false: case lk_false:

View file

@ -75,7 +75,6 @@ import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.ITypedef;
@ -162,7 +161,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
@ -235,7 +233,7 @@ public class CPPSemantics {
} }
// 1: get some context info off of the name to figure out what kind of lookup we want // 1: get some context info off of the name to figure out what kind of lookup we want
LookupData data = createLookupData(name, true); LookupData data = createLookupData(name);
try { try {
// 2: lookup // 2: lookup
@ -271,7 +269,7 @@ public class CPPSemantics {
} }
protected static IBinding postResolution(IBinding binding, IASTName name) { protected static IBinding postResolution(IBinding binding, IASTName name) {
LookupData data = createLookupData(name, true); LookupData data = createLookupData(name);
return postResolution(binding, data); return postResolution(binding, data);
} }
@ -574,7 +572,7 @@ public class CPPSemantics {
return false; return false;
} }
public static LookupData createLookupData(IASTName name, boolean considerAssociatedScopes) { public static LookupData createLookupData(IASTName name) {
LookupData data = new LookupData(name); LookupData data = new LookupData(name);
IASTNode parent = name.getParent(); IASTNode parent = name.getParent();
@ -601,7 +599,7 @@ public class CPPSemantics {
if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) { if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
parent = parent.getParent(); parent = parent.getParent();
IASTInitializerClause[] args = ((IASTFunctionCallExpression) parent).getArguments(); IASTInitializerClause[] args = ((IASTFunctionCallExpression) parent).getArguments();
data.setFunctionArguments(args); data.setFunctionArguments(false, args);
} }
} else if (parent instanceof ICPPASTFieldReference) { } else if (parent instanceof ICPPASTFieldReference) {
IASTNode grand= parent.getParent(); IASTNode grand= parent.getParent();
@ -612,7 +610,7 @@ public class CPPSemantics {
} }
if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) { if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
IASTInitializerClause[] exp = ((IASTFunctionCallExpression) parent.getParent()).getArguments(); IASTInitializerClause[] exp = ((IASTFunctionCallExpression) parent.getParent()).getArguments();
data.setFunctionArguments(exp); data.setFunctionArguments(false, exp);
} }
} else if (parent instanceof ICPPASTNamedTypeSpecifier && parent.getParent() instanceof IASTTypeId) { } else if (parent instanceof ICPPASTNamedTypeSpecifier && parent.getParent() instanceof IASTTypeId) {
IASTTypeId typeId = (IASTTypeId) parent.getParent(); IASTTypeId typeId = (IASTTypeId) parent.getParent();
@ -620,20 +618,20 @@ public class CPPSemantics {
ICPPASTNewExpression newExp = (ICPPASTNewExpression) typeId.getParent(); ICPPASTNewExpression newExp = (ICPPASTNewExpression) typeId.getParent();
IASTInitializer init = newExp.getInitializer(); IASTInitializer init = newExp.getInitializer();
if (init == null) { if (init == null) {
data.setFunctionArguments(); data.setFunctionArguments(false);
} else if (init instanceof ICPPASTConstructorInitializer) { } else if (init instanceof ICPPASTConstructorInitializer) {
data.setFunctionArguments(((ICPPASTConstructorInitializer) init).getArguments()); data.setFunctionArguments(false, ((ICPPASTConstructorInitializer) init).getArguments());
} else if (init instanceof ICPPASTInitializerList) { } else if (init instanceof ICPPASTInitializerList) {
data.setFunctionArguments(new IASTInitializerClause[] {(ICPPASTInitializerList) init}); data.setFunctionArguments(false, (ICPPASTInitializerList) init);
} }
} }
} else if (parent instanceof ICPPASTConstructorChainInitializer) { } else if (parent instanceof ICPPASTConstructorChainInitializer) {
ICPPASTConstructorChainInitializer ctorinit = (ICPPASTConstructorChainInitializer) parent; ICPPASTConstructorChainInitializer ctorinit = (ICPPASTConstructorChainInitializer) parent;
IASTInitializer init = ctorinit.getInitializer(); IASTInitializer init = ctorinit.getInitializer();
if (init instanceof ICPPASTConstructorInitializer) { if (init instanceof ICPPASTConstructorInitializer) {
data.setFunctionArguments(((ICPPASTConstructorInitializer) init).getArguments()); data.setFunctionArguments(false, ((ICPPASTConstructorInitializer) init).getArguments());
} else if (init instanceof ICPPASTInitializerList) { } else if (init instanceof ICPPASTInitializerList) {
data.setFunctionArguments(new IASTInitializerClause[] {(ICPPASTInitializerList) init}); data.setFunctionArguments(false, (ICPPASTInitializerList) init);
} }
} }
@ -1695,7 +1693,7 @@ public class CPPSemantics {
} }
if (name.getPropertyInParent() != STRING_LOOKUP_PROPERTY) { if (name.getPropertyInParent() != STRING_LOOKUP_PROPERTY) {
LookupData data = createLookupData(name, false); LookupData data = createLookupData(name);
data.foundItems = bindings; data.foundItems = bindings;
try { try {
return resolveAmbiguities(data, name); return resolveAmbiguities(data, name);
@ -2240,7 +2238,7 @@ public class CPPSemantics {
numPars= 0; numPars= 0;
int numArgs = argumentCount; int numArgs = argumentCount;
if (function instanceof ICPPMethod && data.firstArgIsImpliedMethodArg) if (function instanceof ICPPMethod && data.argsContainImpliedObject)
numArgs--; numArgs--;
if (def) { if (def) {
@ -2290,7 +2288,8 @@ public class CPPSemantics {
} }
if (!isFuncDecl || data.forExplicitFunctionSpecialization()) { if (!isFuncDecl || data.forExplicitFunctionSpecialization()) {
CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentLValues(), data.astName); CPPTemplates.instantiateFunctionTemplates(fns, data.getFunctionArgumentTypes(), data.getFunctionArgumentLValues(),
data.astName, data.argsContainImpliedObject);
} }
// Reduce our set of candidate functions to only those who have the right number of parameters // Reduce our set of candidate functions to only those who have the right number of parameters
@ -2388,45 +2387,49 @@ public class CPPSemantics {
throws DOMException { throws DOMException {
IType[] argTypes = data.getFunctionArgumentTypes(); IType[] argTypes = data.getFunctionArgumentTypes();
BitSet isLValue= data.getFunctionArgumentLValues(); BitSet isLValue= data.getFunctionArgumentLValues();
int skipArg= 0;
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType(); final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
if (ftype == null) if (ftype == null)
return null; return null;
IType implicitType= null; IType implicitParameterType= null;
IType impliedObjectType= null;
final IType[] paramTypes= ftype.getParameterTypes(); final IType[] paramTypes= ftype.getParameterTypes();
if (fn instanceof ICPPMethod && !(fn instanceof ICPPConstructor)) { if (fn instanceof ICPPMethod && !(fn instanceof ICPPConstructor)) {
implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile()); implicitParameterType = getImplicitParameterType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
if (data.firstArgIsImpliedMethodArg) { if (data.argsContainImpliedObject) {
argTypes = ArrayUtil.removeFirst(argTypes); impliedObjectType= argTypes[0];
isLValue = isLValue.get(1, isLValue.size()); skipArg= 1;
} }
} }
int k= 0; int k= 0;
Cost cost; Cost cost;
final int sourceLen= argTypes.length; final int sourceLen= argTypes.length - skipArg;
final FunctionCost result; final FunctionCost result;
if (implicitType == null) { if (implicitParameterType == null) {
result= new FunctionCost(fn, sourceLen); result= new FunctionCost(fn, sourceLen);
} else { } else {
result= new FunctionCost(fn, sourceLen + 1); result= new FunctionCost(fn, sourceLen + 1);
boolean sourceIsLValue= true; boolean sourceIsLValue= true;
final IType thisType = data.getImpliedObjectArgument(); if (impliedObjectType == null) {
impliedObjectType= data.getImpliedObjectType();
}
if (fn instanceof ICPPMethod && if (fn instanceof ICPPMethod &&
(((ICPPMethod) fn).isDestructor() || ASTInternal.isStatic(fn, false))) { (((ICPPMethod) fn).isDestructor() || ASTInternal.isStatic(fn, false))) {
// 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost // 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
cost = new Cost(thisType, implicitType, Rank.IDENTITY); cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
} else if (thisType == null) { } else if (impliedObjectType == null) {
return null; return null;
} else if (thisType.isSameType(implicitType)) { } else if (impliedObjectType.isSameType(implicitParameterType)) {
cost = new Cost(thisType, implicitType, Rank.IDENTITY); cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
} else { } else {
cost = Conversions.checkImplicitConversionSequence(implicitType, thisType, sourceIsLValue, UDCMode.noUDC, true); cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType, sourceIsLValue, UDCMode.noUDC, true);
if (!cost.converts()) { if (!cost.converts()) {
if (CPPTemplates.isDependentType(implicitType) || CPPTemplates.isDependentType(thisType)) { if (CPPTemplates.isDependentType(implicitParameterType) || CPPTemplates.isDependentType(impliedObjectType)) {
IType s= getNestedType(thisType, TDEF|REF|CVTYPE); IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE);
IType t= getNestedType(implicitType, TDEF|REF|CVTYPE); IType t= getNestedType(implicitParameterType, TDEF|REF|CVTYPE);
if (SemanticUtil.calculateInheritanceDepth(s, t) >= 0) if (SemanticUtil.calculateInheritanceDepth(s, t) >= 0)
return null; return null;
@ -2442,11 +2445,11 @@ public class CPPSemantics {
final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC; final UDCMode udc = allowUDC ? UDCMode.deferUDC : UDCMode.noUDC;
for (int j = 0; j < sourceLen; j++) { for (int j = 0; j < sourceLen; j++) {
final IType argType= SemanticUtil.getNestedType(argTypes[j], TDEF | REF); final IType argType= SemanticUtil.getNestedType(argTypes[j+skipArg], TDEF | REF);
if (argType == null) if (argType == null)
return null; return null;
final boolean sourceIsLValue = isLValue.get(j); final boolean sourceIsLValue = isLValue.get(j+skipArg);
IType paramType; IType paramType;
if (j < paramTypes.length) { if (j < paramTypes.length) {
@ -2477,7 +2480,7 @@ public class CPPSemantics {
return result; return result;
} }
static IType getImplicitType(ICPPMethod m, final boolean isConst, final boolean isVolatile) static IType getImplicitParameterType(ICPPMethod m, final boolean isConst, final boolean isVolatile)
throws DOMException { throws DOMException {
IType implicitType; IType implicitType;
ICPPClassType owner= m.getClassOwner(); ICPPClassType owner= m.getClassOwner();
@ -2716,7 +2719,7 @@ public class CPPSemantics {
if (exp instanceof IASTIdExpression) { if (exp instanceof IASTIdExpression) {
IASTIdExpression idExp = (IASTIdExpression) exp; IASTIdExpression idExp = (IASTIdExpression) exp;
IASTName name = idExp.getName(); IASTName name = idExp.getName();
LookupData data = createLookupData(name, false); LookupData data = createLookupData(name);
try { try {
lookup(data, null); lookup(data, null);
} catch (DOMException e) { } catch (DOMException e) {
@ -2769,24 +2772,22 @@ public class CPPSemantics {
* class member access operators <code>operator->()</code> calls. * class member access operators <code>operator->()</code> calls.
* @throws DOMException * @throws DOMException
*/ */
public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference) throws DOMException { public static IType getFieldOwnerType(ICPPASTFieldReference fieldReference) throws DOMException {
return getChainedMemberAccessOperatorReturnType(fieldReference, null); return getFieldOwnerType(fieldReference, null);
} }
/* /*
* Also collections the function bindings if requested. * Also collections the function bindings if requested.
*/ */
public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference, Collection<ICPPFunction> functionBindings) throws DOMException { public static IType getFieldOwnerType(ICPPASTFieldReference fieldReference, Collection<ICPPFunction> functionBindings) throws DOMException {
final IASTExpression owner = fieldReference.getFieldOwner(); final IASTExpression owner = fieldReference.getFieldOwner();
if (owner == null) if (owner == null)
return null; return null;
IType type= owner.getExpressionType(); IType type= SemanticUtil.getNestedType(owner.getExpressionType(), TDEF|REF);
if (!fieldReference.isPointerDereference()) if (!fieldReference.isPointerDereference())
return type; return type;
IASTExpression[] args = {owner};
// bug 205964: as long as the type is a class type, recurse. // bug 205964: as long as the type is a class type, recurse.
// Be defensive and allow a max of 10 levels. // Be defensive and allow a max of 10 levels.
boolean foundOperator= false; boolean foundOperator= false;
@ -2810,26 +2811,16 @@ public class CPPSemantics {
* examine for type information. * examine for type information.
*/ */
CPPASTName x= new CPPASTName(); IASTExpression arg = createArgForType(fieldReference, type);
boolean isConst= false, isVolatile= false; ICPPFunction op = findOverloadedOperator(fieldReference, new IASTExpression[] {arg}, uTemp, OverloadableOperator.ARROW, NonMemberMode.none);
if (type instanceof IQualifierType) {
isConst= ((IQualifierType) type).isConst();
isVolatile= ((IQualifierType) type).isVolatile();
}
x.setBinding(createVariable(x, uTemp, isConst, isVolatile));
IASTName arw= new CPPASTName(OverloadableOperator.ARROW.toCharArray());
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
innerFR.setParent(fieldReference); // connect to the AST
ICPPFunction op = findOverloadedOperator(innerFR, args, uTemp, OverloadableOperator.ARROW, NonMemberMode.none);
if (op == null) if (op == null)
break; break;
if (functionBindings != null) if (functionBindings != null)
functionBindings.add(op); functionBindings.add(op);
type= SemanticUtil.mapToAST(op.getType().getReturnType(), owner); type= SemanticUtil.getNestedType(op.getType().getReturnType(), TDEF|REF);
type= SemanticUtil.mapToAST(type, owner);
foundOperator= true; foundOperator= true;
} }
@ -2889,8 +2880,8 @@ public class CPPSemantics {
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) { public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp); OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
IASTExpression[] args = { exp.getOperand() };
IType classType = getNestedClassType(exp); IType classType = getNestedClassType(exp);
IASTExpression[] args = new IASTExpression[] {createArgForType(exp, classType)};
return findOverloadedOperator(exp, args, classType, op, NonMemberMode.all); return findOverloadedOperator(exp, args, classType, op, NonMemberMode.all);
} }
@ -2986,9 +2977,9 @@ public class CPPSemantics {
LookupData data = new LookupData(astName); LookupData data = new LookupData(astName);
if (initializer == null) { if (initializer == null) {
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY); data.setFunctionArguments(false);
} else if (initializer instanceof ICPPASTConstructorInitializer) { } else if (initializer instanceof ICPPASTConstructorInitializer) {
data.setFunctionArguments(((ICPPASTConstructorInitializer) initializer).getArguments()); data.setFunctionArguments(false, ((ICPPASTConstructorInitializer) initializer).getArguments());
} else { } else {
return null; return null;
} }
@ -3016,10 +3007,11 @@ public class CPPSemantics {
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY); astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
astName.setName(CharArrayUtils.concat("~".toCharArray(), cls.getNameCharArray())); //$NON-NLS-1$ astName.setName(CharArrayUtils.concat("~".toCharArray(), cls.getNameCharArray())); //$NON-NLS-1$
IASTExpression arg = createArgForType(expr, cls);
LookupData data = new LookupData(astName); LookupData data = new LookupData(astName);
data.forceQualified = true; data.forceQualified = true;
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY); data.setFunctionArguments(true, arg);
try { try {
lookup(data, scope); lookup(data, scope);
IBinding binding = resolveAmbiguities(data, astName); IBinding binding = resolveAmbiguities(data, astName);
@ -3030,6 +3022,17 @@ public class CPPSemantics {
return null; return null;
} }
/**
* mstodo remove
*/
public static IASTExpression createArgForType(IASTNode node, IType type) {
CPPASTName x= new CPPASTName();
x.setBinding(createVariable(x, type, false, false));
final CPPASTIdExpression idExpression = new CPPASTIdExpression(x);
idExpression.setParent(node);
return idExpression;
}
public static ICPPFunction findOverloadedOperator(IASTUnaryExpression exp) { public static ICPPFunction findOverloadedOperator(IASTUnaryExpression exp) {
if (exp.getOperand() == null) if (exp.getOperand() == null)
return null; return null;
@ -3121,7 +3124,7 @@ public class CPPSemantics {
methodName.setParent(parent); methodName.setParent(parent);
methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY); methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
methodData = new LookupData(methodName); methodData = new LookupData(methodName);
methodData.setFunctionArguments(ArrayUtil.removeFirst(args)); methodData.setFunctionArguments(true, args);
methodData.forceQualified = true; // (13.3.1.2.3) methodData.forceQualified = true; // (13.3.1.2.3)
try { try {
@ -3143,7 +3146,7 @@ public class CPPSemantics {
funcName.setParent(parent); funcName.setParent(parent);
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY); funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
LookupData funcData = new LookupData(funcName); LookupData funcData = new LookupData(funcName);
funcData.setFunctionArguments(args); funcData.setFunctionArguments(true, args);
funcData.ignoreMembers = true; // (13.3.1.2.3) funcData.ignoreMembers = true; // (13.3.1.2.3)
if (mode != NonMemberMode.none || callToObjectOfClassType != null) { if (mode != NonMemberMode.none || callToObjectOfClassType != null) {
try { try {
@ -3250,7 +3253,6 @@ public class CPPSemantics {
if (methodData != null && funcData.hasResults()) { if (methodData != null && funcData.hasResults()) {
// if there was two lookups then merge the results // if there was two lookups then merge the results
mergeResults(funcData, methodData.foundItems, false); mergeResults(funcData, methodData.foundItems, false);
funcData.firstArgIsImpliedMethodArg = true;
binding = resolveAmbiguities(funcData, funcName); binding = resolveAmbiguities(funcData, funcName);
} else if (funcData.hasResults()) { } else if (funcData.hasResults()) {
binding = resolveAmbiguities(funcData, funcName); binding = resolveAmbiguities(funcData, funcName);
@ -3312,7 +3314,7 @@ public class CPPSemantics {
public static IBinding[] findBindingsForContentAssist(IASTName name, boolean prefixLookup, public static IBinding[] findBindingsForContentAssist(IASTName name, boolean prefixLookup,
String[] additionalNamespaces) { String[] additionalNamespaces) {
LookupData data = createLookupData(name, true); LookupData data = createLookupData(name);
data.contentAssist = true; data.contentAssist = true;
data.prefixLookup = prefixLookup; data.prefixLookup = prefixLookup;
data.foundItems = new CharArrayObjectMap(2); data.foundItems = new CharArrayObjectMap(2);

View file

@ -1538,7 +1538,8 @@ public class CPPTemplates {
return result; return result;
} }
static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] fnArgs, BitSet argIsLValue, IASTName name) { static protected void instantiateFunctionTemplates(IFunction[] functions, IType[] allFnArgs,
BitSet allArgIsLValue, IASTName name, boolean argsContainImpliedObject) {
boolean requireTemplate= false; boolean requireTemplate= false;
if (name != null) { if (name != null) {
if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) { if (name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
@ -1549,6 +1550,8 @@ public class CPPTemplates {
} }
} }
IType[] reducedFnArgs= null;
BitSet reducedIsLValue= null;
ICPPTemplateArgument[] tmplArgs= null; ICPPTemplateArgument[] tmplArgs= null;
for (int i = 0; i < functions.length; i++) { for (int i = 0; i < functions.length; i++) {
IFunction func = functions[i]; IFunction func = functions[i];
@ -1556,6 +1559,26 @@ public class CPPTemplates {
ICPPFunctionTemplate template= (ICPPFunctionTemplate) func; ICPPFunctionTemplate template= (ICPPFunctionTemplate) func;
functions[i]= null; functions[i]= null;
final IType[] fnArgs;
final BitSet argIsLValue;
if (argsContainImpliedObject && template instanceof ICPPMethod) {
if (reducedIsLValue == null) {
if (allFnArgs != null && allFnArgs.length > 0) {
reducedFnArgs= ArrayUtil.removeFirst(allFnArgs);
}
if (allArgIsLValue == null || allArgIsLValue.length() == 0) {
reducedIsLValue= ALL_RVALUES;
} else {
reducedIsLValue= allArgIsLValue.get(1, allArgIsLValue.length());
}
}
fnArgs= reducedFnArgs;
argIsLValue= reducedIsLValue;
} else {
fnArgs= allFnArgs;
argIsLValue= allArgIsLValue;
}
// extract template arguments and parameter types. // extract template arguments and parameter types.
if (tmplArgs == null || fnArgs == null) { if (tmplArgs == null || fnArgs == null) {
tmplArgs = ICPPTemplateArgument.EMPTY_ARGUMENTS; tmplArgs = ICPPTemplateArgument.EMPTY_ARGUMENTS;

View file

@ -1090,7 +1090,7 @@ public class CPPVisitor extends ASTQueries {
data.usesEnclosingScope= false; data.usesEnclosingScope= false;
} }
final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference) parent; final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference) parent;
IType type = CPPSemantics.getChainedMemberAccessOperatorReturnType(fieldReference); IType type = CPPSemantics.getFieldOwnerType(fieldReference);
if (fieldReference.isPointerDereference()) { if (fieldReference.isPointerDereference()) {
type= getUltimateType(type, false); type= getUltimateType(type, false);
} else { } else {
@ -1973,7 +1973,7 @@ public class CPPVisitor extends ASTQueries {
return type; return type;
} }
public static IType getThisType(IScope scope) { public static IType getImpliedObjectType(IScope scope) {
try { try {
IASTNode node = null; IASTNode node = null;
while (scope != null) { while (scope != null) {
@ -2008,9 +2008,7 @@ public class CPPVisitor extends ASTQueries {
if (type instanceof ICPPClassTemplate) { if (type instanceof ICPPClassTemplate) {
type= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) type); type= CPPTemplates.instantiateWithinClassTemplate((ICPPClassTemplate) type);
} }
type = SemanticUtil.addQualifiers(type, dtor.isConst(), dtor.isVolatile()); return SemanticUtil.addQualifiers(type, dtor.isConst(), dtor.isVolatile());
type = new CPPPointerType(type);
return type;
} }
} }
} }

View file

@ -245,7 +245,7 @@ public class Conversions {
IType convertedType= ft.getReturnType(); IType convertedType= ft.getReturnType();
final boolean isLValue = CPPVisitor.isLValueReference(convertedType); final boolean isLValue = CPPVisitor.isLValueReference(convertedType);
if (isLValue == forLValue) { // require an lvalue or rvalue if (isLValue == forLValue) { // require an lvalue or rvalue
IType implicitObjectType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile()); IType implicitObjectType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
Cost udcCost= isReferenceCompatible(getNestedType(implicitObjectType, TDEF | REF), cv2T2, true); // expression type to implicit object type Cost udcCost= isReferenceCompatible(getNestedType(implicitObjectType, TDEF | REF), cv2T2, true); // expression type to implicit object type
if (udcCost != null) { if (udcCost != null) {
FunctionCost udcFuncCost= new FunctionCost(op, udcCost); FunctionCost udcFuncCost= new FunctionCost(op, udcCost);
@ -585,7 +585,7 @@ public class Conversions {
name.setParent(initializerList); name.setParent(initializerList);
name.setPropertyInParent(CPPSemantics.STRING_LOOKUP_PROPERTY); name.setPropertyInParent(CPPSemantics.STRING_LOOKUP_PROPERTY);
final IASTInitializerClause[] expandedArgs = initializerList.getClauses(); final IASTInitializerClause[] expandedArgs = initializerList.getClauses();
data.setFunctionArguments(expandedArgs); data.setFunctionArguments(false, expandedArgs);
data.fNoNarrowing= true; data.fNoNarrowing= true;
// 13.3.3.1.4 // 13.3.3.1.4
@ -628,7 +628,7 @@ public class Conversions {
FunctionCost cost1= null; FunctionCost cost1= null;
Cost cost2= null; Cost cost2= null;
ICPPConstructor[] ctors= t.getConstructors(); ICPPConstructor[] ctors= t.getConstructors();
CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null); CPPTemplates.instantiateFunctionTemplates(ctors, new IType[]{source}, sourceIsLValue ? LVBITSET : RVBITSET, null, false);
for (ICPPConstructor ctor : ctors) { for (ICPPConstructor ctor : ctors) {
if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) { if (ctor != null && !(ctor instanceof IProblemBinding) && !ctor.isExplicit()) {
@ -674,7 +674,7 @@ public class Conversions {
final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t); final int dist = SemanticUtil.calculateInheritanceDepth(uqReturnType, t);
if (dist >= 0) { if (dist >= 0) {
final ICPPFunctionType ft = op.getType(); final ICPPFunctionType ft = op.getType();
IType implicitType= CPPSemantics.getImplicitType(op, ft.isConst(), ft.isVolatile()); IType implicitType= CPPSemantics.getImplicitParameterType(op, ft.isConst(), ft.isVolatile());
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true); final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
if (udcCost != null) { if (udcCost != null) {
FunctionCost c1= new FunctionCost(op, udcCost); FunctionCost c1= new FunctionCost(op, udcCost);
@ -725,7 +725,7 @@ public class Conversions {
if (isExplicitConversion && c2.getRank() != Rank.IDENTITY) if (isExplicitConversion && c2.getRank() != Rank.IDENTITY)
continue; continue;
ICPPFunctionType ftype = op.getType(); ICPPFunctionType ftype = op.getType();
IType implicitType= CPPSemantics.getImplicitType(op, ftype.isConst(), ftype.isVolatile()); IType implicitType= CPPSemantics.getImplicitParameterType(op, ftype.isConst(), ftype.isVolatile());
final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true); final Cost udcCost = isReferenceCompatible(getNestedType(implicitType, TDEF | REF), source, true);
if (udcCost != null) { if (udcCost != null) {
FunctionCost c1= new FunctionCost(op, udcCost); FunctionCost c1= new FunctionCost(op, udcCost);

View file

@ -21,8 +21,6 @@ import java.util.Map;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
@ -46,7 +44,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
@ -57,7 +54,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
@ -98,8 +94,8 @@ public class LookupData {
public boolean checkPointOfDecl= true; public boolean checkPointOfDecl= true;
/** For field references or qualified names, enclosing template declarations are ignored. */ /** For field references or qualified names, enclosing template declarations are ignored. */
public boolean usesEnclosingScope= true; public boolean usesEnclosingScope= true;
/** When computing the cost of a method call, treat the first argument as the implied method argument. */ /** When computing the cost of a method call, treat the first argument as the implied object. */
public boolean firstArgIsImpliedMethodArg = false; public boolean argsContainImpliedObject = false;
public boolean ignoreMembers = false; public boolean ignoreMembers = false;
/** In list-initialization **/ /** In list-initialization **/
public boolean fNoNarrowing= false; public boolean fNoNarrowing= false;
@ -347,57 +343,27 @@ public class LookupData {
} }
/** /**
* an IType[] of function arguments, including the implied object argument * Returns the implied object type, or <code>null</code>.
*/ */
public IType getImpliedObjectArgument() { public IType getImpliedObjectType() {
if (astName == null) if (astName == null)
return null; return null;
IASTName tempName= astName; IASTName name= astName;
IASTNode tempNameParent= tempName.getParent(); IASTNode nameParent= name.getParent();
while (tempNameParent instanceof IASTName) { while (nameParent instanceof IASTName) {
tempName= (IASTName) tempNameParent; name= (IASTName) nameParent;
tempNameParent= tempName.getParent(); nameParent= name.getParent();
} }
try { try {
final ASTNodeProperty prop = tempName.getPropertyInParent(); final ASTNodeProperty prop = name.getPropertyInParent();
if (prop == CPPSemantics.STRING_LOOKUP_PROPERTY) { if (prop == CPPSemantics.STRING_LOOKUP_PROPERTY) {
if (tempNameParent instanceof ICPPASTUnaryExpression) {
ICPPASTUnaryExpression unaryExp = (ICPPASTUnaryExpression) tempNameParent;
IASTExpression oprd= unaryExp.getOperand();
return oprd.getExpressionType();
}
if (tempNameParent instanceof ICPPASTFieldReference) {
ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) tempNameParent;
IType implied = fieldRef.getFieldOwner().getExpressionType();
if (fieldRef.isPointerDereference() && implied instanceof IPointerType) {
return ((IPointerType) implied).getType();
}
return implied;
}
if (tempNameParent instanceof IASTArraySubscriptExpression) {
IASTExpression exp = ((IASTArraySubscriptExpression) tempNameParent).getArrayExpression();
return exp.getExpressionType();
}
if (tempNameParent instanceof IASTFunctionCallExpression) {
return ((IASTFunctionCallExpression) tempNameParent).getFunctionNameExpression().getExpressionType();
}
if (tempNameParent instanceof IASTBinaryExpression) {
return ((IASTBinaryExpression) tempNameParent).getOperand1().getExpressionType();
}
if (tempNameParent instanceof ICPPASTDeleteExpression) {
IType implied = ((ICPPASTDeleteExpression) tempNameParent).getOperand().getExpressionType();
if(implied instanceof IPointerType) {
return ((IPointerType) implied).getType();
}
return implied;
}
return null; return null;
} }
if (prop == IASTFieldReference.FIELD_NAME) { if (prop == IASTFieldReference.FIELD_NAME) {
ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) tempNameParent; ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) nameParent;
IType implied= CPPSemantics.getChainedMemberAccessOperatorReturnType(fieldRef); IType implied= CPPSemantics.getFieldOwnerType(fieldRef);
if (fieldRef.isPointerDereference()) { if (fieldRef.isPointerDereference()) {
implied= SemanticUtil.getUltimateTypeUptoPointers(implied); implied= SemanticUtil.getUltimateTypeUptoPointers(implied);
if (implied instanceof IPointerType) if (implied instanceof IPointerType)
@ -406,16 +372,12 @@ public class LookupData {
return implied; return implied;
} }
if (prop == IASTIdExpression.ID_NAME) { if (prop == IASTIdExpression.ID_NAME) {
IScope scope = CPPVisitor.getContainingScope(tempName); IScope scope = CPPVisitor.getContainingScope(name);
if (scope instanceof ICPPClassScope) { if (scope instanceof ICPPClassScope) {
return ((ICPPClassScope) scope).getClassType(); return ((ICPPClassScope) scope).getClassType();
} }
IType implied = CPPVisitor.getThisType(scope); return CPPVisitor.getImpliedObjectType(scope);
if (implied instanceof IPointerType) {
return ((IPointerType) implied).getType();
}
return implied;
} }
if (prop == IASTDeclarator.DECLARATOR_NAME) { if (prop == IASTDeclarator.DECLARATOR_NAME) {
if (forExplicitFunctionInstantiation()) { if (forExplicitFunctionInstantiation()) {
@ -513,7 +475,8 @@ public class LookupData {
return false; return false;
} }
public void setFunctionArguments(IASTInitializerClause... exprs) { public void setFunctionArguments(boolean containsImpliedObject, IASTInitializerClause... exprs) {
argsContainImpliedObject= containsImpliedObject;
functionArgs= exprs; functionArgs= exprs;
if (exprs.length != 0) { if (exprs.length != 0) {
IASTNode node= exprs[0]; IASTNode node= exprs[0];

View file

@ -703,7 +703,7 @@ class OpenDeclarationsJob extends Job implements ASTRunnable {
if (binding != null) { if (binding != null) {
sourceQualifiedName= CPPVisitor.getQualifiedName(binding); sourceQualifiedName= CPPVisitor.getQualifiedName(binding);
if (binding instanceof ICPPUnknownBinding) { if (binding instanceof ICPPUnknownBinding) {
LookupData data= CPPSemantics.createLookupData(sourceName, false); LookupData data= CPPSemantics.createLookupData(sourceName);
if (data.isFunctionCall()) { if (data.isFunctionCall()) {
funcArgCount= data.getFunctionArgumentCount(); funcArgCount= data.getFunctionArgumentCount();
} }