1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-10 12:03:16 +02:00

Fixes bugs 269365, 268534, and 266211. Fixed overload resolution for operator functions and also fixed expression lists.

This commit is contained in:
Mike Kucera 2009-03-20 15:24:45 +00:00
parent 2d935d7b6e
commit 6045ee4478
14 changed files with 522 additions and 430 deletions

View file

@ -67,13 +67,30 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// } // }
public void testBinaryExpressions() throws Exception { public void testBinaryExpressions() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertImplicitName("+= 5", 2, ICPPMethod.class); IASTTranslationUnit tu = ba.getTranslationUnit();
ba.assertImplicitName("+ p", 1, ICPPMethod.class); CPPNameCollector col = new CPPNameCollector();
ba.assertImplicitName("- p", 1, ICPPMethod.class); tu.accept(col);
ba.assertImplicitName("* p", 1, ICPPFunction.class); IASTImplicitName n;
ba.assertImplicitName("/ p", 1, ICPPFunction.class);
n = ba.assertImplicitName("+= 5", 2, ICPPMethod.class);
assertSame(n.resolveBinding(), col.getName(14).resolveBinding());
n = ba.assertImplicitName("+ p", 1, ICPPMethod.class);
assertSame(n.resolveBinding(), col.getName(4).resolveBinding());
n = ba.assertImplicitName("- p", 1, ICPPMethod.class);
assertSame(n.resolveBinding(), col.getName(8).resolveBinding());
n = ba.assertImplicitName("* p", 1, ICPPFunction.class);
assertSame(n.resolveBinding(), col.getName(17).resolveBinding());
n = ba.assertImplicitName("/ p", 1, ICPPFunction.class);
assertSame(n.resolveBinding(), col.getName(23).resolveBinding());
n = ba.assertImplicitName("-p;", 1, ICPPMethod.class);
assertSame(n.resolveBinding(), col.getName(12).resolveBinding());
ba.assertNoImplicitName("<< 6", 2); ba.assertNoImplicitName("<< 6", 2);
ba.assertImplicitName("-p;", 1, ICPPMethod.class);
ba.assertNoImplicitName("+p;", 1); ba.assertNoImplicitName("+p;", 1);
} }
@ -114,8 +131,14 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// } // }
public void testPointerToMember() throws Exception { public void testPointerToMember() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
ba.assertNoImplicitName("&Y::x;", 1); ba.assertNoImplicitName("&Y::x;", 1);
ba.assertImplicitName("&y;", 1, ICPPFunction.class);
IASTImplicitName n = ba.assertImplicitName("&y;", 1, ICPPFunction.class);
assertSame(n.resolveBinding(), col.getName(9).resolveBinding());
} }
@ -197,7 +220,7 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// D d; // D d;
// test(a , b , c , d); // func // test(a , b , c , d); // func
// } // }
public void _testCommaOperator() throws Exception { public void testCommaOperator1() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
// expression lists are used in function calls but they should not resolve to the comma operator // expression lists are used in function calls but they should not resolve to the comma operator
ba.assertNoImplicitName(", b , c , d); // func", 1); ba.assertNoImplicitName(", b , c , d); // func", 1);
@ -213,22 +236,65 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
tu.accept(col); tu.accept(col);
assertSame(opAB.resolveBinding(), col.getName(5).resolveBinding()); assertSame(opAB.resolveBinding(), col.getName(5).resolveBinding());
assertSame(opCC.resolveBinding(), col.getName(9).resolveBinding()); assertSame(opCC.resolveBinding(), col.getName(11).resolveBinding());
}
// struct B {};
// struct C {};
// struct E {
// int ee;
// };
// struct A {
// C operator,(B);
// };
// struct D {
// E operator,(D);
// };
// D operator,(C,C);
//
//
// int test(A a, B b, C c, D d) {
// (a , b , c , d).ee; // expr
// }
public void testCommaOperator2() throws Exception {
BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true);
IASTImplicitName opAB = ba.assertImplicitName(", b , c , d", 1, ICPPMethod.class);
IASTImplicitName opCC = ba.assertImplicitName(", c , d", 1, ICPPFunction.class);
IASTImplicitName opDD = ba.assertImplicitName(", d", 1, ICPPMethod.class);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
// 6, 11, 15
assertSame(opAB.resolveBinding(), col.getName(6).resolveBinding());
assertSame(opCC.resolveBinding(), col.getName(15).resolveBinding());
assertSame(opDD.resolveBinding(), col.getName(11).resolveBinding());
ba.assertNonProblem("ee;", 2);
} }
// struct X { // struct X {
// int operator()(bool); // int operator()(bool);
// int operator()(); // int operator()();
// int operator()(int,int);
// }; // };
// //
// int test(X x) { // int test(X x) {
// bool b = true; // bool b = true;
// x(b); // 1 // x(b); // 1
// x(); // 2 // x(); // 2
// x(1,2); // 3
// } // }
public void testFunctionCallOperator() throws Exception { public void testFunctionCallOperator() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
IASTImplicitName n1 = ba.assertImplicitName("(b); // 1", 1, ICPPMethod.class); IASTImplicitName n1 = ba.assertImplicitName("(b); // 1", 1, ICPPMethod.class);
IASTImplicitName n2 = ba.assertImplicitName("); // 1", 1, ICPPMethod.class); IASTImplicitName n2 = ba.assertImplicitName("); // 1", 1, ICPPMethod.class);
@ -237,12 +303,21 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
assertTrue(n2.isAlternate()); assertTrue(n2.isAlternate());
// there should be no overlap // there should be no overlap
ba.assertNoImplicitName("b); // 1", 1); ba.assertNoImplicitName("b); // 1", 1);
assertSame(col.getName(1).resolveBinding(), n1.resolveBinding());
n1 = ba.assertImplicitName("(); // 2", 1, ICPPMethod.class); n1 = ba.assertImplicitName("(); // 2", 1, ICPPMethod.class);
n2 = ba.assertImplicitName("); // 2", 1, ICPPMethod.class); n2 = ba.assertImplicitName("); // 2", 1, ICPPMethod.class);
assertSame(n1.resolveBinding(), n2.resolveBinding()); assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate()); assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate()); assertTrue(n2.isAlternate());
assertSame(col.getName(3).resolveBinding(), n1.resolveBinding());
n1 = ba.assertImplicitName("(1,2); // 3", 1, ICPPMethod.class);
n2 = ba.assertImplicitName("); // 3", 1, ICPPMethod.class);
assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate());
assertSame(col.getName(4).resolveBinding(), n1.resolveBinding());
} }
@ -278,12 +353,17 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// } // }
public void testArraySubscript() throws Exception { public void testArraySubscript() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
IASTImplicitName n1 = ba.assertImplicitName("[0]); //1", 1, ICPPMethod.class); IASTImplicitName n1 = ba.assertImplicitName("[0]); //1", 1, ICPPMethod.class);
ba.assertNoImplicitName("0]); //1", 1); ba.assertNoImplicitName("0]); //1", 1);
IASTImplicitName n2 = ba.assertImplicitName("]); //1", 1, ICPPMethod.class); IASTImplicitName n2 = ba.assertImplicitName("]); //1", 1, ICPPMethod.class);
assertSame(n1.resolveBinding(), n2.resolveBinding()); assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate()); assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate()); assertTrue(n2.isAlternate());
assertSame(col.getName(1).resolveBinding(), n1.resolveBinding());
n1 = ba.assertImplicitName("[q]); //2", 1, ICPPMethod.class); n1 = ba.assertImplicitName("[q]); //2", 1, ICPPMethod.class);
ba.assertNoImplicitName("q]); //2", 1); ba.assertNoImplicitName("q]); //2", 1);
@ -291,6 +371,7 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
assertSame(n1.resolveBinding(), n2.resolveBinding()); assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate()); assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate()); assertTrue(n2.isAlternate());
assertSame(col.getName(3).resolveBinding(), n1.resolveBinding());
} }
@ -304,6 +385,7 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// delete x; // delete x;
// X* xs = new X[5]; // X* xs = new X[5];
// delete[] x; // delete[] x;
// delete 1;
// } // }
public void testDelete() throws Exception { public void testDelete() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
@ -322,6 +404,8 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
names = ba.getImplicitNames("delete[] x;", 6); names = ba.getImplicitNames("delete[] x;", 6);
assertEquals(1, names.length); assertEquals(1, names.length);
assertSame(col.getName(3).resolveBinding(), names[0].resolveBinding()); assertSame(col.getName(3).resolveBinding(), names[0].resolveBinding());
ba.assertNoImplicitName("delete 1;", 6);
} }
@ -333,7 +417,7 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
public void _testImplicitNewAndDelete() throws Exception { public void _testImplicitNewAndDelete() throws Exception {
BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true);
ba.assertNoImplicitName("new X", 3); ba.assertNoImplicitName("new X", 3);
ba.assertNoImplicitName("delete[]", 6); ba.assertNoImplicitName("delete[]", 6); // fails because its picking up the implicit global delete[]
} }
@ -373,13 +457,4 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNoImplicitName("throw;", 5); ba.assertNoImplicitName("throw;", 5);
} }
} }

