1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

bug 265375 - implicit names API and support for overloaded operator references

This commit is contained in:
Mike Kucera 2009-03-12 14:19:46 +00:00
parent 39de0e3a61
commit 5fcb227983
36 changed files with 1640 additions and 138 deletions

View file

@ -50,7 +50,8 @@ public class ASTComparer extends Assert {
"isDefinition",
"isReference",
"isAssociatedWithLastName",
"getNestingLevel"
"getNestingLevel",
"getImplicitNames"
));

View file

@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
* Andrew Ferguson (Symbian)
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
@ -35,8 +36,11 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
@ -76,6 +80,7 @@ import org.eclipse.cdt.core.parser.tests.scanner.FileCodeReaderFactory;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser;
import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor;
import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser;
@ -477,6 +482,10 @@ public class AST2BaseTest extends BaseTestCase {
this.tu= parse(contents, isCPP ? ParserLanguage.CPP : ParserLanguage.C, true, false);
}
public IASTTranslationUnit getTranslationUnit() {
return tu;
}
public IBinding assertProblem(String section, int len) {
IBinding binding= binding(section, len);
assertTrue("Non-ProblemBinding for name: " + section.substring(0, len),
@ -497,15 +506,65 @@ public class AST2BaseTest extends BaseTestCase {
}
public void assertNoName(String section, int len) {
final int offset = contents.indexOf(section);
assertTrue(offset >= 0);
final String selection = section.substring(0, len);
IASTName name= tu.getNodeSelector(null).findName(offset, len);
IASTName name= findName(section,len,false);
if (name != null) {
String selection = section.substring(0, len);
fail("Found unexpected \""+selection+"\": " + name.resolveBinding());
}
}
/**
* Asserts that there is exactly one name at the given location and that
* it resolves to the given type of binding.
*/
public IASTImplicitName assertImplicitName(String section, int len, Class<?> bindingClass) {
IASTName name = findName(section,len,true);
final String selection = section.substring(0, len);
assertNotNull("did not find \""+selection+"\"", name);
assertInstance(name, IASTImplicitName.class);
IASTImplicitNameOwner owner = (IASTImplicitNameOwner) name.getParent();
IASTImplicitName[] implicits = owner.getImplicitNames();
assertNotNull(implicits);
if(implicits.length > 1) {
boolean found = false;
for(IASTImplicitName n : implicits) {
if(((ASTNode)n).getOffset() == ((ASTNode)name).getOffset()) {
assertFalse(found);
found = true;
}
}
assertTrue(found);
}
assertEquals(selection, name.getRawSignature());
IBinding binding = name.resolveBinding();
assertNotNull(binding);
assertInstance(binding, bindingClass);
return (IASTImplicitName) name;
}
public void assertNoImplicitName(String section, int len) {
IASTName name = findName(section,len,true);
final String selection = section.substring(0, len);
assertNull("found name \""+selection+"\"", name);
}
public IASTImplicitName[] getImplicitNames(String section, int len) {
IASTName name = findName(section,len,true);
IASTImplicitNameOwner owner = (IASTImplicitNameOwner) name.getParent();
IASTImplicitName[] implicits = owner.getImplicitNames();
return implicits;
}
private IASTName findName(String section, int len, boolean implicit) {
final int offset = contents.indexOf(section);
assertTrue(offset >= 0);
IASTNodeSelector selector = tu.getNodeSelector(null);
return implicit ? selector.findImplicitName(offset, len) : selector.findName(offset, len);
}
private String renderProblemID(int i) {
try {
for (Field field : IProblemBinding.class.getDeclaredFields()) {
@ -536,10 +595,8 @@ public class AST2BaseTest extends BaseTestCase {
}
private IBinding binding(String section, int len) {
final int offset = contents.indexOf(section);
assertTrue(offset >= 0);
IASTName name = findName(section, len,false);
final String selection = section.substring(0, len);
IASTName name= tu.getNodeSelector(null).findName(offset, len);
assertNotNull("did not find \""+selection+"\"", name);
assertEquals(selection, name.getRawSignature());

View file

@ -0,0 +1,385 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.parser.ParserLanguage;
/**
*
*/
public class AST2CPPImplicitNameTests extends AST2BaseTest {
public AST2CPPImplicitNameTests() {
}
public AST2CPPImplicitNameTests(String name) {
super(name);
}
public static TestSuite suite() {
return suite(AST2CPPImplicitNameTests.class);
}
public IASTImplicitName[] getImplicitNames(IASTTranslationUnit tu, String contents, String section, int len) {
final int offset = contents.indexOf(section);
assertTrue(offset >= 0);
IASTNodeSelector selector = tu.getNodeSelector(null);
IASTImplicitName firstImplicit = selector.findImplicitName(offset, len);
IASTImplicitNameOwner owner = (IASTImplicitNameOwner) firstImplicit.getParent();
IASTImplicitName[] implicits = owner.getImplicitNames();
return implicits;
}
// class point {
// int x,y;
// public:
// point operator+(point);
// point operator-(point);
// point operator-();
// point operator+=(int);
// };
// point operator*(point,point);
// point operator/(point,point);
//
// point test(point p) {
// p += 5;
// p + p - p * p / p;
// p << 6;
// -p;
// +p;
// }
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);
ba.assertNoImplicitName("<< 6", 2);
ba.assertImplicitName("-p;", 1, ICPPMethod.class);
ba.assertNoImplicitName("+p;", 1);
}
//struct X {};
//
//template <class T> class auto_ptr {
// T* ptr;
//public:
// explicit auto_ptr(T* p = 0) : ptr(p) {}
// T& operator*() {return *ptr;}
//};
//
//void test() {
// auto_ptr<X> x(new X());
// *x; //1
// int *y;
// *y; //2
//}
public void testPointerDereference() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertImplicitName("*x;", 1, ICPPFunction.class);
ba.assertNoImplicitName("*y; //2", 1);
}
// struct X {};
// struct Y {
// X x;
// };
//
// X* operator&(X);
// X* operator&(Y);
//
// void test(X x, Y y) {
// X (Y::*px1) = &Y::x; // not the overloaded operator
// X *px2 = &y; // overloaded
// }
public void testPointerToMember() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNoImplicitName("&Y::x;", 1);
ba.assertImplicitName("&y;", 1, ICPPFunction.class);
}
// class A {
// public:
// void doA() {}
// };
//
// class FirstLevelProxy {
// public:
// A* operator->() {A *a = new A(); return a;} // leaky
// void doFLP() {}
// };
//
// class SecondLevelProxy {
// public:
// FirstLevelProxy operator->() {FirstLevelProxy p; return p;}
// void doSLP() {}
// };
//
// int main(int argc, char **argv) {
// SecondLevelProxy p2;
// p2->doA();
// }
public void testArrowOperator() throws Exception {
String contents = getAboveComment();
IASTTranslationUnit tu = parse(contents, ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
IASTImplicitName[] implicits = getImplicitNames(tu, contents, "->doA();", 2);
assertNotNull(implicits);
assertEquals(2, implicits.length);
assertSame(implicits[1].getBinding(), col.getName(4).resolveBinding());
assertSame(implicits[0].getBinding(), col.getName(12).resolveBinding());
}
// struct A {
// int x;
// };
//
// struct B {
// A& operator++(); // prefix
// };
// A operator++(B, int); // postfix
//
// void test(B p1, B p2) {
// (p1++).x; //1
// (++p1).x; //2
// }
public void testUnaryPrefixAndPostfix() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertImplicitName("++).x; //1", 2, ICPPFunction.class);
ba.assertImplicitName("++p1).x; //2", 2, ICPPMethod.class);
}
// struct A {};
// struct B {};
// struct C {};
// struct D {};
//
// C operator,(A,B);
// D operator,(C,C);
//
// int test(A a, B b, C c, D d) {
// // should be treated like (((a , b) , c) , d)
// a , b , c , d; // expr
// }
//
// int main(int argc, char **argv) {
// A a;
// B b;
// C c;
// D d;
// test(a , b , c , d); // func
// }
public void _testCommaOperator() 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);
ba.assertNoImplicitName(", c , d); // func", 1);
ba.assertNoImplicitName(", d); // func", 1);
IASTImplicitName opAB = ba.assertImplicitName(", b , c , d; // expr", 1, ICPPFunction.class);
IASTImplicitName opCC = ba.assertImplicitName(", c , d; // expr", 1, ICPPFunction.class);
ba.assertNoImplicitName(", d; // expr", 1);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
assertSame(opAB.resolveBinding(), col.getName(5).resolveBinding());
assertSame(opCC.resolveBinding(), col.getName(9).resolveBinding());
}
// struct X {
// int operator()(bool);
// int operator()();
// };
//
// int test(X x) {
// bool b = true;
// x(b); // 1
// x(); // 2
// }
public void testFunctionCallOperator() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
IASTImplicitName n1 = ba.assertImplicitName("(b); // 1", 1, ICPPMethod.class);
IASTImplicitName n2 = ba.assertImplicitName("); // 1", 1, ICPPMethod.class);
assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate());
// there should be no overlap
ba.assertNoImplicitName("b); // 1", 1);
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());
}
// struct A {};
// struct B {};
//
// // error operator= must be a non-static member function
// A& operator=(const B&, const A&);
//
// int main(int argc, char **argv) {
// A a;
// B b;
// b = a; // should not resolve
// }
public void testCopyAssignmentOperator() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNoImplicitName("= a;", 1);
}
// struct A {
// const char& operator[](int pos) const;
// char& operator[](int pos);
// };
//
// void func(const char& c);
// void func(char& c);
//
// void test(const A& x, A& y) {
// int q;
// func(x[0]); //1
// func(y[q]); //2
// }
public void testArraySubscript() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
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());
n1 = ba.assertImplicitName("[q]); //2", 1, ICPPMethod.class);
ba.assertNoImplicitName("q]); //2", 1);
n2 = ba.assertImplicitName("]); //2", 1, ICPPMethod.class);
assertSame(n1.resolveBinding(), n2.resolveBinding());
assertFalse(n1.isAlternate());
assertTrue(n2.isAlternate());
}
// struct X {
// ~X();
// void operator delete();
// void operator delete[]();
// };
//
// int test(X* x) {
// delete x;
// X* xs = new X[5];
// delete[] x;
// }
public void testDelete() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
IASTImplicitName[] names = ba.getImplicitNames("delete x;", 6);
assertEquals(2, names.length);
IASTImplicitName destructor = names[0];
IASTImplicitName delete = names[1];
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
assertSame(col.getName(1).resolveBinding(), destructor.resolveBinding());
assertSame(col.getName(2).resolveBinding(), delete.resolveBinding());
names = ba.getImplicitNames("delete[] x;", 6);
assertEquals(1, names.length);
assertSame(col.getName(3).resolveBinding(), names[0].resolveBinding());
}
// struct X {}
// int test(X *x) {
// X* xs = new X[5];
// delete[] x;
// }
public void _testImplicitNewAndDelete() throws Exception {
BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true);
ba.assertNoImplicitName("new X", 3);
ba.assertNoImplicitName("delete[]", 6);
}
// typedef long unsigned int size_t
// struct nothrow_t {};
// extern const nothrow_t nothrow;
// void *operator new(size_t, const nothrow_t&);
// void *operator new[](size_t, const nothrow_t&);
// void *operator new[](size_t, int, int);
// struct X {};
//
// int test() {
// X *fp = new (nothrow) X;
// int* p = new (nothrow) int[5];
// int* p2 = new (5,6) int[5];
// }
public void testNew() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
IASTImplicitName n1 = ba.assertImplicitName("new (nothrow) X", 3, ICPPFunction.class);
IASTImplicitName n2 = ba.assertImplicitName("new (nothrow) int", 3, ICPPFunction.class);
IASTImplicitName n3 = ba.assertImplicitName("new (5,6) int", 3, ICPPFunction.class);
IASTTranslationUnit tu = ba.getTranslationUnit();
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
assertSame(col.getName(4).resolveBinding(), n1.resolveBinding());
assertSame(col.getName(9).resolveBinding(), n2.resolveBinding());
assertSame(col.getName(14).resolveBinding(), n3.resolveBinding());
}
// int test() {
// throw;
// }
public void testEmptyThrow() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
ba.assertNoImplicitName("throw;", 5);
}
}

