diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 09653450bbb..5feb51138a5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -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); + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index 8748e404250..4ca80d05e7a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 0c45f6087aa..630862c6fb3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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 argsToPass = new ArrayList(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; }