View file

@ -6187,7 +6187,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// }; // };
// A a; // A a;
// void B::f() { // void B::f() {
// operator+ (a,a); // ERROR - global operator hidden by member // //operator+ (a,a); // ERROR - global operator hidden by member
// a + a; // OK - calls global operator+ // a + a; // OK - calls global operator+
// } // }
public void test13_3_1_2s10() throws Exception { public void test13_3_1_2s10() throws Exception {

View file

@ -7029,4 +7029,52 @@ public class AST2CPPTests extends AST2BaseTest {
final String code = getAboveComment(); final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP); parseAndCheckBindings(code, ParserLanguage.CPP);
} }
// struct A { int a; };
// struct B { int b; };
//
// struct X {
// A operator+(int);
// X(int);
// };
//
// A operator+(X,X);
// B operator+(X,double);
//
// void test(X x) {
// (x + 1).a; //1
// (1 + x).a; //2
// (x + 1.0).b; //3
// }
public void testOverloadResolutionForOperators_Bug266211() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNonProblem("a; //1", 1, ICPPField.class);
ba.assertNonProblem("a; //2", 1, ICPPField.class);
ba.assertNonProblem("b; //3", 1, ICPPField.class);
}
// struct A { int a; };
// struct X {
// A operator+(X);
// void m();
// };
//
// A operator+(X,double);
//
// void X::m() {
// X x;
// (x + x).a; //1
// (x + 1.0).a; //2
// }
public void testOverloadResolutionForOperators_Bug268534() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNonProblem("a; //1", 1, ICPPField.class);
ba.assertNonProblem("a; //2", 1, ICPPField.class);
}
} }

View file

@ -54,7 +54,6 @@ public class DOMParserTestSuite extends TestCase {
suite.addTest(FaultToleranceTests.suite()); suite.addTest(FaultToleranceTests.suite());
suite.addTest(LanguageExtensionsTest.suite()); suite.addTest(LanguageExtensionsTest.suite());
suite.addTest(ASTInactiveCodeTests.suite()); suite.addTest(ASTInactiveCodeTests.suite());
suite.addTest(AST2CPPImplicitNameTests.suite());
return suite; return suite;
} }
} }

View file

@ -9,6 +9,7 @@
* Andrew Niefer (IBM Corporation) - initial API and implementation * Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian) * Andrew Ferguson (Symbian)
* Mike Kucera (IBM)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.core.parser.util; package org.eclipse.cdt.core.parser.util;
@ -386,4 +387,26 @@ public class ArrayUtil {
} }
return result; return result;
} }
/**
* Returns a new array that contains all of the elements of the
* given array except the first one.
*
* @since 5.1
* @throws NullPointerException if args is null
* @throws IllegalArgumentException if args.length <= 0
*/
@SuppressWarnings("unchecked")
public static <T> T[] removeFirst(T[] args) {
int n = args.length;
if(n <= 0)
throw new IllegalArgumentException();
T[] newArgs = (T[]) Array.newInstance(args.getClass().getComponentType(), n-1);
for(int i = 1; i < n; i++) {
newArgs[i-1] = args[i];
}
return newArgs;
}
} }

View file

