From 5fcb227983bc4c15e085f8da3019a815505caadd Mon Sep 17 00:00:00 2001 From: Mike Kucera Date: Thu, 12 Mar 2009 14:19:46 +0000 Subject: [PATCH] bug 265375 - implicit names API and support for overloaded operator references --- .../cdt/core/parser/tests/ASTComparer.java | 3 +- .../core/parser/tests/ast2/AST2BaseTest.java | 71 +++- .../tests/ast2/AST2CPPImplicitNameTests.java | 385 ++++++++++++++++++ .../parser/tests/ast2/DOMParserTestSuite.java | 2 + .../core/suite/AutomatedIntegrationSuite.java | 6 +- .../eclipse/cdt/core/dom/ast/ASTVisitor.java | 22 +- .../cdt/core/dom/ast/IASTImplicitName.java | 65 +++ .../core/dom/ast/IASTImplicitNameOwner.java | 26 ++ .../eclipse/cdt/core/dom/ast/IASTNode.java | 8 +- .../cdt/core/dom/ast/IASTNodeSelector.java | 23 ++ .../cpp/ICPPASTArraySubscriptExpression.java | 22 + .../dom/ast/cpp/ICPPASTBinaryExpression.java | 4 +- .../dom/ast/cpp/ICPPASTDeleteExpression.java | 4 +- .../dom/ast/cpp/ICPPASTExpressionList.java | 22 + .../dom/ast/cpp/ICPPASTFieldReference.java | 4 +- .../cpp/ICPPASTFunctionCallExpression.java | 22 + .../dom/ast/cpp/ICPPASTNewExpression.java | 12 +- .../dom/ast/cpp/ICPPASTUnaryExpression.java | 4 +- .../cdt/core/dom/ast/cpp/ICPPNodeFactory.java | 7 + .../core/dom/parser/ASTNodeSelector.java | 40 +- .../dom/parser/FindNodeForOffsetAction.java | 5 + .../cpp/CPPASTArraySubscriptExpression.java | 56 ++- .../parser/cpp/CPPASTBinaryExpression.java | 94 ++++- .../parser/cpp/CPPASTDeleteExpression.java | 94 ++++- .../dom/parser/cpp/CPPASTExpressionList.java | 121 +++++- .../dom/parser/cpp/CPPASTFieldReference.java | 50 ++- .../cpp/CPPASTFunctionCallExpression.java | 85 +++- .../dom/parser/cpp/CPPASTImplicitName.java | 134 ++++++ .../dom/parser/cpp/CPPASTNewExpression.java | 76 +++- .../dom/parser/cpp/CPPASTUnaryExpression.java | 63 ++- .../core/dom/parser/cpp/CPPNodeFactory.java | 16 +- .../dom/parser/cpp/OverloadableOperator.java | 36 +- .../parser/cpp/semantics/CPPSemantics.java | 169 +++++++- .../dom/parser/cpp/semantics/LookupData.java | 12 +- .../core/parser/scanner/TokenUtil.java | 14 + .../core/pdom/indexer/IndexerASTVisitor.java | 1 + 36 files changed, 1640 insertions(+), 138 deletions(-) create mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitName.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitNameOwner.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTArraySubscriptExpression.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTExpressionList.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionCallExpression.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java index 49e36dddf9b..6110daeb3cd 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ASTComparer.java @@ -50,7 +50,8 @@ public class ASTComparer extends Assert { "isDefinition", "isReference", "isAssociatedWithLastName", - "getNestingLevel" + "getNestingLevel", + "getImplicitNames" )); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java index af8d2a9deee..cb67fdbbb07 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java @@ -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()); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java new file mode 100644 index 00000000000..2e8ace3b39e --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPImplicitNameTests.java @@ -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 auto_ptr { + // T* ptr; + //public: + // explicit auto_ptr(T* p = 0) : ptr(p) {} + // T& operator*() {return *ptr;} + //}; + // + //void test() { + // auto_ptr 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); + } + + + + + + + + + +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index 5cba94fb06c..fdbec95fa5d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -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; } } diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java index 367770d9ea4..1f8e77dfca8 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java @@ -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()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTVisitor.java index 469aa630bf5..a59431bcacd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTVisitor.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitName.java new file mode 100644 index 00000000000..6751396d423 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitName.java @@ -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; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitNameOwner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitNameOwner.java new file mode 100644 index 00000000000..21b3c3b9179 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTImplicitNameOwner.java @@ -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(); + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java index debe8d2253e..e9411d21b38 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java @@ -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: * * @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java index 4cbecbb5117..3ff6ebfe195 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNodeSelector.java @@ -23,19 +23,42 @@ public interface IASTNodeSelector { /** * Returns the name for the exact given range, or null 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 null 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 null 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 null 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 null if there is no such node. *

diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTArraySubscriptExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTArraySubscriptExpression.java new file mode 100644 index 00000000000..cfeb6342564 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTArraySubscriptExpression.java @@ -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(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTBinaryExpression.java index 7cce16e3124..275fabc57a9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTBinaryExpression.java @@ -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 { /** * op_pmdot pointer-to-member field dereference. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeleteExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeleteExpression.java index 1cc522a0d51..1cafaa5543e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeleteExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeleteExpression.java @@ -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 { /** * OPERAND is the expression representing the pointer being diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTExpressionList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTExpressionList.java new file mode 100644 index 00000000000..15e900eaf23 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTExpressionList.java @@ -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(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java index 0adfd74bb6f..e276d157bbe 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFieldReference.java @@ -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? diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionCallExpression.java new file mode 100644 index 00000000000..8c8e91facea --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionCallExpression.java @@ -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(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNewExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNewExpression.java index ef83a48e331..85780652f53 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNewExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTNewExpression.java @@ -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. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTUnaryExpression.java index 895c7714e81..010c7c08f08 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTUnaryExpression.java @@ -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 { /** * op_throw throw exp diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java index 65a1ff9df3a..d48d19ca926 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java @@ -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); + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java index 9309ac30e04..6c2417e63b1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNodeSelector.java @@ -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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java index 8a915819ead..d007f33a149 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FindNodeForOffsetAction.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java index 49ece3d6ad1..0b73f49cb4a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTArraySubscriptExpression.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java index ec2e6fa5892..e583dcd15fb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java @@ -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; + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java index fc3192ffb54..a4263dc88ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeleteExpression.java @@ -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 names = new ArrayList(); + + 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 ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java index 89e5c537e2d..22fb700f923 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTExpressionList.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java index b7feb987572..b0ab585f07e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFieldReference.java @@ -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 functionBindings = new ArrayList(); + 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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index 1367a6586a4..e6428015e1a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java new file mode 100644 index 00000000000..691e4eb5e75 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java @@ -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; + } + + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java index a418c48618b..b442627c937 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTNewExpression.java @@ -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 ) ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java index cab01d70547..f53b78f04f6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTUnaryExpression.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index 2a10bfa166c..7a1774f657b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/OverloadableOperator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/OverloadableOperator.java index bd8330d3650..4bcead9677a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/OverloadableOperator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/OverloadableOperator.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index ef43c5f6687..b3b0e82e234 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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 operator->() 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 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 args = new ArrayList(); + 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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 57e9dd23154..551b6f3f7c4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -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]; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java index cf6f54564e1..ea5776c30bf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java @@ -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; + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java index 2a6a099519f..dbf2a273d98 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java @@ -47,6 +47,7 @@ abstract public class IndexerASTVisitor extends ASTVisitor { public IndexerASTVisitor() { shouldVisitNames= true; + shouldVisitImplicitNames = true; shouldVisitDeclarations= true; shouldVisitInitializers= true; shouldVisitDeclSpecifiers= true;