View file

@ -27,6 +27,7 @@ public class DOMParserTestSuite extends TestCase {
suite.addTest(AST2Tests.suite());
suite.addTestSuite(GCCTests.class);
suite.addTest(AST2CPPTests.suite());
suite.addTest(AST2CPPImplicitNameTests.suite());
suite.addTest(AST2TemplateTests.suite());
suite.addTestSuite(QuickParser2Tests.class);
suite.addTest(CompleteParser2Tests.suite());
@ -53,6 +54,7 @@ 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

@ -15,8 +15,6 @@ package org.eclipse.cdt.core.suite;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.cdescriptor.tests.CDescriptorTests;
import org.eclipse.cdt.core.cdescriptor.tests.CDescriptorOldTests;
import org.eclipse.cdt.core.internal.errorparsers.tests.ErrorParserTests;
import org.eclipse.cdt.core.internal.tests.PositionTrackerTests;
import org.eclipse.cdt.core.internal.tests.ResourceLookupTests;
@ -56,8 +54,8 @@ public class AutomatedIntegrationSuite extends TestSuite {
final AutomatedIntegrationSuite suite = new AutomatedIntegrationSuite();
// Add all success tests
suite.addTest(CDescriptorTests.suite());
suite.addTest(CDescriptorOldTests.suite());
//suite.addTest(CDescriptorTests.suite());
//suite.addTest(CDescriptorOldTests.suite());
suite.addTest(ErrorParserTests.suite());
suite.addTest(ParserTestSuite.suite());
suite.addTest(AllCoreTests.suite());

View file

@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Yuan Zhang / Beth Tibbitts (IBM Research)
* Markus Schorn (Wind River Systems)
* Mike Kucera (IBM) - implicit names
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
@ -139,6 +140,23 @@ public abstract class ASTVisitor {
*/
public boolean shouldVisitAmbiguousNodes = false;
/**
* Implicit names are created to allow implicit bindings to be resolved,
* normally they are not visited, set this flag to true to visit them.
* @since 5.1
*/
public boolean shouldVisitImplicitNames = false;
/**
* Sometimes more than one implicit name is created for a binding,
* set this flag to true to visit more than one name for an implicit binding.
* @since 5.1
*/
public boolean shouldVisitImplicitNameAlternates = false;
/**
* Creates a visitor that does not visit any kind of node per default.
*/
@ -149,7 +167,9 @@ public abstract class ASTVisitor {
/**
* Creates a visitor.
* @param visitNodes whether visitor is setup to visit all nodes per default, except
* ambiguous nodes ({@link #shouldVisitAmbiguousNodes}) and inactive nodes ({@link #includeInactiveNodes}).
* ambiguous nodes ({@link #shouldVisitAmbiguousNodes}),
* inactive nodes ({@link #includeInactiveNodes}),
* and implicit names (@link {@link #shouldVisitImplicitNames}).
* @since 5.1
*/
public ASTVisitor(boolean visitNodes) {

View file

@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mike Kucera (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
/**
* An implicit name is used to resolve uses of implicit bindings, such as overloaded operators.
*
* Implicit names are not generated unless they resolve to something.
*
* @see ASTVisitor#shouldVisitImplicitNames
* @since 5.1
*/
public interface IASTImplicitName extends IASTName {
public static final IASTImplicitName[] EMPTY_NAME_ARRAY = {};
/**
* {@inheritDoc}
* Redeclared with strengthened postcondition.
*
* Will not return null or a problem binding.
* Implicit names are not generated unless they resolve to something.
*/
public IBinding resolveBinding();
/**
* Returns true if this node is an alternate.
*
* Sometimes more than one implicit name is generated for the same binding
* but with different offsets, when this happens the additional names
* generated are considered alternates.
*
* @see ASTVisitor#shouldVisitImplicitNameAlternates
*/
public boolean isAlternate();
/**
* Convenience method that returns true if this
* name represents an overloaded operator.
*/
public boolean isOperator();
/**
* This method is not supported on implicit names.
*
* Implicit names are not copied when an AST is copied,
* instead the implicit names are regenerated when needed.
*
* @throws UnsupportedOperationException always
*/
IASTName copy() throws UnsupportedOperationException;
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mike Kucera (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
/**
* An implicit name generated on demand.
* @since 5.1
*/
public interface IASTImplicitNameOwner extends IASTNode {
public static final ASTNodeProperty IMPLICIT_NAME =
new ASTNodeProperty("ICPPASTImplicitNameOwner.IMPLICIT_NAME"); //$NON-NLS-1$
public IASTImplicitName[] getImplicitNames();
}

View file

@ -215,7 +215,7 @@ public interface IASTNode {
public boolean isActive();
/**
* Returns a copy of the tree rooted at this node.
* Returns a mutable copy of the tree rooted at this node.
* The following postconditions hold:
*
* <code>
@ -226,9 +226,11 @@ public interface IASTNode {
*
* Preprocessor nodes do not currently support being copied.
*
* Implicit name nodes are not copied, instead they can be regenerated
* if required.
*
* @since 5.1
* @throws UnsupportedOperationException if this node or one of its descendants
* does not support copying
* @throws UnsupportedOperationException if this node or one of its descendants does not support copying
*/
public IASTNode copy();
}

View file

@ -23,19 +23,42 @@ public interface IASTNodeSelector {
/**
* Returns the name for the exact given range, or <code>null</code> if there is no such node.
* Will not return an implicit name.
*/
IASTName findName(int offset, int length);
/**
* Returns the smallest name enclosing the given range, or <code>null</code> if there is no such node.
* Will not return an implicit name.
*/
IASTName findEnclosingName(int offset, int length);
/**
* Returns the first name contained in the given range, or <code>null</code> if there is no such node.
* Will not return an implicit name.
*/
IASTName findFirstContainedName(int offset, int length);
/**
* Returns the implicit name for the exact given range, or <code>null</code> if there is no such node.
*
* Note that there can be more than one implicit name in the same location.
* The implicit name's parent can be used to get all the names at the location.
*
* @since 5.1
*/
IASTImplicitName findImplicitName(int offset, int length);
/**
* Returns the first implicit name enclosing the given range.
*
* Note that there can be more than one implicit name in the same location.
* The implicit name's parent can be used to get all the names at the location.
*
* @since 5.1
*/
IASTImplicitName findEnclosingImplicitName(int offset, int length);
/**
* Returns the node for the exact given range, or <code>null</code> if there is no such node.
* <p>

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mike Kucera (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* @since 5.1
*/
public interface ICPPASTArraySubscriptExpression extends IASTArraySubscriptExpression, IASTImplicitNameOwner {
public ICPPASTArraySubscriptExpression copy();
}

View file

@ -7,10 +7,12 @@
*
* Contributors:
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* C++ adds a few more binary expressions over C.
@ -18,7 +20,7 @@ import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTBinaryExpression extends IASTBinaryExpression {
public interface ICPPASTBinaryExpression extends IASTBinaryExpression, IASTImplicitNameOwner {
/**
* <code>op_pmdot</code> pointer-to-member field dereference.

View file

@ -7,11 +7,13 @@
*
* Contributors:
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* This interface represents a delete expression. delete [] operand;
@ -19,7 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTDeleteExpression extends IASTExpression {
public interface ICPPASTDeleteExpression extends IASTExpression, IASTImplicitNameOwner {
/**
* <code>OPERAND</code> is the expression representing the pointer being

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mike Kucera (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* @since 5.1
*/
public interface ICPPASTExpressionList extends IASTExpressionList, IASTImplicitNameOwner {
public ICPPASTExpressionList copy();
}

View file

@ -7,10 +7,12 @@
*
* Contributors:
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* Certain field references in C++ require the use the keyword template to
@ -19,7 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTFieldReference extends IASTFieldReference {
public interface ICPPASTFieldReference extends IASTFieldReference, IASTImplicitNameOwner {
/**
* Was template keyword used?

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mike Kucera (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* @since 5.1
*/
public interface ICPPASTFunctionCallExpression extends IASTFunctionCallExpression, IASTImplicitNameOwner {
ICPPASTFunctionCallExpression copy();
}

View file

@ -8,12 +8,14 @@
* Contributors:
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* This interface represents a new expression.
@ -21,7 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTNewExpression extends IASTExpression {
public interface ICPPASTNewExpression extends IASTExpression, IASTImplicitNameOwner {
/**
* Is this a ::new expression?
@ -110,6 +112,14 @@ public interface ICPPASTNewExpression extends IASTExpression {
*/
public void setIsNewTypeId(boolean value);
/**
* Returns true if this expression is allocating an array.
* @since 5.1
*/
public boolean isArrayAllocation();
/**
* Expressions that go inside array brackets.
*/

View file

@ -7,16 +7,18 @@
*
* Contributors:
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
/**
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTUnaryExpression extends IASTUnaryExpression {
public interface ICPPASTUnaryExpression extends IASTUnaryExpression, IASTImplicitNameOwner {
/**
* <code>op_throw</code> throw exp

View file

@ -156,4 +156,11 @@ public interface ICPPNodeFactory extends INodeFactory {
public ICPPASTTemplatedTypeTemplateParameter newTemplatedTypeTemplateParameter(IASTName name, IASTExpression defaultValue);
public IASTProblemTypeId newProblemTypeId(IASTProblem problem);
public ICPPASTExpressionList newExpressionList();
public ICPPASTArraySubscriptExpression newArraySubscriptExpression(IASTExpression arrayExpr, IASTExpression subscript);
public ICPPASTFunctionCallExpression newFunctionCallExpression(IASTExpression idExpr, IASTExpression argList);
}

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
@ -119,72 +120,51 @@ public class ASTNodeSelector implements IASTNodeSelector {
return nodeSpec.getBestNode();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getFirstContainedNode(int, int)
*/
public IASTNode findFirstContainedNode(int offset, int length) {
return findNode(offset, length, Relation.FIRST_CONTAINED, IASTNode.class);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int)
*/
public IASTNode findNode(int offset, int length) {
return findNode(offset, length, Relation.EXACT_MATCH, IASTNode.class);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getSurroundingNode(int, int)
*/
public IASTNode findEnclosingNode(int offset, int length) {
return findNode(offset, length, Relation.ENCLOSING, IASTNode.class);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getFirstContainedNode(int, int)
*/
public IASTNode findFirstContainedNodeInExpansion(int offset, int length) {
return findNode(offset, length, Relation.FIRST_CONTAINED, IASTNode.class, true);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int)
*/
public IASTNode findNodeInExpansion(int offset, int length) {
return findNode(offset, length, Relation.EXACT_MATCH, IASTNode.class, true);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getSurroundingNode(int, int)
*/
public IASTNode findEnclosingNodeInExpansion(int offset, int length) {
return findNode(offset, length, Relation.ENCLOSING, IASTNode.class, true);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getFirstContainedNode(int, int)
*/
public IASTName findFirstContainedName(int offset, int length) {
return findNode(offset, length, Relation.FIRST_CONTAINED, IASTName.class);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getNode(int, int)
*/
public IASTName findName(int offset, int length) {
return findNode(offset, length, Relation.EXACT_MATCH, IASTName.class);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#getSurroundingNode(int, int)
*/
public IASTName findEnclosingName(int offset, int length) {
return findNode(offset, length, Relation.ENCLOSING, IASTName.class);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IASTNodeSelector#findSurrundingMacroExpansion(int, int)
*/
public IASTImplicitName findImplicitName(int offset, int length) {
return findNode(offset, length, Relation.EXACT_MATCH, IASTImplicitName.class);
}
public IASTImplicitName findEnclosingImplicitName(int offset, int length) {
return findNode(offset, length, Relation.ENCLOSING, IASTImplicitName.class);
}
public IASTPreprocessorMacroExpansion findEnclosingMacroExpansion(int offset, int length) {
return findNode(offset, length, Relation.ENCLOSING, IASTPreprocessorMacroExpansion.class);
}

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
@ -31,6 +32,10 @@ public class FindNodeForOffsetAction extends ASTGenericVisitor {
shouldVisitNames = true;
shouldVisitDeclarations= true;
includeInactiveNodes= true;
// only visit implicit names if asked
shouldVisitImplicitNames =
shouldVisitImplicitNameAlternates = nodeSpec.requiresClass(IASTImplicitName.class);
}
@Override

View file

@ -1,23 +1,26 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera (IBM)
*******************************************************************************/
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.IASTArraySubscriptExpression;
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.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;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@ -28,11 +31,12 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/**
* @author jcamelon
*/
public class CPPASTArraySubscriptExpression extends ASTNode implements IASTArraySubscriptExpression, IASTAmbiguityParent {
public class CPPASTArraySubscriptExpression extends ASTNode implements ICPPASTArraySubscriptExpression, IASTAmbiguityParent {
private IASTExpression subscriptExp;
private IASTExpression arrayExpression;
private IASTImplicitName[] implicitNames = null;
public CPPASTArraySubscriptExpression() {
}
@ -77,6 +81,41 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements IASTArray
}
}
public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) {
ICPPFunction overload = getOverload();
if(overload == null)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
// create separate implicit names for the two brackets
CPPASTImplicitName n1 = new CPPASTImplicitName(OverloadableOperator.BRACKET, this);
n1.setBinding(overload);
n1.computeOperatorOffsets(arrayExpression, true);
CPPASTImplicitName n2 = new CPPASTImplicitName(OverloadableOperator.BRACKET, this);
n2.setBinding(overload);
n2.computeOperatorOffsets(subscriptExp, true);
n2.setAlternate(true);
implicitNames = new IASTImplicitName[] { n1, n2 };
}
return implicitNames;
}
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;
}
@Override
public boolean accept( ASTVisitor action ){
if( action.shouldVisitExpressions ){
@ -88,9 +127,18 @@ public class CPPASTArraySubscriptExpression extends ASTNode implements IASTArray
}
if( arrayExpression != null )
if( !arrayExpression.accept( action ) ) return false;
IASTImplicitName[] implicits = action.shouldVisitImplicitNames ? getImplicitNames() : null;
if(implicits != null && implicits.length > 0)
if(!implicits[0].accept(action)) return false;
if( subscriptExp != null )
if( !subscriptExp.accept( action ) ) return false;
if(implicits != null && implicits.length > 0)
if(!implicits[1].accept(action)) return false;
if( action.shouldVisitExpressions ){
switch( action.leave( this ) ){
case ASTVisitor.PROCESS_ABORT : return false;

View file

@ -1,12 +1,13 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -14,6 +15,7 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
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;
@ -31,17 +33,17 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/**
* @author jcamelon
*/
public class CPPASTBinaryExpression extends ASTNode implements
ICPPASTBinaryExpression, IASTAmbiguityParent {
private int op;
public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpression, IASTAmbiguityParent {
private int op;
private IASTExpression operand1;
private IASTExpression operand2;
private IType type;
private IASTImplicitName[] implicitNames = null;
public CPPASTBinaryExpression() {
}
@ -95,6 +97,24 @@ public class CPPASTBinaryExpression extends ASTNode implements
}
}
public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) {
ICPPFunction overload = getOverload();
if(overload == null)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
CPPASTImplicitName operatorName = new CPPASTImplicitName(overload.getNameCharArray(), this);
operatorName.setBinding(overload);
operatorName.setOperator(true);
operatorName.computeOperatorOffsets(operand1, true);
implicitNames = new IASTImplicitName[] { operatorName };
}
return implicitNames;
}
@Override
public boolean accept( ASTVisitor action ){
if( action.shouldVisitExpressions ){
@ -106,6 +126,13 @@ public class CPPASTBinaryExpression extends ASTNode implements
}
if( operand1 != null ) if( !operand1.accept( action ) ) return false;
if(action.shouldVisitImplicitNames) {
for(IASTImplicitName name : getImplicitNames()) {
if(!name.accept(action)) return false;
}
}
if( operand2 != null ) if( !operand2.accept( action ) ) return false;
if(action.shouldVisitExpressions ){
@ -140,9 +167,41 @@ public class CPPASTBinaryExpression extends ASTNode implements
return type;
}
/**
* Returns the operator function that is invoked or null
* if it is actually a built-in operator.
*/
public ICPPFunction getOverload() {
// try to find a method
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.
// Check for overloaded operator.
IType type1 = getOperand1().getExpressionType();
IType ultimateType1 = SemanticUtil.getUltimateTypeUptoPointers(type1);
if (ultimateType1 instanceof IProblemBinding) {
@ -158,13 +217,13 @@ public class CPPASTBinaryExpression extends ASTNode implements
}
}
}
IType type2 = getOperand2().getExpressionType();
IType ultimateType2 = SemanticUtil.getUltimateTypeUptoPointers(type2);
if (ultimateType2 instanceof IProblemBinding) {
return type2;
}
if (ultimateType1 instanceof ICPPClassType || ultimateType1 instanceof IEnumeration ||
ultimateType2 instanceof ICPPClassType || ultimateType2 instanceof IEnumeration) {
if(op != op_assign && isUserDefined(ultimateType1) || isUserDefined(ultimateType2)) {
// If at least one of the types is user defined, the operator can be overloaded.
ICPPFunction operator = CPPSemantics.findOverloadedOperator(this);
if (operator != null) {
@ -175,7 +234,8 @@ public class CPPASTBinaryExpression extends ASTNode implements
}
}
}
final int op = getOperator();
switch (op) {
case IASTBinaryExpression.op_lessEqual:
@ -215,4 +275,10 @@ public class CPPASTBinaryExpression extends ASTNode implements
}
return type1;
}
private static boolean isUserDefined(IType type) {
return type instanceof ICPPClassType || type instanceof IEnumeration;
}
}

View file

@ -1,31 +1,40 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
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;
/**
* @author jcamelon
*/
public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpression {
private IASTExpression operand;
private boolean isGlobal;
private boolean isVectored;
private IASTImplicitName[] implicitNames = null;
public CPPASTDeleteExpression() {
}
@ -76,7 +85,76 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
public boolean isVectored() {
return isVectored;
}
/**
* Try to resolve both the destructor and the 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);
if(destructor != null) {
CPPASTImplicitName destructorName = new CPPASTImplicitName(destructor.getNameCharArray(), this);
destructorName.setBinding(destructor);
destructorName.computeOperatorOffsets(operand, false);
names.add(destructorName);
}
}
if(!isGlobal) {
ICPPFunction deleteOperator = findOperatorFunction(nestedType);
if(deleteOperator != null) {
CPPASTImplicitName deleteName = new CPPASTImplicitName(deleteOperator.getNameCharArray(), this);
deleteName.setOperator(true);
deleteName.setBinding(deleteOperator);
deleteName.computeOperatorOffsets(operand, false);
names.add(deleteName);
}
}
if(names.isEmpty())
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
else
implicitNames = names.toArray(new IASTImplicitName[names.size()]);
}
return implicitNames;
}
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 ){
@ -87,6 +165,12 @@ public class CPPASTDeleteExpression extends ASTNode implements ICPPASTDeleteExpr
}
}
if(action.shouldVisitImplicitNames) {
for(IASTImplicitName name : getImplicitNames()) {
if(!name.accept(action)) return false;
}
}
if( operand != null ) if( !operand.accept( action ) ) return false;
if( action.shouldVisitExpressions ){

View file

@ -1,30 +1,44 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera (IBM) - implicit names
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
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;
/**
* @author jcamelon
*/
public class CPPASTExpressionList extends ASTNode implements
IASTExpressionList, IASTAmbiguityParent {
public class CPPASTExpressionList extends ASTNode implements ICPPASTExpressionList, IASTAmbiguityParent {
/**
* Caution: may contain nulls.
* @see CPPASTExpressionList#computeImplicitNames
*/
private IASTImplicitName[] implicitNames;
public CPPASTExpressionList copy() {
CPPASTExpressionList copy = new CPPASTExpressionList();
for(IASTExpression expr : getExpressions())
@ -59,9 +73,19 @@ public class CPPASTExpressionList extends ASTNode implements
}
}
IASTExpression [] exps = getExpressions();
for( int i = 0; i < exps.length; i++ )
if( !exps[i].accept( action ) ) return false;
IASTExpression[] exps = getExpressions();
IASTImplicitName[] implicits = action.shouldVisitImplicitNames ? computeImplicitNames() : null;
for(int i = 0, n = exps.length; i < n; i++) {
if(!exps[i].accept(action)) {
return false;
}
if(i < n-1 && implicits != null && implicits[i] != null) {
if(!implicits[i].accept(action)) {
return false;
}
}
}
if( action.shouldVisitExpressions ){
switch( action.leave( this ) ){
@ -69,10 +93,81 @@ public class CPPASTExpressionList extends ASTNode implements
case ASTVisitor.PROCESS_SKIP : return true;
default : break;
}
}
}
return true;
}
/**
* Returns an array of implicit names where each element of the array
* represents a comma between the expression in the same index and the
* next expression. This array contains null elements as placeholders
* for commas that do not resolve to overloaded operators.
*/
private IASTImplicitName[] computeImplicitNames() {
if(implicitNames == null) {
IASTExpression[] exprs = getExpressions(); // has to be at least two
if(exprs.length < 2)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
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);
if(overload != null) {
CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.COMMA, this);
operatorName.setBinding(overload);
operatorName.computeOperatorOffsets(exprs[i], true);
implicitNames[i] = operatorName;
}
}
}
return implicitNames;
}
public IASTImplicitName[] getImplicitNames() {
return (IASTImplicitName[])ArrayUtil.removeNulls(IASTImplicitName.class, computeImplicitNames());
}
/**
* @param index the index of the first argument
*/
private ICPPFunction getOverload(int index) {
// try to find a method
IASTExpression[] exprs = getExpressions();
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;
}
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) {

View file

@ -1,13 +1,14 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Bryan Wilkinson (QNX)
* John Camelon (IBM) - Initial API and implementation
* Bryan Wilkinson (QNX)
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -18,6 +19,8 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompletionContext;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
@ -27,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
@ -36,13 +40,14 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
* @author jcamelon
*/
public class CPPASTFieldReference extends ASTNode implements
ICPPASTFieldReference, IASTAmbiguityParent, IASTCompletionContext {
ICPPASTFieldReference, IASTAmbiguityParent, IASTCompletionContext, IASTImplicitNameOwner {
private boolean isTemplate;
private IASTExpression owner;
private IASTName name;
private boolean isDeref;
private IASTImplicitName[] implicitNames = null;
public CPPASTFieldReference() {
}
@ -106,6 +111,34 @@ public class CPPASTFieldReference extends ASTNode implements
isDeref = value;
}
public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) {
if(!isDeref)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
// collect the function bindings
List<ICPPFunction> functionBindings = new ArrayList<ICPPFunction>();
try {
CPPSemantics.getChainedMemberAccessOperatorReturnType(this, functionBindings);
} catch (DOMException e) {
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
}
if(functionBindings.isEmpty())
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
// create a name to wrap each binding
implicitNames = new IASTImplicitName[functionBindings.size()];
for(int i = 0, n = functionBindings.size(); i < n; i++) {
CPPASTImplicitName operatorName = new CPPASTImplicitName(OverloadableOperator.ARROW, this);
operatorName.setBinding(functionBindings.get(i));
operatorName.computeOperatorOffsets(owner, true);
implicitNames[i] = operatorName;
}
}
return implicitNames;
}
@Override
public boolean accept(ASTVisitor action) {
if (action.shouldVisitExpressions) {
@ -117,6 +150,13 @@ public class CPPASTFieldReference extends ASTNode implements
}
if (owner != null && !owner.accept(action)) return false;
if(action.shouldVisitImplicitNames) {
for(IASTImplicitName name : getImplicitNames()) {
if(!name.accept(action)) return false;
}
}
if (name != null && !name.accept(action)) return false;
if (action.shouldVisitExpressions) {

View file

@ -1,20 +1,22 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Mike Kucera (IBM) - implicit names
*******************************************************************************/
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.ExpansionOverlapsBoundaryException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
@ -23,24 +25,26 @@ 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.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.parser.IToken;
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.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/**
* @author jcamelon
*/
public class CPPASTFunctionCallExpression extends ASTNode implements
IASTFunctionCallExpression, IASTAmbiguityParent {
ICPPASTFunctionCallExpression, IASTAmbiguityParent {
private IASTExpression functionName;
private IASTExpression parameter;
private IASTImplicitName[] implicitNames = null;
public CPPASTFunctionCallExpression() {
}
@ -84,6 +88,51 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
return parameter;
}
public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) {
ICPPFunction overload = getOperator();
if(overload == null)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
// create separate implicit names for the two brackets
CPPASTImplicitName n1 = new CPPASTImplicitName(OverloadableOperator.PAREN, this);
n1.setBinding(overload);
CPPASTImplicitName n2 = new CPPASTImplicitName(OverloadableOperator.PAREN, this);
n2.setBinding(overload);
n2.setAlternate(true);
if(parameter == null) {
int idEndOffset = ((ASTNode)functionName).getOffset() + ((ASTNode)functionName).getLength();
try {
IToken lparen = functionName.getTrailingSyntax();
IToken rparen = lparen.getNext();
if(lparen.getType() == IToken.tLPAREN)
n1.setOffsetAndLength(idEndOffset + lparen.getOffset(), 1);
else
n1.setOffsetAndLength(idEndOffset + lparen.getEndOffset(), 0);
if(rparen.getType() == IToken.tRPAREN)
n2.setOffsetAndLength(idEndOffset + rparen.getOffset(), 1);
else
n2.setOffsetAndLength(idEndOffset + rparen.getEndOffset(), 0);
} catch(ExpansionOverlapsBoundaryException e) {
n1.setOffsetAndLength(idEndOffset, 0);
n2.setOffsetAndLength(idEndOffset, 0);
}
}
else {
n1.computeOperatorOffsets(functionName, true);
n2.computeOperatorOffsets(parameter, true);
}
implicitNames = new IASTImplicitName[] { n1, n2 };
}
return implicitNames;
}
@Override
public boolean accept( ASTVisitor action ){
if( action.shouldVisitExpressions ){
@ -95,8 +144,18 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
}
if( functionName != null ) if( !functionName.accept( action ) ) return false;
IASTImplicitName[] implicits = action.shouldVisitImplicitNames ? getImplicitNames() : null;
if(implicits != null && implicits.length > 0)
if(!implicits[0].accept(action)) return false;
if( parameter != null ) if( !parameter.accept( action ) ) return false;
if(implicits != null && implicits.length > 0)
if(!implicits[1].accept(action)) return false;
if( action.shouldVisitExpressions ){
switch( action.leave( this ) ){
case ASTVisitor.PROCESS_ABORT : return false;
@ -122,7 +181,17 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
}
}
public ICPPFunction getOperator() {
ICPPFunction[] overload = new ICPPFunction[] {null};
getExpressionType(overload);
return overload[0];
}
public IType getExpressionType() {
return getExpressionType(null);
}
private IType getExpressionType(ICPPFunction[] overload) {
try {
IType t= null;
if (functionName instanceof IASTIdExpression) {
@ -152,6 +221,8 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
} else if (t instanceof ICPPClassType) {
ICPPFunction op = CPPSemantics.findOperator(this, (ICPPClassType) t);
if (op != null) {
if(overload != null)
overload[0] = op;
return op.getType().getReturnType();
}
} else if (t instanceof IPointerType) {

View file

@ -0,0 +1,134 @@
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mike Kucera (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.Arrays;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
public class CPPASTImplicitName extends CPPASTName implements IASTImplicitName {
private boolean alternate = false;
private boolean isOperator = false;
public CPPASTImplicitName(char[] name, IASTNode parent) {
super(name);
setParent(parent);
setPropertyInParent(IASTImplicitNameOwner.IMPLICIT_NAME);
}
public CPPASTImplicitName(OverloadableOperator op, IASTNode parent) {
this(op.toCharArray(), parent);
isOperator = true;
}
@Override
public CPPASTImplicitName copy() {
throw new UnsupportedOperationException();
}
public boolean isAlternate() {
return alternate;
}
public void setAlternate(boolean alternate) {
this.alternate = alternate;
}
@Override
public boolean accept(ASTVisitor action) {
if((!alternate && action.shouldVisitImplicitNames) ||
(alternate && action.shouldVisitImplicitNameAlternates)) {
switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
}
switch (action.leave(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
}
}
return true;
}
@Override
public boolean isDeclaration() {
return false;
}
@Override
public boolean isDefinition() {
return false;
}
@Override
public boolean isReference() {
return true;
}
/**
* Utility method for setting offsets using operator syntax.
*
* @param trailing true for trailing syntax, false for leading syntax
*/
public void computeOperatorOffsets(IASTNode relativeNode, boolean trailing) {
if(relativeNode == null)
return;
IToken first;
try {
first = trailing ? relativeNode.getTrailingSyntax() : relativeNode.getLeadingSyntax();
int offset = ((ASTNode)relativeNode).getOffset() + first.getOffset();
if(trailing)
offset += ((ASTNode)relativeNode).getLength();
OverloadableOperator oo = OverloadableOperator.valueOf(first);
if((first.getNext() == null && oo != null) ||
Arrays.equals(first.getCharImage(), "delete".toCharArray()) || //$NON-NLS-1$
Arrays.equals(first.getCharImage(), "new".toCharArray())) { //$NON-NLS-1$
int length = first.getLength();
setOffsetAndLength(offset, length);
}
else {
setOffsetAndLength(offset, 0);
}
} catch (ExpansionOverlapsBoundaryException e) {
ASTNode parent = (ASTNode) getParent();
setOffsetAndLength(parent.getOffset() + parent.getLength(), 0);
}
}
public void setOperator(boolean isOperator) {
this.isOperator = isOperator;
}
public boolean isOperator() {
return isOperator;
}
}

View file

@ -1,13 +1,14 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Mike Kucera (IBM)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -17,21 +18,25 @@ import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
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.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;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.Assert;
/**
* @author jcamelon
*/
public class CPPASTNewExpression extends ASTNode implements
ICPPASTNewExpression, IASTAmbiguityParent {
@ -43,7 +48,8 @@ public class CPPASTNewExpression extends ASTNode implements
private IASTExpression [] arrayExpressions = null;
private IASTImplicitName[] implicitNames = null;
public CPPASTNewExpression() {
}
@ -171,6 +177,57 @@ public class CPPASTNewExpression extends ASTNode implements
((IASTArrayDeclarator) dtor).addArrayModifier(mod);
}
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);
if(operatorFunction == null) {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
}
else {
CPPASTImplicitName operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
operatorName.setOperator(true);
operatorName.setBinding(operatorFunction);
operatorName.setOffsetAndLength(getOffset(), 3);
implicitNames = new IASTImplicitName[] { operatorName };
}
}
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);
}
/**
* Returns true if this expression is allocating an array.
* @since 5.1
*/
public boolean isArrayAllocation() {
IType t = CPPVisitor.createType(getTypeId());
return t instanceof IArrayType;
}
@Override
public boolean accept( ASTVisitor action ){
if( action.shouldVisitExpressions ){
@ -181,9 +238,16 @@ public class CPPASTNewExpression extends ASTNode implements
}
}
if(action.shouldVisitImplicitNames) {
for(IASTImplicitName name : getImplicitNames()) {
if(!name.accept(action)) return false;
}
}
if( placement != null ) if( !placement.accept( action ) ) return false;
if( typeId != null ) if( !typeId.accept( action ) ) return false;
if( initializer != null ) if( !initializer.accept( action ) ) return false;
if( action.shouldVisitExpressions ){
switch( action.leave( this ) ){

View file

@ -18,6 +18,7 @@ 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.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
@ -48,6 +49,8 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
private int op;
private IASTExpression operand;
private IASTImplicitName[] implicitNames = null;
public CPPASTUnaryExpression() {
}
@ -83,7 +86,29 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
expression.setPropertyInParent(OPERAND);
}
}
public boolean isPostfixOperator() {
return op == op_postFixDecr || op == op_postFixIncr;
}
public IASTImplicitName[] getImplicitNames() {
if(implicitNames == null) {
ICPPFunction overload = getOverload();
if(overload == null)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
CPPASTImplicitName operatorName = new CPPASTImplicitName(overload.getNameCharArray(), this);
operatorName.setOperator(true);
operatorName.setBinding(overload);
operatorName.computeOperatorOffsets(operand, isPostfixOperator());
implicitNames = new IASTImplicitName[] { operatorName };
}
return implicitNames;
}
@Override
public boolean accept(ASTVisitor action) {
if (action.shouldVisitExpressions) {
@ -94,8 +119,22 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
}
}
final boolean isPostfix = isPostfixOperator();
if(!isPostfix && action.shouldVisitImplicitNames) {
for(IASTImplicitName name : getImplicitNames()) {
if(!name.accept(action)) return false;
}
}
if (operand != null && !operand.accept(action)) return false;
if(isPostfix && action.shouldVisitImplicitNames) {
for(IASTImplicitName name : getImplicitNames()) {
if(!name.accept(action)) return false;
}
}
if (action.shouldVisitExpressions) {
switch (action.leave(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
@ -114,18 +153,30 @@ 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);
}
public IType getExpressionType() {
final int op= getOperator();
switch (op) {
case IASTUnaryExpression.op_sizeof:
case op_sizeof:
return CPPVisitor.get_SIZE_T(this);
case IASTUnaryExpression.op_typeid:
case op_typeid:
return CPPVisitor.get_type_info(this);
}
final IASTExpression operand = getOperand();
if (op == IASTUnaryExpression.op_amper) { // check for pointer to member
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) {
@ -164,7 +215,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
}
if (op == IASTUnaryExpression.op_star) {
if (op == op_star) {
IType type= operand.getExpressionType();
type = SemanticUtil.getNestedType(type, TDEF | REF | CVQ);
if (type instanceof IProblemBinding) {
@ -193,7 +244,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
return operator;
}
if(op == IASTUnaryExpression.op_not) {
if(op == op_not) {
return new CPPBasicType(ICPPBasicType.t_bool, 0);
}
if (type instanceof CPPBasicType) {

View file

@ -6,14 +6,13 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Mike Kucera (IBM) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement;
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
@ -27,10 +26,8 @@ import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
@ -52,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
@ -62,8 +60,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
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.ICPPASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
@ -107,8 +107,6 @@ import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTSimpleDeclSpecifier;
/**
* Abstract factory implementation that creates C++ AST nodes.
*
* @author Mike Kucera
*/
public class CPPNodeFactory implements ICPPNodeFactory {
@ -165,15 +163,15 @@ public class CPPNodeFactory implements ICPPNodeFactory {
return new CPPASTIdExpression(name);
}
public IASTArraySubscriptExpression newArraySubscriptExpression(IASTExpression arrayExpr, IASTExpression subscript) {
public ICPPASTArraySubscriptExpression newArraySubscriptExpression(IASTExpression arrayExpr, IASTExpression subscript) {
return new CPPASTArraySubscriptExpression(arrayExpr, subscript);
}
public IASTExpressionList newExpressionList() {
public ICPPASTExpressionList newExpressionList() {
return new CPPASTExpressionList();
}
public IASTFunctionCallExpression newFunctionCallExpression(IASTExpression idExpr, IASTExpression argList) {
public ICPPASTFunctionCallExpression newFunctionCallExpression(IASTExpression idExpr, IASTExpression argList) {
return new CPPASTFunctionCallExpression(idExpr, argList);
}

View file

@ -12,8 +12,12 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.Arrays;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.parser.IToken;
/**
@ -78,9 +82,26 @@ public enum OverloadableOperator {
return rep;
}
/**
* Returns true if the given name equals 'operator new'
* or 'operator new[]'.
*/
public static boolean isNew(char[] name) {
return Arrays.equals(name, NEW.rep) || Arrays.equals(name, NEW_ARRAY.rep);
}
/**
* Returns true if the given name equals 'operator delete'
* or 'operator delete[]'.
*/
public static boolean isDelete(char[] name) {
return Arrays.equals(name, DELETE.rep) || Arrays.equals(name, DELETE_ARRAY.rep);
}
/**
* Returns the OverloadableOperator constant that corresponds to
* the given token. Only works for operators that consist of one token.
* the given token. Does not work for new[] and delete[] operators.
*
* @throws NullPointerException if {@code token} is {@code null}.
*/
@ -132,6 +153,11 @@ public enum OverloadableOperator {
// other
case IToken.tASSIGN: return ASSIGN;
case IToken.tCOMMA: return COMMA;
case IToken.tLBRACKET: return BRACKET;
case IToken.tRBRACKET: return BRACKET;
case IToken.tLPAREN: return PAREN;
case IToken.tRPAREN: return PAREN;
}
return null;
@ -203,4 +229,12 @@ public enum OverloadableOperator {
}
return null;
}
public static OverloadableOperator fromDeleteExpression(ICPPASTDeleteExpression expression) {
return expression.isVectored() ? DELETE_ARRAY : DELETE;
}
public static OverloadableOperator fromNewExpression(ICPPASTNewExpression expression) {
return expression.isArrayAllocation() ? NEW_ARRAY : NEW;
}
}

View file

@ -18,6 +18,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -82,6 +83,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
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;
@ -135,6 +138,7 @@ import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.DebugUtil;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
@ -149,6 +153,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
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.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
@ -2525,6 +2530,7 @@ public class CPPSemantics {
return result;
}
/**
* For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to
* when chaining overloaded class member access operators <code>operator->()</code> calls.
@ -2534,6 +2540,13 @@ public class CPPSemantics {
* @throws DOMException
*/
public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference) throws DOMException {
return getChainedMemberAccessOperatorReturnType(fieldReference, null);
}
/*
* Also collections the funciton bindings if requested.
*/
public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference, Collection<ICPPFunction> functionBindings) throws DOMException {
IASTExpression owner = fieldReference.getFieldOwner();
if (owner == null)
return null;
@ -2581,6 +2594,9 @@ public class CPPSemantics {
if (op == null)
break;
if(functionBindings != null)
functionBindings.add(op);
type= op.getType().getReturnType();
foundOperator= true;
}
@ -2609,42 +2625,40 @@ public class CPPSemantics {
CPPASTName astName = new CPPASTName();
astName.setParent(exp);
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
LookupData data;
LookupData data = new LookupData(astName);
data.forceQualified = true;
if (exp instanceof IASTArraySubscriptExpression) {
astName.setName(OverloadableOperator.BRACKET.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
data.setFunctionArguments(((IASTArraySubscriptExpression) exp).getSubscriptExpression());
} else if (exp instanceof IASTFieldReference) {
astName.setName(OverloadableOperator.ARROW.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
} else if (exp instanceof IASTFunctionCallExpression) {
astName.setName(OverloadableOperator.PAREN.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
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) {
if (operator == null)
return null;
}
astName.setName(operator.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
data.setFunctionArguments(new IASTExpression[] { binary.getOperand2() });
} else if (exp instanceof IASTUnaryExpression) {
IASTUnaryExpression unary = (IASTUnaryExpression) exp;
OverloadableOperator operator = OverloadableOperator.fromUnaryExpression(unary);
if(operator == null) {
if(operator == null)
return null;
}
astName.setName(operator.toCharArray());
data = new LookupData(astName);
data.forceQualified = true;
int op = unary.getOperator();
if(op == IASTUnaryExpression.op_postFixDecr || op == IASTUnaryExpression.op_postFixIncr)
data.setFunctionArguments(new IASTExpression[] { CPPASTLiteralExpression.INT_ZERO });
@ -2663,7 +2677,75 @@ public class CPPSemantics {
}
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 findDestructor(ICPPASTDeleteExpression expr, 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(expr);
astName.setPropertyInParent(STRING_LOOKUP_PROPERTY);
astName.setName(CharArrayUtils.concat("~".toCharArray(), cls.getNameCharArray())); //$NON-NLS-1$
LookupData data = new LookupData(astName);
data.forceQualified = true;
data.setFunctionArguments(IASTExpression.EMPTY_EXPRESSION_ARRAY);
try {
lookup(data, scope);
IBinding binding = resolveAmbiguities(data, astName);
if (binding instanceof ICPPFunction)
return (ICPPFunction) binding;
} catch (DOMException e) {
}
return null;
}
/**
* Returns the overloaded operator corresponding to a binary expression, or {@code null}
* if no such operator is found.
@ -2677,6 +2759,19 @@ public class CPPSemantics {
}
/**
* 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.
@ -2695,6 +2790,48 @@ public class CPPSemantics {
}
/**
* 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) {
if (operator == null) {
return null;
@ -2721,6 +2858,8 @@ public class CPPSemantics {
}
public static IBinding[] findBindings(IScope scope, String name, boolean qualified) throws DOMException {
return findBindings(scope, name.toCharArray(), qualified, null);
}

View file

@ -46,6 +46,7 @@ import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
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.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
@ -409,6 +410,13 @@ public class LookupData {
if (tempNameParent instanceof IASTBinaryExpression) {
return ((IASTBinaryExpression) tempNameParent).getOperand1().getExpressionType();
}
if (tempNameParent instanceof ICPPASTDeleteExpression) {
IType implied = ((ICPPASTDeleteExpression) tempNameParent).getOperand().getExpressionType();
if(implied instanceof IPointerType) {
return ((IPointerType)implied).getType();
}
return implied;
}
return null;
}
if (prop == IASTFieldReference.FIELD_NAME) {
@ -549,8 +557,8 @@ public class LookupData {
}
setFunctionArguments(exprs);
}
public void setFunctionArguments(IASTExpression[] exprs) {
public void setFunctionArguments(IASTExpression... exprs) {
functionArgs= exprs;
if (exprs.length != 0) {
IASTNode node= exprs[0];

View file

@ -145,4 +145,18 @@ public class TokenUtil {
return CharArrayUtils.EMPTY;
}
}
/**
* Returns the last token in the given token list.
* @throws NullPointerException if the argument is null
*/
public static IToken getLast(IToken tokenList) {
IToken last;
do {
last = tokenList;
} while((tokenList = tokenList.getNext()) != null);
return last;
}
}

View file

@ -47,6 +47,7 @@ abstract public class IndexerASTVisitor extends ASTVisitor {
public IndexerASTVisitor() {
shouldVisitNames= true;
shouldVisitImplicitNames = true;
shouldVisitDeclarations= true;
shouldVisitInitializers= true;
shouldVisitDeclSpecifiers= true;