@ -18,7 +18,6 @@ import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IArrayType;
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.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@ -105,15 +104,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr
public ICPPFunction getOverload() { public ICPPFunction getOverload() {
IType type1 = arrayExpression.getExpressionType(); return CPPSemantics.findOverloadedOperator(this);
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
if (ultimateType1 instanceof IProblemBinding) {
return null;
}
if (ultimateType1 instanceof ICPPClassType) {
return CPPSemantics.findOperator(this, (ICPPClassType) ultimateType1);
}
return null;
} }
@Override @Override
@ -172,7 +163,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr
return CPPUnknownClass.createUnnamedInstance(); return CPPUnknownClass.createUnnamedInstance();
} }
if (t instanceof ICPPClassType) { if (t instanceof ICPPClassType) {
ICPPFunction op = CPPSemantics.findOperator(this, (ICPPClassType) t); ICPPFunction op = getOverload();
if (op != null) { if (op != null) {
return op.getType().getReturnType(); return op.getType().getReturnType();
} }

View file

@ -17,13 +17,11 @@ import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
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.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@ -171,35 +169,9 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
if (overload != UNINITIALIZED) if (overload != UNINITIALIZED)
return overload; return overload;
return overload= computeOverload(); return overload = CPPSemantics.findOverloadedOperator(this);
} }
private ICPPFunction computeOverload() {
IType type1 = getOperand1().getExpressionType();
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
if (ultimateType1 instanceof IProblemBinding) {
return null;
}
if (ultimateType1 instanceof ICPPClassType) {
ICPPFunction operator = CPPSemantics.findOperator(this, (ICPPClassType) ultimateType1);
if (operator != null)
return operator;
}
// try to find a function
if(op != op_assign) {
IType type2 = getOperand2().getExpressionType();
IType ultimateType2 = SemanticUtil.getUltimateTypeUptoPointers(type2);
if (ultimateType2 instanceof IProblemBinding)
return null;
if (isUserDefined(ultimateType1) || isUserDefined(ultimateType2))
return CPPSemantics.findOverloadedOperator(this);
}
return null;
}
private IType createExpressionType() { private IType createExpressionType() {
// Check for overloaded operator. // Check for overloaded operator.
ICPPFunction o= getOverload(); ICPPFunction o= getOverload();
@ -263,9 +235,4 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
return type1; return type1;
} }
private static boolean isUserDefined(IType type) {
return type instanceof ICPPClassType || type instanceof IEnumeration;
}
} }

View file

