1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 09:25:31 +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 {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertImplicitName("+= 5", 2, ICPPMethod.class);
ba.assertImplicitName("+ p", 1, ICPPMethod.class);
ba.assertImplicitName("- p", 1, ICPPMethod.class);
ba.assertImplicitName("* p", 1, ICPPFunction.class);
ba.assertImplicitName("/ p", 1, ICPPFunction.class);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
IASTImplicitName n;
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.assertImplicitName("-p;", 1, ICPPMethod.class);
ba.assertNoImplicitName("+p;", 1);
}
@ -114,8 +131,14 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// }
public void testPointerToMember() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
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;
// test(a , b , c , d); // func
// }
public void _testCommaOperator() throws Exception {
public void testCommaOperator1() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
// expression lists are used in function calls but they should not resolve to the comma operator
ba.assertNoImplicitName(", b , c , d); // func", 1);
@ -213,22 +236,65 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
tu.accept(col);
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 {
// int operator()(bool);
// int operator()();
// int operator()(int,int);
// };
//
// int test(X x) {
// bool b = true;
// x(b); // 1
// x(); // 2
// x(1,2); // 3
// }
public void testFunctionCallOperator() throws Exception {
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 n2 = ba.assertImplicitName("); // 1", 1, ICPPMethod.class);
@ -237,12 +303,21 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
assertTrue(n2.isAlternate());
// there should be no overlap
ba.assertNoImplicitName("b); // 1", 1);
assertSame(col.getName(1).resolveBinding(), n1.resolveBinding());
n1 = ba.assertImplicitName("(); // 2", 1, ICPPMethod.class);
n2 = ba.assertImplicitName("); // 2", 1, ICPPMethod.class);
assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.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 {
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);
ba.assertNoImplicitName("0]); //1", 1);
IASTImplicitName n2 = ba.assertImplicitName("]); //1", 1, ICPPMethod.class);
assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate());
assertSame(col.getName(1).resolveBinding(), n1.resolveBinding());
n1 = ba.assertImplicitName("[q]); //2", 1, ICPPMethod.class);
ba.assertNoImplicitName("q]); //2", 1);
@ -291,6 +371,7 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate());
assertSame(col.getName(3).resolveBinding(), n1.resolveBinding());
}
@ -304,6 +385,7 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
// delete x;
// X* xs = new X[5];
// delete[] x;
// delete 1;
// }
public void testDelete() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
@ -322,6 +404,8 @@ public class AST2CPPImplicitNameTests extends AST2BaseTest {
names = ba.getImplicitNames("delete[] x;", 6);
assertEquals(1, names.length);
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 {
BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true);
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);
ba.assertNoImplicitName("throw;", 5);
}
}

View file

@ -6187,7 +6187,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
// };
// A a;
// 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+
// }
public void test13_3_1_2s10() throws Exception {

View file

@ -7029,4 +7029,52 @@ public class AST2CPPTests extends AST2BaseTest {
final String code = getAboveComment();
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(LanguageExtensionsTest.suite());
suite.addTest(ASTInactiveCodeTests.suite());
suite.addTest(AST2CPPImplicitNameTests.suite());
return suite;
}
}

View file

