1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 06:32:10 +02:00

Call to object of class type, bug 267389.

This commit is contained in:
Markus Schorn 2009-07-10 15:23:32 +00:00
parent 45cd6c2948
commit 57f33ecc8a
3 changed files with 80 additions and 19 deletions

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Ed Swartz (Nokia)
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
@ -121,9 +121,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.parser.ParserException;
/**
* @author aniefer
*/
public class AST2CPPTests extends AST2BaseTest {
public AST2CPPTests() {
@ -7182,5 +7179,20 @@ public class AST2CPPTests extends AST2BaseTest {
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// int foo(int x);
// int bar(int x);
//
// typedef int (*fp)(int);
// struct A {
// operator fp() { return foo; }
// } a;
//
// int i = bar(a(1)); // problem on bar
public void testCallToObjectOfClassType_267389() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
}

View file

@ -222,7 +222,9 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
} else if (t instanceof ICPPClassType) {
ICPPFunction op = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
if (op != null) {
if(overload != null)
// overload can be a surrogate function call, which consists of a conversion and a call to
// a dynamically computed function pointer.
if(overload != null && !(op instanceof CPPImplicitFunction))
overload[0] = op;
return op.getType().getReturnType();
}

View file

@ -147,6 +147,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
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.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.GCCBuiltinSymbolProvider.CPPBuiltinParameter;
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.CPPASTLiteralExpression;
@ -157,6 +158,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypeIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTUnaryExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
@ -183,6 +186,7 @@ import org.eclipse.cdt.internal.core.index.IIndexScope;
* Name resolution
*/
public class CPPSemantics {
/**
* The maximum depth to search ancestors before assuming infinite looping.
*/
@ -192,6 +196,7 @@ public class CPPSemantics {
new ASTNodeProperty("CPPSemantics.STRING_LOOKUP_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$
public static final String EMPTY_NAME = ""; //$NON-NLS-1$
public static final char[] OPERATOR_ = new char[] {'o','p','e','r','a','t','o','r',' '};
private static final char[] CALL_FUNCTION = "call-function".toCharArray(); //$NON-NLS-1$
public static final IType VOID_TYPE = new CPPBasicType(IBasicType.t_void, 0);
// Set to true for debugging.
@ -2591,7 +2596,7 @@ public class CPPSemantics {
return type;
char[] operatorName = OverloadableOperator.ARROW.toCharArray();
IASTExpression[] args = {null};
IASTExpression[] args = {owner};
// bug 205964: as long as the type is a class type, recurse.
// Be defensive and allow a max of 10 levels.
@ -2653,7 +2658,7 @@ public class CPPSemantics {
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
char[] name = OverloadableOperator.BRACKET.toCharArray();
IASTExpression[] args = { null, exp.getSubscriptExpression() };
IASTExpression[] args = {exp.getArrayExpression(), exp.getSubscriptExpression()};
IType type1 = exp.getArrayExpression().getExpressionType();
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
return findOverloadedOperator(exp, args, ultimateType1, name, false);
@ -2667,15 +2672,15 @@ public class CPPSemantics {
if (param instanceof IASTExpressionList) {
IASTExpression[] actualArgs = ((IASTExpressionList)param).getExpressions();
ArrayList<IASTExpression> argsToPass = new ArrayList<IASTExpression>(actualArgs.length + 1);
argsToPass.add(null);
argsToPass.add(exp.getFunctionNameExpression());
for (IASTExpression e : actualArgs) {
argsToPass.add(e);
}
args = argsToPass.toArray(new IASTExpression[argsToPass.size()]);
} else if (param != null) {
args = new IASTExpression[] { null, param };
args = new IASTExpression[] { exp.getFunctionNameExpression(), param };
} else {
args = new IASTExpression[] { null };
args = new IASTExpression[] { exp.getFunctionNameExpression() };
}
return findOverloadedOperator(exp, args, type, name, false);
@ -2828,13 +2833,17 @@ public class CPPSemantics {
}
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTExpression[] args, IType methodLookupType, char[] operatorName, boolean lookupNonMember) {
ICPPClassType callToObjectOfClassType= null;
// Find a method
LookupData methodData = null;
CPPASTName methodName = null;
if (methodLookupType instanceof IProblemBinding)
return null;
if (methodLookupType instanceof ICPPClassType) {
methodName = new CPPASTName(operatorName);
ICPPClassType classType = (ICPPClassType)methodLookupType;
methodName = new CPPASTName(operatorName);
methodName.setParent(parent);
methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
methodData = new LookupData(methodName);
@ -2842,10 +2851,14 @@ public class CPPSemantics {
methodData.forceQualified = true; // (13.3.1.2.3)
try {
IScope scope = ((ICPPClassType)methodLookupType).getCompositeScope();
IScope scope = classType.getCompositeScope();
if (scope == null)
return null;
lookup(methodData, scope);
if (parent instanceof IASTFunctionCallExpression) {
callToObjectOfClassType= classType;
}
} catch (DOMException e) {
return null;
}
@ -2854,7 +2867,7 @@ public class CPPSemantics {
// Find a function
LookupData funcData = null;
CPPASTName funcName = null;
if (lookupNonMember) {
if (lookupNonMember || callToObjectOfClassType != null) {
funcName = new CPPASTName(operatorName);
funcName.setParent(parent);
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
@ -2863,16 +2876,35 @@ public class CPPSemantics {
funcData.ignoreMembers = true; // (13.3.1.2.3)
try {
IScope scope = CPPVisitor.getContainingScope(parent);
if (scope == null)
return null;
lookup(funcData, scope);
if (lookupNonMember) {
IScope scope = CPPVisitor.getContainingScope(parent);
if (scope == null)
return null;
lookup(funcData, scope);
}
if (callToObjectOfClassType != null) {
// 13.3.1.1.2 call to object of class type
ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
for (ICPPMethod op : ops) {
IFunctionType ft= op.getType();
if (ft != null) {
IType rt= SemanticUtil.getNestedType(ft.getReturnType(), SemanticUtil.TDEF);
if (rt instanceof IPointerType) {
IType ptt= SemanticUtil.getNestedType(((IPointerType)rt).getType(), SemanticUtil.TDEF);
if (ptt instanceof IFunctionType) {
IFunctionType ft2= (IFunctionType) ptt;
IBinding sf= createSurrogateCallFunction(parent.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
mergeResults(funcData, sf, false);
}
}
}
}
}
} catch (DOMException e) {
return null;
}
}
// Resolve ambiguities
try {
IBinding binding = null;
if (methodData != null && funcData != null) {
@ -2894,7 +2926,22 @@ public class CPPSemantics {
return null;
}
private static boolean isUserDefined(IType type) {
private static IBinding createSurrogateCallFunction(IScope scope, IType returnType, IType rt, IType[] parameterTypes) {
IType[] parms = new IType[parameterTypes.length+1];
IParameter[] theParms = new IParameter[parms.length];
parms[0] = rt;
theParms[0]= new CPPBuiltinParameter(rt);
for (int i = 1; i < parms.length; i++) {
IType t = parameterTypes[i-1];
parms[i]= t;
theParms[i]= new CPPBuiltinParameter(t);
}
ICPPFunctionType functionType = new CPPFunctionType(returnType, parms);
return new CPPImplicitFunction(CALL_FUNCTION, scope, functionType, theParms, false);
}
private static boolean isUserDefined(IType type) {
return type instanceof ICPPClassType || type instanceof IEnumeration;
}