@ -14,17 +14,13 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
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.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpression { public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpression {
@ -87,18 +83,14 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
} }
/** /**
* Try to resolve both the destructor and the operator delete. * Try to resolve both the destructor and operator delete.
*/ */
public IASTImplicitName[] getImplicitNames() { public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) { if(implicitNames == null) {
ICPPClassType nestedType = getNestedClassType();
if(nestedType == null)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
List<IASTImplicitName> names = new ArrayList<IASTImplicitName>(); List<IASTImplicitName> names = new ArrayList<IASTImplicitName>();
if(!isVectored) { if(!isVectored) {
ICPPFunction destructor = CPPSemantics.findDestructor(this, nestedType); ICPPFunction destructor = CPPSemantics.findDestructor(this);
if(destructor != null) { if(destructor != null) {
CPPASTImplicitName destructorName = new CPPASTImplicitName(destructor.getNameCharArray(), this); CPPASTImplicitName destructorName = new CPPASTImplicitName(destructor.getNameCharArray(), this);
destructorName.setBinding(destructor); destructorName.setBinding(destructor);
@ -108,7 +100,7 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
} }
if(!isGlobal) { if(!isGlobal) {
ICPPFunction deleteOperator = findOperatorFunction(nestedType); ICPPFunction deleteOperator = CPPSemantics.findOverloadedOperator(this);
if(deleteOperator != null) { if(deleteOperator != null) {
CPPASTImplicitName deleteName = new CPPASTImplicitName(deleteOperator.getNameCharArray(), this); CPPASTImplicitName deleteName = new CPPASTImplicitName(deleteOperator.getNameCharArray(), this);
deleteName.setOperator(true); deleteName.setOperator(true);
@ -128,33 +120,6 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
} }
private ICPPClassType getNestedClassType() {
IType type1 = operand.getExpressionType();
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
if(ultimateType1 instanceof IPointerType) {
try {
IType classType = ((IPointerType)ultimateType1).getType();
if(classType instanceof ICPPClassType)
return (ICPPClassType) classType;
} catch (DOMException e) {
return null;
}
}
return null;
}
// TODO this code is repeated in too many places
private ICPPFunction findOperatorFunction(IType type) {
if(type instanceof ICPPClassType) {
ICPPFunction operator = CPPSemantics.findOperator(this, (ICPPClassType) type);
if(operator != null)
return operator;
return CPPSemantics.findOverloadedOperator(this);
}
return null;
}
@Override @Override
public boolean accept( ASTVisitor action ){ public boolean accept( ASTVisitor action ){
if( action.shouldVisitExpressions ){ if( action.shouldVisitExpressions ){

View file

@ -12,21 +12,18 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
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.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; 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.IASTAmbiguityParent;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent { public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent {
@ -38,6 +35,8 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
*/ */
private IASTImplicitName[] implicitNames; private IASTImplicitName[] implicitNames;
private ICPPFunction[] overloads = null;
public CPPASTExpressionList copy() { public CPPASTExpressionList copy() {
CPPASTExpressionList copy = new CPPASTExpressionList(); CPPASTExpressionList copy = new CPPASTExpressionList();
@ -112,11 +111,9 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
implicitNames = new IASTImplicitName[exprs.length-1]; implicitNames = new IASTImplicitName[exprs.length-1];
if(getPropertyInParent() == IASTFunctionCallExpression.PARAMETERS) ICPPFunction[] overloads = getOverloads();
return implicitNames; for(int i = 0; i < overloads.length; i++) {
ICPPFunction overload = overloads[i];
for(int i = 0, n = exprs.length-1; i < n; i++) {
ICPPFunction overload = getOverload(i);
if(overload != null) { if(overload != null) {
CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.COMMA, this); CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.COMMA, this);
operatorName.setBinding(overload); operatorName.setBinding(overload);
@ -135,37 +132,33 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
} }
/** private ICPPFunction[] getOverloads() {
* @param index the index of the first argument if(overloads == null) {
*/ IASTExpression[] exprs = getExpressions();
private ICPPFunction getOverload(int index) { if(exprs.length < 2 || getPropertyInParent() == IASTFunctionCallExpression.PARAMETERS)
// try to find a method return overloads = new ICPPFunction[0];
IASTExpression[] exprs = getExpressions();
IType type1 = exprs[index].getExpressionType(); overloads = new ICPPFunction[exprs.length-1];
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1); IType lookupType = exprs[0].getExpressionType();
if (ultimateType1 instanceof IProblemBinding) {
return null;
}
if (ultimateType1 instanceof ICPPClassType) {
ICPPFunction operator = CPPSemantics.findOperatorComma(this, index, (ICPPClassType) ultimateType1);
if (operator != null)
return operator;
}
// try to find a function for(int i = 1; i < exprs.length; i++) {
IType type2 = exprs[index+1].getExpressionType(); IASTExpression e1 = exprs[i-1], e2 = exprs[i];
IType ultimateType2 = SemanticUtil.getUltimateTypeUptoPointers(type2); ICPPFunction overload = CPPSemantics.findOverloadedOperatorComma(e1, e2, lookupType);
if (ultimateType2 instanceof IProblemBinding) if(overload == null) {
return null; lookupType = e2.getExpressionType();
if (isUserDefined(ultimateType1) || isUserDefined(ultimateType2)) }
return CPPSemantics.findOverloadedOperator(this, index); else {
overloads[i-1] = overload;
try {
lookupType = overload.getType().getReturnType();
} catch (DOMException e) {
lookupType = e2.getExpressionType();
}
}
}
}
return null; return overloads;
}
private static boolean isUserDefined(IType type) {
return type instanceof ICPPClassType || type instanceof IEnumeration;
} }
public void replace(IASTNode child, IASTNode other) { public void replace(IASTNode child, IASTNode other) {
@ -180,6 +173,16 @@ public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionLi
} }
public IType getExpressionType() { public IType getExpressionType() {
ICPPFunction[] overloads = getOverloads();
if(overloads.length > 0) {
ICPPFunction last = overloads[overloads.length-1];
if(last != null) {
try {
return last.getType().getReturnType();
} catch (DOMException e) { }
}
}
for (int i = expressions.length-1; i >= 0 ; i--) { for (int i = expressions.length-1; i >= 0 ; i--) {
IASTExpression expr= expressions[i]; IASTExpression expr= expressions[i];
if (expr != null) if (expr != null)

View file

@ -219,7 +219,7 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
if (t instanceof IFunctionType) { if (t instanceof IFunctionType) {
return ((IFunctionType) t).getReturnType(); return ((IFunctionType) t).getReturnType();
} else if (t instanceof ICPPClassType) { } else if (t instanceof ICPPClassType) {
ICPPFunction op = CPPSemantics.findOperator(this, (ICPPClassType) t); ICPPFunction op = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
if (op != null) { if (op != null) {
if(overload != null) if(overload != null)
overload[0] = op; overload[0] = op;

View file

@ -23,12 +23,9 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
@ -180,17 +177,7 @@ public class CPPASTNewExpression extends ASTNode implements
public IASTImplicitName[] getImplicitNames() { public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) { if(implicitNames == null) {
IType type = getExpressionType(); ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this);
if(type instanceof IProblem)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
try {
type = ((IPointerType)type).getType();
} catch (DOMException e) {
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
}
ICPPFunction operatorFunction = findOperatorFunction(type);
if(operatorFunction == null) { if(operatorFunction == null) {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
} }
@ -207,17 +194,6 @@ public class CPPASTNewExpression extends ASTNode implements
} }
// TODO this code is repeated in too many places
private ICPPFunction findOperatorFunction(IType type) {
if(type instanceof ICPPClassType) {
ICPPFunction operator = CPPSemantics.findOperator(this, (ICPPClassType) type);
if(operator != null)
return operator;
}
return CPPSemantics.findOverloadedOperator(this);
}
/** /**
* Returns true if this expression is allocating an array. * Returns true if this expression is allocating an array.
* @since 5.1 * @since 5.1

View file

@ -31,7 +31,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; 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.ICPPASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; 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.ICPPMember;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@ -46,9 +45,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
* Unary expression in c++ * Unary expression in c++
*/ */
public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpression, IASTAmbiguityParent { public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpression, IASTAmbiguityParent {
private static final ICPPFunction UNINITIALIZED = new CPPFunction(null);
private int op; private int op;
private IASTExpression operand; private IASTExpression operand;
private ICPPFunction overload = UNINITIALIZED;
private IASTImplicitName[] implicitNames = null; private IASTImplicitName[] implicitNames = null;
public CPPASTUnaryExpression() { public CPPASTUnaryExpression() {
@ -155,13 +156,46 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
public ICPPFunction getOverload() { public ICPPFunction getOverload() {
if(operand == null) if (overload != UNINITIALIZED)
return null; return overload;
if(getExpressionType() instanceof CPPPointerToMemberType) // then it must be the builtin &
return null; overload = CPPSemantics.findOverloadedOperator(this);
IType type = operand.getExpressionType(); if(operand != null && op == op_amper && computePointerToMemberType() instanceof CPPPointerToMemberType)
type = SemanticUtil.getNestedType(type, TDEF | REF); overload = null;
return findOperatorFunction(type);
return overload;
}
private IType computePointerToMemberType() {
IASTNode child= operand;
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();
IBinding b= name.resolveBinding();
if (b instanceof ICPPMember) {
ICPPMember member= (ICPPMember) b;
try {
if (name instanceof ICPPASTQualifiedName) {
if (!member.isStatic()) { // so if the member is static it will fall through
if (!inParenthesis) {
return new CPPPointerToMemberType(member.getType(), member.getClassOwner(), false, false);
} else if (member instanceof IFunction) {
return new ProblemBinding(operand, IProblemBinding.SEMANTIC_INVALID_TYPE, operand.getRawSignature().toCharArray());
}
}
}
} catch (DOMException e) {
return e.getProblem();
}
}
}
return null;
} }
@ -177,40 +211,16 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
final IASTExpression operand = getOperand(); final IASTExpression operand = getOperand();
if (op == op_amper) { // check for pointer to member if (op == op_amper) { // check for pointer to member
IASTNode child= operand; IType ptm = computePointerToMemberType();
boolean inParenthesis= false; if(ptm != null)
while (child instanceof IASTUnaryExpression && ((IASTUnaryExpression) child).getOperator() == IASTUnaryExpression.op_bracketedPrimary) { return ptm;
child= ((IASTUnaryExpression) child).getOperand();
inParenthesis= true;
}
if (child instanceof IASTIdExpression) {
IASTName name= ((IASTIdExpression) child).getName();
IBinding b= name.resolveBinding();
if (b instanceof ICPPMember) {
ICPPMember member= (ICPPMember) b;
try {
if (name instanceof ICPPASTQualifiedName) {
if (!member.isStatic()) { // so if the member is static it will fall through
if (!inParenthesis) {
return new CPPPointerToMemberType(member.getType(), member.getClassOwner(), false, false);
} else if (member instanceof IFunction) {
return new ProblemBinding(operand, IProblemBinding.SEMANTIC_INVALID_TYPE, operand.getRawSignature().toCharArray());
}
}
}
} catch (DOMException e) {
return e.getProblem();
}
}
}
IType type= operand.getExpressionType(); IType operator = findOperatorReturnType();
type = SemanticUtil.getNestedType(type, TDEF | REF);
IType operator = findOperatorReturnType(type);
if(operator != null) if(operator != null)
return operator; return operator;
IType type= operand.getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF);
return new CPPPointerType(type); return new CPPPointerType(type);
} }
@ -222,7 +232,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
return type; return type;
} }
try { try {
IType operator = findOperatorReturnType(type); IType operator = findOperatorReturnType();
if(operator != null) { if(operator != null) {
return operator; return operator;
} else if (type instanceof IPointerType || type instanceof IArrayType) { } else if (type instanceof IPointerType || type instanceof IArrayType) {
@ -239,7 +249,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
IType type= operand.getExpressionType(); IType type= operand.getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF); type = SemanticUtil.getNestedType(type, TDEF | REF);
IType operator = findOperatorReturnType(type); IType operator = findOperatorReturnType();
if(operator != null) { if(operator != null) {
return operator; return operator;
} }
@ -254,8 +264,8 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
} }
private IType findOperatorReturnType(IType type) { private IType findOperatorReturnType() {
ICPPFunction operatorFunction = findOperatorFunction(type); ICPPFunction operatorFunction = getOverload();
if(operatorFunction != null) { if(operatorFunction != null) {
try { try {
return operatorFunction.getType().getReturnType(); return operatorFunction.getType().getReturnType();
@ -267,14 +277,4 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
} }
private ICPPFunction findOperatorFunction(IType type) {
if(type instanceof ICPPClassType) {
ICPPFunction operator = CPPSemantics.findOperator(this, (ICPPClassType) type);
if(operator != null)
return operator;
return CPPSemantics.findOverloadedOperator(this);
}
return null;
}
} }

View file

@ -84,7 +84,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
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.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
@ -136,6 +135,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
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.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharArrayUtils;
@ -154,6 +154,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypeIdExpression; 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.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.CPPNamespace; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
@ -248,8 +249,10 @@ public class CPPSemantics {
return postResolution(binding, data); return postResolution(binding, data);
} }
private static IBinding postResolution(IBinding binding, LookupData data) { private static IBinding postResolution(IBinding binding, LookupData data) {
if (data.checkAssociatedScopes()) { // If the normal lookup of the unqualified name finds a class member function, then ADL does not occur
if (data.checkAssociatedScopes() && !data.hasMemberFunctionResult()) {
// 3.4.2 argument dependent name lookup, aka Koenig lookup // 3.4.2 argument dependent name lookup, aka Koenig lookup
try { try {
boolean doKoenig= true; boolean doKoenig= true;
@ -753,13 +756,14 @@ public class CPPSemantics {
scope= (ICPPScope) data.tu.mapToASTScope(((IIndexScope) scope)); scope= (ICPPScope) data.tu.mapToASTScope(((IIndexScope) scope));
} }
if (!data.usingDirectivesOnly) { if (!data.usingDirectivesOnly && !(data.ignoreMembers && scope instanceof ICPPClassScope)) {
IBinding[] bindings= getBindingsFromScope(scope, fileSet, data); IBinding[] bindings= getBindingsFromScope(scope, fileSet, data);
if (data.typesOnly) { if (data.typesOnly) {
removeObjects(bindings); removeObjects(bindings);
} }
mergeResults(data, bindings, true); mergeResults(data, bindings, true);
// store using-directives found in this block or namespace for later use. // store using-directives found in this block or namespace for later use.
if ((!data.hasResults() || !data.qualified() || data.contentAssist) && scope instanceof ICPPNamespaceScope) { if ((!data.hasResults() || !data.qualified() || data.contentAssist) && scope instanceof ICPPNamespaceScope) {
final ICPPNamespaceScope blockScope= (ICPPNamespaceScope) scope; final ICPPNamespaceScope blockScope= (ICPPNamespaceScope) scope;
@ -1928,14 +1932,15 @@ public class CPPSemantics {
return; return;
final boolean def = data.forFunctionDeclaration(); final boolean def = data.forFunctionDeclaration();
int numArgs= data.getFunctionArgumentCount(); int argumentCount = data.getFunctionArgumentCount();
if (def && numArgs == 1) {
if (def && argumentCount == 1) {
// check for parameter of type void // check for parameter of type void
final IType[] argTypes = data.getFunctionArgumentTypes(); final IType[] argTypes = data.getFunctionArgumentTypes();
if (argTypes.length == 1) { if (argTypes.length == 1) {
IType t= getNestedType(argTypes[0], TDEF); IType t= getNestedType(argTypes[0], TDEF);
if (t instanceof IBasicType && ((IBasicType)t).getType() == IBasicType.t_void) { if (t instanceof IBasicType && ((IBasicType)t).getType() == IBasicType.t_void) {
numArgs= 0; argumentCount= 0;
} }
} }
} }
@ -1962,6 +1967,11 @@ public class CPPSemantics {
// as long as possible. // as long as possible.
final IType[] parameterTypes = function.getType().getParameterTypes(); final IType[] parameterTypes = function.getType().getParameterTypes();
int numPars = parameterTypes.length; int numPars = parameterTypes.length;
int numArgs = argumentCount;
if(function instanceof ICPPMethod && data.firstArgIsImpliedMethodArg)
numArgs--;
if (numArgs < 2 && numPars == 1) { if (numArgs < 2 && numPars == 1) {
// check for void // check for void
IType t = getNestedType(parameterTypes[0], TDEF); IType t = getNestedType(parameterTypes[0], TDEF);
@ -2060,14 +2070,12 @@ public class CPPSemantics {
Cost[] bestFnCost = null; // the cost of the best function Cost[] bestFnCost = null; // the cost of the best function
boolean bestHasAmbiguousParam = false; // bestFn has an ambiguous parameter conversion (not ok, ambiguous) boolean bestHasAmbiguousParam = false; // bestFn has an ambiguous parameter conversion (not ok, ambiguous)
final IType thisType = data.getImpliedObjectArgument();
// Loop over all functions // Loop over all functions
for (IFunction fn : fns) { for (IFunction fn : fns) {
if (fn == null || bestFn == fn) if (fn == null || bestFn == fn)
continue; continue;
final Cost[] fnCost= costForFunctionCall(fn, thisType, argTypes, args, allowUDC); final Cost[] fnCost= costForFunctionCall(fn, argTypes, args, allowUDC, data);
if (fnCost == null) if (fnCost == null)
continue; continue;
@ -2166,8 +2174,7 @@ public class CPPSemantics {
return bestFn; return bestFn;
} }
private static Cost[] costForFunctionCall(IFunction fn, IType thisType, IType[] argTypes, IASTExpression[] args, private static Cost[] costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args, boolean allowUDC, LookupData data) throws DOMException {
boolean allowUDC) throws DOMException {
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType(); final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
if (ftype == null) if (ftype == null)
return null; return null;
@ -2176,6 +2183,10 @@ public class CPPSemantics {
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()); implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
if(data.firstArgIsImpliedMethodArg) {
argTypes = ArrayUtil.removeFirst(argTypes);
args = ArrayUtil.removeFirst(args);
}
} }
int k= 0; int k= 0;
@ -2186,6 +2197,9 @@ public class CPPSemantics {
result= new Cost[sourceLen]; result= new Cost[sourceLen];
} else { } else {
result= new Cost[sourceLen+1]; result= new Cost[sourceLen+1];
final IType thisType = data.getImpliedObjectArgument();
if (ASTInternal.isStatic(fn, false)) { if (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(thisType, implicitType, Rank.IDENTITY);
@ -2559,6 +2573,9 @@ public class CPPSemantics {
if (!fieldReference.isPointerDereference()) if (!fieldReference.isPointerDereference())
return type; return type;
char[] operatorName = OverloadableOperator.ARROW.toCharArray();
IASTExpression[] args = {null};
// 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;
@ -2594,7 +2611,7 @@ public class CPPSemantics {
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x)); IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
innerFR.setParent(fieldReference); // connect to the AST innerFR.setParent(fieldReference); // connect to the AST
ICPPFunction op = CPPSemantics.findOperator(innerFR, (ICPPClassType) uTemp); ICPPFunction op = findOverloadedOperator(innerFR, args, uTemp, operatorName, false);
if (op == null) if (op == null)
break; break;
@ -2616,111 +2633,98 @@ public class CPPSemantics {
}; };
} }
public static ICPPFunction findOperator(IASTExpression exp, ICPPClassType cls) {
IScope scope = null;
try {
scope = cls.getCompositeScope();
} catch (DOMException e1) {
return null;
}
if (scope == null)
return null;
CPPASTName astName = new CPPASTName(); public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
astName.setParent(exp); char[] name = OverloadableOperator.BRACKET.toCharArray();
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY); IASTExpression[] args = { null, exp.getSubscriptExpression() };
LookupData data = new LookupData(astName); IType type1 = exp.getArrayExpression().getExpressionType();
data.forceQualified = true; IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
return findOverloadedOperator(exp, args, ultimateType1, name, false);
if (exp instanceof IASTArraySubscriptExpression) {
astName.setName(OverloadableOperator.BRACKET.toCharArray());
data.setFunctionArguments(((IASTArraySubscriptExpression) exp).getSubscriptExpression());
} else if (exp instanceof IASTFieldReference) {
astName.setName(OverloadableOperator.ARROW.toCharArray());
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
} else if (exp instanceof IASTFunctionCallExpression) {
astName.setName(OverloadableOperator.PAREN.toCharArray());
data.setFunctionArguments(((IASTFunctionCallExpression) exp).getParameterExpression());
} else if (exp instanceof ICPPASTDeleteExpression) {
OverloadableOperator oo = OverloadableOperator.fromDeleteExpression((ICPPASTDeleteExpression)exp);
astName.setName(oo.toCharArray());
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
} else if (exp instanceof ICPPASTNewExpression) {
ICPPASTNewExpression newExpression = (ICPPASTNewExpression) exp;
OverloadableOperator operator = OverloadableOperator.fromNewExpression(newExpression);
astName.setName(operator.toCharArray());
data.setFunctionArguments(newExpression.getNewPlacement());
} else if (exp instanceof IASTBinaryExpression) {
final IASTBinaryExpression binary = (IASTBinaryExpression) exp;
OverloadableOperator operator = OverloadableOperator.fromBinaryExpression(binary);
if (operator == null)
return null;
astName.setName(operator.toCharArray());
data.setFunctionArguments(new IASTExpression[] { binary.getOperand2() });
} else if (exp instanceof IASTUnaryExpression) {
IASTUnaryExpression unary = (IASTUnaryExpression) exp;
OverloadableOperator operator = OverloadableOperator.fromUnaryExpression(unary);
if(operator == null)
return null;
astName.setName(operator.toCharArray());
int op = unary.getOperator();
if(op == IASTUnaryExpression.op_postFixDecr || op == IASTUnaryExpression.op_postFixIncr)
data.setFunctionArguments(new IASTExpression[] { CPPASTLiteralExpression.INT_ZERO });
else
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
} else {
return null;
}
try {
lookup(data, scope);
IBinding binding = resolveAmbiguities(data, astName);
if (binding instanceof ICPPFunction)
return (ICPPFunction) binding;
} catch (DOMException e) {
}
return null;
}
/**
*
* @param expressionList
* @param index the index of the first parameter
*/
public static ICPPFunction findOperatorComma(ICPPASTExpressionList expressionList, int index, ICPPClassType cls) {
IScope scope = null;
try {
scope = cls.getCompositeScope();
} catch (DOMException e1) {
return null;
}
if (scope == null)
return null;
CPPASTName astName = new CPPASTName();
astName.setParent(expressionList);
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
astName.setName(OverloadableOperator.COMMA.toCharArray());
LookupData data = new LookupData(astName);
data.forceQualified = true;
IASTExpression[] exprs = expressionList.getExpressions();
data.setFunctionArguments(new IASTExpression[] { exprs[index], exprs[index+1] });
try {
lookup(data, scope);
IBinding binding = resolveAmbiguities(data, astName);
if (binding instanceof ICPPFunction)
return (ICPPFunction) binding;
} catch (DOMException e) {
}
return null;
} }
public static ICPPFunction findOverloadedOperator(IASTFunctionCallExpression exp, ICPPClassType type) {
char[] name = OverloadableOperator.PAREN.toCharArray();
IASTExpression param = exp.getParameterExpression();
IASTExpression[] args;
if(param instanceof IASTExpressionList) {
IASTExpression[] actualArgs = ((IASTExpressionList)param).getExpressions();
ArrayList<IASTExpression> argsToPass = new ArrayList<IASTExpression>(actualArgs.length + 1);
argsToPass.add(null);
for(IASTExpression e : actualArgs) {
argsToPass.add(e);
}
args = argsToPass.toArray(new IASTExpression[argsToPass.size()]);
}
else if(param != null) {
args = new IASTExpression[] { null, param };
}
else {
args = new IASTExpression[] { null };
}
return findOverloadedOperator(exp, args, type, name, false);
}
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
OverloadableOperator op = OverloadableOperator.fromNewExpression(exp);
IType type = exp.getExpressionType();
if(type instanceof IProblem)
return null;
try {
type = ((IPointerType)type).getType();
} catch (DOMException e) {
return null;
}
IASTTypeId typeId = exp.getTypeId().copy();
IASTExpression sizeExpression = new CPPASTTypeIdExpression(IASTTypeIdExpression.op_sizeof, typeId);
sizeExpression.setParent(exp);
IASTExpression placement = exp.getNewPlacement();
List<IASTExpression> args = new ArrayList<IASTExpression>();
args.add(sizeExpression);
if(placement instanceof IASTExpressionList) {
for(IASTExpression p : ((IASTExpressionList)placement).getExpressions())
args.add(p);
}
else if(placement != null) {
args.add(placement);
}
IASTExpression[] argArray = args.toArray(new IASTExpression[args.size()]);
return findOverloadedOperator(exp, argArray, type, op.toCharArray(), true);
}
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
OverloadableOperator op = OverloadableOperator.fromDeleteExpression(exp);
IASTExpression[] args = { exp.getOperand() };
IType classType = getNestedClassType(exp);
return findOverloadedOperator(exp, args, classType, op.toCharArray(), true);
}
private static ICPPClassType getNestedClassType(ICPPASTDeleteExpression exp) {
IType type1 = exp.getOperand().getExpressionType();
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
if(ultimateType1 instanceof IPointerType) {
try {
IType classType = ((IPointerType)ultimateType1).getType();
if(classType instanceof ICPPClassType)
return (ICPPClassType) classType;
} catch (DOMException e) {
return null;
}
}
return null;
}
public static ICPPFunction findDestructor(ICPPASTDeleteExpression expr) {
ICPPClassType cls = getNestedClassType(expr);
if(cls == null)
return null;
public static ICPPFunction findDestructor(ICPPASTDeleteExpression expr, ICPPClassType cls) {
IScope scope = null; IScope scope = null;
try { try {
scope = cls.getCompositeScope(); scope = cls.getCompositeScope();
@ -2749,119 +2753,144 @@ public class CPPSemantics {
return null; return null;
} }
/**
* Returns the overloaded operator corresponding to a binary expression, or {@code null}
* if no such operator is found.
* @param exp a binary expression
* @return the overloaded operator, or {@code null}.
*/
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
OverloadableOperator operator = OverloadableOperator.fromBinaryExpression(exp);
IASTExpression[] args = { exp.getOperand1(), exp.getOperand2() };
return findOverloadedOperator(exp, operator, args);
}
/**
* Returns the overloaded operator corresponding to a binary expression, or {@code null}
* if no such operator is found.
* @param exp a binary expression
* @return the overloaded operator, or {@code null}.
*/
public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression exp) {
OverloadableOperator operator = OverloadableOperator.fromDeleteExpression(exp);
IASTExpression[] args = { exp.getOperand() };
return findOverloadedOperator(exp, operator, args);
}
/**
* Returns the overloaded operator corresponding to a unary expression, or {@code null}
* if no such operator is found.
*/
public static ICPPFunction findOverloadedOperator(IASTUnaryExpression exp) { public static ICPPFunction findOverloadedOperator(IASTUnaryExpression exp) {
OverloadableOperator operator = OverloadableOperator.fromUnaryExpression(exp); if(exp.getOperand() == null)
return null;
IASTExpression[] args = null; OverloadableOperator op = OverloadableOperator.fromUnaryExpression(exp);
int op = exp.getOperator(); if(op == null)
if(op == IASTUnaryExpression.op_postFixDecr || op == IASTUnaryExpression.op_postFixIncr) return null;
IASTExpression[] args;
int operator = exp.getOperator();
if(operator == IASTUnaryExpression.op_postFixDecr || operator == IASTUnaryExpression.op_postFixIncr)
args = new IASTExpression[] { exp.getOperand(), CPPASTLiteralExpression.INT_ZERO }; args = new IASTExpression[] { exp.getOperand(), CPPASTLiteralExpression.INT_ZERO };
else else
args = new IASTExpression[] { exp.getOperand() }; args = new IASTExpression[] { exp.getOperand() };
return findOverloadedOperator(exp, operator, args); IType type = exp.getOperand().getExpressionType();
} type = SemanticUtil.getNestedType(type, TDEF | REF | CVQ);
return findOverloadedOperator(exp, args, type, op.toCharArray(), true);
/**
* Returns the overloaded operator corresponding to a comma in an expression list,
* or {@code null} if no such operator is found.
* @param index the index of the left argument to the comma operator
* @throws IndexOutOfBoundsException if index is invalid
*/
public static ICPPFunction findOverloadedOperator(ICPPASTExpressionList exp, int index) {
OverloadableOperator operator = OverloadableOperator.COMMA;
IASTExpression[] exprs = exp.getExpressions();
IASTExpression[] args = { exprs[index], exprs[index+1] };
return findOverloadedOperator(exp, operator, args);
}
/**
* Returns the overloaded operator corresponding to a comma in an expression list,
* or {@code null} if no such operator is found.
* @throws IndexOutOfBoundsException if index is invalid
*/
public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression exp) {
OverloadableOperator operator = OverloadableOperator.fromNewExpression(exp);
IASTTypeId typeId = exp.getTypeId().copy();
IASTExpression sizeExpression = new CPPASTTypeIdExpression(IASTTypeIdExpression.op_sizeof, typeId);
sizeExpression.setParent(exp);
IASTExpression placement = exp.getNewPlacement();
List<IASTExpression> args = new ArrayList<IASTExpression>();
args.add(sizeExpression);
if(placement instanceof IASTExpressionList) {
for(IASTExpression p : ((IASTExpressionList)placement).getExpressions())
args.add(p);
}
else if(placement != null) {
args.add(placement);
}
return findOverloadedOperator(exp, operator, args.toArray(new IASTExpression[args.size()]));
} }
private static ICPPFunction findOverloadedOperator(IASTExpression exp, OverloadableOperator operator, IASTExpression[] args) { public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
if (operator == null) { OverloadableOperator op = OverloadableOperator.fromBinaryExpression(exp);
return null; if(op == null)
}
IScope scope = CPPVisitor.getContainingScope(exp);
if (scope == null)
return null; return null;
CPPASTName astName = new CPPASTName(); IType op1type = SemanticUtil.getUltimateTypeUptoPointers(exp.getOperand1().getExpressionType());
astName.setParent(exp); IASTExpression[] args = new IASTExpression[] { exp.getOperand1(), exp.getOperand2() } ;
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
astName.setName(operator.toCharArray()); boolean lookupNonMember = false;
LookupData data = new LookupData(astName); if(exp.getOperator() != IASTBinaryExpression.op_assign) {
data.setFunctionArguments(args); IType op2type = SemanticUtil.getUltimateTypeUptoPointers(exp.getOperand2().getExpressionType());
if(op2type instanceof IProblemBinding)
return null;
if(isUserDefined(op1type) || isUserDefined(op2type))
lookupNonMember = true;
}
return findOverloadedOperator(exp, args, op1type, op.toCharArray(), lookupNonMember);
}
/**
* Returns the operator,() function that would apply to the two given arguments.
* The lookup type of the class where the operator,() might be found must also be provided.
*/
public static ICPPFunction findOverloadedOperatorComma(IASTExpression first, IASTExpression second, final IType lookupType) {
IASTUnaryExpression dummy = new CPPASTUnaryExpression() {
@Override public IType getExpressionType() { return lookupType; }
@Override public IASTExpression getOperand() {
return new CPPASTUnaryExpression() {
@Override public IType getExpressionType() { return lookupType; }
};
}
};
dummy.setParent(first);
char[] name = OverloadableOperator.COMMA.toCharArray();
IASTExpression[] args = new IASTExpression[] { dummy , second };
return findOverloadedOperator(dummy, args, lookupType, name, true);
}
private static ICPPFunction findOverloadedOperator(IASTExpression parent, IASTExpression[] args, IType methodLookupType, char[] operatorName, boolean lookupNonMember) {
// find a method
LookupData methodData = null;
CPPASTName methodName = null;
if(methodLookupType instanceof IProblemBinding)
return null;
if(methodLookupType instanceof ICPPClassType) {
methodName = new CPPASTName(operatorName);
methodName.setParent(parent);
methodName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
methodData = new LookupData(methodName);
methodData.setFunctionArguments(ArrayUtil.removeFirst(args));
methodData.forceQualified = true; // (13.3.1.2.3)
try {
IScope scope = ((ICPPClassType)methodLookupType).getCompositeScope();
if (scope == null)
return null;
lookup(methodData, scope);
} catch (DOMException e) {
return null;
}
}
// find a function
LookupData funcData = null;
CPPASTName funcName = null;
if(lookupNonMember) {
funcName = new CPPASTName(operatorName);
funcName.setParent(parent);
funcName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
funcData = new LookupData(funcName);
funcData.setFunctionArguments(args);
funcData.ignoreMembers = true; // (13.3.1.2.3)
try {
IScope scope = CPPVisitor.getContainingScope(parent);
if (scope == null)
return null;
lookup(funcData, scope);
} catch (DOMException e) {
return null;
}
}
// resolve ambiguities
try {
IBinding binding = null;
if(methodData != null && funcData != null) {
// if there was two lookups then merge the results
mergeResults(funcData, methodData.foundItems, false);
funcData.firstArgIsImpliedMethodArg = true;
binding = resolveAmbiguities(funcData, funcName);
}
else if(funcData != null) {
binding = resolveAmbiguities(funcData, funcName);
}
else if(methodData != null) {
binding = resolveAmbiguities(methodData, methodName);
}
try {
lookup(data, scope);
IBinding binding = resolveAmbiguities(data, astName);
if (binding instanceof ICPPFunction) if (binding instanceof ICPPFunction)
return (ICPPFunction) binding; return (ICPPFunction) binding;
} catch (DOMException e) {}
} catch (DOMException e) {
}
return null; return null;
} }
private static boolean isUserDefined(IType type) {
return type instanceof ICPPClassType || type instanceof IEnumeration;
}
public static IBinding[] findBindings(IScope scope, String name, boolean qualified) throws DOMException { public static IBinding[] findBindings(IScope scope, String name, boolean qualified) throws DOMException {

View file

@ -63,6 +63,7 @@ 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;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
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.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
@ -104,6 +105,8 @@ public class LookupData {
public boolean considerConstructors = false; public boolean considerConstructors = false;
public boolean checkPointOfDecl= true; // for lookup of unknown bindings the point of declaration can be reversed. public boolean checkPointOfDecl= true; // for lookup of unknown bindings the point of declaration can be reversed.
public boolean usesEnclosingScope= true; // for field references or qualified names, enclosing template declarations are ignored. public boolean usesEnclosingScope= true; // for field references or qualified names, enclosing template declarations are ignored.
public boolean firstArgIsImpliedMethodArg = false; // when computing the cost of a method call treat the first argument as the implied method argument
public boolean ignoreMembers = false;
public ICPPClassType skippedScope; public ICPPClassType skippedScope;
public Object foundItems = null; public Object foundItems = null;
@ -370,6 +373,19 @@ public class LookupData {
return false; return false;
} }
public boolean hasMemberFunctionResult() {
if(foundItems == null)
return false;
if(foundItems instanceof Object[]) {
for(Object item : (Object[])foundItems) {
if(item instanceof ICPPMethod) {
return true;
}
}
}
return false;
}
/** /**
* an IType[] of function arguments, including the implied object argument * an IType[] of function arguments, including the implied object argument
*/ */