@ -9,6 +9,7 @@
* Andrew Niefer (IBM Corporation) - initial API and implementation
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.core.parser.util;
@ -386,4 +387,26 @@ public class ArrayUtil {
}
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.IArrayType;
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.cpp.ICPPASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@ -105,15 +104,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr
public ICPPFunction getOverload() {
IType type1 = arrayExpression.getExpressionType();
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
if (ultimateType1 instanceof IProblemBinding) {
return null;
}
if (ultimateType1 instanceof ICPPClassType) {
return CPPSemantics.findOperator(this, (ICPPClassType) ultimateType1);
}
return null;
return CPPSemantics.findOverloadedOperator(this);
}
@Override
@ -172,7 +163,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTAr
return CPPUnknownClass.createUnnamedInstance();
}
if (t instanceof ICPPClassType) {
ICPPFunction op = CPPSemantics.findOperator(this, (ICPPClassType) t);
ICPPFunction op = getOverload();
if (op != null) {
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.IASTImplicitName;
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.IProblemBinding;
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.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.ICPPPointerToMemberType;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@ -171,35 +169,9 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
if (overload != UNINITIALIZED)
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() {
// Check for overloaded operator.
ICPPFunction o= getOverload();
@ -262,10 +234,5 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
}
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 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.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IPointerType;
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.ICPPClassType;
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.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
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() {
if(implicitNames == null) {
ICPPClassType nestedType = getNestedClassType();
if(nestedType == null)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
List<IASTImplicitName> names = new ArrayList<IASTImplicitName>();
if(!isVectored) {
ICPPFunction destructor = CPPSemantics.findDestructor(this, nestedType);
ICPPFunction destructor = CPPSemantics.findDestructor(this);
if(destructor != null) {
CPPASTImplicitName destructorName = new CPPASTImplicitName(destructor.getNameCharArray(), this);
destructorName.setBinding(destructor);
@ -108,7 +100,7 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
}
if(!isGlobal) {
ICPPFunction deleteOperator = findOperatorFunction(nestedType);
ICPPFunction deleteOperator = CPPSemantics.findOverloadedOperator(this);
if(deleteOperator != null) {
CPPASTImplicitName deleteName = new CPPASTImplicitName(deleteOperator.getNameCharArray(), this);
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
public boolean accept( ASTVisitor action ){
if( action.shouldVisitExpressions ){

View file

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

View file

@ -219,7 +219,7 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
if (t instanceof IFunctionType) {
return ((IFunctionType) t).getReturnType();
} else if (t instanceof ICPPClassType) {
ICPPFunction op = CPPSemantics.findOperator(this, (ICPPClassType) t);
ICPPFunction op = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
if (op != null) {
if(overload != null)
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.IASTTypeId;
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.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.parser.IProblem;
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.IASTAmbiguityParent;
@ -180,17 +177,7 @@ public class CPPASTNewExpression extends ASTNode implements
public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) {
IType type = getExpressionType();
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);
ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this);
if(operatorFunction == null) {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
}
@ -205,17 +192,6 @@ public class CPPASTNewExpression extends ASTNode implements
return implicitNames;
}
// 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);
}
/**

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.ICPPASTUnaryExpression;
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.ICPPMember;
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++
*/
public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpression, IASTAmbiguityParent {
private static final ICPPFunction UNINITIALIZED = new CPPFunction(null);
private int op;
private IASTExpression operand;
private ICPPFunction overload = UNINITIALIZED;
private IASTImplicitName[] implicitNames = null;
public CPPASTUnaryExpression() {
@ -155,13 +156,46 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
public ICPPFunction getOverload() {
if(operand == null)
return null;
if(getExpressionType() instanceof CPPPointerToMemberType) // then it must be the builtin &
return null;
IType type = operand.getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF);
return findOperatorFunction(type);
if (overload != UNINITIALIZED)
return overload;
overload = CPPSemantics.findOverloadedOperator(this);
if(operand != null && op == op_amper && computePointerToMemberType() instanceof CPPPointerToMemberType)
overload = null;
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();
if (op == op_amper) { // check for pointer to member
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();
}
}
}
IType ptm = computePointerToMemberType();
if(ptm != null)
return ptm;
IType type= operand.getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF);
IType operator = findOperatorReturnType(type);
IType operator = findOperatorReturnType();
if(operator != null)
return operator;
IType type= operand.getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF);
return new CPPPointerType(type);
}
@ -222,7 +232,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
return type;
}
try {
IType operator = findOperatorReturnType(type);
IType operator = findOperatorReturnType();
if(operator != null) {
return operator;
} else if (type instanceof IPointerType || type instanceof IArrayType) {
@ -239,7 +249,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
IType type= operand.getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF);
IType operator = findOperatorReturnType(type);
IType operator = findOperatorReturnType();
if(operator != null) {
return operator;
}
@ -254,8 +264,8 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
}
private IType findOperatorReturnType(IType type) {
ICPPFunction operatorFunction = findOperatorFunction(type);
private IType findOperatorReturnType() {
ICPPFunction operatorFunction = getOverload();
if(operatorFunction != null) {
try {
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.ICPPASTDeclSpecifier;
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.ICPPASTForStatement;
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.index.IIndexBinding;
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.CharArrayObjectMap;
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.CPPASTTranslationUnit;
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.CPPNamespace;
@ -248,8 +249,10 @@ public class CPPSemantics {
return postResolution(binding, 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
try {
boolean doKoenig= true;
@ -753,13 +756,14 @@ public class CPPSemantics {
scope= (ICPPScope) data.tu.mapToASTScope(((IIndexScope) scope));
}
if (!data.usingDirectivesOnly) {
if (!data.usingDirectivesOnly && !(data.ignoreMembers && scope instanceof ICPPClassScope)) {
IBinding[] bindings= getBindingsFromScope(scope, fileSet, data);
if (data.typesOnly) {
removeObjects(bindings);
}
mergeResults(data, bindings, true);
// store using-directives found in this block or namespace for later use.
if ((!data.hasResults() || !data.qualified() || data.contentAssist) && scope instanceof ICPPNamespaceScope) {
final ICPPNamespaceScope blockScope= (ICPPNamespaceScope) scope;
@ -1928,14 +1932,15 @@ public class CPPSemantics {
return;
final boolean def = data.forFunctionDeclaration();
int numArgs= data.getFunctionArgumentCount();
if (def && numArgs == 1) {
int argumentCount = data.getFunctionArgumentCount();
if (def && argumentCount == 1) {
// check for parameter of type void
final IType[] argTypes = data.getFunctionArgumentTypes();
if (argTypes.length == 1) {
IType t= getNestedType(argTypes[0], TDEF);
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.
final IType[] parameterTypes = function.getType().getParameterTypes();
int numPars = parameterTypes.length;
int numArgs = argumentCount;
if(function instanceof ICPPMethod && data.firstArgIsImpliedMethodArg)
numArgs--;
if (numArgs < 2 && numPars == 1) {
// check for void
IType t = getNestedType(parameterTypes[0], TDEF);
@ -2059,15 +2069,13 @@ public class CPPSemantics {
IFunction bestFn = null; // the best function
Cost[] bestFnCost = null; // the cost of the best function
boolean bestHasAmbiguousParam = false; // bestFn has an ambiguous parameter conversion (not ok, ambiguous)
final IType thisType = data.getImpliedObjectArgument();
// Loop over all functions
for (IFunction fn : fns) {
if (fn == null || bestFn == fn)
continue;
final Cost[] fnCost= costForFunctionCall(fn, thisType, argTypes, args, allowUDC);
final Cost[] fnCost= costForFunctionCall(fn, argTypes, args, allowUDC, data);
if (fnCost == null)
continue;
@ -2166,8 +2174,7 @@ public class CPPSemantics {
return bestFn;
}
private static Cost[] costForFunctionCall(IFunction fn, IType thisType, IType[] argTypes, IASTExpression[] args,
boolean allowUDC) throws DOMException {
private static Cost[] costForFunctionCall(IFunction fn, IType[] argTypes, IASTExpression[] args, boolean allowUDC, LookupData data) throws DOMException {
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
if (ftype == null)
return null;
@ -2176,8 +2183,12 @@ public class CPPSemantics {
final IType[] paramTypes= ftype.getParameterTypes();
if (fn instanceof ICPPMethod && !(fn instanceof ICPPConstructor)) {
implicitType = getImplicitType((ICPPMethod) fn, ftype.isConst(), ftype.isVolatile());
if(data.firstArgIsImpliedMethodArg) {
argTypes = ArrayUtil.removeFirst(argTypes);
args = ArrayUtil.removeFirst(args);
}
}
int k= 0;
Cost cost;
final int sourceLen= argTypes.length;
@ -2186,6 +2197,9 @@ public class CPPSemantics {
result= new Cost[sourceLen];
} else {
result= new Cost[sourceLen+1];
final IType thisType = data.getImpliedObjectArgument();
if (ASTInternal.isStatic(fn, false)) {
// 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
cost = new Cost(thisType, implicitType, Rank.IDENTITY);
@ -2559,6 +2573,9 @@ public class CPPSemantics {
if (!fieldReference.isPointerDereference())
return type;
char[] operatorName = OverloadableOperator.ARROW.toCharArray();
IASTExpression[] args = {null};
// bug 205964: as long as the type is a class type, recurse.
// Be defensive and allow a max of 10 levels.
boolean foundOperator= false;
@ -2594,7 +2611,7 @@ public class CPPSemantics {
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
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)
break;
@ -2615,112 +2632,99 @@ 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;
public static ICPPFunction findOverloadedOperator(IASTArraySubscriptExpression exp) {
char[] name = OverloadableOperator.BRACKET.toCharArray();
IASTExpression[] args = { null, exp.getSubscriptExpression() };
IType type1 = exp.getArrayExpression().getExpressionType();
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
return findOverloadedOperator(exp, args, ultimateType1, name, false);
}
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);
CPPASTName astName = new CPPASTName();
astName.setParent(exp);
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
LookupData data = new LookupData(astName);
data.forceQualified = true;
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 {
IType type = exp.getExpressionType();
if(type instanceof IProblem)
return null;
}
try {
lookup(data, scope);
IBinding binding = resolveAmbiguities(data, astName);
if (binding instanceof ICPPFunction)
return (ICPPFunction) binding;
type = ((IPointerType)type).getType();
} 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) {
}
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) {
public static ICPPFunction findDestructor(ICPPASTDeleteExpression expr) {
ICPPClassType cls = getNestedClassType(expr);
if(cls == null)
return null;
IScope scope = null;
try {
scope = cls.getCompositeScope();
@ -2749,120 +2753,145 @@ public class CPPSemantics {
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) {
OverloadableOperator operator = OverloadableOperator.fromUnaryExpression(exp);
IASTExpression[] args = null;
int op = exp.getOperator();
if(op == IASTUnaryExpression.op_postFixDecr || op == IASTUnaryExpression.op_postFixIncr)
if(exp.getOperand() == null)
return null;
OverloadableOperator op = OverloadableOperator.fromUnaryExpression(exp);
if(op == null)
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 };
else
args = new IASTExpression[] { exp.getOperand() };
return findOverloadedOperator(exp, operator, args);
}
IType type = exp.getOperand().getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF | CVQ);
/**
* 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()]));
return findOverloadedOperator(exp, args, type, op.toCharArray(), true);
}
private static ICPPFunction findOverloadedOperator(IASTExpression exp, OverloadableOperator operator, IASTExpression[] args) {
if (operator == null) {
return null;
}
IScope scope = CPPVisitor.getContainingScope(exp);
if (scope == null)
public static ICPPFunction findOverloadedOperator(IASTBinaryExpression exp) {
OverloadableOperator op = OverloadableOperator.fromBinaryExpression(exp);
if(op == null)
return null;
CPPASTName astName = new CPPASTName();
astName.setParent(exp);
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
astName.setName(operator.toCharArray());
LookupData data = new LookupData(astName);
data.setFunctionArguments(args);
try {
lookup(data, scope);
IBinding binding = resolveAmbiguities(data, astName);
IType op1type = SemanticUtil.getUltimateTypeUptoPointers(exp.getOperand1().getExpressionType());
IASTExpression[] args = new IASTExpression[] { exp.getOperand1(), exp.getOperand2() } ;
boolean lookupNonMember = false;
if(exp.getOperator() != IASTBinaryExpression.op_assign) {
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);
}
if (binding instanceof ICPPFunction)
return (ICPPFunction) binding;
} catch (DOMException e) {}
} catch (DOMException e) {
}
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 {
return findBindings(scope, name.toCharArray(), qualified, null);

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.ICPPClassScope;
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.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
@ -104,7 +105,9 @@ public class LookupData {
public boolean considerConstructors = false;
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 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 Object foundItems = null;
private Object[] functionArgs;
@ -370,6 +373,19 @@ public class LookupData {
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
*/