/******************************************************************************* * Copyright (c) 2009, 2010 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) * Sergey Prigogin (Google) * Markus Schorn (Wind River Systems) *******************************************************************************/ 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.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.parser.ParserLanguage; /** * Tests for classes implementing IASTImplicitNameOwner interface. */ 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); IASTTranslationUnit tu = ba.getTranslationUnit(); CPPNameCollector col = new CPPNameCollector(); tu.accept(col); IASTImplicitName n; n = ba.assertImplicitName("+= 5", 2, ICPPMethod.class); assertSame(n.resolveBinding(), col.getName(14).resolveBinding()); n = ba.assertImplicitName("+ p", 1, ICPPMethod.class); assertSame(n.resolveBinding(), col.getName(4).resolveBinding()); n = ba.assertImplicitName("- p", 1, ICPPMethod.class); assertSame(n.resolveBinding(), col.getName(8).resolveBinding()); n = ba.assertImplicitName("* p", 1, ICPPFunction.class); assertSame(n.resolveBinding(), col.getName(17).resolveBinding()); n = ba.assertImplicitName("/ p", 1, ICPPFunction.class); assertSame(n.resolveBinding(), col.getName(23).resolveBinding()); n = ba.assertImplicitName("-p;", 1, ICPPMethod.class); assertSame(n.resolveBinding(), col.getName(12).resolveBinding()); ba.assertNoImplicitName("<< 6", 2); ba.assertNoImplicitName("+p;", 1); } // struct X {}; // // template <class T> class auto_ptr { // T* ptr; // public: // explicit auto_ptr(T* p = 0) : ptr(p) {} // T& operator*() { return *ptr; } // }; // // void test() { // auto_ptr<X> x(new X()); // *x; //1 // int* y; // *y; //2 // } public void testPointerDereference() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); ba.assertImplicitName("*x;", 1, ICPPFunction.class); ba.assertNoImplicitName("*y; //2", 1); } // struct X {}; // struct Y { // X x; // }; // // X* operator&(X); // X* operator&(Y); // // void test(X x, Y y) { // X (Y::*px1) = &Y::x; // not the overloaded operator // X* px2 = &y; // overloaded // } public void testPointerToMember() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); IASTTranslationUnit tu = ba.getTranslationUnit(); CPPNameCollector col = new CPPNameCollector(); tu.accept(col); ba.assertNoImplicitName("&Y::x;", 1); IASTImplicitName n = ba.assertImplicitName("&y;", 1, ICPPFunction.class); assertSame(n.resolveBinding(), col.getName(9).resolveBinding()); } // 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 testCommaOperator1() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); // expression lists are used in function calls but they should not resolve to the comma operator ba.assertNoImplicitName(", b, c, d); // func", 1); 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(11).resolveBinding()); } // struct B {}; // struct C {}; // struct E { // int ee; // }; // struct A { // C operator,(B); // }; // struct D { // E operator,(D); // }; // D operator,(C,C); // // int test(A a, B b, C c, D d) { // (a, b, c, d).ee; // expr // } public void testCommaOperator2() throws Exception { BindingAssertionHelper ba = new BindingAssertionHelper(getAboveComment(), true); IASTImplicitName opAB = ba.assertImplicitName(", b, c, d", 1, ICPPMethod.class); IASTImplicitName opCC = ba.assertImplicitName(", c, d", 1, ICPPFunction.class); IASTImplicitName opDD = ba.assertImplicitName(", d", 1, ICPPMethod.class); IASTTranslationUnit tu = ba.getTranslationUnit(); CPPNameCollector col = new CPPNameCollector(); tu.accept(col); // 6, 11, 15 assertSame(opAB.resolveBinding(), col.getName(6).resolveBinding()); assertSame(opCC.resolveBinding(), col.getName(15).resolveBinding()); assertSame(opDD.resolveBinding(), col.getName(11).resolveBinding()); ba.assertNonProblem("ee;", 2); } // struct X { // int operator()(bool); // int operator()(); // int operator()(int, int); // }; // // int test(X x) { // bool b = true; // x(b); // 1 // x(); // 2 // x(1, 2); // 3 // } public void testFunctionCallOperator() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); IASTTranslationUnit tu = ba.getTranslationUnit(); CPPNameCollector col = new CPPNameCollector(); tu.accept(col); IASTImplicitName n1 = ba.assertImplicitName("(b); // 1", 1, ICPPMethod.class); IASTImplicitName n2 = ba.assertImplicitName("); // 1", 1, ICPPMethod.class); assertSame(n1.resolveBinding(), n2.resolveBinding()); assertFalse(n1.isAlternate()); assertTrue(n2.isAlternate()); // there should be no overlap ba.assertNoImplicitName("b); // 1", 1); assertSame(col.getName(1).resolveBinding(), n1.resolveBinding()); n1 = ba.assertImplicitName("(); // 2", 1, ICPPMethod.class); n2 = ba.assertImplicitName("); // 2", 1, ICPPMethod.class); assertSame(n1.resolveBinding(), n2.resolveBinding()); assertFalse(n1.isAlternate()); assertTrue(n2.isAlternate()); assertSame(col.getName(3).resolveBinding(), n1.resolveBinding()); n1 = ba.assertImplicitName("(1, 2); // 3", 1, ICPPMethod.class); n2 = ba.assertImplicitName("); // 3", 1, ICPPMethod.class); assertSame(n1.resolveBinding(), n2.resolveBinding()); assertFalse(n1.isAlternate()); assertTrue(n2.isAlternate()); assertSame(col.getName(4).resolveBinding(), n1.resolveBinding()); } // 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); IASTTranslationUnit tu = ba.getTranslationUnit(); CPPNameCollector col = new CPPNameCollector(); tu.accept(col); IASTImplicitName n1 = ba.assertImplicitName("[0]); //1", 1, ICPPMethod.class); ba.assertNoImplicitName("0]); //1", 1); IASTImplicitName n2 = ba.assertImplicitName("]); //1", 1, ICPPMethod.class); assertSame(n1.resolveBinding(), n2.resolveBinding()); assertFalse(n1.isAlternate()); assertTrue(n2.isAlternate()); assertSame(col.getName(1).resolveBinding(), n1.resolveBinding()); n1 = ba.assertImplicitName("[q]); //2", 1, ICPPMethod.class); ba.assertNoImplicitName("q]); //2", 1); n2 = ba.assertImplicitName("]); //2", 1, ICPPMethod.class); assertSame(n1.resolveBinding(), n2.resolveBinding()); assertFalse(n1.isAlternate()); assertTrue(n2.isAlternate()); assertSame(col.getName(3).resolveBinding(), n1.resolveBinding()); } // struct X { // ~X(); // void operator delete(void *); // void operator delete[](void *); // }; // // int test(X* x) { // delete x; // X* xs = new X[5]; // delete[] x; // delete 1; // } 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(4).resolveBinding(), names[0].resolveBinding()); ba.assertNoImplicitName("delete 1;", 6); } // struct A { // void operator delete(void * a); // }; // struct B {}; // void operator delete(void * b); // // void test() { // A *a = new A; // delete a; // // B* b = new B; // delete b; // } public void testOverloadedDelete_Bug351547() throws Exception { BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true); IBinding m= bh.assertNonProblem("operator delete(void * a)", 15); IBinding f= bh.assertNonProblem("operator delete(void * b)", 15); IASTImplicitName[] names = bh.getImplicitNames("delete a;", 6); assertEquals(2, names.length); assertTrue(((ICPPMethod) names[0].resolveBinding()).isDestructor()); assertSame(m, names[1].resolveBinding()); names = bh.getImplicitNames("delete b;", 6); assertTrue(((ICPPMethod) names[0].resolveBinding()).isDestructor()); assertEquals(2, names.length); assertSame(f, names[1].resolveBinding()); } // typedef int size_t; // struct A { // void* operator new(size_t a); // }; // struct B {}; // void* operator new(size_t b); // // void test() { // A *a = new A; // B* b = new B; // } public void testOverloadedNew_Bug354585() throws Exception { BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true); IBinding m= bh.assertNonProblem("operator new(size_t a)", 12); IBinding f= bh.assertNonProblem("operator new(size_t b)", 12); IASTImplicitName[] names = bh.getImplicitNames("new A;", 3); assertEquals(1, names.length); assertSame(m, names[0].resolveBinding()); names = bh.getImplicitNames("new B;", 3); assertEquals(1, names.length); assertSame(f, 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); } // struct A { // A() {} // A(int) {} // template <typename T> // A(T, int) {} // }; // typedef A B; // // void test() { // B a; // B b(1); // B c = 1; // B d("", 1); // extern B e; // } // // struct C { // static B s = 1; // static B t; // B u; // B v; // C(int p) : u(), v(p) {} // }; // B C::t = 1; public void testConstructorCall() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); IASTTranslationUnit tu = ba.getTranslationUnit(); ICPPConstructor ctor0 = ba.assertNonProblem("A()", 1, ICPPConstructor.class); ICPPConstructor ctor1 = ba.assertNonProblem("A(int)", 1, ICPPConstructor.class); ICPPConstructor ctor2 = ba.assertNonProblem("A(T, int)", 1, ICPPConstructor.class); IASTImplicitName a = ba.assertImplicitName("a;", 1, ICPPConstructor.class); assertSame(ctor0, a.resolveBinding()); IASTImplicitName b = ba.assertImplicitName("b(", 1, ICPPConstructor.class); assertSame(ctor1, b.resolveBinding()); IASTImplicitName c = ba.assertImplicitName("c =", 1, ICPPConstructor.class); assertSame(ctor1, c.resolveBinding()); IASTImplicitName d = ba.assertImplicitName("d(", 1, ICPPConstructor.class); assertSame(ctor2, ((ICPPTemplateInstance) d.resolveBinding()).getTemplateDefinition()); ba.assertNoImplicitName("e;", 1); IASTImplicitName s = ba.assertImplicitName("s =", 1, ICPPConstructor.class); assertSame(ctor1, s.resolveBinding()); ba.assertNoImplicitName("t;", 1); IASTImplicitName t = ba.assertImplicitName("t =", 1, ICPPConstructor.class); assertSame(ctor1, t.resolveBinding()); ba.assertNoImplicitName("u;", 1); IASTImplicitName u = ba.assertImplicitName("u()", 1, ICPPConstructor.class); assertSame(ctor0, u.resolveBinding()); IASTImplicitName v = ba.assertImplicitName("v(p)", 1, ICPPConstructor.class); assertSame(ctor1, v.resolveBinding()); } // enum A {aa}; // struct B{ operator A();}; // bool operator==(A, A); // overrides the built-in operator. // // void test() { // B b; // if (aa==b) { // } // } public void testBuiltinOperators_294543() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); IASTTranslationUnit tu = ba.getTranslationUnit(); ICPPFunction op = ba.assertNonProblem("operator==", 0); IASTImplicitName a = ba.assertImplicitName("==b", 2, ICPPFunction.class); assertSame(op, a.resolveBinding()); } }