mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
Call to object of class type, bug 267389.
This commit is contained in:
parent
45cd6c2948
commit
57f33ecc8a
3 changed files with 80 additions and 19 deletions
|
@ -6,7 +6,7 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM Corporation - initial API and implementation
|
* Andrew Niefer (IBM Corporation) - initial API and implementation
|
||||||
* Ed Swartz (Nokia)
|
* Ed Swartz (Nokia)
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
* Andrew Ferguson (Symbian)
|
* 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.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
import org.eclipse.cdt.internal.core.parser.ParserException;
|
import org.eclipse.cdt.internal.core.parser.ParserException;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author aniefer
|
|
||||||
*/
|
|
||||||
public class AST2CPPTests extends AST2BaseTest {
|
public class AST2CPPTests extends AST2BaseTest {
|
||||||
|
|
||||||
public AST2CPPTests() {
|
public AST2CPPTests() {
|
||||||
|
@ -7182,5 +7179,20 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
|
|
||||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,9 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
|
||||||
} else if (t instanceof ICPPClassType) {
|
} else if (t instanceof ICPPClassType) {
|
||||||
ICPPFunction op = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
|
ICPPFunction op = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
|
||||||
if (op != null) {
|
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;
|
overload[0] = op;
|
||||||
return op.getType().getReturnType();
|
return op.getType().getReturnType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.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.GCCBuiltinSymbolProvider.CPPBuiltinParameter;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
|
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;
|
||||||
|
@ -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.CPPASTUnaryExpression;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
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.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.CPPNamespace;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
|
||||||
|
@ -183,6 +186,7 @@ import org.eclipse.cdt.internal.core.index.IIndexScope;
|
||||||
* Name resolution
|
* Name resolution
|
||||||
*/
|
*/
|
||||||
public class CPPSemantics {
|
public class CPPSemantics {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum depth to search ancestors before assuming infinite looping.
|
* 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$
|
new ASTNodeProperty("CPPSemantics.STRING_LOOKUP_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$
|
||||||
public static final String EMPTY_NAME = ""; //$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',' '};
|
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);
|
public static final IType VOID_TYPE = new CPPBasicType(IBasicType.t_void, 0);
|
||||||
|
|
||||||
// Set to true for debugging.
|
// Set to true for debugging.
|
||||||
|
@ -2591,7 +2596,7 @@ public class CPPSemantics {
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
char[] operatorName = OverloadableOperator.ARROW.toCharArray();
|
char[] operatorName = OverloadableOperator.ARROW.toCharArray();
|
||||||
IASTExpression[] args = {null};
|
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.
|
||||||
|
@ -2653,7 +2658,7 @@ public class CPPSemantics {
|
||||||
|
|
||||||
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
|
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
|
||||||
char[] name = OverloadableOperator.BRACKET.toCharArray();
|
char[] name = OverloadableOperator.BRACKET.toCharArray();
|
||||||
IASTExpression[] args = { null, exp.getSubscriptExpression() };
|
IASTExpression[] args = {exp.getArrayExpression(), exp.getSubscriptExpression()};
|
||||||
IType type1 = exp.getArrayExpression().getExpressionType();
|
IType type1 = exp.getArrayExpression().getExpressionType();
|
||||||
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
|
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
|
||||||
return findOverloadedOperator(exp, args, ultimateType1, name, false);
|
return findOverloadedOperator(exp, args, ultimateType1, name, false);
|
||||||
|
@ -2667,15 +2672,15 @@ public class CPPSemantics {
|
||||||
if (param instanceof IASTExpressionList) {
|
if (param instanceof IASTExpressionList) {
|
||||||
IASTExpression[] actualArgs = ((IASTExpressionList)param).getExpressions();
|
IASTExpression[] actualArgs = ((IASTExpressionList)param).getExpressions();
|
||||||
ArrayList<IASTExpression> argsToPass = new ArrayList<IASTExpression>(actualArgs.length + 1);
|
ArrayList<IASTExpression> argsToPass = new ArrayList<IASTExpression>(actualArgs.length + 1);
|
||||||
argsToPass.add(null);
|
argsToPass.add(exp.getFunctionNameExpression());
|
||||||
for (IASTExpression e : actualArgs) {
|
for (IASTExpression e : actualArgs) {
|
||||||
argsToPass.add(e);
|
argsToPass.add(e);
|
||||||
}
|
}
|
||||||
args = argsToPass.toArray(new IASTExpression[argsToPass.size()]);
|
args = argsToPass.toArray(new IASTExpression[argsToPass.size()]);
|
||||||
} else if (param != null) {
|
} else if (param != null) {
|
||||||
args = new IASTExpression[] { null, param };
|
args = new IASTExpression[] { exp.getFunctionNameExpression(), param };
|
||||||
} else {
|
} else {
|
||||||
args = new IASTExpression[] { null };
|
args = new IASTExpression[] { exp.getFunctionNameExpression() };
|
||||||
}
|
}
|
||||||
|
|
||||||
return findOverloadedOperator(exp, args, type, name, false);
|
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) {
|
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTExpression[] args, IType methodLookupType, char[] operatorName, boolean lookupNonMember) {
|
||||||
|
ICPPClassType callToObjectOfClassType= null;
|
||||||
|
|
||||||
// Find a method
|
// Find a method
|
||||||
LookupData methodData = null;
|
LookupData methodData = null;
|
||||||
CPPASTName methodName = null;
|
CPPASTName methodName = null;
|
||||||
if (methodLookupType instanceof IProblemBinding)
|
if (methodLookupType instanceof IProblemBinding)
|
||||||
return null;
|
return null;
|
||||||
if (methodLookupType instanceof ICPPClassType) {
|
if (methodLookupType instanceof ICPPClassType) {
|
||||||
methodName = new CPPASTName(operatorName);
|
ICPPClassType classType = (ICPPClassType)methodLookupType;
|
||||||
|
|
||||||
|
methodName = new CPPASTName(operatorName);
|
||||||
methodName.setParent(parent);
|
methodName.setParent(parent);
|
||||||
methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||||
methodData = new LookupData(methodName);
|
methodData = new LookupData(methodName);
|
||||||
|
@ -2842,10 +2851,14 @@ public class CPPSemantics {
|
||||||
methodData.forceQualified = true; // (13.3.1.2.3)
|
methodData.forceQualified = true; // (13.3.1.2.3)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IScope scope = ((ICPPClassType)methodLookupType).getCompositeScope();
|
IScope scope = classType.getCompositeScope();
|
||||||
if (scope == null)
|
if (scope == null)
|
||||||
return null;
|
return null;
|
||||||
lookup(methodData, scope);
|
lookup(methodData, scope);
|
||||||
|
|
||||||
|
if (parent instanceof IASTFunctionCallExpression) {
|
||||||
|
callToObjectOfClassType= classType;
|
||||||
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -2854,7 +2867,7 @@ public class CPPSemantics {
|
||||||
// Find a function
|
// Find a function
|
||||||
LookupData funcData = null;
|
LookupData funcData = null;
|
||||||
CPPASTName funcName = null;
|
CPPASTName funcName = null;
|
||||||
if (lookupNonMember) {
|
if (lookupNonMember || callToObjectOfClassType != null) {
|
||||||
funcName = new CPPASTName(operatorName);
|
funcName = new CPPASTName(operatorName);
|
||||||
funcName.setParent(parent);
|
funcName.setParent(parent);
|
||||||
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
|
||||||
|
@ -2863,16 +2876,35 @@ public class CPPSemantics {
|
||||||
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
funcData.ignoreMembers = true; // (13.3.1.2.3)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IScope scope = CPPVisitor.getContainingScope(parent);
|
if (lookupNonMember) {
|
||||||
if (scope == null)
|
IScope scope = CPPVisitor.getContainingScope(parent);
|
||||||
return null;
|
if (scope == null)
|
||||||
lookup(funcData, scope);
|
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) {
|
} catch (DOMException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve ambiguities
|
|
||||||
try {
|
try {
|
||||||
IBinding binding = null;
|
IBinding binding = null;
|
||||||
if (methodData != null && funcData != null) {
|
if (methodData != null && funcData != null) {
|
||||||
|
@ -2894,7 +2926,22 @@ public class CPPSemantics {
|
||||||
return null;
|
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;
|
return type instanceof ICPPClassType || type instanceof IEnumeration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue