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 6ae99164de3..8ff3205dcf8 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 @@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -35,6 +36,7 @@ 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.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTypeId; @@ -543,24 +545,36 @@ public class AST2BaseTest extends BaseTestCase { } assertEquals(count, sum); } - - final protected IASTFunctionDefinition getFunctionDefinition(IASTTranslationUnit tu, int i_decl) { + + final protected T getDeclaration(IASTTranslationUnit tu, int i_decl) { + Class tclass; IASTDeclaration[] decls= tu.getDeclarations(); assertTrue(decls.length > i_decl); - assertInstance(decls[i_decl], IASTFunctionDefinition.class); - return (IASTFunctionDefinition) decls[i_decl]; + return (T) decls[i_decl]; } - final protected IASTStatement getStatement(IASTFunctionDefinition fdef, int i_stmt) { + final protected T getDeclaration(IASTCompositeTypeSpecifier ct, int i_decl) { + Class tclass; + IASTDeclaration[] decls= ct.getMembers(); + assertTrue(decls.length > i_decl); + return (T) decls[i_decl]; + } + + final protected T getCompositeType(IASTTranslationUnit tu, int i_decl) { + IASTSimpleDeclaration sdecl= getDeclaration(tu, i_decl); + return (T) sdecl.getDeclSpecifier(); + } + + final protected T getStatement(IASTFunctionDefinition fdef, int i_stmt) { IASTCompoundStatement compound= (IASTCompoundStatement) fdef.getBody(); IASTStatement[] stmts= compound.getStatements(); assertTrue(stmts.length > i_stmt); - return stmts[i_stmt]; + return (T) stmts[i_stmt]; } - final protected IASTExpression getExpressionOfStatement(IASTFunctionDefinition fdef, int i) { + final protected T getExpressionOfStatement(IASTFunctionDefinition fdef, int i) { IASTStatement stmt= getStatement(fdef, i); assertInstance(stmt, IASTExpressionStatement.class); - return ((IASTExpressionStatement) stmt).getExpression(); + return (T) ((IASTExpressionStatement) stmt).getExpression(); } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java index ecc5c7fb991..85ecf131ee7 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java @@ -90,18 +90,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest { parse(getAboveComment(), ParserLanguage.CPP, true, 0); } - // class C { }; - // void f(int(C)) { } // void f(int (*fp)(C c)) { } - // // not: void f(int C); - // int g(C); - // void foo() { - // f(1); //error: cannot convert 1 to function pointer - // f(g); //OK - // } - public void _test8_2s7a() throws Exception { // TODO raised bug 90633 - parse(getAboveComment(), ParserLanguage.CPP, true, 0); - } - // char msg[] = "Syntax error on line %s // "; public void _test8_5_2s1() throws Exception { // TODO raised bug 90647 diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java index 2f7412bb118..2bd9c35815b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java @@ -13,14 +13,18 @@ package org.eclipse.cdt.core.parser.tests.ast2; import junit.framework.TestSuite; +import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionList; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; @@ -776,14 +780,13 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { // }; public void test5_3_4s3() throws Exception { IASTTranslationUnit tu= parse(getAboveComment(), ParserLanguage.CPP, true, 0); - IASTFunctionDefinition fdef= getFunctionDefinition(tu, 0); + IASTFunctionDefinition fdef= getDeclaration(tu, 0); IASTExpression expr= getExpressionOfStatement(fdef, 0); assertInstance(expr, ICPPASTNewExpression.class); ICPPASTNewExpression newExpr= (ICPPASTNewExpression) expr; assertNull(newExpr.getNewPlacement()); assertNull(newExpr.getNewInitializer()); - assertEquals(0, newExpr.getNewTypeIdArrayExpressions().length); IASTTypeId typeid= newExpr.getTypeId(); isTypeEqual(CPPVisitor.createType(typeid), "int () * []"); } @@ -795,11 +798,11 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { // new T[5]; // new (2,f) T[5]; // }; - public void _test5_3_4s12() throws Exception { - // failing see https://bugs.eclipse.org/bugs/show_bug.cgi?id=236856 + public void test5_3_4s12() throws Exception { + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=236856 IASTTranslationUnit tu= parse(getAboveComment(), ParserLanguage.CPP, true, 0); - IASTFunctionDefinition fdef= getFunctionDefinition(tu, 1); + IASTFunctionDefinition fdef= getDeclaration(tu, 1); // new T; IASTExpression expr= getExpressionOfStatement(fdef, 0); @@ -807,7 +810,6 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { ICPPASTNewExpression newExpr= (ICPPASTNewExpression) expr; assertNull(newExpr.getNewPlacement()); assertNull(newExpr.getNewInitializer()); - assertEquals(0, newExpr.getNewTypeIdArrayExpressions().length); isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int"); // new(2,f) T; @@ -816,7 +818,6 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { newExpr= (ICPPASTNewExpression) expr; assertInstance(newExpr.getNewPlacement(), IASTExpressionList.class); assertNull(newExpr.getNewInitializer()); - assertEquals(0, newExpr.getNewTypeIdArrayExpressions().length); isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int"); // new T[5]; @@ -825,7 +826,6 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { newExpr= (ICPPASTNewExpression) expr; assertNull(newExpr.getNewPlacement()); assertNull(newExpr.getNewInitializer()); - assertEquals(1, newExpr.getNewTypeIdArrayExpressions().length); isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int []"); // new (2,f) T[5]; @@ -834,7 +834,6 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { newExpr= (ICPPASTNewExpression) expr; assertInstance(newExpr.getNewPlacement(), IASTExpressionList.class); assertNull(newExpr.getNewInitializer()); - assertEquals(1, newExpr.getNewTypeIdArrayExpressions().length); isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int []"); } @@ -1133,7 +1132,10 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { // // an ordinary member function, not a constructor // } S; public void test7_1_3s5b() throws Exception { - parse(getAboveComment(), ParserLanguage.CPP, true, 0); + IASTTranslationUnit tu= parseWithErrors(getAboveComment(), ParserLanguage.CPP); + IASTCompositeTypeSpecifier comp= getCompositeType(tu, 0); + IASTDeclaration d= getDeclaration(comp, 0); + assertInstance(d, IASTProblemDeclaration.class); } // int foo() { @@ -1776,10 +1778,27 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { parse(getAboveComment(), ParserLanguage.CPP, true, 0); } + // class C { }; + // void f(int(C)) { } // void f(int (*fp)(C c)) { } + // // not: void f(int C); + // int g(C); + // void foo() { + // f(1); //error: cannot convert 1 to function pointer + // f(g); //OK + // } + public void test8_2s7a() throws Exception { // TODO raised bug 90633 + final String code = getAboveComment(); + parse(code, ParserLanguage.CPP, true, 1); + + BindingAssertionHelper ba= new BindingAssertionHelper(code, true); + IFunction f= ba.assertNonProblem("f", 1, IFunction.class); + isTypeEqual(f.getType(), "void (int (C) *)"); + } + // class C { }; // void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10])); // // not: void h(int *C[10]); - public void _test8_2s7b() throws Exception { + public void test8_2s7b() throws Exception { final String code = getAboveComment(); parse(code, ParserLanguage.CPP, true, 0); BindingAssertionHelper ba= new BindingAssertionHelper(code, true); @@ -3958,7 +3977,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { // int f(char*); // void g() // { - // extern f(int); + // extern int f(int); // f("asdf"); //error: f(int) hides f(char*) // // so there is no f(char*) in this scope // } @@ -5634,7 +5653,7 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { parse(getAboveComment(), ParserLanguage.CPP, true, 0); } - // class Matherr { virtual vf(); }; + // class Matherr { virtual void vf(); }; // class Overflow: public Matherr { }; // class Underflow: public Matherr { }; // class Zerodivide: public Matherr { }; @@ -6185,7 +6204,10 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { // int ef(D&); // int ff(X&); public void test11_3s2() throws Exception { //bug 92793 - parse(getAboveComment(), ParserLanguage.CPP, true, 0); + IASTTranslationUnit tu= parse(getAboveComment(), ParserLanguage.CPP, true, 0); + IASTCompositeTypeSpecifier D= getCompositeType(tu, 2); + IASTDeclaration accessDecl= getDeclaration(D, 2); + assertInstance(accessDecl, ICPPASTUsingDeclaration.class); } // int z() { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index d79e497e5f7..8ea2260a6f3 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; 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.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; @@ -83,6 +84,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; @@ -1621,7 +1623,7 @@ public class AST2CPPTests extends AST2BaseTest { } // namespace Y { void f(float); } - // namespace A { using namespace Y; f(int); } + // namespace A { using namespace Y; void f(int); } // namespace B { void f(char); } // namespace AB { using namespace A; using namespace B; } // void h(){ @@ -3561,33 +3563,39 @@ public class AST2CPPTests extends AST2BaseTest { // 1,4,12,21 - conversion // 2, 16 .isConversion + + final IASTName int1 = col.getName(1); + assertNotNull(int1); + assertTrue(int1 instanceof ICPPASTConversionName); + assertNotNull(((ICPPASTConversionName) int1).getTypeId()); - assertEquals(col.size(), 22); + IASTFunctionDefinition fdef= getDeclaration(tu, 1); + final IASTName x_int = fdef.getDeclarator().getName(); + assertNotNull(x_int); + assertTrue(x_int instanceof ICPPASTQualifiedName); + assertTrue(((ICPPASTQualifiedName) x_int).isConversionOrOperator()); + + final IASTName int2= ((ICPPASTQualifiedName)x_int).getLastName(); + assertNotNull(int2); + assertTrue(int2 instanceof ICPPASTConversionName); + assertNotNull(((ICPPASTConversionName) int2).getTypeId()); - assertNotNull(col.getName(1)); - assertNotNull(col.getName(4)); - assertNotNull(col.getName(12)); - assertNotNull(col.getName(21)); - assertNotNull(col.getName(2)); - assertNotNull(col.getName(16)); - - // ensure the conversions are conversions - assertTrue(col.getName(1) instanceof ICPPASTConversionName); - assertTrue(col.getName(4) instanceof ICPPASTConversionName); - assertTrue(col.getName(12) instanceof ICPPASTConversionName); - assertTrue(col.getName(21) instanceof ICPPASTConversionName); - assertNotNull(((ICPPASTConversionName) col.getName(1)).getTypeId()); - assertNotNull(((ICPPASTConversionName) col.getName(4)).getTypeId()); - assertNotNull(((ICPPASTConversionName) col.getName(12)).getTypeId()); - assertNotNull(((ICPPASTConversionName) col.getName(21)).getTypeId()); - - // ensure qualified name isConversionOrOperator - assertTrue(col.getName(2) instanceof ICPPASTQualifiedName); - assertTrue(col.getName(16) instanceof ICPPASTQualifiedName); - assertTrue(((ICPPASTQualifiedName) col.getName(2)) - .isConversionOrOperator()); - assertTrue(((ICPPASTQualifiedName) col.getName(16)) - .isConversionOrOperator()); + final IASTName int3 = col.getName(12); + assertNotNull(int3); + assertTrue(int3 instanceof ICPPASTConversionName); + assertNotNull(((ICPPASTConversionName) int3).getTypeId()); + + ICPPASTTemplateDeclaration tdef= getDeclaration(tu, 3); + fdef= (IASTFunctionDefinition) tdef.getDeclaration(); + final IASTName x_ac_int = fdef.getDeclarator().getName(); + assertNotNull(x_ac_int); + assertTrue(x_ac_int instanceof ICPPASTQualifiedName); + assertTrue(((ICPPASTQualifiedName) x_ac_int).isConversionOrOperator()); + + final IASTName int4= ((ICPPASTQualifiedName)x_ac_int).getLastName(); + assertNotNull(int4); + assertTrue(int4 instanceof ICPPASTConversionName); + assertNotNull(((ICPPASTConversionName) int4).getTypeId()); } public void testBug88662() throws Exception { @@ -4066,7 +4074,7 @@ public class AST2CPPTests extends AST2BaseTest { assertSame(d2, r); } - // class P { + // class Point { // Point() : xCoord(0) {} // int xCoord; // }; @@ -5021,10 +5029,6 @@ public class AST2CPPTests extends AST2BaseTest { assertSame( blah, col.getName(6).resolveBinding() ); } - public void testBug80171() throws Exception { - parseAndCheckBindings( "static var;"); //$NON-NLS-1$ - } - public void testBug78800() throws Exception { parseAndCheckBindings( "class Matrix { public: Matrix & operator *(Matrix &); }; Matrix rotate, translate; Matrix transform = rotate * translate;" ); //$NON-NLS-1$ } @@ -5658,7 +5662,7 @@ public class AST2CPPTests extends AST2BaseTest { // X::~X() {} // X::operator int() {} // X::xtint(a); // 2 - public void _testEmptyDeclSpecifier() throws Exception { + public void testEmptyDeclSpecifier() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); ba.assertNonProblem("X {", 1, ICPPClassType.class); ba.assertNonProblem("X()", 1, ICPPConstructor.class); @@ -5677,46 +5681,46 @@ public class AST2CPPTests extends AST2BaseTest { // int p[100]; // void test(int f) { // new T; + // new T(); // new T(f); // new (p) T; + // new (p) T(); // new (p) T(f); // new (T); + // new (T)(); // new (T)(f); // new (p) (T); + // new (p) (T)(); // new (p) (T)(f); // new T[f][f]; - // new T[f][f](f); // new (p) T[f][f]; - // new (p) T[f][f](f); // new (T[f][f]); - // new (T[f][f])(f); // new (p) (T[f][f]); - // new (p) (T[f][f])(f); // }; - public void _testNewPlacement_Bug236856() throws Exception { + public void testNewPlacement() throws Exception { IASTTranslationUnit tu= parseAndCheckBindings(getAboveComment()); - IASTFunctionDefinition fdef= getFunctionDefinition(tu, 3); + IASTFunctionDefinition fdef= getDeclaration(tu, 3); - checkNewExpression(fdef, 0, null, "int", 0, null); - checkNewExpression(fdef, 1, null, "int", 0, IASTIdExpression.class); - checkNewExpression(fdef, 2, IASTIdExpression.class, "int", 0, null); - checkNewExpression(fdef, 3, IASTIdExpression.class, "int", 0, IASTIdExpression.class); - checkNewExpression(fdef, 4, null, "int", 0, null); - checkNewExpression(fdef, 5, null, "int", 0, IASTIdExpression.class); - checkNewExpression(fdef, 6, IASTIdExpression.class, "int", 0, null); - checkNewExpression(fdef, 7, IASTIdExpression.class, "int", 0, IASTIdExpression.class); + checkNewExpression(fdef, 0, null, "int", null); + checkNewExpression(fdef, 1, null, "int", IASTExpressionList.class); + checkNewExpression(fdef, 2, null, "int", IASTIdExpression.class); + checkNewExpression(fdef, 3, IASTIdExpression.class, "int", null); + checkNewExpression(fdef, 4, IASTIdExpression.class, "int", IASTExpressionList.class); + checkNewExpression(fdef, 5, IASTIdExpression.class, "int", IASTIdExpression.class); + checkNewExpression(fdef, 6, null, "int", null); + checkNewExpression(fdef, 7, null, "int", IASTExpressionList.class); + checkNewExpression(fdef, 8, null, "int", IASTIdExpression.class); + checkNewExpression(fdef, 9, IASTIdExpression.class, "int", null); + checkNewExpression(fdef, 10, IASTIdExpression.class, "int", IASTExpressionList.class); + checkNewExpression(fdef, 11, IASTIdExpression.class, "int", IASTIdExpression.class); - checkNewExpression(fdef, 8, null, "int [] []", 2, null); - checkNewExpression(fdef, 9, null, "int [] []", 2, IASTIdExpression.class); - checkNewExpression(fdef, 10, IASTIdExpression.class, "int [] []", 2, null); - checkNewExpression(fdef, 11, IASTIdExpression.class, "int [] []", 2, IASTIdExpression.class); - checkNewExpression(fdef, 12, null, "int [] []", 2, null); - checkNewExpression(fdef, 13, null, "int [] []", 2, IASTIdExpression.class); - checkNewExpression(fdef, 14, IASTIdExpression.class, "int [] []", 2, null); - checkNewExpression(fdef, 15, IASTIdExpression.class, "int [] []", 2, IASTIdExpression.class); + checkNewExpression(fdef, 12, null, "int [] []", null); + checkNewExpression(fdef, 13, IASTIdExpression.class, "int [] []", null); + checkNewExpression(fdef, 14, null, "int [] []", null); + checkNewExpression(fdef, 15, IASTIdExpression.class, "int [] []", null); } - private void checkNewExpression(IASTFunctionDefinition fdef, int i_expr, Class placement, String type, int array, Class init) { + private void checkNewExpression(IASTFunctionDefinition fdef, int i_expr, Class placement, String type, Class init) { IASTExpression expr; ICPPASTNewExpression newExpr; expr= getExpressionOfStatement(fdef, i_expr); @@ -5732,8 +5736,6 @@ public class AST2CPPTests extends AST2BaseTest { } else { assertInstance(newExpr.getNewInitializer(), init); } - assertEquals(array, newExpr.getNewTypeIdArrayExpressions().length); isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), type); } - } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecFailingTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecFailingTest.java index a655facfd2c..a4a8578d790 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecFailingTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecFailingTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2008 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 @@ -10,10 +10,11 @@ *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.ast2; -import org.eclipse.cdt.core.parser.ParserLanguage; + /** * @author dsteffle + * mstodo the class should be removed */ public class AST2CSpecFailingTest extends AST2SpecBaseTest { @@ -38,19 +39,20 @@ public class AST2CSpecFailingTest extends AST2SpecBaseTest { --End Example] */ public void test6_7_7s6() throws Exception { - StringBuffer buffer = new StringBuffer(); - buffer.append("typedef signed int t;\n"); //$NON-NLS-1$ - buffer.append("typedef int plain;\n"); //$NON-NLS-1$ - buffer.append("struct tag {\n"); //$NON-NLS-1$ - buffer.append("unsigned t:4;\n"); //$NON-NLS-1$ - buffer.append("const t:5;\n"); //$NON-NLS-1$ - buffer.append("plain r:5;\n"); //$NON-NLS-1$ - buffer.append("};\n"); //$NON-NLS-1$ - buffer.append("t f(t (t));\n"); //$NON-NLS-1$ - buffer.append("long t;\n"); //$NON-NLS-1$ - try { - parse(buffer.toString(), ParserLanguage.C, true, 0); - assertTrue(false); - } catch (Exception e) {} + // test is no longer failing, was moved to AST2CSpecTest +// StringBuffer buffer = new StringBuffer(); +// buffer.append("typedef signed int t;\n"); //$NON-NLS-1$ +// buffer.append("typedef int plain;\n"); //$NON-NLS-1$ +// buffer.append("struct tag {\n"); //$NON-NLS-1$ +// buffer.append("unsigned t:4;\n"); //$NON-NLS-1$ +// buffer.append("const t:5;\n"); //$NON-NLS-1$ +// buffer.append("plain r:5;\n"); //$NON-NLS-1$ +// buffer.append("};\n"); //$NON-NLS-1$ +// buffer.append("t f(t (t));\n"); //$NON-NLS-1$ +// buffer.append("long t;\n"); //$NON-NLS-1$ +// try { +// parse(buffer.toString(), ParserLanguage.C, true, 0); +// assertTrue(false); +// } catch (Exception e) {} } -} \ No newline at end of file +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecTest.java index 7733d156563..38189e50b59 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CSpecTest.java @@ -2078,4 +2078,32 @@ public class AST2CSpecTest extends AST2SpecBaseTest { parseCandCPP(buffer.toString(), false, 0); } + + /** + [--Start Example(C 6.7.7-6): + typedef signed int t; + typedef int plain; + struct tag { + unsigned t:4; + const t:5; + plain r:5; + }; + t f(t (t)); + long t; + --End Example] + */ + public void test6_7_7s6() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("typedef signed int t;\n"); //$NON-NLS-1$ + buffer.append("typedef int plain;\n"); //$NON-NLS-1$ + buffer.append("struct tag {\n"); //$NON-NLS-1$ + buffer.append("unsigned t:4;\n"); //$NON-NLS-1$ + buffer.append("const t:5;\n"); //$NON-NLS-1$ + buffer.append("plain r:5;\n"); //$NON-NLS-1$ + buffer.append("};\n"); //$NON-NLS-1$ + buffer.append("t f(t (t));\n"); //$NON-NLS-1$ + buffer.append("long t;\n"); //$NON-NLS-1$ + + parse(buffer.toString(), ParserLanguage.C, true, 0); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SpecBaseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SpecBaseTest.java index f1f6394096d..2762fd8a300 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SpecBaseTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2SpecBaseTest.java @@ -65,7 +65,11 @@ public class AST2SpecBaseTest extends AST2BaseTest { parse( code, ParserLanguage.C, false, true, checkBindings, expectedProblemBindings, null); parse( code, ParserLanguage.CPP, false, true, checkBindings, expectedProblemBindings, null ); } - + + protected IASTTranslationUnit parseWithErrors( String code, ParserLanguage lang) throws ParserException { + return parse(code, lang, false, false, false, 0, null ); + } + protected IASTTranslationUnit parse( String code, ParserLanguage lang, boolean checkBindings, int expectedProblemBindings ) throws ParserException { return parse(code, lang, false, true, checkBindings, expectedProblemBindings, null ); } @@ -134,7 +138,7 @@ public class AST2SpecBaseTest extends AST2BaseTest { NameResolver res = new NameResolver(); tu.accept( res ); if (res.problemBindings.size() != expectedProblemBindings ) - throw new ParserException("Expected " + expectedProblemBindings + " problems, encountered " + res.problemBindings.size() ); //$NON-NLS-1$ //$NON-NLS-2$ + throw new ParserException("Expected " + expectedProblemBindings + " problems, encountered " + res.problemBindings.size() ); if (problems != null) { for (int i = 0; i < problems.length; i++) { assertEquals(problems[i], res.problemBindings.get(i)); @@ -143,24 +147,24 @@ public class AST2SpecBaseTest extends AST2BaseTest { } if( parser2.encounteredError() && expectNoProblems ) - throw new ParserException( "FAILURE"); //$NON-NLS-1$ + throw new ParserException( "FAILURE"); if( lang == ParserLanguage.C && expectNoProblems ) { if (CVisitor.getProblems(tu).length != 0) { - throw new ParserException (" CVisitor has AST Problems " ); //$NON-NLS-1$ + throw new ParserException (" CVisitor has AST Problems " ); } if (tu.getPreprocessorProblems().length != 0) { - throw new ParserException (" C TranslationUnit has Preprocessor Problems " ); //$NON-NLS-1$ + throw new ParserException (" C TranslationUnit has Preprocessor Problems " ); } } else if ( lang == ParserLanguage.CPP && expectNoProblems ) { if (CPPVisitor.getProblems(tu).length != 0) { - throw new ParserException (" CPPVisitor has AST Problems " ); //$NON-NLS-1$ + throw new ParserException (" CPPVisitor has AST Problems " ); } if (tu.getPreprocessorProblems().length != 0) { - throw new ParserException (" CPP TranslationUnit has Preprocessor Problems " ); //$NON-NLS-1$ + throw new ParserException (" CPP TranslationUnit has Preprocessor Problems " ); } } @@ -179,6 +183,7 @@ public class AST2SpecBaseTest extends AST2BaseTest { public int numNullBindings = 0; + @Override public int visit(IASTName name) { nameList.add(name); IBinding binding = name.resolveBinding(); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index 85f5867259e..bf44ca0f848 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -3746,8 +3746,17 @@ public class AST2Tests extends AST2BaseTest { assertInstance(col.getName(11).resolveBinding(), ITypedef.class); // function ptr - assertInstance(col.getName(12).resolveBinding(), ITypedef.class); - assertInstance(col.getName(13).resolveBinding(), IProblemBinding.class); + final IBinding typedef = col.getName(12).resolveBinding(); + final IBinding secondJ = col.getName(13).resolveBinding(); + assertInstance(typedef, ITypedef.class); + if (lang == ParserLanguage.CPP) { + assertInstance(secondJ, IProblemBinding.class); + } else { + // for plain C this is actually not a problem, the second J has to be interpreted as a (useless) + // parameter name. + assertInstance(typedef, ITypedef.class); + isTypeEqual(((ITypedef) typedef).getType(), "int (int) *"); + } } } @@ -4817,9 +4826,7 @@ public class AST2Tests extends AST2BaseTest { // int f3(int (tint)); // int f4(int (identifier)); // int f5(int *(tint[10])); - public void _testParamWithFunctionType_Bug84242() throws Exception { - // works for plain-c, see testcase below. - // mstodo also check related failure AST2CPPSpecFailingTest._test8_2s7a() + public void testParamWithFunctionType_Bug84242() throws Exception { final String comment= getAboveComment(); final boolean[] isCpps= {false, true}; for (boolean isCpp : isCpps) { @@ -4844,7 +4851,7 @@ public class AST2Tests extends AST2BaseTest { // class C { }; // void f1(int(C)) { } - public void _testParamWithFunctionTypeCpp_Bug84242() throws Exception { + public void testParamWithFunctionTypeCpp_Bug84242() throws Exception { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); IFunction f= ba.assertNonProblem("f1", 2, IFunction.class); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CommentTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CommentTests.java index b89c169fe54..f0d8de7e3f4 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CommentTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CommentTests.java @@ -120,17 +120,17 @@ public class CommentTests extends AST2BaseTest { private String getCppSource() { StringBuffer buffer = new StringBuffer(); - buffer.append("CppClass()\n"); + buffer.append("void CppClass()\n"); buffer.append("{\n"); buffer.append(" // Comment in cpp\n"); - buffer.append(" value = 1 + /*The magic 5 */5 * 6;\n"); + buffer.append(" int value = 1 + /*The magic 5 */5 * 6;\n"); buffer.append(" // Another comment\n"); buffer.append(" value++;\n"); buffer.append("}\n"); buffer.append("/* A blockcomment \n"); buffer.append("* over multiple lines */\n"); buffer.append("//Toplevel comment\n"); - buffer.append("doIrgendwas(){\n"); + buffer.append("void doIrgendwas(){\n"); buffer.append(" //A little bit code\n"); buffer.append(" int i = 3; //Trailing comment\n"); buffer.append(" ;\n"); @@ -152,7 +152,7 @@ public class CommentTests extends AST2BaseTest { buffer.append(" int n = i++ +5;\n"); buffer.append(" //Last comment in cpp\n"); buffer.append("}\n"); - buffer.append("globaleFuntktion(){\n"); + buffer.append("int globaleFuntktion(){\n"); buffer.append("//An integer\n"); buffer.append("int i;\n"); buffer.append("}\n"); @@ -243,8 +243,7 @@ public class CommentTests extends AST2BaseTest { assertEquals(5, comments.length); assertNotNull(comments[0].getFileLocation()); assertNotNull(comments[0].getNodeLocations()); - for (int i = 0; i < comments.length; i++) { - IASTComment comment = comments[i]; + for (IASTComment comment : comments) { IASTFileLocation loc= comment.getFileLocation(); int idx= loc.getNodeOffset() + comment.getRawSignature().indexOf("TODO"); assertEquals("TODO", code.substring(idx, idx+4)); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java index bc4e25d8a23..5fa38091420 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java @@ -854,8 +854,7 @@ public class CompleteParser2Tests extends BaseTestCase { assertInstances( col, A, 2 ); } - // failing, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=236856 - public void _testNewExpressions() throws Exception { + public void testNewExpressions() throws Exception { IASTTranslationUnit tu = parse( "typedef int A; int B; int C; int D; int P; int*p = new (P) (A[B][C][D]);" ); //$NON-NLS-1$ CPPNameCollector col = new CPPNameCollector(); tu.accept( col ); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMSelectionParseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMSelectionParseTest.java index 34d5ddec319..7c09d764eef 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMSelectionParseTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMSelectionParseTest.java @@ -98,9 +98,9 @@ public class DOMSelectionParseTest extends DOMSelectionParseBaseTest { public void testBaseCase_FunctionDeclaration() throws Exception { - String code = "int x(); x( );"; //$NON-NLS-1$ - int offset1 = code.indexOf( "x()" ); //$NON-NLS-1$ - int offset2 = code.indexOf( "()"); //$NON-NLS-1$ + String code = "int x(); void test() {x( );}"; //$NON-NLS-1$ + int offset1 = code.indexOf( "x( )" ); //$NON-NLS-1$ + int offset2 = code.indexOf( "( )"); //$NON-NLS-1$ IASTNode node = parse( code, offset1, offset2 ); assertTrue( node instanceof IASTName ); assertTrue( ((IASTName)node).resolveBinding() instanceof IFunction ); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/QuickParser2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/QuickParser2Tests.java index 1b126525206..40de3b495b5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/QuickParser2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/QuickParser2Tests.java @@ -521,7 +521,7 @@ public class QuickParser2Tests extends TestCase { public void testBug36769A() throws Exception { - parse("template cls::operator &() const {}\n"); + parse("template cls::operator otherType() const {}\n"); parse("template cls::cls() {}\n"); parse("template cls::~cls() {}\n"); } @@ -535,7 +535,11 @@ public class QuickParser2Tests extends TestCase { } public void testBugFunctor758() throws Exception { - parse("template Functor(Fun fun) : spImpl_(new FunctorHandler(fun)){}"); + parse( + "class Functor {"+ + "template Functor(Fun fun) : spImpl_(new FunctorHandler(fun)){}" + + "};" + ); } public void testBug36932() throws Exception { @@ -642,10 +646,10 @@ public class QuickParser2Tests extends TestCase { public void testBug36696() throws Exception { Writer code = new StringWriter(); - code - .write("template RefCounted(const RefCounted& rhs)\n"); - code - .write(": pCount_(reinterpret_cast(rhs).pCount_) {}\n"); + code.write("template class RefCounted {"); + code.write("template RefCounted(const RefCounted& rhs)\n"); + code.write(": pCount_(reinterpret_cast(rhs).pCount_) {}\n"); + code.write("};"); parse(code.toString()); } @@ -839,7 +843,11 @@ public class QuickParser2Tests extends TestCase { } public void testBug36690() throws Exception { - parse("Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get())){}"); + parse( + "class Functor {" + + "Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get())){}" + + "}" + ); } public void testBug36703() throws Exception { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java index 330e7479f93..268ca5e9a51 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/prefix/BasicCompletionTest.java @@ -78,22 +78,22 @@ public class BasicCompletionTest extends CompletionTestBase { public void testTypedef() throws Exception { String code = - "typedef int blah;" + + "void test() {typedef int blah;" + "bl"; // C++ IASTCompletionNode node = getGPPCompletionNode(code); IASTName[] names = node.getNames(); assertEquals(2, names.length); - assertNull(names[0].getTranslationUnit()); - IBinding[] bindings = names[1].getCompletionContext().findBindings(names[1], true); + assertNull(names[1].getTranslationUnit()); + IBinding[] bindings = names[0].getCompletionContext().findBindings(names[0], true); assertEquals(1, bindings.length); assertEquals("blah", ((ITypedef)bindings[0]).getName()); // C node = getGCCCompletionNode(code); names = node.getNames(); - assertEquals(1, names.length); + assert(names.length > 0); bindings = names[0].getCompletionContext().findBindings(names[0], true); assertEquals(1, bindings.length); assertEquals("blah", ((ITypedef)bindings[0]).getName()); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/append/ArraySizeExpressionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/append/ArraySizeExpressionTest.java index 36890e2a407..e4d6f8dfb55 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/append/ArraySizeExpressionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/append/ArraySizeExpressionTest.java @@ -13,10 +13,14 @@ package org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.append; import junit.framework.Test; +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.ChangeGeneratorTest; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTArrayModifier; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModification; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModificationStore; @@ -47,8 +51,11 @@ public class ArraySizeExpressionTest extends ChangeGeneratorTest { public int visit(IASTExpression expression) { if (expression instanceof ICPPASTNewExpression) { ICPPASTNewExpression newExpression = (ICPPASTNewExpression) expression; - newExpression.getNewTypeIdArrayExpressions(); - ASTModification modification = new ASTModification(ASTModification.ModificationKind.APPEND_CHILD, newExpression, new CPPASTLiteralExpression(0, "5"), null); //$NON-NLS-1$ + IASTTypeId id= newExpression.getTypeId(); + IASTArrayDeclarator dtor= (IASTArrayDeclarator) id.getAbstractDeclarator(); + IASTArrayModifier[] mods= dtor.getArrayModifiers(); + IASTArrayModifier add= new CPPASTArrayModifier(new CPPASTLiteralExpression(0, "5")); + ASTModification modification = new ASTModification(ASTModification.ModificationKind.APPEND_CHILD, dtor, add, null); modStore.storeModification(null, modification); } return PROCESS_CONTINUE; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/insertbefore/ArraySizeExpressionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/insertbefore/ArraySizeExpressionTest.java index caae9c52925..a92f8c4a3b3 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/insertbefore/ArraySizeExpressionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/insertbefore/ArraySizeExpressionTest.java @@ -13,10 +13,14 @@ package org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.insertbefore; import junit.framework.Test; +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.ChangeGeneratorTest; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTArrayModifier; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModification; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModificationStore; @@ -49,8 +53,11 @@ public class ArraySizeExpressionTest extends ChangeGeneratorTest { public int visit(IASTExpression expression) { if (expression instanceof ICPPASTNewExpression) { ICPPASTNewExpression newExpression = (ICPPASTNewExpression) expression; - IASTExpression[] arraySizeExpressions = newExpression.getNewTypeIdArrayExpressions(); - ASTModification modification = new ASTModification(ASTModification.ModificationKind.INSERT_BEFORE, arraySizeExpressions[0], new CPPASTLiteralExpression(0, "6"), null); //$NON-NLS-1$ + IASTTypeId id= newExpression.getTypeId(); + IASTArrayDeclarator dtor= (IASTArrayDeclarator) id.getAbstractDeclarator(); + IASTArrayModifier[] mods= dtor.getArrayModifiers(); + IASTArrayModifier add= new CPPASTArrayModifier(new CPPASTLiteralExpression(0, "6")); + ASTModification modification = new ASTModification(ASTModification.ModificationKind.INSERT_BEFORE, mods[0], add, null); modStore.storeModification(null, modification); } return PROCESS_CONTINUE; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/remove/ArraySizeExpressionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/remove/ArraySizeExpressionTest.java index a7813073d61..75c3d82b0af 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/remove/ArraySizeExpressionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/remove/ArraySizeExpressionTest.java @@ -13,7 +13,10 @@ package org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.remove; import junit.framework.Test; +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.ChangeGeneratorTest; @@ -47,8 +50,10 @@ public class ArraySizeExpressionTest extends ChangeGeneratorTest { public int visit(IASTExpression expression) { if (expression instanceof ICPPASTNewExpression) { ICPPASTNewExpression newExpression = (ICPPASTNewExpression) expression; - IASTExpression[] arraySizeExpressions = newExpression.getNewTypeIdArrayExpressions(); - ASTModification modification = new ASTModification(ASTModification.ModificationKind.REPLACE, arraySizeExpressions[1], null, null); + IASTTypeId id= newExpression.getTypeId(); + IASTArrayDeclarator dtor= (IASTArrayDeclarator) id.getAbstractDeclarator(); + IASTArrayModifier[] mods= dtor.getArrayModifiers(); + ASTModification modification = new ASTModification(ASTModification.ModificationKind.REPLACE, mods[1], null, null); modStore.storeModification(null, modification); } return PROCESS_CONTINUE; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/replace/ArraySizeExpressionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/replace/ArraySizeExpressionTest.java index 215b9f9e61a..b4f8b84a176 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/replace/ArraySizeExpressionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/rewrite/changegenerator/replace/ArraySizeExpressionTest.java @@ -13,7 +13,10 @@ package org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.replace; import junit.framework.Test; +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; import org.eclipse.cdt.core.parser.tests.rewrite.changegenerator.ChangeGeneratorTest; @@ -54,8 +57,11 @@ public class ArraySizeExpressionTest extends ChangeGeneratorTest { public int visit(IASTExpression expression) { if (expression instanceof ICPPASTNewExpression) { ICPPASTNewExpression newExpression = (ICPPASTNewExpression) expression; - IASTExpression[] arraySizeExpressions = newExpression.getNewTypeIdArrayExpressions(); - ASTModification modification = new ASTModification(ASTModification.ModificationKind.REPLACE, arraySizeExpressions[1], new CPPASTLiteralExpression(0, "7"), null); //$NON-NLS-1$ + IASTTypeId id= newExpression.getTypeId(); + IASTArrayDeclarator dtor= (IASTArrayDeclarator) id.getAbstractDeclarator(); + IASTArrayModifier[] mods= dtor.getArrayModifiers(); + IASTExpression expr= mods[1].getConstantExpression(); + ASTModification modification = new ASTModification(ASTModification.ModificationKind.REPLACE, expr, new CPPASTLiteralExpression(0, "7"), null); //$NON-NLS-1$ modStore.storeModification(null, modification); } return PROCESS_CONTINUE; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMCBugsTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMCBugsTest.java index e2d00141903..e978995197a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMCBugsTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMCBugsTest.java @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2007 Symbian Software Systems and others. + * Copyright (c) 2007, 2008 Symbian Software Systems 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: - * Andrew Ferguson (Symbian) - Initial implementation + * Andrew Ferguson (Symbian) - Initial implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.pdom.tests; @@ -19,6 +20,7 @@ import junit.framework.Test; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IType; @@ -46,6 +48,7 @@ public class PDOMCBugsTest extends BaseTestCase { return suite(PDOMCBugsTest.class); } + @Override protected void setUp() throws Exception { cproject= CProjectHelper.createCProject("PDOMCBugsTest"+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER); Bundle b = CTestPlugin.getDefault().getBundle(); @@ -59,6 +62,7 @@ public class PDOMCBugsTest extends BaseTestCase { super.setUp(); } + @Override protected void tearDown() throws Exception { if (cproject != null) { cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor()); @@ -79,16 +83,16 @@ public class PDOMCBugsTest extends BaseTestCase { IBinding[] bindings= pdom.findBindings(Pattern.compile(".*"), false, IndexFilter.ALL, NPM); assertEquals(7, bindings.length); Set bnames= new HashSet(); - for(int i=0; ileading =>trailing -Klasse1(); = //Comment +Klasse0(); = //Comment =>freestanding @@ -760,7 +760,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -785,7 +785,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; //TEST i++; @@ -810,7 +810,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -840,7 +840,7 @@ public: Klasse1(); std::string toString(); //KommentarDavor - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -852,7 +852,7 @@ private: //= =>leading -inlineMethode() +void inlineMethode() { int i = 0; i++; @@ -874,7 +874,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -893,7 +893,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -913,7 +913,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -933,7 +933,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -949,7 +949,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -967,7 +967,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -990,7 +990,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1008,7 +1008,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1027,7 +1027,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1047,7 +1047,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1069,7 +1069,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1087,7 +1087,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1108,7 +1108,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1131,7 +1131,7 @@ public: Klasse1(); std::string toString(); //TEST - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1143,7 +1143,7 @@ private: //= =>leading -inlineMethode() +void inlineMethode() { int i = 0; i++; @@ -1162,7 +1162,7 @@ public: Klasse1(); std::string toString(); /*TEST*/ - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1174,7 +1174,7 @@ private: //= =>leading -inlineMethode() +void inlineMethode() { int i = 0; i++; @@ -1193,7 +1193,7 @@ class Klasse1 //Nachher public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1210,7 +1210,7 @@ class Klasse1 //Nachher public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1234,7 +1234,7 @@ class Klasse1 /*Nachher*/ public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1251,7 +1251,7 @@ class Klasse1 /*Nachher*/ public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1276,7 +1276,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1294,7 +1294,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1319,7 +1319,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1337,7 +1337,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1364,7 +1364,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1382,7 +1382,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1407,7 +1407,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1433,7 +1433,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1459,7 +1459,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1489,7 +1489,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1520,7 +1520,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; @@ -1547,7 +1547,7 @@ class Klasse1 public: Klasse1(); std::string toString(); - inlineMethode() + void inlineMethode() { int i = 0; i++; diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/FileManager.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/FileManager.java index b2648eaaf74..a7ce30ecf8c 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/FileManager.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/FileManager.java @@ -16,7 +16,7 @@ */ package org.eclipse.cdt.core.testplugin; -import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import org.eclipse.core.resources.IFile; @@ -30,36 +30,37 @@ import org.eclipse.core.runtime.CoreException; * Window>Preferences>Java>Code Generation>Code and Comments */ public class FileManager { - ArrayList fileHandles; + HashSet fileHandles; public FileManager(){ - fileHandles = new ArrayList(); + fileHandles = new HashSet(); } public void addFile(IFile file){ fileHandles.add(file); } - public void closeAllFiles() throws CoreException{ - Iterator iter = fileHandles.iterator(); - while (iter.hasNext()){ - IFile tempFile = (IFile) iter.next(); - tempFile.refreshLocal(IResource.DEPTH_INFINITE,null); - - try { - tempFile.delete(true,null); - } catch (CoreException e) { + public void closeAllFiles() throws CoreException, InterruptedException{ + int wait= 1; + for (int i = 0; i < 11; i++) { + for (Iterator iter= fileHandles.iterator(); iter.hasNext();) { + IFile tempFile = (IFile) iter.next(); try { - Thread.sleep(2000); - } catch (InterruptedException e1) { - - } - finally{ + if (i==1) { + tempFile.refreshLocal(IResource.DEPTH_INFINITE,null); + } tempFile.delete(true,null); + iter.remove(); + } catch (CoreException e) { + if (wait > 2000) + throw e; } - } - + + if (fileHandles.isEmpty()) + return; + Thread.sleep(wait); + wait*=2; } } } \ No newline at end of file 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 7469235e9f2..c560b0eec3f 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 @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2008 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 + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; @@ -81,8 +82,7 @@ public interface ICPPASTNewExpression extends IASTExpression { public static final ASTNodeProperty TYPE_ID = new ASTNodeProperty("ICPPASTNewExpression.TYPE_ID - The type being 'newed'"); //$NON-NLS-1$ /** - * Get the type Id. - * + * Get the type Id. The type-id includes the optional array modifications. * @return IASTTypeId */ public IASTTypeId getTypeId(); @@ -96,9 +96,8 @@ public interface ICPPASTNewExpression extends IASTExpression { public void setTypeId(IASTTypeId typeId); /** - * Is the typeID a new type ID? - * - * @return boolean + * Returns whether the the typeID a new type ID, which is the case when + * the type-id is provided without parenthesis. */ public boolean isNewTypeId(); @@ -117,18 +116,15 @@ public interface ICPPASTNewExpression extends IASTExpression { "ICPPASTNewExpression.NEW_TYPEID_ARRAY_EXPRESSION - Expressions inside array brackets"); //$NON-NLS-1$ /** - * Get the new array size expressions. - * - * @return IASTExpression [] + * @deprecated the id-expressions are part of the type-id. */ + @Deprecated public IASTExpression[] getNewTypeIdArrayExpressions(); /** - * Add another array size expression. - * - * @param expression - * IASTExpression + * @deprecated the id-expressions are part of the type-id */ + @Deprecated public void addNewTypeIdArrayExpression(IASTExpression expression); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 245d4988339..377ad230f3a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -37,6 +37,7 @@ 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; import org.eclipse.cdt.core.dom.ast.IASTIfStatement; @@ -78,8 +79,7 @@ import org.eclipse.cdt.core.parser.ParserMode; * @author jcamelon */ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { - - protected final AbstractParserLogService log; + protected final AbstractParserLogService log; protected final IScanner scanner; protected final ParserMode mode; @@ -192,6 +192,12 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { ASTNode node = (ASTNode) n; return node.getOffset() + node.getLength(); } + + protected void adjustLength(IASTNode n, IASTNode endNode) { + final int endOffset= calculateEndOffset(endNode); + final ASTNode node = (ASTNode) n; + node.setLength(endOffset-node.getOffset()); + } /** * Consume the next token available, regardless of the type. @@ -201,13 +207,12 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { * If there is no token to consume. */ protected IToken consume() throws EndOfFileException { - - if (currToken == null) + if (currToken == null) { currToken = fetchToken(); - IToken lastToken = null; - if (currToken != null) - lastToken = currToken; - currToken = currToken.getNext(); + } + + final IToken lastToken = currToken; + currToken= lastToken.getNext(); return lastToken; } @@ -220,13 +225,33 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { * @throws BacktrackException * If LT(1) != type */ - protected IToken consume(int type) throws EndOfFileException, - BacktrackException { - if (LT(1) == type) - return consume(); - IToken la = LA(1); - throwBacktrack(la.getOffset(), la.getLength()); - return null; + protected IToken consume(int type) throws EndOfFileException, BacktrackException { + final IToken la1= LA(1); + if (la1.getType() != type) + throwBacktrack(la1); + + return consume(); + } + + /** + * Consume the next token available only if the type is as specified. In case we + * reached the end of completion, no token is consumed and the eoc-token returned. + * + * @param type + * The type of token that you are expecting. + * @return the token that was consumed and removed from our buffer. + * @throws BacktrackException + * If LT(1) != type + */ + protected IToken consumeOrEOC(int type) throws EndOfFileException, BacktrackException { + final IToken la1= LA(1); + final int lt1 = la1.getType(); + if (lt1 != type) { + if (lt1 == IToken.tEOC) + return la1; + throwBacktrack(la1); + } + return consume(); } /** @@ -560,6 +585,16 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected abstract IGNUASTCompoundStatementExpression createCompoundStatementExpression(); + protected IASTExpression possiblyEmptyExpressionList(int endToken) throws BacktrackException, EndOfFileException { + IToken la1= LA(1); + if (la1.getType() == endToken) { + IASTExpressionList expressionList = createExpressionList(); + ((ASTNode) expressionList).setOffsetAndLength(la1.getOffset(), 0); + return expressionList; + } + return expression(); + } + protected IASTExpression expression() throws BacktrackException, EndOfFileException { IToken la = LA(1); int startingOffset = la.getOffset(); @@ -593,14 +628,11 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected abstract IASTExpression multiplicativeExpression() throws BacktrackException, EndOfFileException; - protected abstract IASTTypeId typeId(boolean forNewExpression) - throws EndOfFileException; + protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException; - protected abstract IASTExpression castExpression() - throws BacktrackException, EndOfFileException; + protected abstract IASTExpression castExpression() throws BacktrackException, EndOfFileException; - protected abstract IASTExpression unaryExpression() - throws BacktrackException, EndOfFileException; + protected abstract IASTExpression unaryExpression() throws BacktrackException, EndOfFileException; protected abstract IASTExpression buildTypeIdExpression(int op, IASTTypeId typeId, int startingOffset, int endingOffset); @@ -818,7 +850,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { boolean needBack = false; try { consume(); - d = typeId(false); + d = typeId(DeclarationOptions.TYPEID); if (d == null) needBack = true; else @@ -862,7 +894,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } catch (BacktrackException e) { backup(m); - d = typeId(false); + d = typeId(DeclarationOptions.TYPEID); if (d == null) throw e; } @@ -874,14 +906,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { if (d != null) return buildTypeIdExpression(IGNUASTTypeIdExpression.op_typeof, d, offset, lastOffset); - if (expression != null) - return buildUnaryExpression(IGNUASTUnaryExpression.op_typeof, expression, offset, lastOffset); - - return null; + return buildUnaryExpression(IGNUASTUnaryExpression.op_typeof, expression, offset, lastOffset); } - protected IASTStatement handleFunctionBody() throws BacktrackException, - EndOfFileException { + protected IASTStatement handleFunctionBody() throws BacktrackException, EndOfFileException { if (mode == ParserMode.QUICK_PARSE || mode == ParserMode.STRUCTURAL_PARSE) { IToken curr = LA(1); IToken last = skipOverCompoundStatement(); @@ -896,9 +924,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { IASTCompoundStatement cs = createCompoundStatement(); ((ASTNode) cs).setOffsetAndLength(curr.getOffset(), last.getEndOffset() - curr.getOffset()); return cs; - } else if (mode == ParserMode.COMPLETE_PARSE) - return functionBody(); - return null; + } + + // full parse + return functionBody(); } /** @@ -912,184 +941,50 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return compoundStatement(); } - protected abstract IASTDeclarator initDeclarator() - throws EndOfFileException, BacktrackException; + protected abstract IASTDeclarator initDeclarator(DeclarationOptions option) throws EndOfFileException, BacktrackException; /** - * @param flags input flags that are used to make our decision + * @param option the options with which to parse the declaration * @throws FoundDeclaratorException encountered EOF while looking ahead */ - protected void lookAheadForDeclarator(Flags flags) throws FoundDeclaratorException { - if (flags.typeId) - return; + protected void lookAheadForDeclarator(final DeclarationOptions option) throws FoundDeclaratorException { IToken mark = null; try { mark = mark(); - } catch (EndOfFileException eof) { - return; - } - try - { - if( LT(1) == IToken.tIDENTIFIER && LT(2) == IToken.tIDENTIFIER ) - return; - } - catch( EndOfFileException eof ) - { - backup( mark ); - return; - } - try { - IASTDeclarator d = initDeclarator(); - IToken la = LA(1); - backup(mark); - if (la == null || la.getType() == IToken.tEOC) - return; - final ASTNode n = ((ASTNode) d); - final int length = n.getLength(); - final int offset = n.getOffset(); - if (length == 0) - return; - if (flags.parm) { - ASTNode name = (ASTNode) d.getName(); - if (name.getOffset() == offset) { - // fix for bugs 147903 and 179493 - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=147903 - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=179493 - if (name.getLength() == length || d instanceof IASTArrayDeclarator) { - return; - } - } - if (d.getInitializer() != null) { - ASTNode init = (ASTNode) d.getInitializer(); - if (name.getOffset() == offset - && n.getOffset() + n.getLength() == init - .getOffset() - + init.getLength()) - return; - } + final IASTDeclarator dtor= initDeclarator(option); + final IToken la = LA(1); + if (la == null || la == mark) + return; - switch (la.getType()) { - case IToken.tCOMMA: - case IToken.tRPAREN: - throw new FoundDeclaratorException( d, la ); - default: - return; - } - } - - checkTokenVsDeclarator(la, d); - return; + if (verifyLookaheadDeclarator(option, dtor, la)) + throw new FoundDeclaratorException(dtor, la); } catch (BacktrackException bte) { - backup(mark); - return; } catch (EndOfFileException e) { - backup(mark); - return; + } finally { + if (mark != null) + backup(mark); } } - protected void checkTokenVsDeclarator(IToken la, IASTDeclarator d) throws FoundDeclaratorException { - switch (la.getType()) { - case IToken.tCOMMA: - case IToken.tLBRACE: - throw new FoundDeclaratorException( d, la ); - case IToken.tSEMI: - if (d instanceof IASTFieldDeclarator) - return; - throw new FoundDeclaratorException( d, la ); - default: - return; - } - } + protected abstract boolean verifyLookaheadDeclarator(DeclarationOptions option, IASTDeclarator d, IToken nextToken); - public static class FoundDeclaratorException extends Exception - { + public static class FoundDeclaratorException extends Exception { private static final long serialVersionUID = 0; - public final IASTDeclarator declarator; - public final IToken currToken; public IASTDeclSpecifier declSpec; + public IASTDeclarator declarator; + + public IASTDeclSpecifier altSpec; + public IASTDeclarator altDeclarator; - public FoundDeclaratorException( IASTDeclarator d, IToken t ) - { + public IToken currToken; + + public FoundDeclaratorException(IASTDeclarator d, IToken t) { this.declarator = d; this.currToken =t; } } - public static class Flags { - private boolean encounteredTypename = false; - - // have we encountered a typeName yet? - private boolean encounteredRawType = false; - - // have we encountered a raw type yet? - boolean parm = false; - - // is this for a simpleDeclaration or parameterDeclaration? - boolean constructor = false; - - boolean typeId = false; - - // are we attempting the constructor strategy? - public Flags(boolean parm, boolean c, boolean t) { - this.parm = parm; - constructor = c; - typeId = t; - } - - public Flags(boolean parm, boolean typeId) { - this(parm, false, typeId); - } - - /** - * @return true if we have encountered a simple type up to this point, - * false otherwise - */ - public boolean haveEncounteredRawType() { - return encounteredRawType; - } - - /** - * @return true if we have encountered a typename up to this point, - * false otherwise - */ - public boolean haveEncounteredTypename() { - return encounteredTypename; - } - - /** - * @param b - - * set to true if we encounter a raw type (int, short, etc.) - */ - public void setEncounteredRawType(boolean b) { - encounteredRawType = b; - } - - /** - * @param b - - * set to true if we encounter a typename - */ - public void setEncounteredTypename(boolean b) { - encounteredTypename = b; - } - - /** - * @return true if we are parsing for a ParameterDeclaration - */ - public boolean isForParameterDeclaration() { - return parm; - } - - /** - * @return whether or not we are attempting the constructor strategy or - * not - */ - public boolean isForConstructor() { - return constructor; - } - } - /** * Parse an enumeration specifier, as according to the ANSI specs in C & * C++. enumSpecifier: "enum" (name)? "{" (enumerator-list) "}" @@ -1246,8 +1141,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected abstract IASTCaseStatement createCaseStatement(); - protected abstract IASTDeclaration declaration() throws BacktrackException, - EndOfFileException; + protected abstract IASTDeclaration declaration(DeclarationOptions option) throws BacktrackException, EndOfFileException; protected IASTDeclaration asmDeclaration() throws EndOfFileException, @@ -1330,7 +1224,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { * This method will attempt to parse a statement as both an expression and a declaration, * if both parses succeed then an ambiguity node is returned. */ - protected IASTStatement parseDeclarationOrExpressionStatement() throws EndOfFileException, BacktrackException { + protected IASTStatement parseDeclarationOrExpressionStatement(DeclarationOptions option) throws EndOfFileException, BacktrackException { // First attempt to parse an expressionStatement // Note: the function style cast ambiguity is handled in expression // Since it only happens when we are in a statement @@ -1354,7 +1248,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { // Now attempt to parse a declarationStatement IASTDeclarationStatement ds = null; try { - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(option); ds = createDeclarationStatement(); ds.setDeclaration(d); ((ASTNode) ds).setOffsetAndLength(((ASTNode) d).getOffset(), ((ASTNode) d).getLength()); @@ -1369,10 +1263,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return ds; } if (ds == null) { - while (true) { - if (consume() == lastTokenOfExpression) - break; - } + backup(lastTokenOfExpression); consume(); return expressionStatement; } @@ -1396,61 +1287,49 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } } - // x = y; // implicit int - // valid at Translation Unit scope but not valid as a statement in a function body - if(isImplicitInt(ds.getDeclaration())) { - backup(mark); - while (true) { - if (consume() == lastTokenOfExpression) - break; - } + final IASTDeclaration declaration = ds.getDeclaration(); + if (declaration instanceof IASTSimpleDeclaration) { + final IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) declaration; + IASTDeclSpecifier declspec= simpleDecl.getDeclSpecifier(); + if (declspec instanceof IASTNamedTypeSpecifier) { + final IASTDeclarator[] declarators = simpleDecl.getDeclarators(); - return expressionStatement; - } + // x; + // can be parsed as a named declaration specifier without a declarator + if (declarators.length == 0) { + backup(lastTokenOfExpression); consume(); + return expressionStatement; + } - // generalization of the previous check for implicit int - if (ds.getDeclaration() instanceof IASTAmbiguousDeclaration ) { - IASTAmbiguousDeclaration amb = (IASTAmbiguousDeclaration) ds.getDeclaration(); - boolean allImplicitInt = true; - for(IASTDeclaration ambD : amb.getDeclarations()) { - if(!isImplicitInt(ambD)) { - allImplicitInt = false; - break; - } - } - if(allImplicitInt) { - backup(mark); - while (true) { - if (consume() == lastTokenOfExpression) - break; - } - return expressionStatement; - } - } - - // x; - // a single identifier can be parsed as a named declaration specifier without a declarator - if(ds.getDeclaration() instanceof IASTSimpleDeclaration && - ((IASTSimpleDeclaration) ds.getDeclaration()).getDeclSpecifier() instanceof IASTNamedTypeSpecifier) { - final IASTDeclarator[] declarators = ((IASTSimpleDeclaration) ds.getDeclaration()).getDeclarators(); - if (declarators.length == 0 - || (declarators.length == 1 && (declarators[0].getName() - .toCharArray().length == 0 && declarators[0] - .getNestedDeclarator() == null))) { - backup(mark); - while (true) { - if (consume() == lastTokenOfExpression) - break; - } - - return expressionStatement; - } - } + // a function call interpreted as declaration: 'func(x);' --> 'func x;' + if (declarators.length == 1) { + IASTName name= ((IASTNamedTypeSpecifier) declspec).getName(); + final IASTDeclarator dtor= declarators[0]; + if (name.contains(declspec)) { + if (dtor.getNestedDeclarator() != null) { + if (dtor instanceof IASTAmbiguousDeclarator == false + && dtor instanceof IASTArrayDeclarator == false + && dtor instanceof IASTFieldDeclarator == false + && dtor instanceof IASTFunctionDeclarator == false) { + backup(lastTokenOfExpression); consume(); + return expressionStatement; + } + } + } + + if (dtor.getName().toCharArray().length == 0 && dtor.getNestedDeclarator() == null) { + throw new Error(); +// backup(lastTokenOfExpression); consume(); +// return expressionStatement; + } + } + } + } // create and return ambiguity node IASTAmbiguousStatement statement = createAmbiguousStatement(); - statement.addStatement(ds); statement.addStatement(expressionStatement); + statement.addStatement(ds); ((ASTNode) statement).setOffsetAndLength((ASTNode) ds); return statement; } @@ -1746,7 +1625,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { try { if (typeIdWithParentheses) consume(IToken.tLPAREN); - typeId = typeId(false); + typeId = typeId(DeclarationOptions.TYPEID); if (typeId != null) { if (typeIdWithParentheses) { switch (LT(1)) { @@ -1827,16 +1706,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return null; } - protected abstract IASTDeclaration simpleDeclaration() throws BacktrackException, - EndOfFileException; - /** * @throws BacktrackException */ - protected IASTStatement forInitStatement() throws BacktrackException, EndOfFileException { + protected IASTStatement forInitStatement(DeclarationOptions option) throws BacktrackException, EndOfFileException { if( LT(1) == IToken.tSEMI ) return parseNullStatement(); - return parseDeclarationOrExpressionStatement(); + return parseDeclarationOrExpressionStatement(option); } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java new file mode 100644 index 00000000000..9fab6865c7f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. 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: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +/** + * Configures the parsing of a declaration in various contexts. + * @since 5.0 + */ +public class DeclarationOptions { + final public static int ALLOW_EMPTY_SPECIFIER= 0x01; + final public static int ALLOW_ABSTRACT= 0x02; + final public static int REQUIRE_ABSTRACT= 0x04; + final public static int ALLOW_BITFIELD= 0x08; + final public static int NO_INITIALIZER= 0x10; + final public static int ALLOW_CONSTRUCTOR_INITIALIZER= 0x20; + final public static int NO_FUNCTIONS= 0x40; + final public static int NO_ARRAYS= 0x80; + final public static int NO_NESTED= 0x100; + + public static final DeclarationOptions + GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_CONSTRUCTOR_INITIALIZER), + C_MEMBER= new DeclarationOptions(ALLOW_BITFIELD), + CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD | ALLOW_CONSTRUCTOR_INITIALIZER), + LOCAL= new DeclarationOptions(ALLOW_CONSTRUCTOR_INITIALIZER), + PARAMETER= new DeclarationOptions(ALLOW_ABSTRACT), + TYPEID= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER), + TYPEID_NEW= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | NO_FUNCTIONS | NO_NESTED), + TYPEID_CONVERSION= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | NO_FUNCTIONS | NO_NESTED), + EXCEPTION= new DeclarationOptions(ALLOW_ABSTRACT | NO_INITIALIZER), + CONDITION= new DeclarationOptions(ALLOW_CONSTRUCTOR_INITIALIZER), + C_PARAMETER_NON_ABSTRACT= new DeclarationOptions(ALLOW_ABSTRACT | ALLOW_EMPTY_SPECIFIER); + + final public boolean fAllowEmptySpecifier; + final public boolean fAllowAbstract; + final public boolean fRequireAbstract; + final public boolean fAllowBitField; + final public boolean fAllowInitializer; + final public boolean fAllowConstructorInitializer; + final public boolean fAllowFunctions; + final public boolean fAllowNested; + + public DeclarationOptions(int options) { + fAllowEmptySpecifier= (options & ALLOW_EMPTY_SPECIFIER) != 0; + fRequireAbstract= (options & REQUIRE_ABSTRACT) != 0; + fAllowAbstract= fRequireAbstract || (options & ALLOW_ABSTRACT) != 0; + fAllowBitField= (options & ALLOW_BITFIELD) != 0; + fAllowInitializer= (options & NO_INITIALIZER) == 0; + fAllowConstructorInitializer= fAllowInitializer && (options & ALLOW_CONSTRUCTOR_INITIALIZER) != 0; + fAllowFunctions= (options & NO_FUNCTIONS) == 0; + fAllowNested= (options & NO_NESTED) == 0; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTAmbiguousDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTAmbiguousDeclarator.java new file mode 100644 index 00000000000..fa6f9cb031c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTAmbiguousDeclarator.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Wind River Systems, Inc. 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: + * Markus Schorn - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; + +/** + * Needed to handle the ambiguous declarator. + * @since 5.0 + */ +public interface IASTAmbiguousDeclarator extends IASTDeclarator { + + public static final ASTNodeProperty SUBDECLARATOR = new ASTNodeProperty( "IASTAmbiguousDeclarator.SUBDECLARATOR"); //$NON-NLS-1$ + + /** + * Add an alternative to this ambiguous declarator. + */ + public void addDeclarator(IASTDeclarator e); + + /** + * Return an array of all alternatives for this ambiguous declarator. + */ + public IASTDeclarator[] getDeclarators(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTAmbiguousParameterDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTAmbiguousParameterDeclaration.java new file mode 100644 index 00000000000..5b012f729a1 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTAmbiguousParameterDeclaration.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Wind River Systems, Inc. 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: + * Markus Schorn - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; + +/** + * Needed to handle the ambiguity for parameter declarations in plain C + * @since 5.0 + */ +public interface IASTAmbiguousParameterDeclaration extends IASTParameterDeclaration { + + public static final ASTNodeProperty SUBDECLARATION = new ASTNodeProperty( "IASTAmbiguousParameterDeclaration.SUBDECLARATION"); //$NON-NLS-1$ + + /** + * Add an alternative to this ambiguous parameter declaration. + */ + public void addParameterDeclaration(IASTParameterDeclaration e); + + /** + * Return an array of all alternatives for this ambiguous parameter declaration. + */ + public IASTParameterDeclaration[] getParameterDeclarations(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousDeclarator.java new file mode 100644 index 00000000000..3d5372d5242 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousDeclarator.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Wind River Systems, Inc. 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: + * Markus Schorn - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.c; + +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; +import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator; +import org.eclipse.core.runtime.Assert; + +/** + * Handles ambiguities when parsing declarators. + *
+ * Example: void f(int (D)); // is D a type? + * @since 5.0.1 + */ +public class CASTAmbiguousDeclarator extends CASTAmbiguity implements IASTAmbiguousDeclarator { + + private IASTDeclarator[] dtors = new IASTDeclarator[2]; + private int dtorPos=-1; + + + public CASTAmbiguousDeclarator(IASTDeclarator... decls) { + for(IASTDeclarator d : decls) { + if (d != null) { + addDeclarator(d); + } + } + } + + public void addDeclarator(IASTDeclarator d) { + if (d != null) { + dtors = (IASTDeclarator[]) ArrayUtil.append(IASTDeclarator.class, dtors, ++dtorPos, d); + d.setParent(this); + d.setPropertyInParent(SUBDECLARATOR); + } + } + + public IASTDeclarator[] getDeclarators() { + dtors = (IASTDeclarator[]) ArrayUtil.removeNullsAfter(IASTDeclarator.class, dtors, dtorPos ); + return dtors; + } + + @Override + protected IASTNode[] getNodes() { + return getDeclarators(); + } + + public IASTInitializer getInitializer() { + return dtors[0].getInitializer(); + } + + public IASTName getName() { + return dtors[0].getName(); + } + + public IASTDeclarator getNestedDeclarator() { + return dtors[0].getNestedDeclarator(); + } + + public IASTPointerOperator[] getPointerOperators() { + return dtors[0].getPointerOperators(); + } + + public int getRoleForName(IASTName name) { + return dtors[0].getRoleForName(name); + } + + public void addPointerOperator(IASTPointerOperator operator) { + Assert.isLegal(false); + } + + public void setInitializer(IASTInitializer initializer) { + Assert.isLegal(false); + } + + public void setName(IASTName name) { + Assert.isLegal(false); + } + + public void setNestedDeclarator(IASTDeclarator nested) { + Assert.isLegal(false); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousParameterDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousParameterDeclaration.java new file mode 100644 index 00000000000..3dcc41174a7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousParameterDeclaration.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Wind River Systems, Inc. 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: + * Markus Schorn - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.c; + +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousParameterDeclaration; +import org.eclipse.core.runtime.Assert; + +/** + * Handles ambiguities for parameter declarations. + *
+ * void function(const D*); // is D a type? + * @since 5.0.1 + */ +public class CASTAmbiguousParameterDeclaration extends CASTAmbiguity implements IASTAmbiguousParameterDeclaration { + + private IASTParameterDeclaration[] paramDecls = new IASTParameterDeclaration[2]; + private int declPos=-1; + + + public CASTAmbiguousParameterDeclaration(IASTParameterDeclaration... decls) { + for(IASTParameterDeclaration d : decls) + addParameterDeclaration(d); + } + + public void addParameterDeclaration(IASTParameterDeclaration d) { + if (d != null) { + paramDecls = (IASTParameterDeclaration[]) ArrayUtil.append(IASTParameterDeclaration.class, paramDecls, ++declPos, d); + d.setParent(this); + d.setPropertyInParent(SUBDECLARATION); + } + } + + public IASTParameterDeclaration[] getParameterDeclarations() { + paramDecls = (IASTParameterDeclaration[]) ArrayUtil.removeNullsAfter(IASTParameterDeclaration.class, paramDecls, declPos ); + return paramDecls; + } + + @Override + protected IASTNode[] getNodes() { + return getParameterDeclarations(); + } + + public IASTDeclSpecifier getDeclSpecifier() { + return paramDecls[0].getDeclSpecifier(); + } + + public IASTDeclarator getDeclarator() { + return paramDecls[0].getDeclarator(); + } + + public void setDeclSpecifier(IASTDeclSpecifier declSpec) { + Assert.isLegal(false); + } + + public void setDeclarator(IASTDeclarator declarator) { + Assert.isLegal(false); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArrayModifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArrayModifier.java index 32c759ef228..ee75a39facd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArrayModifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTArrayModifier.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation + * IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTDeclarator.java index f04b93afba6..a273c7865f0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTDeclarator.java @@ -26,11 +26,12 @@ import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * @author jcamelon */ -public class CASTDeclarator extends CASTNode implements IASTDeclarator { +public class CASTDeclarator extends CASTNode implements IASTDeclarator, IASTAmbiguityParent { private IASTInitializer initializer; private IASTName name; @@ -207,4 +208,12 @@ public class CASTDeclarator extends CASTNode implements IASTDeclarator { } return r_unclear; } + + public void replace(IASTNode child, IASTNode other) { + if (child == nestedDeclarator) { + other.setPropertyInParent(child.getPropertyInParent()); + other.setParent(child.getParent()); + nestedDeclarator= (IASTDeclarator) other; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDeclarator.java index e66b9dbf107..3fbb0dce880 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFieldDeclarator.java @@ -6,7 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation + * IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -16,17 +17,13 @@ import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator; import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * @author jcamelon */ -public class CASTFieldDeclarator extends CASTDeclarator implements - IASTFieldDeclarator, IASTAmbiguityParent { - +public class CASTFieldDeclarator extends CASTDeclarator implements IASTFieldDeclarator { private IASTExpression bitFieldSize; - public CASTFieldDeclarator() { } @@ -57,12 +54,14 @@ public class CASTFieldDeclarator extends CASTDeclarator implements return true; } - public void replace(IASTNode child, IASTNode other) { - if( child == bitFieldSize) - { + @Override + public void replace(IASTNode child, IASTNode other) { + if( child == bitFieldSize) { other.setPropertyInParent( child.getPropertyInParent() ); other.setParent( child.getParent() ); bitFieldSize = (IASTExpression) other; + } else { + super.replace(child, other); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionDeclarator.java index b223d3b402f..7168b812af8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTFunctionDeclarator.java @@ -6,13 +6,14 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation - * Markus Schorn (Wind River Systems) + * IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.parser.util.ArrayUtil; @@ -26,8 +27,6 @@ public class CASTFunctionDeclarator extends CASTDeclarator implements IASTStanda private int parametersPos=-1; private boolean varArgs; - - public CASTFunctionDeclarator() { } @@ -65,4 +64,19 @@ public class CASTFunctionDeclarator extends CASTDeclarator implements IASTStanda } return true; } + + @Override + public void replace(IASTNode child, IASTNode other) { + if( parameters != null ) { + for (int i = 0; i < parameters.length; ++i) { + if (child == parameters[i]) { + other.setPropertyInParent(child.getPropertyInParent()); + other.setParent(child.getParent()); + parameters[i]= (IASTParameterDeclaration) other; + return; + } + } + } + super.replace(child, other); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java index d4721e269a0..4e4f5b59157 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java @@ -223,4 +223,8 @@ public class CASTName extends CASTNode implements IASTName, IASTCompletionContex } return (IBinding[])ArrayUtil.removeNulls(IBinding.class, bindings); } + + public IASTName getLastName() { + return this; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTParameterDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTParameterDeclaration.java index ba30d158900..217ca9834b5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTParameterDeclaration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTParameterDeclaration.java @@ -6,22 +6,23 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation - * Yuan Zhang / Beth Tibbitts (IBM Research) + * IBM Rational Software - Initial API and implementation + * Yuan Zhang / Beth Tibbitts (IBM Research) + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * @author jcamelon */ -public class CASTParameterDeclaration extends CASTNode implements - IASTParameterDeclaration { - +public class CASTParameterDeclaration extends CASTNode implements IASTParameterDeclaration, IASTAmbiguityParent { private IASTDeclSpecifier declSpec; private IASTDeclarator declarator; @@ -79,4 +80,12 @@ public class CASTParameterDeclaration extends CASTNode implements } return true; } + + public void replace(IASTNode child, IASTNode other) { + if (child == declarator) { + other.setPropertyInParent(child.getPropertyInParent()); + other.setParent(child.getParent()); + declarator= (IASTDeclarator) other; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CBasicType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CBasicType.java index c1ca4f79654..11cfab8cf62 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CBasicType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CBasicType.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM Rational Software - Initial API and implementation - * Markus Schorn (Wind River Systems) + * IBM Rational Software - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -53,8 +53,9 @@ public class CBasicType implements ICBasicType { if( type == IBasicType.t_unspecified ){ if( (qualifiers & ( IS_COMPLEX | IS_IMAGINARY )) != 0 ) type = IBasicType.t_float; - else if( (qualifiers & ~( IS_COMPLEX | IS_IMAGINARY )) != 0 ) + else { type = IBasicType.t_int; + } } } @@ -65,8 +66,9 @@ public class CBasicType implements ICBasicType { if( type == IBasicType.t_unspecified ){ if( (qualifiers & ( IS_COMPLEX | IS_IMAGINARY )) != 0 ) type = IBasicType.t_float; - else if( (qualifiers & ~( IS_COMPLEX | IS_IMAGINARY )) != 0 ) + else { type = IBasicType.t_int; + } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index 5901eb7bc2c..2088f0bdc60 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -36,6 +36,7 @@ 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.IASTFieldReference; import org.eclipse.cdt.core.dom.ast.IASTForStatement; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; @@ -2156,4 +2157,55 @@ public class CVisitor { return true; } + + + /** + * Returns the innermost declarator nested within the given declarator, or + * declarator itself. + * @since 5.0 + */ + public static IASTDeclarator findInnermostDeclarator(IASTDeclarator declarator) { + IASTDeclarator innermost= null; + while(declarator != null) { + innermost= declarator; + declarator= declarator.getNestedDeclarator(); + } + return innermost; + } + + /** + * Returns the outermost declarator the given declarator nests within, or + * declarator itself. + * @since 5.0 + */ + public static IASTDeclarator findOutermostDeclarator(IASTDeclarator declarator) { + while(true) { + IASTNode parent= declarator.getParent(); + if (parent instanceof IASTDeclarator) { + declarator= (IASTDeclarator) parent; + } else { + return declarator; + } + } + } + + /** + * Searches for the innermost declarator that contributes the the type declared. + * @since 5.0 + */ + public static IASTDeclarator findTypeRelevantDeclarator(IASTDeclarator declarator) { + IASTDeclarator result= findInnermostDeclarator(declarator); + while (result.getPointerOperators().length == 0 + && result instanceof IASTFieldDeclarator == false + && result instanceof IASTFunctionDeclarator == false + && result instanceof IASTArrayModifier == false) { + final IASTNode parent= result.getParent(); + if (parent instanceof IASTDeclarator) { + result= (IASTDeclarator) parent; + } else { + return result; + } + } + return result; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index af6e7ab22fb..ac1676681e8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -110,26 +110,24 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; 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.BacktrackException; +import org.eclipse.cdt.internal.core.dom.parser.DeclarationOptions; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement; /** - * @author jcamelon + * Source parser for gnu-c syntax. */ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { - - private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() { - }; + private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4; + private static final int DEFAULT_PARAMETERS_LIST_SIZE = 4; + private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {}; private final boolean supportGCCStyleDesignators; - private IIndex index; + protected CASTTranslationUnit translationUnit; + + private int fPreventKnrCheck= 0; - /** - * @param scanner - * @param parserMode - * @param logService - */ public GNUCSourceParser(IScanner scanner, ParserMode parserMode, IParserLogService logService, ICParserExtensionConfiguration config) { this(scanner, parserMode, logService, config, null); @@ -357,120 +355,100 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { protected ICASTFieldDesignator createFieldDesignator() { return new CASTFieldDesignator(); } - - @Override - protected IASTDeclaration declaration() throws EndOfFileException, - BacktrackException { + + @Override + protected IASTDeclaration declaration(final DeclarationOptions declOption) throws EndOfFileException, BacktrackException { switch (LT(1)) { case IToken.t_asm: return asmDeclaration(); default: - IASTDeclaration d = simpleDeclaration(); + IASTDeclaration d = simpleDeclaration(declOption); return d; } - } - /** - * @throws BacktrackException - * @throws EndOfFileException - */ - @Override - protected IASTDeclaration simpleDeclaration() throws BacktrackException, - EndOfFileException { - IToken firstToken = LA(1); - int firstOffset = firstToken.getOffset(); + private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException { + final IToken firstToken = LA(1); if (firstToken.getType() == IToken.tLBRACE) - throwBacktrack(firstToken.getOffset(), firstToken.getLength()); - - firstToken = null; // necessary for scalability + throwBacktrack(firstToken); + + final int firstOffset = firstToken.getOffset(); + int endOffset= firstOffset; IASTDeclSpecifier declSpec; - IASTDeclarator [] declarators = new IASTDeclarator[2]; - boolean skipAhead = false; + IASTDeclarator dtor= null; try { - declSpec = declSpecifierSeq(false, false); + declSpec = declSpecifierSeq(declOption); + final int lt1= LT(1); + if (lt1 != IToken.tSEMI && lt1 != IToken.tEOC) { + dtor= initDeclarator(declOption); + } } catch (FoundDeclaratorException e) { - skipAhead = true; - declSpec = e.declSpec; - declarators = (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, e.declarator ); + if (e.altSpec != null) { + declSpec= e.altSpec; + dtor= e.altDeclarator; + } else { + declSpec = e.declSpec; + dtor= e.declarator; + } backup( e.currToken ); } - - if (LT(1) != IToken.tSEMI) { - if( ! skipAhead ) - declarators = (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, initDeclarator()); - - while (LT(1) == IToken.tCOMMA) { - consume(); - declarators = (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, initDeclarator()); - } + IASTDeclarator[] declarators= {dtor}; + while (LT(1) == IToken.tCOMMA) { + consume(); + declarators= (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, initDeclarator(declOption)); } - declarators = (IASTDeclarator[]) ArrayUtil.removeNulls( IASTDeclarator.class, declarators ); - - boolean hasFunctionBody = false; - boolean hasFunctionTryBlock = false; - boolean consumedSemi = false; - int semiOffset = 0; + declarators= (IASTDeclarator[]) ArrayUtil.removeNulls( IASTDeclarator.class, declarators ); switch (LT(1)) { - case IToken.tSEMI: - semiOffset = consume().getEndOffset(); - consumedSemi = true; - break; case IToken.tLBRACE: + return functionDefinition(firstOffset, declSpec, declarators); + + case IToken.tSEMI: + endOffset= consume().getEndOffset(); + break; case IToken.tEOC: + endOffset= figureEndOffset(declSpec, declarators); break; default: throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); } - if (!consumedSemi) { - if (LT(1) == IToken.tLBRACE) { - hasFunctionBody = true; - } - - if (hasFunctionTryBlock && !hasFunctionBody) - throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); - } - - if (hasFunctionBody) { - if (declarators.length != 1) - throwBacktrack(firstOffset, LA(1).getEndOffset()); - - IASTDeclarator declarator = declarators[0]; - if (!(declarator instanceof IASTFunctionDeclarator)) - throwBacktrack(firstOffset, LA(1).getEndOffset()); - - IASTFunctionDefinition funcDefinition = createFunctionDefinition(); - ((ASTNode) funcDefinition).setOffset(firstOffset); - funcDefinition.setDeclSpecifier(declSpec); - funcDefinition.setDeclarator((IASTFunctionDeclarator) declarator); - - IASTStatement s = handleFunctionBody(); - if (s != null) { - funcDefinition.setBody(s); - } - ((ASTNode) funcDefinition).setLength(calculateEndOffset(s) - firstOffset); - return funcDefinition; - } - + // no function body IASTSimpleDeclaration simpleDeclaration = createSimpleDeclaration(); - - int length = figureEndOffset(declSpec, declarators) - firstOffset; - if (consumedSemi) - length = semiOffset - firstOffset; - ((ASTNode) simpleDeclaration).setOffsetAndLength(firstOffset, length); simpleDeclaration.setDeclSpecifier(declSpec); - for (int i = 0; i < declarators.length; ++i) { IASTDeclarator declarator = declarators[i]; simpleDeclaration.addDeclarator(declarator); } + + ((ASTNode) simpleDeclaration).setOffsetAndLength(firstOffset, endOffset-firstOffset); return simpleDeclaration; } + private IASTDeclaration functionDefinition(int firstOffset, IASTDeclSpecifier declSpec, + IASTDeclarator[] declarators) throws BacktrackException, EndOfFileException { + if (declarators.length != 1) + throwBacktrack(firstOffset, LA(1).getEndOffset()); + +// IASTDeclarator declarator= CVisitor.findTypeRelevantDeclarator(declarators[0]); // mstodo + + IASTDeclarator declarator = declarators[0]; + if (!(declarator instanceof IASTFunctionDeclarator)) + throwBacktrack(firstOffset, LA(1).getEndOffset()); + + IASTFunctionDefinition funcDefinition = createFunctionDefinition(); + funcDefinition.setDeclSpecifier(declSpec); + funcDefinition.setDeclarator((IASTFunctionDeclarator) declarator); + + IASTStatement s= handleFunctionBody(); + funcDefinition.setBody(s); + ((ASTNode) funcDefinition).setOffsetAndLength(firstOffset, calculateEndOffset(s) - firstOffset); + + return funcDefinition; + } + protected IASTFunctionDefinition createFunctionDefinition() { return new CASTFunctionDefinition(); } @@ -480,14 +458,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return new CASTSimpleDeclaration(); } - protected CASTTranslationUnit translationUnit; - - private boolean knr = false; - - private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4; - - private static final int DEFAULT_PARAMETERS_LIST_SIZE = 4; - protected CASTTranslationUnit createTranslationUnit() { CASTTranslationUnit t = new CASTTranslationUnit(); t.setOffset(0); @@ -527,7 +497,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { if (LT(1) == IToken.tEOC) break; int checkOffset = LA(1).hashCode(); - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(DeclarationOptions.GLOBAL); translationUnit.addDeclaration(d); if (LA(1).hashCode() == checkOffset) failParseWithErrorHandling(); @@ -694,7 +664,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { consume(); if (!avoidCastExpressionByHeuristics()) { - IASTTypeId typeId = typeId(false); + IASTTypeId typeId = typeId(DeclarationOptions.TYPEID); if (typeId != null && LT(1) == IToken.tRPAREN) { consume(); try { @@ -775,7 +745,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { IToken m = mark(); try { int offset = consume().getOffset(); - IASTTypeId t = typeId(false); + IASTTypeId t= typeId(DeclarationOptions.TYPEID); if (t != null) { consume(IToken.tRPAREN).getEndOffset(); if (LT(1) == IToken.tLBRACE) { @@ -1003,7 +973,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } @Override - protected IASTTypeId typeId(boolean forNewExpression) throws EndOfFileException { + protected IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException { if (!canBeTypeSpecifier()) { return null; } @@ -1012,19 +982,21 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { IASTDeclSpecifier declSpecifier = null; IASTDeclarator declarator = null; + fPreventKnrCheck++; try { - try - { - declSpecifier = declSpecifierSeq(false, true); + try { + declSpecifier= declSpecifierSeq(option); + declarator= declarator(option); } catch (FoundDeclaratorException e) { - return null; + declSpecifier= e.declSpec; + declarator= e.declarator; + backup(e.currToken); } - declarator = declarator(); } catch (BacktrackException bt) { return null; + } finally { + fPreventKnrCheck--; } - if (declarator == null || declarator.getName().toCharArray().length > 0) - return null; IASTTypeId result = createTypeId(); ((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset( @@ -1100,304 +1072,316 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return new CASTPointer(); } - protected IASTDeclSpecifier declSpecifierSeq(boolean parm, boolean forTypeId) - throws BacktrackException, EndOfFileException, FoundDeclaratorException { - Flags flags = new Flags(parm,forTypeId); + private final static int INLINE=0x1, CONST=0x2, RESTRICT=0x4, VOLATILE=0x8, + SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100; - int startingOffset = LA(1).getOffset(); - int storageClass = IASTDeclSpecifier.sc_unspecified; - boolean isInline = false; - boolean isConst = false, isRestrict = false, isVolatile = false; - boolean isShort = false, isLong = false, isUnsigned = false, isIdentifier = false, isSigned = false, isLongLong = false; - boolean isComplex = false, isImaginary = false; - int simpleType = IASTSimpleDeclSpecifier.t_unspecified; - IToken identifier = null; - IASTCompositeTypeSpecifier structSpec = null; - IASTElaboratedTypeSpecifier elabSpec = null; - IASTEnumerationSpecifier enumSpec = null; - IASTExpression typeofExpression = null; - IToken last = null; + protected IASTDeclSpecifier declSpecifierSeq(final DeclarationOptions declOption) + throws BacktrackException, EndOfFileException, FoundDeclaratorException { + + final int offset= LA(1).getOffset(); + int endOffset= offset; + int storageClass= IASTDeclSpecifier.sc_unspecified; + int simpleType= IASTSimpleDeclSpecifier.t_unspecified; + int options= 0; + int isLong= 0; + + IToken identifier= null; + IASTDeclSpecifier result= null; + IASTExpression typeofExpression= null; + + boolean encounteredRawType= false; + boolean encounteredTypename= false; declSpecifiers: for (;;) { - switch (LT(1)) { + final IToken token= LA(1); + final int lt1= token.getType(); + switch (lt1) { // Storage Class Specifiers case IToken.t_auto: - last = consume(); + endOffset= consume().getEndOffset(); storageClass = IASTDeclSpecifier.sc_auto; break; case IToken.t_register: storageClass = IASTDeclSpecifier.sc_register; - last = consume(); + endOffset= consume().getEndOffset(); break; case IToken.t_static: storageClass = IASTDeclSpecifier.sc_static; - last = consume(); + endOffset= consume().getEndOffset(); break; case IToken.t_extern: storageClass = IASTDeclSpecifier.sc_extern; - last = consume(); + endOffset= consume().getEndOffset(); break; case IToken.t_typedef: storageClass = IASTDeclSpecifier.sc_typedef; - last = consume(); + endOffset= consume().getEndOffset(); break; // Function Specifier case IToken.t_inline: - isInline = true; - last = consume(); + options |= INLINE; + endOffset= consume().getEndOffset(); break; // Type Qualifiers case IToken.t_const: - isConst = true; - last = consume(); + options |= CONST; + endOffset= consume().getEndOffset(); break; case IToken.t_volatile: - isVolatile = true; - last = consume(); + options |= VOLATILE; + endOffset= consume().getEndOffset(); break; case IToken.t_restrict: - isRestrict = true; - last = consume(); + options |= RESTRICT; + endOffset= consume().getEndOffset(); break; // Type Specifiers case IToken.t_void: - flags.setEncounteredRawType(true); - last = consume(); simpleType = IASTSimpleDeclSpecifier.t_void; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_char: - flags.setEncounteredRawType(true); - last = consume(); simpleType = IASTSimpleDeclSpecifier.t_char; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_short: - flags.setEncounteredRawType(true); - last = consume(); - isShort = true; + options |= SHORT; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_int: - flags.setEncounteredRawType(true); - last = consume(); simpleType = IASTSimpleDeclSpecifier.t_int; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_long: - flags.setEncounteredRawType(true); - last = consume(); - if (isLong) { - isLongLong = true; - isLong = false; - } else - isLong = true; + isLong++; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_float: - flags.setEncounteredRawType(true); - last = consume(); simpleType = IASTSimpleDeclSpecifier.t_float; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_double: - flags.setEncounteredRawType(true); - last = consume(); simpleType = IASTSimpleDeclSpecifier.t_double; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_signed: - flags.setEncounteredRawType(true); - last = consume(); - isSigned = true; + options |= SIGNED; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_unsigned: - flags.setEncounteredRawType(true); - last = consume(); - isUnsigned = true; + options |= UNSIGNED; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t__Bool: - flags.setEncounteredRawType(true); - last = consume(); simpleType = ICASTSimpleDeclSpecifier.t_Bool; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t__Complex: - last = consume(); - isComplex=true; + options |= COMPLEX; + endOffset= consume().getEndOffset(); break; case IToken.t__Imaginary: - last = consume(); - isImaginary=true; + options |= IMAGINARY; + endOffset= consume().getEndOffset(); break; case IToken.tIDENTIFIER: case IToken.tCOMPLETION: case IToken.tEOC: - // TODO - Kludgy way to handle constructors/destructors - if (flags.haveEncounteredRawType()) { - break declSpecifiers; - } - if (flags.haveEncounteredTypename()) { + if (encounteredTypename || encounteredRawType) { break declSpecifiers; } try { - lookAheadForDeclarator(flags); - } catch (FoundDeclaratorException e) { - ICASTSimpleDeclSpecifier declSpec= createSimpleTypeSpecifier(); - - declSpec.setConst(isConst); - declSpec.setRestrict(isRestrict); - declSpec.setVolatile(isVolatile); - declSpec.setInline(isInline); - declSpec.setStorageClass(storageClass); + if (endOffset != offset || declOption.fAllowEmptySpecifier) { + lookAheadForDeclarator(declOption); + } + } catch (FoundDeclaratorException e) { + e.declSpec= createSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); - declSpec.setType(simpleType); - declSpec.setLong(isLong); - declSpec.setLongLong(isLongLong); - declSpec.setUnsigned(isUnsigned); - declSpec.setSigned(isSigned); - declSpec.setShort(isShort); - ((ASTNode) declSpec).setOffsetAndLength(startingOffset, - (last != null) ? last.getEndOffset() - startingOffset : 0); - e.declSpec = declSpec; - throw e; - } + IToken mark= mark(); + try { + final IToken idToken= identifier(); // for the specifier + final IASTDeclarator altDtor = initDeclarator(declOption); + if (LA(1) == e.currToken) { + e.altDeclarator= altDtor; + e.altSpec= createNamedTypeSpecifier(idToken, storageClass, options, offset, idToken.getEndOffset()); + } + } catch (BacktrackException bt) { + } finally { + backup(mark); + } + throw e; + } identifier = identifier(); - last = identifier; - isIdentifier = true; - flags.setEncounteredTypename(true); + endOffset= identifier.getEndOffset(); + encounteredTypename= true; break; case IToken.t_struct: case IToken.t_union: - if (flags.haveEncounteredTypename()) - throwBacktrack(LA(1)); + if (encounteredTypename || encounteredRawType) + throwBacktrack(token); try { - structSpec = structOrUnionSpecifier(); - flags.setEncounteredTypename(true); - break; + result= structOrUnionSpecifier(); } catch (BacktrackException bt) { - elabSpec = elaboratedTypeSpecifier(); - flags.setEncounteredTypename(true); - break; + result= elaboratedTypeSpecifier(); } + endOffset= calculateEndOffset(result); + encounteredTypename= true; + break; case IToken.t_enum: - if (flags.haveEncounteredTypename()) - throwBacktrack(LA(1)); + if (encounteredTypename || encounteredRawType) + throwBacktrack(token); try { - enumSpec = enumSpecifier(); - flags.setEncounteredTypename(true); - break; + result= enumSpecifier(); } catch (BacktrackException bt) { // this is an elaborated class specifier - elabSpec = elaboratedTypeSpecifier(); - flags.setEncounteredTypename(true); - break; + result= elaboratedTypeSpecifier(); } + endOffset= calculateEndOffset(result); + encounteredTypename= true; + break; + case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec - if (supportAttributeSpecifiers) - __attribute_decl_seq(true, false); - else - throwBacktrack(LA(1).getOffset(), LA(1).getLength()); + if (!supportAttributeSpecifiers) + throwBacktrack(token); + __attribute_decl_seq(true, false); break; case IGCCToken.t__declspec: // __declspec precedes the identifier - if (identifier == null && supportDeclspecSpecifiers) - __attribute_decl_seq(false, true); - else - throwBacktrack(LA(1).getOffset(), LA(1).getLength()); + if (identifier != null || !supportDeclspecSpecifiers) + throwBacktrack(token); + __attribute_decl_seq(false, true); break; + default: - if (LT(1) >= IExtensionToken.t__otherDeclSpecModifierFirst && LT(1) <= IExtensionToken.t__otherDeclSpecModifierLast) { + if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) { handleOtherDeclSpecModifier(); + endOffset= LA(1).getOffset(); break; } - if (supportTypeOfUnaries && LT(1) == IGCCToken.t_typeof) { + if (lt1 == IGCCToken.t_typeof) { + if (encounteredRawType || encounteredTypename) + throwBacktrack(token); + typeofExpression = unaryTypeofExpression(); - if (typeofExpression != null) { - flags.setEncounteredTypename(true); - } + encounteredTypename= true; + endOffset= calculateEndOffset(typeofExpression); + break; } break declSpecifiers; } + + if (encounteredRawType && encounteredTypename) + throwBacktrack(token); } - if (structSpec != null) { - ((ASTNode) structSpec).setOffsetAndLength(startingOffset, - calculateEndOffset(structSpec) - startingOffset); - structSpec.setConst(isConst); - ((ICASTCompositeTypeSpecifier) structSpec).setRestrict(isRestrict); - structSpec.setVolatile(isVolatile); - structSpec.setInline(isInline); - structSpec.setStorageClass(storageClass); - - return structSpec; + // check for empty specification + if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !declOption.fAllowEmptySpecifier) { + if (offset == endOffset) { + throwBacktrack(LA(1)); + } } - - if (enumSpec != null) { - ((ASTNode) enumSpec).setOffsetAndLength(startingOffset, - calculateEndOffset(enumSpec) - startingOffset); - enumSpec.setConst(isConst); - ((CASTEnumerationSpecifier) enumSpec).setRestrict(isRestrict); - enumSpec.setVolatile(isVolatile); - enumSpec.setInline(isInline); - enumSpec.setStorageClass(storageClass); - return enumSpec; - - } - if (elabSpec != null) { - ((ASTNode) elabSpec).setOffsetAndLength(startingOffset, - calculateEndOffset(elabSpec) - startingOffset); - elabSpec.setConst(isConst); - ((CASTElaboratedTypeSpecifier) elabSpec).setRestrict(isRestrict); - elabSpec.setVolatile(isVolatile); - elabSpec.setInline(isInline); - elabSpec.setStorageClass(storageClass); - - return elabSpec; - } - if (isIdentifier) { - ICASTTypedefNameSpecifier declSpec = (ICASTTypedefNameSpecifier)createNamedTypeSpecifier(); - declSpec.setConst(isConst); - declSpec.setRestrict(isRestrict); - declSpec.setVolatile(isVolatile); - declSpec.setInline(isInline); - declSpec.setStorageClass(storageClass); - - if (last != null) { - ((ASTNode) declSpec).setOffsetAndLength(startingOffset, last.getEndOffset() - startingOffset); + + if (result != null) { + configureDeclSpec(result, storageClass, options); + if ((options & RESTRICT) != 0) { + if (result instanceof ICASTCompositeTypeSpecifier) { + ((ICASTCompositeTypeSpecifier) result).setRestrict(true); + } else if (result instanceof CASTEnumerationSpecifier) { + ((CASTEnumerationSpecifier) result).setRestrict(true); + } else if (result instanceof CASTElaboratedTypeSpecifier) { + ((CASTElaboratedTypeSpecifier) result).setRestrict(true); + } } - IASTName name = createName(identifier); - declSpec.setName(name); - return declSpec; + ((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); + return result; } - ICASTSimpleDeclSpecifier declSpec = null; + + if (identifier != null) + return createNamedTypeSpecifier(identifier, storageClass, options, offset, endOffset); + + return createSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); + } + + private ICASTTypedefNameSpecifier createNamedTypeSpecifier(IToken identifier, int storageClass, + int options, int offset, int endOffset) { + ICASTTypedefNameSpecifier declSpec = (ICASTTypedefNameSpecifier)createNamedTypeSpecifier(); + IASTName name = createName(identifier); + declSpec.setName(name); + configureDeclSpec(declSpec, storageClass, options); + declSpec.setRestrict((options & RESTRICT) != 0); + ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset - offset); + return declSpec; + } + + private ICASTSimpleDeclSpecifier createSimpleDeclSpec(int storageClass, int simpleType, + int options, int isLong, IASTExpression typeofExpression, int offset, int endOffset) { + ICASTSimpleDeclSpecifier declSpec = null; if (typeofExpression != null) { declSpec = createGCCSimpleTypeSpecifier(); ((IGCCASTSimpleDeclSpecifier) declSpec).setTypeofExpression(typeofExpression); - } else { declSpec = createSimpleTypeSpecifier(); } - declSpec.setConst(isConst); - declSpec.setRestrict(isRestrict); - declSpec.setVolatile(isVolatile); - declSpec.setInline(isInline); - declSpec.setStorageClass(storageClass); + configureDeclSpec(declSpec, storageClass, options); + declSpec.setType(simpleType); + declSpec.setLong(isLong == 1); + declSpec.setLongLong(isLong > 1); + declSpec.setRestrict((options & RESTRICT) != 0); + declSpec.setUnsigned((options & UNSIGNED) != 0); + declSpec.setSigned((options & SIGNED) != 0); + declSpec.setShort((options & SHORT) != 0); + declSpec.setComplex((options & COMPLEX) != 0); + declSpec.setImaginary((options & IMAGINARY) != 0); - declSpec.setType(simpleType); - declSpec.setLong(isLong); - declSpec.setLongLong(isLongLong); - declSpec.setUnsigned(isUnsigned); - declSpec.setSigned(isSigned); - declSpec.setShort(isShort); - declSpec.setComplex(isComplex); - declSpec.setImaginary(isImaginary); - if( typeofExpression != null && last == null ){ - ((ASTNode)declSpec).setOffsetAndLength( (ASTNode)typeofExpression ); - } else { - ((ASTNode) declSpec).setOffsetAndLength(startingOffset, - (last != null) ? last.getEndOffset() - startingOffset : 0); - } - return declSpec; - } + ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset - offset); + return declSpec; + } + private void configureDeclSpec(IASTDeclSpecifier declSpec, int storageClass, int options) { + declSpec.setStorageClass(storageClass); + declSpec.setConst((options & CONST) != 0); + declSpec.setVolatile((options & VOLATILE) != 0); + declSpec.setInline((options & INLINE) != 0); + } + + @Override + protected boolean verifyLookaheadDeclarator(DeclarationOptions option, IASTDeclarator dtor, IToken nextToken) { + switch (nextToken.getType()) { + case IToken.tCOMMA: + return true; + case IToken.tLBRACE: + if (option == DeclarationOptions.GLOBAL || option == DeclarationOptions.C_MEMBER) { + if (CVisitor.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) { + return true; + } + } + break; + case IToken.tSEMI: + return option == DeclarationOptions.GLOBAL || option == DeclarationOptions.C_MEMBER || + option == DeclarationOptions.LOCAL; + + case IToken.tRPAREN: + return option == DeclarationOptions.PARAMETER + || option == DeclarationOptions.C_PARAMETER_NON_ABSTRACT; + } + return false; + } + protected ICASTSimpleDeclSpecifier createSimpleTypeSpecifier() { return new CASTSimpleDeclSpecifier(); } @@ -1479,7 +1463,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { default: int checkToken = LA(1).hashCode(); try { - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(DeclarationOptions.C_MEMBER); result.addMemberDeclaration(d); } catch (BacktrackException bt) { if (checkToken == LA(1).hashCode()) @@ -1540,8 +1524,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } @Override - protected IASTDeclarator initDeclarator() throws EndOfFileException, BacktrackException { - IASTDeclarator d = declarator(); + protected IASTDeclarator initDeclarator(final DeclarationOptions option) throws EndOfFileException, BacktrackException { + IASTDeclarator d = declarator(option); IASTInitializer i = optionalCInitializer(); if (i != null) { @@ -1551,265 +1535,337 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return d; } - protected IASTDeclarator declarator() throws EndOfFileException, BacktrackException { - IASTDeclarator innerDecl = null; - IASTName declaratorName = null; - IToken la = LA(1); - int startingOffset = la.getOffset(); - int finalOffset = startingOffset; - la = null; + protected IASTDeclarator declarator(DeclarationOptions option) throws EndOfFileException, BacktrackException { + final int startingOffset = LA(1).getOffset(); + int endOffset = startingOffset; + List pointerOps = new ArrayList(DEFAULT_POINTEROPS_LIST_SIZE); - List parameters = Collections.emptyList(); - List arrayMods = Collections.emptyList(); - boolean encounteredVarArgs = false; - IASTExpression bitField = null; - boolean isFunction = false; - IASTName[] parmNames = null; - IASTDeclaration[] parmDeclarations = null; - int numKnRCParms = 0; - - overallLoop: do { - - consumePointerOperators(pointerOps); + consumePointerOperators(pointerOps); + if (!pointerOps.isEmpty()) { + endOffset = calculateEndOffset(pointerOps.get(pointerOps.size() - 1)); + } - // Accept __attribute__ or __declspec after the pointer ops and before the declarator ex: void * __attribute__((__cdecl__)) foo(); - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - - if (!pointerOps.isEmpty()) { - finalOffset = calculateEndOffset(pointerOps - .get(pointerOps.size() - 1)); - } + // Accept __attribute__ or __declspec between pointer operators and declarator. + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + + // Look for identifier or nested declarator + final int lt1= LT(1); + if (lt1 == IToken.tIDENTIFIER) { + if (option.fRequireAbstract) + throwBacktrack(LA(1)); - if (LT(1) == IToken.tLPAREN) { - consume(); - innerDecl = declarator(); - finalOffset = consume(IToken.tRPAREN).getEndOffset(); - declaratorName = createName(); - } else if (LT(1) == IToken.tIDENTIFIER) { - declaratorName = createName(identifier()); - finalOffset = calculateEndOffset(declaratorName); - } else - declaratorName = createName(); + final IASTName declaratorName = createName(identifier()); + endOffset= calculateEndOffset(declaratorName); + return declarator(pointerOps, declaratorName, null, startingOffset, endOffset, option); + } + + if (lt1 == IToken.tLPAREN) { + IASTDeclarator cand1= null; + IToken cand1End= null; + // try an abstract function declarator + if (option.fAllowAbstract) { + final IToken mark= mark(); + try { + cand1= declarator(pointerOps, createName(), null, startingOffset, endOffset, option); + if (option.fRequireAbstract) + return cand1; - for (;;) { - switch (LT(1)) { - case IToken.tLPAREN: - // parameterDeclarationClause - // d.setIsFunction(true); - // TODO need to create a temporary scope object here - IToken last = consume(); - finalOffset = last.getEndOffset(); - isFunction = true; - boolean seenParameter = false; + cand1End= LA(1); + } catch (BacktrackException e) { + } + backup(mark); + } + // try a nested declarator + try { + consume(); + if (LT(1) == IToken.tRPAREN) + throwBacktrack(LA(1)); + + final IASTDeclarator nested= declarator(option); + endOffset= consume(IToken.tRPAREN).getEndOffset(); + final IASTDeclarator cand2= declarator(pointerOps, null, nested, startingOffset, endOffset, option); + if (cand1 == null || cand1End == null) + return cand2; + final IToken cand2End= LA(1); + if (cand1End == cand2End) { + CASTAmbiguousDeclarator result= new CASTAmbiguousDeclarator(cand1, cand2); + ((ASTNode) result).setOffsetAndLength((ASTNode) cand1); + return result; + } + // use the longer variant + if (cand1End.getOffset() < cand2End.getOffset()) + return cand2; + + } catch (BacktrackException e) { + if (cand1 == null) + throw e; + } + backup(cand1End); + return cand1; + } + + // try abstract declarator + if (!option.fAllowAbstract) { + // bit-fields may be abstract + if (!option.fAllowBitField || LT(1) != IToken.tCOLON) + throwBacktrack(LA(1)); + } + return declarator(pointerOps, createName(), null, startingOffset, endOffset, option); + } + + private IASTDeclarator declarator(final List pointerOps, + final IASTName declaratorName, final IASTDeclarator nestedDeclarator, + final int startingOffset, int endOffset, + final DeclarationOptions option) throws EndOfFileException, BacktrackException { + IASTDeclarator result= null; + loop: while(true) { + final int lt1= LT(1); + switch (lt1) { + case IToken.tLPAREN: + result= functionDeclarator(isAbstract(declaratorName, nestedDeclarator) + ? DeclarationOptions.PARAMETER : DeclarationOptions.C_PARAMETER_NON_ABSTRACT); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IToken.tLBRACKET: + result= arrayDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IToken.tCOLON: + if (!option.fAllowBitField) + throwBacktrack(LA(1)); + + result= bitFieldDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IGCCToken.t__attribute__: // if __attribute__ is after a declarator + if (!supportAttributeSpecifiers) + throwBacktrack(LA(1)); + __attribute_decl_seq(true, supportDeclspecSpecifiers); + break; + case IGCCToken.t__declspec: + if (!supportDeclspecSpecifiers) + throwBacktrack(LA(1)); + __attribute_decl_seq(supportAttributeSpecifiers, true); + break; + default: + break loop; + } + } + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - // count the number of K&R C parameters (0 K&R C parameters - // essentially means it's not K&R C) - if( !knr && supportKnRC) - numKnRCParms = countKnRCParms(); - - if (numKnRCParms > 0) { // KnR C parameters were found so - // handle the declarator accordingly - parmNames = new IASTName[numKnRCParms]; - parmDeclarations = new IASTDeclaration[numKnRCParms]; + if (result == null) { + result= createDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + } else { + endOffset= calculateEndOffset(result); + } - for (int i = 0; i <= parmNames.length; i++) { - switch (LT(1)) { - case IToken.tCOMMA: - last = consume(); - parmNames[i] = createName(identifier()); - seenParameter = true; - break; - case IToken.tIDENTIFIER: - if (seenParameter) - throwBacktrack(startingOffset, last.getEndOffset() - startingOffset); - - parmNames[i] = createName(identifier()); - seenParameter = true; - break; - case IToken.tRPAREN: - last = consume(); - break; - default: - break; - } - } - - // now that the parameter names are parsed, parse the - // parameter declarations - for (int i = 0; i < numKnRCParms - && LT(1) != IToken.tLBRACE; i++) { // max - // parameter - // declarations - // same as - // parameter - // name count - // (could be - // less) - try { - boolean hasValidDecltors = true; - - IASTDeclaration decl = simpleDeclaration(); - IASTSimpleDeclaration declaration = null; - if (decl instanceof IASTSimpleDeclaration) { - declaration = ((IASTSimpleDeclaration) decl); - - IASTDeclarator[] decltors = declaration.getDeclarators(); - for (IASTDeclarator decltor : decltors) { - boolean decltorOk = false; - for (IASTName parmName : parmNames) { - if (CharArrayUtils.equals( - decltor.getName().toCharArray(), - parmName.toCharArray())) { - decltorOk = true; - break; - } - } - if (!decltorOk) - hasValidDecltors = false; - } - } else { - hasValidDecltors = false; - } - - if (hasValidDecltors) { - parmDeclarations[i] = declaration; - } else { - parmDeclarations[i] = createKnRCProblemDeclaration( - ((ASTNode) decl).getLength(), - ((ASTNode) decl).getOffset()); - } - } catch (BacktrackException b) { - parmDeclarations[i] = createKnRCProblemDeclaration( - b.getLength(), b.getOffset()); - } - } - - break overallLoop; - } - - parameterDeclarationLoop: for (;;) { - switch (LT(1)) { - case IToken.tRPAREN: - case IToken.tEOC: - last = consume(); - finalOffset = last.getEndOffset(); - break parameterDeclarationLoop; - case IToken.tELLIPSIS: - last = consume(); - encounteredVarArgs = true; - finalOffset = last.getEndOffset(); - break; - case IToken.tCOMMA: - last = consume(); - finalOffset = last.getEndOffset(); - seenParameter = false; - break; - default: - if (seenParameter) - throwBacktrack(startingOffset, last.getEndOffset() - startingOffset); - IASTParameterDeclaration pd = parameterDeclaration(); - finalOffset = calculateEndOffset(pd); - if (parameters == Collections.EMPTY_LIST) - parameters = new ArrayList(DEFAULT_PARAMETERS_LIST_SIZE); - parameters.add(pd); - seenParameter = true; - } - } - - break; - case IToken.tLBRACKET: - if (arrayMods == Collections.EMPTY_LIST) - arrayMods = new ArrayList(DEFAULT_POINTEROPS_LIST_SIZE); - consumeArrayModifiers(arrayMods); - if (!arrayMods.isEmpty()) - finalOffset = calculateEndOffset(arrayMods.get(arrayMods.size() - 1)); - continue; - case IToken.tCOLON: - consume(); - bitField = constantExpression(); - finalOffset = calculateEndOffset(bitField); - break; - case IGCCToken.t__attribute__: // if __attribute__ is after the declarator - if(supportAttributeSpecifiers) - __attribute_decl_seq(true, false); - else - throwBacktrack(LA(1).getOffset(), LA(1).getLength()); - break; - case IGCCToken.t__declspec: - if(supportDeclspecSpecifiers) - __attribute_decl_seq(false, true); - else - throwBacktrack(LA(1).getOffset(), LA(1).getLength()); - break; - default: - break; - } - break; - } - - } while (false); - - if (LT(1) == IToken.t_asm) { // asm labels bug 226121 + if (LT(1) == IToken.t_asm) { // asm labels bug 226121 consume(); - finalOffset= asmExpression(null).getEndOffset(); + endOffset= asmExpression(null).getEndOffset(); + + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); } - // Consume any number of __attribute__ and __declspec tokens after the parameters - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + for (IASTPointerOperator po : pointerOps) { + result.addPointerOperator(po); + } - IASTDeclarator d = null; - if (numKnRCParms > 0 && supportKnRC) { - ICASTKnRFunctionDeclarator functionDecltor = createKnRFunctionDeclarator(); - parmDeclarations = (IASTDeclaration[]) ArrayUtil.removeNulls( IASTDeclaration.class, parmDeclarations ); - for (int i = 0; i < parmDeclarations.length; ++i) { - if (parmDeclarations[i] != null) { - finalOffset = calculateEndOffset(parmDeclarations[i]); - } - } - functionDecltor.setParameterDeclarations(parmDeclarations); - functionDecltor.setParameterNames(parmNames); - if (declaratorName != null) { - functionDecltor.setName(declaratorName); - } - - d = functionDecltor; - } else if (isFunction) { - IASTStandardFunctionDeclarator fc = createFunctionDeclarator(); - fc.setVarArgs(encounteredVarArgs); - for (int i = 0; i < parameters.size(); ++i) { - IASTParameterDeclaration p = (IASTParameterDeclaration) parameters.get(i); - fc.addParameterDeclaration(p); - } - d = fc; - } else if (arrayMods != Collections.EMPTY_LIST) { - d = createArrayDeclarator(); - for (int i = 0; i < arrayMods.size(); ++i) { - IASTArrayModifier m = (IASTArrayModifier) arrayMods.get(i); - ((IASTArrayDeclarator) d).addArrayModifier(m); - } - } else if (bitField != null) { - IASTFieldDeclarator fl = createFieldDeclarator(); - fl.setBitFieldSize(bitField); - d = fl; - } else { - d = createDeclarator(); - } - for (int i = 0; i < pointerOps.size(); ++i) { - IASTPointerOperator po = pointerOps.get(i); - d.addPointerOperator(po); - } - if (innerDecl != null) { - d.setNestedDeclarator(innerDecl); - } - if (declaratorName != null) { - d.setName(declaratorName); - } - - ((ASTNode) d).setOffsetAndLength(startingOffset, finalOffset - startingOffset); - return d; + ((ASTNode) result).setOffsetAndLength(startingOffset, endOffset - startingOffset); + return result; } - protected IASTArrayDeclarator createArrayDeclarator() { + private boolean isAbstract(IASTName declaratorName, IASTDeclarator nestedDeclarator) { + nestedDeclarator= CVisitor.findInnermostDeclarator(nestedDeclarator); + if (nestedDeclarator != null) { + declaratorName= nestedDeclarator.getName(); + } + return declaratorName == null || declaratorName.toCharArray().length == 0; + } + + private void setDeclaratorID(IASTDeclarator declarator, IASTName declaratorName, IASTDeclarator nestedDeclarator) { + if (nestedDeclarator != null) { + declarator.setNestedDeclarator(nestedDeclarator); + declarator.setName(createName()); + } else { + declarator.setName(declaratorName); + } + } + + private IASTDeclarator functionDeclarator(DeclarationOptions paramOption) throws EndOfFileException, BacktrackException { + IToken last = consume(IToken.tLPAREN); + int startOffset= last.getOffset(); + + // check for K&R C parameters (0 means it's not K&R C) + if (fPreventKnrCheck==0 && supportKnRC) { + fPreventKnrCheck++; + try { + final int numKnRCParms = countKnRCParms(); + if (numKnRCParms > 0) { // KnR C parameters were found + IASTName[] parmNames = new IASTName[numKnRCParms]; + IASTDeclaration[] parmDeclarations = new IASTDeclaration[numKnRCParms]; + + boolean seenParameter= false; + for (int i = 0; i <= parmNames.length; i++) { + switch (LT(1)) { + case IToken.tCOMMA: + last = consume(); + parmNames[i] = createName(identifier()); + seenParameter = true; + break; + case IToken.tIDENTIFIER: + if (seenParameter) + throwBacktrack(startOffset, last.getEndOffset() - startOffset); + + parmNames[i] = createName(identifier()); + seenParameter = true; + break; + case IToken.tRPAREN: + last = consume(); + break; + default: + break; + } + } + + // now that the parameter names are parsed, parse the parameter declarations + // count for parameter declarations <= count for parameter names. + int endOffset= last.getEndOffset(); + for (int i = 0; i < numKnRCParms && LT(1) != IToken.tLBRACE; i++) { + try { + IASTDeclaration decl= simpleDeclaration(DeclarationOptions.LOCAL); + IASTSimpleDeclaration ok= checkKnrParameterDeclaration(decl, parmNames); + if (ok != null) { + parmDeclarations[i]= ok; + endOffset= calculateEndOffset(ok); + } else { + final ASTNode node = (ASTNode) decl; + parmDeclarations[i] = createKnRCProblemDeclaration(node.getOffset(), node.getLength()); + endOffset= calculateEndOffset(node); + } + } catch (BacktrackException b) { + parmDeclarations[i] = createKnRCProblemDeclaration(b.getOffset(), b.getLength()); + endOffset= b.getOffset() + b.getLength(); + } + } + + ICASTKnRFunctionDeclarator functionDecltor = createKnRFunctionDeclarator(); + parmDeclarations = (IASTDeclaration[]) ArrayUtil.removeNulls( IASTDeclaration.class, parmDeclarations ); + functionDecltor.setParameterDeclarations(parmDeclarations); + functionDecltor.setParameterNames(parmNames); + ((ASTNode) functionDecltor).setOffsetAndLength(startOffset, endOffset-startOffset); + return functionDecltor; + } + } finally { + fPreventKnrCheck--; + } + } + + boolean seenParameter= false; + boolean encounteredVarArgs= false; + List parameters= null; + int endOffset= last.getEndOffset(); + + paramLoop: while(true) { + switch (LT(1)) { + case IToken.tRPAREN: + case IToken.tEOC: + endOffset= consume().getEndOffset(); + break paramLoop; + case IToken.tELLIPSIS: + endOffset= consume().getEndOffset(); + encounteredVarArgs = true; + break; + case IToken.tCOMMA: + endOffset= consume().getEndOffset(); + seenParameter = false; + break; + default: + if (seenParameter) + throwBacktrack(startOffset, endOffset - startOffset); + + IASTParameterDeclaration pd = parameterDeclaration(paramOption); + endOffset = calculateEndOffset(pd); + if (parameters == null) + parameters = new ArrayList(DEFAULT_PARAMETERS_LIST_SIZE); + parameters.add(pd); + seenParameter = true; + break; + } + } + IASTStandardFunctionDeclarator fc = createFunctionDeclarator(); + fc.setVarArgs(encounteredVarArgs); + if (parameters != null) { + for (IASTParameterDeclaration pd : parameters) { + fc.addParameterDeclaration(pd); + } + } + ((ASTNode) fc).setOffsetAndLength(startOffset, endOffset-startOffset); + return fc; + } + + private IASTSimpleDeclaration checkKnrParameterDeclaration(IASTDeclaration decl, final IASTName[] parmNames) { + if (decl instanceof IASTSimpleDeclaration == false) + return null; + + IASTSimpleDeclaration declaration= ((IASTSimpleDeclaration) decl); + IASTDeclarator[] decltors = declaration.getDeclarators(); + for (IASTDeclarator decltor : decltors) { + boolean decltorOk = false; + final char[] nchars = decltor.getName().toCharArray(); + for (IASTName parmName : parmNames) { + if (CharArrayUtils.equals(nchars, parmName.toCharArray())) { + decltorOk= true; + break; + } + } + if (!decltorOk) + return null; + } + return declaration; + } + + /** + * Parse an array declarator starting at the square bracket. + */ + private IASTArrayDeclarator arrayDeclarator() throws EndOfFileException, BacktrackException { + ArrayList arrayMods = new ArrayList(DEFAULT_POINTEROPS_LIST_SIZE); + int start= LA(1).getOffset(); + consumeArrayModifiers(arrayMods); + if (arrayMods.isEmpty()) + throwBacktrack(LA(1)); + + final int endOffset = calculateEndOffset(arrayMods.get(arrayMods.size() - 1)); + final IASTArrayDeclarator d = createArrayDeclarator(); + for (IASTArrayModifier m : arrayMods) { + d.addArrayModifier(m); + } + + ((ASTNode) d).setOffsetAndLength(start, endOffset-start); + return d; + } + + + /** + * Parses for a bit field declarator starting with the colon + */ + private IASTFieldDeclarator bitFieldDeclarator() throws EndOfFileException, BacktrackException { + int start= consume(IToken.tCOLON).getOffset(); + + final IASTExpression bitField = constantExpression(); + final int endOffset = calculateEndOffset(bitField); + + IASTFieldDeclarator d = createFieldDeclarator(); + d.setBitFieldSize(bitField); + + ((ASTNode) d).setOffsetAndLength(start, endOffset-start); + return d; + } + + protected IASTArrayDeclarator createArrayDeclarator() { return new CASTArrayDeclarator(); } @@ -1842,9 +1898,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return new CASTDeclarator(); } - protected void consumeArrayModifiers(List arrayMods) - throws EndOfFileException, BacktrackException { - + protected void consumeArrayModifiers(List arrayMods) throws EndOfFileException, BacktrackException { while (LT(1) == IToken.tLBRACKET) { // eat the '[' int startOffset = consume().getOffset(); @@ -1931,38 +1985,43 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return new CASTArrayModifier(); } - protected IASTParameterDeclaration parameterDeclaration() - throws BacktrackException, EndOfFileException { - IToken current = LA(1); + protected IASTParameterDeclaration parameterDeclaration(DeclarationOptions option) throws BacktrackException, EndOfFileException { + final IToken current = LA(1); int startingOffset = current.getOffset(); IASTDeclSpecifier declSpec = null; - try - { - declSpec = declSpecifierSeq(true, false); - } - catch( FoundDeclaratorException fd ) - { - declSpec = fd.declSpec; - } - - // bug 167833, no declspec no parameter. - if (current == LA(1)) - throwBacktrack(current.getOffset(), current.getLength()); - IASTDeclarator declarator = null; - if (LT(1) != IToken.tSEMI) - declarator = initDeclarator(); - - if (current == LA(1)) - throwBacktrack(current.getOffset(), figureEndOffset(declSpec, - declarator) - - current.getOffset()); + IASTDeclSpecifier altDeclSpec = null; + IASTDeclarator altDeclarator = null; + + try { + fPreventKnrCheck++; + declSpec= declSpecifierSeq(option); + declarator = initDeclarator(option); + } catch(FoundDeclaratorException fd) { + declSpec= fd.declSpec; + declarator= fd.declarator; + altDeclSpec= fd.altSpec; + altDeclarator= fd.altDeclarator; + backup(fd.currToken); + } finally { + fPreventKnrCheck--; + } + final int length = figureEndOffset(declSpec, declarator) - startingOffset; IASTParameterDeclaration result = createParameterDeclaration(); - ((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset(declSpec, declarator) - startingOffset); + ((ASTNode) result).setOffsetAndLength(startingOffset, length); result.setDeclSpecifier(declSpec); result.setDeclarator(declarator); + if (altDeclarator != null && altDeclSpec != null) { + IASTParameterDeclaration alt = createParameterDeclaration(); + ((ASTNode) alt).setOffsetAndLength(startingOffset, length); + alt.setDeclSpecifier(altDeclSpec); + alt.setDeclarator(altDeclarator); + // order is important, prefer alternative over the declarator found via the lookahead. + result= new CASTAmbiguousParameterDeclaration(alt, result); + ((ASTNode) result).setOffsetAndLength((ASTNode) alt); + } return result; } @@ -2140,7 +2199,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return parseLabelStatement(); } - return parseDeclarationOrExpressionStatement(); + return parseDeclarationOrExpressionStatement(DeclarationOptions.LOCAL); } } @@ -2173,7 +2232,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { boolean previousWasIdentifier = false; try { - knr = true; mark = mark(); // starts at the beginning of the parameter list @@ -2221,7 +2279,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { while (LT(1) != IToken.tLBRACE) { // fix for 100104: check if the parameter declaration is a valid one try { - simpleDeclaration(); + simpleDeclaration(DeclarationOptions.LOCAL); } catch (BacktrackException e) { backup(mark); return 0; @@ -2242,17 +2300,13 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return 0; } - finally - { - knr = false; - } } - private IASTProblemDeclaration createKnRCProblemDeclaration(int length, int offset) throws EndOfFileException { + private IASTProblemDeclaration createKnRCProblemDeclaration(int offset, int length) throws EndOfFileException { IASTProblem p = createProblem(IProblem.SYNTAX_ERROR, offset, length); IASTProblemDeclaration pd = createProblemDeclaration(); pd.setProblem(p); - ((ASTNode) pd).setOffsetAndLength(((ASTNode) p).getOffset(), ((ASTNode) p).getLength()); + ((ASTNode) pd).setOffsetAndLength((ASTNode) p); // consume until LBRACE is found (to leave off at the function body and // continue from there) @@ -2440,7 +2494,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { int startOffset; startOffset = consume().getOffset(); consume(IToken.tLPAREN); - IASTStatement init = forInitStatement(); + IASTStatement init = forInitStatement(DeclarationOptions.LOCAL); IASTExpression for_condition = null; switch (LT(1)) { case IToken.tSEMI: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousDeclarator.java new file mode 100644 index 00000000000..c5d81177cd7 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousDeclarator.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Wind River Systems, Inc. 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: + * Markus Schorn - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTInitializer; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; +import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator; +import org.eclipse.core.runtime.Assert; + +/** + * Handles ambiguities when parsing declarators. + *
+ * Example: void f(int (D)); // is D a type? + * @since 5.0.1 + */ +public class CPPASTAmbiguousDeclarator extends CPPASTAmbiguity implements IASTAmbiguousDeclarator { + + private IASTDeclarator[] dtors = new IASTDeclarator[2]; + private int dtorPos=-1; + + + public CPPASTAmbiguousDeclarator(IASTDeclarator... decls) { + for(IASTDeclarator d : decls) { + if (d != null) { + addDeclarator(d); + } + } + } + + public void addDeclarator(IASTDeclarator d) { + if (d != null) { + dtors = (IASTDeclarator[]) ArrayUtil.append(IASTDeclarator.class, dtors, ++dtorPos, d); + d.setParent(this); + d.setPropertyInParent(SUBDECLARATOR); + } + } + + public IASTDeclarator[] getDeclarators() { + dtors = (IASTDeclarator[]) ArrayUtil.removeNullsAfter(IASTDeclarator.class, dtors, dtorPos ); + return dtors; + } + + @Override + protected IASTNode[] getNodes() { + return getDeclarators(); + } + + public IASTInitializer getInitializer() { + return dtors[0].getInitializer(); + } + + public IASTName getName() { + return dtors[0].getName(); + } + + public IASTDeclarator getNestedDeclarator() { + return dtors[0].getNestedDeclarator(); + } + + public IASTPointerOperator[] getPointerOperators() { + return dtors[0].getPointerOperators(); + } + + public int getRoleForName(IASTName name) { + return dtors[0].getRoleForName(name); + } + + public void addPointerOperator(IASTPointerOperator operator) { + Assert.isLegal(false); + } + + public void setInitializer(IASTInitializer initializer) { + Assert.isLegal(false); + } + + public void setName(IASTName name) { + Assert.isLegal(false); + } + + public void setNestedDeclarator(IASTDeclarator nested) { + Assert.isLegal(false); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java index ce6814c949f..f6ca702b48b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java @@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; /** * @author jcamelon @@ -115,23 +116,20 @@ public class CPPASTDeclarator extends CPPASTNode implements IASTDeclarator { if( !ptrOps[i].accept( action ) ) return false; } - if( getPropertyInParent() != IASTTypeId.ABSTRACT_DECLARATOR && - nestedDeclarator == null ) - { - if( getParent() instanceof IASTDeclarator ) - { - IASTDeclarator outermostDeclarator = (IASTDeclarator) getParent(); - while( outermostDeclarator.getParent() instanceof IASTDeclarator ) - outermostDeclarator = (IASTDeclarator) outermostDeclarator.getParent(); - if( outermostDeclarator.getPropertyInParent() != IASTTypeId.ABSTRACT_DECLARATOR ) - if( name != null ) if( !name.accept( action ) ) return false; + if (nestedDeclarator == null && name != null) { + IASTDeclarator outermost= CPPVisitor.findOutermostDeclarator(this); + if (outermost.getPropertyInParent() != IASTTypeId.ABSTRACT_DECLARATOR) { + if (!name.accept(action)) return false; } - else - if( name != null ) if( !name.accept( action ) ) return false; } - if( nestedDeclarator != null ) if( !nestedDeclarator.accept( action ) ) return false; + if (nestedDeclarator != null) { + if (!nestedDeclarator.accept(action)) return false; + } + if (!postAccept(action)) + return false; + if( action.shouldVisitDeclarators ){ switch( action.leave( this ) ){ case ASTVisitor.PROCESS_ABORT : return false; @@ -139,8 +137,7 @@ public class CPPASTDeclarator extends CPPASTNode implements IASTDeclarator { default : break; } } - - return postAccept( action ); + return true; } protected boolean postAccept( ASTVisitor action ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java index 280d6728d76..7dfb5bd95b1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java @@ -274,4 +274,8 @@ public class CPPASTName extends CPPASTNode implements IASTName, IASTCompletionCo public ILinkage getLinkage() { return Linkage.CPP_LINKAGE; } + + public IASTName getLastName() { + return this; + } } 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 106e7ddaa46..1e4abc2277e 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 @@ -6,19 +6,25 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +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.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; -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.CPPVisitor; +import org.eclipse.core.runtime.Assert; /** * @author jcamelon @@ -31,6 +37,9 @@ public class CPPASTNewExpression extends CPPASTNode implements private IASTExpression initializer; private IASTTypeId typeId; private boolean isNewTypeId; + + private IASTExpression [] arrayExpressions = null; + public CPPASTNewExpression() { @@ -96,20 +105,44 @@ public class CPPASTNewExpression extends CPPASTNode implements } public IASTExpression [] getNewTypeIdArrayExpressions() { - if( arrayExpressions == null ) return IASTExpression.EMPTY_EXPRESSION_ARRAY; - return (IASTExpression[]) ArrayUtil.trim( IASTExpression.class, arrayExpressions ); + if( arrayExpressions == null ) { + if (typeId != null) { + IASTDeclarator dtor= CPPVisitor.findInnermostDeclarator(typeId.getAbstractDeclarator()); + if (dtor instanceof IASTArrayDeclarator) { + IASTArrayDeclarator ad= (IASTArrayDeclarator) dtor; + IASTArrayModifier[] ams= ad.getArrayModifiers(); + arrayExpressions= new IASTExpression[ams.length]; + for (int i = 0; i < ams.length; i++) { + IASTArrayModifier am = ams[i]; + arrayExpressions[i]= am.getConstantExpression(); + } + return arrayExpressions; + } + } + arrayExpressions= IASTExpression.EMPTY_EXPRESSION_ARRAY; + } + return arrayExpressions; } public void addNewTypeIdArrayExpression(IASTExpression expression) { - arrayExpressions = (IASTExpression[]) ArrayUtil.append( IASTExpression.class, arrayExpressions, expression ); - if(expression != null) { - expression.setParent(this); - expression.setPropertyInParent(NEW_TYPEID_ARRAY_EXPRESSION); - } + Assert.isNotNull(typeId); + IASTDeclarator dtor= CPPVisitor.findInnermostDeclarator(typeId.getAbstractDeclarator()); + if (dtor instanceof IASTArrayDeclarator == false) { + Assert.isNotNull(dtor); + Assert.isTrue(dtor.getParent() == typeId); + IASTArrayDeclarator adtor= new CPPASTArrayDeclarator(dtor.getName()); + IASTPointerOperator[] ptrOps= dtor.getPointerOperators(); + for (IASTPointerOperator ptr : ptrOps) { + adtor.addPointerOperator(ptr); + } + typeId.setAbstractDeclarator(adtor); + dtor= adtor; + } + IASTArrayModifier mod= new CPPASTArrayModifier(expression); + ((ASTNode) mod).setOffsetAndLength((ASTNode)expression); + ((IASTArrayDeclarator) dtor).addArrayModifier(mod); } - private IASTExpression [] arrayExpressions = null; - @Override public boolean accept( ASTVisitor action ){ if( action.shouldVisitExpressions ){ @@ -122,11 +155,6 @@ public class CPPASTNewExpression extends CPPASTNode implements if( placement != null ) if( !placement.accept( action ) ) return false; if( typeId != null ) if( !typeId.accept( action ) ) return false; - - IASTExpression [] exps = getNewTypeIdArrayExpressions(); - for( int i = 0; i < exps.length; i++ ) - if( !exps[i].accept( action ) ) return false; - if( initializer != null ) if( !initializer.accept( action ) ) return false; if( action.shouldVisitExpressions ){ @@ -152,14 +180,6 @@ public class CPPASTNewExpression extends CPPASTNode implements other.setParent( child.getParent() ); initializer = (IASTExpression) other; } - if( arrayExpressions == null ) return; - for( int i = 0; i < arrayExpressions.length; ++i ) - if( arrayExpressions[i] == child ) - { - other.setPropertyInParent( child.getPropertyInParent() ); - other.setParent( child.getParent() ); - arrayExpressions[i] = (IASTExpression) other; - } } public IType getExpressionType() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTParameterDeclaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTParameterDeclaration.java index 402275cd28c..ea0b808eeb6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTParameterDeclaration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTParameterDeclaration.java @@ -6,19 +6,22 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * IBM - Initial API and implementation + * IBM - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; /** * @author jcamelon */ -public class CPPASTParameterDeclaration extends CPPASTNode implements ICPPASTParameterDeclaration { +public class CPPASTParameterDeclaration extends CPPASTNode implements ICPPASTParameterDeclaration, IASTAmbiguityParent { private IASTDeclSpecifier declSpec; private IASTDeclarator declarator; @@ -78,4 +81,12 @@ public class CPPASTParameterDeclaration extends CPPASTNode implements ICPPASTPar } return true; } + + public void replace(IASTNode child, IASTNode other) { + if (child == declarator) { + other.setPropertyInParent(child.getPropertyInParent()); + other.setParent(child.getParent()); + declarator= (IASTDeclarator) other; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java index 9d651bd4b4a..01aa578e36e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTQualifiedName.java @@ -99,10 +99,10 @@ public class CPPASTQualifiedName extends CPPASTNode implements } public IASTName getLastName() { - if (names == null || names.length == 0) + if (namesPos < 0) return null; - return names[names.length - 1]; + return names[namesPos]; } public char[] toCharArray() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java index 9329912db9a..a85546022dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTemplateId.java @@ -197,10 +197,11 @@ public class CPPASTTemplateId extends CPPASTNode implements ICPPASTTemplateId, I } } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IASTName#getLinkage() - */ public ILinkage getLinkage() { return Linkage.CPP_LINKAGE; } + + public IASTName getLastName() { + return this; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index d9f7c3fabfc..933be75beca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -16,7 +16,6 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTVisitor; @@ -78,6 +77,7 @@ import org.eclipse.cdt.core.dom.ast.IASTWhileStatement; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; +import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression; @@ -85,6 +85,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; 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.ICPPASTConstructorInitializer; +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.ICPPASTElaboratedTypeSpecifier; @@ -124,7 +125,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTBinaryExpression; -import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointerToMember; @@ -141,14 +141,18 @@ import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.ITokenDuple; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; 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.BacktrackException; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclaration; +import org.eclipse.cdt.internal.core.dom.parser.DeclarationOptions; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement; -import org.eclipse.cdt.internal.core.parser.SimpleDeclarationStrategy; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTElaboratedTypeSpecifier; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTEnumerationSpecifier; +import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.parser.TemplateParameterManager; import org.eclipse.cdt.internal.core.parser.token.BasicTokenDuple; import org.eclipse.cdt.internal.core.parser.token.OperatorTokenDuple; @@ -162,17 +166,18 @@ import org.eclipse.cdt.internal.core.parser.token.TokenFactory; * @author jcamelon */ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { - - - private static final int DEFAULT_CATCH_HANDLER_LIST_SIZE = 4; - - + private static final int DEFAULT_CATCH_HANDLER_LIST_SIZE= 4; + private static final int DEFAULT_PARAMETER_LIST_SIZE= 4; + private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {}; + private static enum DtorStrategy {PREFER_FUNCTION, PREFER_NESTED} + private ScopeStack templateIdScopes = new ScopeStack(); - private int templateCount = 0; private int functionBodyCount= 0; private int templateArgListCount= 0; - private int rejectLogicalOperatorInTemplateID; + private int rejectLogicalOperatorInTemplateID= 0; + private char[] currentClassName; + protected CPPASTTranslationUnit translationUnit; @@ -287,7 +292,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { try { while (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) { IToken argStart = mark(); - IASTTypeId typeId = typeId(false); + IASTTypeId typeId = typeId(DeclarationOptions.TYPEID); if(typeId != null && (LT(1)==IToken.tCOMMA || LT(1)==IToken.tGT || LT(1)==IToken.tEOC)) { // potentially a type-id - check for id-expression ambiguity @@ -548,8 +553,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } else { // must be a conversion function IToken t = LA(1); - typeId = typeId(true); - if (typeId == null) throw backtrack; + typeId= typeId(DeclarationOptions.TYPEID_CONVERSION); + if (typeId == null) + throwBacktrack(t); + if (t != LA(1)) { while (t.getNext() != LA(1)) { t = t.getNext(); @@ -943,7 +950,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { try { if (!avoidCastExpressionByHeuristics()) { - IASTTypeId typeId = typeId(false); + IASTTypeId typeId = typeId(DeclarationOptions.TYPEID); if (typeId != null && LT(1) == IToken.tRPAREN) { consume(); if (initialSize > 0) { @@ -970,7 +977,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } @Override - protected IASTTypeId typeId(boolean forNewExpression) throws EndOfFileException { + protected IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException { if (!canBeTypeSpecifier()) { return null; } @@ -979,57 +986,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { IASTDeclSpecifier declSpecifier = null; IASTDeclarator declarator = null; try { - try { - declSpecifier = declSpecifierSeq(true, true); - } - catch (FoundDeclaratorException e) { - return null; + declSpecifier = declSpecifierSeq(option); + if (LT(1) != IToken.tEOC) { + declarator= declarator(DtorStrategy.PREFER_FUNCTION, option); } - if (LT(1) != IToken.tEOC) - declarator = declarator(SimpleDeclarationStrategy.TRY_FUNCTION, forNewExpression); + } catch (FoundDeclaratorException e) { + declSpecifier= e.declSpec; + declarator= e.declarator; + backup(e.currToken); } catch (BacktrackException bt) { return null; - /* - backup(mark); - if (declarator != null || declSpecifier != null) - throwBacktrack(startingOffset, figureEndOffset(declSpecifier, - declarator) - - startingOffset); - else - throwBacktrack(startingOffset, bt.getLength()); - */ } - if (declarator != null) { - if (declarator.getName().toCharArray().length > 0) { - return null; - /* - backup(mark); - throwBacktrack(startingOffset, figureEndOffset(declSpecifier, - declarator) - - startingOffset); - */ - } - if (declSpecifier instanceof IASTSimpleDeclSpecifier - && ((ASTNode) declSpecifier).getLength() == 0) { - return null; - /* - backup(mark); - throwBacktrack(startingOffset, figureEndOffset(declSpecifier, - declarator) - - startingOffset); - */ - } - if (declarator instanceof IASTArrayDeclarator && forNewExpression) { - return null; - /* - backup(mark); - throwBacktrack(startingOffset, figureEndOffset(declSpecifier, - declarator) - - startingOffset); - */ - } - } - IASTTypeId result = createTypeId(); ((ASTNode) result).setOffsetAndLength(startingOffset, figureEndOffset( declSpecifier, declarator) - startingOffset); @@ -1078,238 +1045,140 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } /** - * Parse a new-expression. - * - * @throws BacktrackException - * newexpression: ::? new newplacement? newtypeid - * newinitializer? ::? new newplacement? ( typeid ) - * newinitializer? newplacement: ( expressionlist ) newtypeid: - * typespecifierseq newdeclarator? newdeclarator: ptroperator * - * newdeclarator? | directnewdeclarator directnewdeclarator: [ - * expression ] directnewdeclarator [ constantexpression ] - * newinitializer: ( expressionlist? ) + * Parse a new-expression. There is room for ambiguities. With P for placement, T for typeid, + * and I for initializer the potential patterns (with the new omitted) are: + * easy: T, T(I) + * medium: (P) T(I), (P) (T)(I) + * hard: (T), (P) T, (P) T, (P) (T), (T)(I) */ protected IASTExpression newExpression() throws BacktrackException, EndOfFileException { IToken la = LA(1); - int startingOffset = la.getOffset(); - int lastOffset = 0; + int offset= la.getOffset(); - boolean isGlobal = false; - if (LT(1) == IToken.tCOLONCOLON) { - lastOffset = consume().getEndOffset(); - isGlobal = true; + final boolean isGlobal = la.getType() == IToken.tCOLONCOLON; + if (isGlobal) { + consume(); } - lastOffset = consume().getEndOffset(); - boolean typeIdInParen = false; - boolean placementParseFailure = true; - IToken beforeSecondParen = null; - IToken backtrackMarker = null; - IASTTypeId typeId = null; - IASTExpression newPlacementExpressions = null; - IASTExpression newInitializerExpressions = null; - boolean isNewTypeId = false; - - master_new_loop: for (int i = 0; i < 2; ++i) { - IToken loopMark = LA(1); - if (LT(1) == IToken.tLPAREN) { - lastOffset = consume().getEndOffset(); - if (templateIdScopes.size() > 0) { - templateIdScopes.push(IToken.tLPAREN); - } - try { - // Try to consume placement list - if (i == 0) { - backtrackMarker = mark(); - newPlacementExpressions = expression(); - lastOffset = consume(IToken.tRPAREN).getEndOffset(); - if (LT(1) == IToken.tLBRACKET) { - backup(backtrackMarker); - if (templateIdScopes.size() > 0) { - templateIdScopes.pop(); - } // pop 1st Parent - placementParseFailure = true; - throwBacktrack(backtrackMarker.getOffset(), - backtrackMarker.getLength()); - } else - placementParseFailure = false; - } - - if (LT(1) == IToken.tLPAREN) { - beforeSecondParen = mark(); - lastOffset = consume().getEndOffset(); - if (templateIdScopes.size() > 0) { - templateIdScopes.push(IToken.tLPAREN); - } // push 2nd Paren - typeIdInParen = true; - } - } catch (BacktrackException e) { - backup(backtrackMarker); - } - if (placementParseFailure) { - // CASE: new (typeid-not-looking-as-placement) ... - // the first expression in () is not a placement - // - then it has to be typeId - typeId = typeId(false); - if (typeId == null) throw backtrack; - lastOffset = consume(IToken.tRPAREN).getEndOffset(); - if (templateIdScopes.size() > 0) { - templateIdScopes.pop(); - } // pop 1st Paren - break master_new_loop; - } - if (!typeIdInParen) { - if (LT(1) == IToken.tLBRACKET) { - // CASE: new (typeid-looking-as-placement) [expr]... - // the first expression in () has been parsed as a - // placement; - // however, we assume that it was in fact typeId, and - // this - // new statement creates an array. - // Do nothing, fallback to array/initializer processing - } else { - // CASE: new (placement) typeid ... - // the first expression in () is parsed as a placement, - // and the next expression doesn't start with '(' or '[' - // - then it has to be typeId - backtrackMarker = mark(); - typeId = typeId(true); - if (typeId != null) { - lastOffset = calculateEndOffset(typeId); - break master_new_loop; - } - // Hmmm, so it wasn't typeId after all... Then it is - // CASE: new (typeid-looking-as-placement) - backup(loopMark); - placementParseFailure = true; - continue master_new_loop; - } - } else { - // Tricky cases: first expression in () is parsed as a - // placement, - // and the next expression starts with '('. - // The problem is, the first expression might as well be a - // typeid - typeId = typeId(true); - if (typeId == null) { - backup(beforeSecondParen); - if (templateIdScopes.size() > 0) { - templateIdScopes.pop(); - } - } else - try { - lastOffset = consume(IToken.tRPAREN).getEndOffset(); - if (templateIdScopes.size() > 0) { - templateIdScopes.pop(); - } // popping the 2nd Paren - - if (LT(1) == IToken.tLPAREN - || LT(1) == IToken.tLBRACKET) { - // CASE: new (placement)(typeid)(initializer) - // CASE: new (placement)(typeid)[] ... - // Great, so far all our assumptions have been - // correct - // Do nothing, fallback to array/initializer - // processing - } else { - // CASE: new (placement)(typeid) - // CASE: new - // (typeid-looking-as-placement)(initializer-looking-as-typeid) - // Worst-case scenario - this cannot be resolved w/o - // more semantic information. - // Luckily, we don't need to know what was that - we - // only know that - // new-expression ends here. - ICPPASTNewExpression result = createNewExpression(); - ((ASTNode) result) - .setOffsetAndLength(startingOffset, - lastOffset - startingOffset); - result.setIsGlobal(isGlobal); - result.setIsNewTypeId(isNewTypeId); - result.setTypeId(typeId); - if (newPlacementExpressions != null) { - result.setNewPlacement(newPlacementExpressions); - } - return result; - } - break master_new_loop; - } catch (BacktrackException e) { - // CASE: new - // (typeid-looking-as-placement)(initializer-not-looking-as-typeid) - // Fallback to initializer processing - backup(beforeSecondParen); - if (templateIdScopes.size() > 0) { - templateIdScopes.pop(); - }// pop that 2nd paren - } - } - } else { - // CASE: new typeid ... - // new parameters do not start with '(' - // i.e it has to be a plain typeId - typeId = typeId(true); - if (typeId == null) throw backtrack; - lastOffset = calculateEndOffset(typeId); - isNewTypeId = true; - break master_new_loop; - } - } - ICPPASTNewExpression result = createNewExpression(); - ((ASTNode) result).setOffsetAndLength(startingOffset, lastOffset - - startingOffset); - result.setIsGlobal(isGlobal); - if (typeId != null) { - result.setIsNewTypeId(isNewTypeId); - result.setTypeId(typeId); - } - if (newPlacementExpressions != null) { - result.setNewPlacement(newPlacementExpressions); - } - - while (LT(1) == IToken.tLBRACKET) { - // array new - lastOffset = consume().getEndOffset(); - - if (templateIdScopes.size() > 0) { - templateIdScopes.push(IToken.tLBRACKET); - } - - IASTExpression a = assignmentExpression(); - lastOffset = consume(IToken.tRBRACKET).getEndOffset(); - result.addNewTypeIdArrayExpression(a); - - if (templateIdScopes.size() > 0) { - templateIdScopes.pop(); - } - } - // newinitializer + consume(IToken.t_new); if (LT(1) == IToken.tLPAREN) { - lastOffset = consume().getEndOffset(); - if (templateIdScopes.size() > 0) { - templateIdScopes.push(IToken.tLPAREN); - } + consume(); - // we want to know the difference between no newInitializer and an - // empty new Initializer - // if the next token is the RPAREN, then we have an Empty expression - // in our list. - if (LT(1) != IToken.tRPAREN) - newInitializerExpressions = expression(); + // consider placement first (P) ... + IASTExpression plcmt= null; + IASTTypeId typeid= null; + boolean isNewTypeId= true; + IASTExpression init= null; + int endOffset= 0; + IToken mark= mark(); + IToken end= null; + try { + plcmt= expression(); + endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset(); + + if (LT(1) == IToken.tLPAREN) { + // (P)(T) ... + isNewTypeId= false; + consume(IToken.tLPAREN); + typeid= typeId(DeclarationOptions.TYPEID); + if (typeid == null) + throw backtrack; + endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset(); + } else { + // (P) T ... + typeid= typeId(DeclarationOptions.TYPEID_NEW); + if (typeid == null) + throw backtrack; + endOffset= calculateEndOffset(typeid); + } + end= LA(1); + } catch (BacktrackException e) { + plcmt= null; + typeid= null; + } - if (LT(1) == IToken.tEOC) { - lastOffset = consume().getEndOffset(); - } else { - lastOffset = consume(IToken.tRPAREN).getEndOffset(); - } - - if (templateIdScopes.size() > 0) { - templateIdScopes.pop(); - } - if (newInitializerExpressions != null) { - result.setNewInitializer(newInitializerExpressions); - } + if (typeid != null && plcmt != null && LT(1) == IToken.tLPAREN) { + // (P)(T)(I) or (P) T (I) + consume(IToken.tLPAREN); + init= possiblyEmptyExpressionList(IToken.tRPAREN); + endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset(); + return newExpression(isGlobal, plcmt, typeid, isNewTypeId, init, offset, endOffset); + } + // (T) ... + backup(mark); + IASTTypeId typeid2= null; + IASTExpression init2= null; + int endOffset2; + try { + typeid2= typeId(DeclarationOptions.TYPEID); + if (typeid2 == null) + throw backtrack; + endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset(); + + if (LT(1) == IToken.tLPAREN) { + if (plcmt != null && + CPPVisitor.findTypeRelevantDeclarator(typeid2.getAbstractDeclarator()) instanceof IASTArrayDeclarator) { + throwBacktrack(LA(1)); + } + + // (T)(I) + consume(IToken.tLPAREN); + init2= possiblyEmptyExpressionList(IToken.tRPAREN); + endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset(); + } + } catch (BacktrackException e) { + if (plcmt == null) + throw e; + endOffset2= -1; + } + + + if (plcmt == null || endOffset2 > endOffset) + return newExpression(isGlobal, null, typeid2, false, init2, offset, endOffset2); + + if (endOffset != endOffset2) { + backup(end); + return newExpression(isGlobal, plcmt, typeid, isNewTypeId, init, offset, endOffset); + } + + // ambiguity: + IASTExpression ex1= newExpression(isGlobal, plcmt, typeid, isNewTypeId, init, offset, endOffset); + IASTExpression ex2= newExpression(isGlobal, null, typeid2, false, init2, offset, endOffset2); + IASTAmbiguousExpression ambiguity= createAmbiguousExpression(); + ambiguity.addExpression(ex1); + ambiguity.addExpression(ex2); + ((ASTNode) ambiguity).setOffsetAndLength((ASTNode) ex1); + return ambiguity; } - ((ASTNode) result).setLength(lastOffset - startingOffset); + + // T ... + final IASTTypeId typeid = typeId(DeclarationOptions.TYPEID_NEW); + if (typeid == null) + throw backtrack; + int endOffset = calculateEndOffset(typeid); + IASTExpression init= null; + if (LT(1) == IToken.tLPAREN) { + // T(I) + consume(IToken.tLPAREN); + init= possiblyEmptyExpressionList(IToken.tRPAREN); + endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset(); + } + return newExpression(isGlobal, null, typeid, true, init, offset, endOffset); + } + + private IASTExpression newExpression(boolean isGlobal, IASTExpression placement, IASTTypeId typeid, + boolean isNewTypeId, IASTExpression init, int offset, int endOffset) { + ICPPASTNewExpression result = createNewExpression(); + result.setIsGlobal(isGlobal); + result.setIsNewTypeId(isNewTypeId); + result.setTypeId(typeid); + if (placement != null) { + result.setNewPlacement(placement); + } + if (init != null) { + result.setNewInitializer(init); + } + ((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); return result; } @@ -1827,7 +1696,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { int startingOffset = LA(1).getOffset(); IToken op = consume(); consume(IToken.tLT); - IASTTypeId typeID = typeId(false); + IASTTypeId typeID = typeId(DeclarationOptions.TYPEID); if (typeID == null) { throw backtrack; } consume(IToken.tGT); consume(IToken.tLPAREN); @@ -1867,8 +1736,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { private final boolean supportMinAndMaxOperators; - private final boolean supportComplex; - private final boolean supportLongLong; private final IIndex index; @@ -1907,7 +1774,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { allowCPPRestrict = config.allowRestrictPointerOperators(); supportExtendedTemplateSyntax = config.supportExtendedTemplateSyntax(); supportMinAndMaxOperators = config.supportMinAndMaxOperators(); - supportComplex = config.supportComplexNumbers(); supportLongLong = config.supportLongLongs(); this.index= index; } @@ -1923,7 +1789,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { */ protected IASTDeclaration usingClause() throws EndOfFileException, BacktrackException { - IToken firstToken = consume(); + final int offset= consume().getOffset(); if (LT(1) == IToken.t_namespace) { // using-directive @@ -1936,7 +1802,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { name = createName(name()); break; default: - throwBacktrack(firstToken.getOffset(), endOffset - firstToken.getOffset()); + throwBacktrack(offset, endOffset - offset); } switch (LT(1)) { @@ -1949,13 +1815,18 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } ICPPASTUsingDirective astUD = createUsingDirective(); - ((ASTNode) astUD).setOffsetAndLength(firstToken.getOffset(), endOffset - firstToken.getOffset()); + ((ASTNode) astUD).setOffsetAndLength(offset, endOffset - offset); astUD.setQualifiedName(name); return astUD; } - boolean typeName = false; + ICPPASTUsingDeclaration result = usingDeclaration(offset); + return result; + } + private ICPPASTUsingDeclaration usingDeclaration(final int offset) throws EndOfFileException, + BacktrackException { + boolean typeName = false; if (LT(1) == IToken.t_typename) { typeName = true; consume(); @@ -1973,11 +1844,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } ICPPASTUsingDeclaration result = createUsingDeclaration(); - ((ASTNode) result).setOffsetAndLength(firstToken.getOffset(), end - firstToken.getOffset()); + ((ASTNode) result).setOffsetAndLength(offset, end - offset); result.setIsTypename(typeName); result.setName(name); - return result; - } + return result; + } protected ICPPASTUsingDeclaration createUsingDeclaration() { @@ -2015,7 +1886,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { break linkageDeclarationLoop; default: try { - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(DeclarationOptions.GLOBAL); linkage.addDeclaration(d); } catch (BacktrackException bt) { IASTProblem p = failParse(bt); @@ -2038,7 +1909,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } // single declaration - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(DeclarationOptions.GLOBAL); linkage.addDeclaration(d); ((ASTNode) linkage).setLength(calculateEndOffset(d) - firstToken.getOffset()); return linkage; @@ -2054,11 +1925,12 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * template-declaration: export? template < template-parameter-list > * declaration explicit-instantiation: template declaration * explicit-specialization: template <>declaration + * @param option * * @throws BacktrackException * request for a backtrack */ - protected IASTDeclaration templateDeclaration() throws EndOfFileException, + protected IASTDeclaration templateDeclaration(DeclarationOptions option) throws EndOfFileException, BacktrackException { IToken mark = mark(); IToken firstToken = null; @@ -2106,7 +1978,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } else templateInstantiation = createTemplateInstantiation(); try { - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(option); ((ASTNode) templateInstantiation).setOffsetAndLength(firstToken .getOffset(), calculateEndOffset(d) - firstToken.getOffset()); templateInstantiation.setDeclaration(d); @@ -2122,7 +1994,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { ICPPASTTemplateSpecialization templateSpecialization = createTemplateSpecialization(); try { - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(option); ((ASTNode) templateSpecialization).setOffsetAndLength( firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset()); templateSpecialization.setDeclaration(d); @@ -2139,7 +2011,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { ICPPASTTemplateDeclaration templateDecl = createTemplateDeclaration(); try { - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(option); ((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset()); templateDecl.setExported(exported); @@ -2219,7 +2091,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { lastOffset = calculateEndOffset(identifierName); if (LT(1) == IToken.tASSIGN) { // optional = type-id consume(); - typeId = typeId(false); // type-id + typeId = typeId(DeclarationOptions.TYPEID); // type-id if (typeId == null) throw backtrack; lastOffset = calculateEndOffset(typeId); @@ -2305,7 +2177,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * request a backtrack */ @Override - protected IASTDeclaration declaration() throws EndOfFileException, BacktrackException { + protected IASTDeclaration declaration(DeclarationOptions option) throws EndOfFileException, BacktrackException { switch (LT(1)) { case IToken.t_asm: return asmDeclaration(); @@ -2315,96 +2187,31 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return usingClause(); case IToken.t_export: case IToken.t_template: - return templateDeclaration(); + return templateDeclaration(option); case IToken.t_extern: if (LT(2) == IToken.tSTRING) return linkageSpecification(); if (supportExtendedTemplateSyntax && LT(2) == IToken.t_template) - return templateDeclaration(); + return templateDeclaration(option); break; case IToken.t_static: case IToken.t_inline: if (supportExtendedTemplateSyntax && LT(2) == IToken.t_template) - return templateDeclaration(); + return templateDeclaration(option); break; + case IToken.tSEMI: + IToken t= consume(); + IASTSimpleDeclaration decl= createSimpleDeclaration(); + IASTSimpleDeclSpecifier declspec= createSimpleDeclSpecifier(); + decl.setDeclSpecifier(declspec); + ((ASTNode) declspec).setOffsetAndLength(t.getOffset(), 0); + ((ASTNode) decl).setOffsetAndLength(t.getOffset(), t.getLength()); + return decl; } - return simpleDeclarationStrategyUnion(); + return simpleDeclaration(option); } - - protected IASTDeclaration simpleDeclarationStrategyUnion() throws EndOfFileException, BacktrackException { - IToken simpleDeclarationMark = mark(); - IASTDeclaration d1 = null, d2 = null; - IToken after = null; - try { - d1 = simpleDeclaration(SimpleDeclarationStrategy.TRY_FUNCTION, false); - try { - after = LA(1); - } catch (EndOfFileException eof) { - } - } catch (BacktrackException bt) { - } - if (d1 != null) { - if( templateCount != 0 ) - return d1; - if( functionBodyCount == 0 ) - return d1; - if (d1 instanceof IASTFunctionDefinition) - return d1; - if (d1 instanceof IASTSimpleDeclaration) { - IASTSimpleDeclaration sd = (IASTSimpleDeclaration) d1; - if( sd.getDeclSpecifier() instanceof ICPPASTDeclSpecifier && ((ICPPASTDeclSpecifier)sd.getDeclSpecifier()).isFriend() ) - return d1; - if (sd.getDeclarators().length != 1) - return d1; - if (sd.getDeclSpecifier() instanceof IASTSimpleDeclSpecifier) { - IASTSimpleDeclSpecifier simpleSpec = (IASTSimpleDeclSpecifier) sd.getDeclSpecifier(); - if( simpleSpec.getType() == IASTSimpleDeclSpecifier.t_void && sd.getDeclarators()[0].getPointerOperators().length == 0 ) - return d1; - } - - if (sd.getDeclarators()[0] instanceof IASTStandardFunctionDeclarator) { - if (sd.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) - return d1; - } else - return d1; - } - } - - // did not work - backup(simpleDeclarationMark); - - try { - d2 = simpleDeclaration(SimpleDeclarationStrategy.TRY_VARIABLE, false); - if (after != null && after != LA(1)) { - backup(after); - return d1; - } - } catch (BacktrackException be) { - if (d1 == null) - throw be; - } - - if (d2 == null && d1 != null) { - backup(after); - return d1; - } - - if (d1 == null && d2 != null) - return d2; - - IASTAmbiguousDeclaration result = createAmbiguousDeclaration(); - ((ASTNode) result).setOffsetAndLength((ASTNode) d1); - result.addDeclaration(d1); - result.addDeclaration(d2); - return result; - } - - protected IASTAmbiguousDeclaration createAmbiguousDeclaration() { - return new CPPASTAmbiguousDeclaration(); - } - /** * Serves as the namespace declaration portion of the ANSI C++ grammar. * namespace-definition: namespace identifier { namespace-body } | namespace { @@ -2441,7 +2248,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { default: int checkToken = LA(1).hashCode(); try { - IASTDeclaration d = declaration(); + IASTDeclaration d = declaration(DeclarationOptions.GLOBAL); namespaceDefinition.addDeclaration(d); } catch (BacktrackException bt) { IASTProblem p = failParse(bt); @@ -2641,158 +2448,140 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } /** - * Serves as the catch-all for all complicated declarations, including - * function-definitions. simpleDeclaration : (declSpecifier)* - * (initDeclarator ("," initDeclarator)*)? (";" | { functionBody } Notes: - - * append functionDefinition stuff to end of this rule To do: - work in - * functionTryBlock - * - * @throws BacktrackException - * request a backtrack + * Parses a declaration with the given options. */ - protected IASTDeclaration simpleDeclaration( - SimpleDeclarationStrategy strategy, boolean fromCatchHandler) + protected IASTDeclaration simpleDeclaration(DeclarationOptions option) throws BacktrackException, EndOfFileException { - IToken firstToken = LA(1); - int firstOffset = firstToken.getOffset(); + final IToken firstToken = LA(1); if (firstToken.getType() == IToken.tLBRACE) - throwBacktrack(firstOffset, firstToken.getLength()); - firstToken = null; // necessary for scalability + throwBacktrack(firstToken); + + final int firstOffset= firstToken.getOffset(); + int endOffset= firstOffset; - IASTDeclSpecifier declSpec; - IASTDeclarator[] declarators = new IASTDeclarator[2]; - boolean tryAgain = false; + ICPPASTDeclSpecifier declSpec; + IASTDeclarator dtor= null; try { - declSpec = declSpecifierSeq(false, false); + declSpec = declSpecifierSeq(option); + final int lt1= LT(1); + if (lt1 == IToken.tSEMI) { + if (!validWithoutDtor(option, declSpec)) { + throwBacktrack(LA(1)); + } + } else if (lt1 != IToken.tEOC) { + dtor= initDeclarator(declSpec, option); + } } catch (FoundDeclaratorException e) { - tryAgain = true; - declSpec = e.declSpec; - declarators = (IASTDeclarator[]) ArrayUtil.append(IASTDeclarator.class, declarators, e.declarator); - backup( e.currToken ); + declSpec= (ICPPASTDeclSpecifier) e.declSpec; + dtor= e.declarator; + backup(e.currToken); } - if (LT(1) != IToken.tSEMI && LT(1) != IToken.tEOC) { - if( !tryAgain ) - declarators = (IASTDeclarator[]) ArrayUtil.append(IASTDeclarator.class, declarators, initDeclarator(strategy)); - while (LT(1) == IToken.tCOMMA) { - consume(); - declarators = (IASTDeclarator[]) ArrayUtil.append(IASTDeclarator.class, declarators, initDeclarator(strategy)); - } + IASTDeclarator[] declarators= {dtor}; + while (LT(1) == IToken.tCOMMA) { + consume(); + declarators= (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, initDeclarator(declSpec, option)); } + declarators= (IASTDeclarator[]) ArrayUtil.removeNulls( IASTDeclarator.class, declarators ); - declarators = (IASTDeclarator[]) ArrayUtil.removeNulls(IASTDeclarator.class, declarators); - - boolean hasFunctionBody = false; + boolean needFunctionBody = false; boolean hasFunctionTryBlock = false; - boolean consumedSemi = false; - int semiOffset = 0; - List constructorChain = Collections.emptyList(); switch (LT(1)) { + case IToken.tEOC: + endOffset= figureEndOffset(declSpec, declarators); + break; case IToken.tSEMI: - if( fromCatchHandler ) - break; - semiOffset = consume().getEndOffset(); - consumedSemi = true; + endOffset= consume().getEndOffset(); break; case IToken.t_try: consume(); - if (LT(1) == IToken.tCOLON) { - constructorChain = new ArrayList(DEFAULT_CONSTRUCTOR_CHAIN_LIST_SIZE); - ctorInitializer(constructorChain); - } - hasFunctionTryBlock = true; + needFunctionBody= true; + hasFunctionTryBlock= true; break; case IToken.tCOLON: - constructorChain = new ArrayList(DEFAULT_CONSTRUCTOR_CHAIN_LIST_SIZE); - ctorInitializer(constructorChain); - hasFunctionBody = true; - break; case IToken.tLBRACE: - break; - case IToken.tRPAREN: - if (!fromCatchHandler) - throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); - break; - case IToken.tEOC: - // Pretend we consumed the semi - consumedSemi = true; + needFunctionBody = true; break; default: throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); } - if (!consumedSemi) { - if (LT(1) == IToken.tLBRACE) { - hasFunctionBody = true; - } - - if (hasFunctionTryBlock && !hasFunctionBody) - throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); + if (needFunctionBody) { + if (declarators.length != 1) + throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); + + // mstodo + final IASTDeclarator fdtor= declarators[0]; + if (fdtor instanceof ICPPASTFunctionDeclarator == false) + throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); + + return functionDefinition(firstOffset, declSpec, fdtor, hasFunctionTryBlock); } - if (hasFunctionBody) { - if (declarators.length != 1) - throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); - - IASTDeclarator declarator = declarators[0]; - if (!(declarator instanceof IASTStandardFunctionDeclarator)) - throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset); - - if (!constructorChain.isEmpty() && declarator instanceof ICPPASTFunctionDeclarator) { - ICPPASTFunctionDeclarator fd = (ICPPASTFunctionDeclarator) declarator; - - int size = constructorChain.size(); - for (int i = 0; i < size; ++i) { - ICPPASTConstructorChainInitializer initializer = (ICPPASTConstructorChainInitializer) constructorChain.get(i); - fd.addConstructorToChain(initializer); - } - - // fix for 86698, now that the constructorChain is established, - // update the declarator's length - if (fd instanceof ASTNode && constructorChain.get(size - 1) instanceof ASTNode) { - ASTNode init = (ASTNode) constructorChain.get(size - 1); - ((ASTNode) fd).setLength(init.getOffset() + init.getLength() - ((ASTNode) fd).getOffset()); - } - } - - IASTFunctionDefinition funcDefinition = createFunctionDefinition(); - ((ASTNode) funcDefinition).setOffset(firstOffset); - funcDefinition.setDeclSpecifier(declSpec); - funcDefinition.setDeclarator((IASTStandardFunctionDeclarator) declarator); - - IASTStatement s = handleFunctionBody(); - if (s != null) { - funcDefinition.setBody(s); - } - ((ASTNode) funcDefinition).setLength(calculateEndOffset(s) - firstOffset); - - if (hasFunctionTryBlock && declarator instanceof ICPPASTFunctionTryBlockDeclarator) { - List handlers = new ArrayList(DEFAULT_CATCH_HANDLER_LIST_SIZE); - catchHandlerSequence(handlers); - for (int i = 0; i < handlers.size(); ++i) { - ICPPASTCatchHandler handler = handlers.get(i); - ((ICPPASTFunctionTryBlockDeclarator) declarator).addCatchHandler(handler); - ((ASTNode) funcDefinition).setLength(calculateEndOffset(handler) - firstOffset); - } - } - return funcDefinition; - } - - IASTSimpleDeclaration simpleDeclaration = createSimpleDeclaration(); - int length = figureEndOffset(declSpec, declarators) - firstOffset; - if (consumedSemi) - length = semiOffset - firstOffset; - - ((ASTNode) simpleDeclaration).setOffsetAndLength(firstOffset, length); + // no function body + IASTSimpleDeclaration simpleDeclaration= createSimpleDeclaration(); simpleDeclaration.setDeclSpecifier(declSpec); - - for (int i = 0; i < declarators.length; ++i) { - simpleDeclaration.addDeclarator(declarators[i]); + for (IASTDeclarator declarator : declarators) { + simpleDeclaration.addDeclarator(declarator); } + + ((ASTNode) simpleDeclaration).setOffsetAndLength(firstOffset, endOffset-firstOffset); return simpleDeclaration; } + private boolean validWithoutDtor(DeclarationOptions option, ICPPASTDeclSpecifier declSpec) { + if (declSpec instanceof IASTCompositeTypeSpecifier) + return true; + if (declSpec instanceof IASTElaboratedTypeSpecifier) + return true; + if (declSpec instanceof IASTEnumerationSpecifier) + return true; + + return false; + } + + private IASTDeclaration functionDefinition(final int firstOffset, IASTDeclSpecifier declSpec, + IASTDeclarator declarator, boolean hasFunctionTryBlock) + throws EndOfFileException, BacktrackException { + if (LT(1) == IToken.tCOLON) { + List constructorChain= new ArrayList(DEFAULT_CONSTRUCTOR_CHAIN_LIST_SIZE); + ctorInitializer(constructorChain); + if (!constructorChain.isEmpty() && declarator instanceof ICPPASTFunctionDeclarator) { + ICPPASTFunctionDeclarator fd = (ICPPASTFunctionDeclarator) declarator; + for (ICPPASTConstructorChainInitializer initializer : constructorChain) { + fd.addConstructorToChain(initializer); + } + // fix for 86698, update the declarator's length + adjustLength(fd, constructorChain.get(constructorChain.size()-1)); + } + } + + + final IASTStatement body= handleFunctionBody(); + int endOffset= calculateEndOffset(body); + + if (hasFunctionTryBlock) { + List handlers = new ArrayList(DEFAULT_CATCH_HANDLER_LIST_SIZE); + catchHandlerSequence(handlers); + if (!handlers.isEmpty() && declarator instanceof ICPPASTFunctionTryBlockDeclarator) { + ICPPASTFunctionTryBlockDeclarator tbd= (ICPPASTFunctionTryBlockDeclarator) declarator; + for (ICPPASTCatchHandler catchHandler : handlers) { + tbd.addCatchHandler(catchHandler); + } + endOffset= calculateEndOffset(handlers.get(handlers.size()-1)); + } + } + + IASTFunctionDefinition funcDefinition = createFunctionDefinition(); + funcDefinition.setDeclSpecifier(declSpec); + funcDefinition.setDeclarator((IASTStandardFunctionDeclarator) declarator); + funcDefinition.setBody(body); + + ((ASTNode) funcDefinition).setOffsetAndLength(firstOffset, endOffset-firstOffset); + return funcDefinition; + } + protected IASTFunctionDefinition createFunctionDefinition() { return new CPPASTFunctionDefinition(); @@ -2813,7 +2602,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * @throws BacktrackException * request a backtrack */ - protected void ctorInitializer(List collection) throws EndOfFileException, + protected void ctorInitializer(List collection) throws EndOfFileException, BacktrackException { consume(); ctorLoop: for (;;) { @@ -2875,33 +2664,26 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * @throws BacktrackException * request a backtrack */ - protected ICPPASTParameterDeclaration parameterDeclaration() - throws BacktrackException, EndOfFileException { - IToken current = LA(1); - IASTDeclSpecifier declSpec = null; + protected ICPPASTParameterDeclaration parameterDeclaration() throws BacktrackException, EndOfFileException { + final int startOffset= LA(1).getOffset(); + + IASTDeclSpecifier declSpec; + IASTDeclarator declarator; try { - declSpec = declSpecifierSeq(true, false); + declSpec= declSpecifierSeq(DeclarationOptions.PARAMETER); + declarator= initDeclarator(declSpec, DeclarationOptions.PARAMETER); } catch (FoundDeclaratorException e) { - throwBacktrack( e.currToken ); - } - IASTDeclarator declarator = null; - switch (LT(1)) { - case IToken.tSEMI: - case IToken.tEOC: - break; - default: - declarator = initDeclarator(SimpleDeclarationStrategy.TRY_FUNCTION); + declSpec= e.declSpec; + declarator= e.declarator; + backup(e.currToken); } - if (current == LA(1)) { - throwBacktrack(current.getOffset(), figureEndOffset(declSpec, declarator) - current.getOffset()); - } - ICPPASTParameterDeclaration parm = createParameterDeclaration(); - ((ASTNode) parm).setOffsetAndLength(current.getOffset(), figureEndOffset(declSpec, declarator) - current.getOffset()); + final ICPPASTParameterDeclaration parm = createParameterDeclaration(); parm.setDeclSpecifier(declSpec); - if (declarator != null) { - parm.setDeclarator(declarator); - } + parm.setDeclarator(declarator); + + final int endOffset = figureEndOffset(declSpec, declarator); + ((ASTNode) parm).setOffsetAndLength(startOffset, endOffset - startOffset); return parm; } @@ -2910,390 +2692,398 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return new CPPASTParameterDeclaration(); } + + private final static int INLINE=0x1, CONST=0x2, RESTRICT=0x4, VOLATILE=0x8, + SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100, + VIRTUAL=0x200, EXPLICIT=0x400, FRIEND=0x800; + + /** * This function parses a declaration specifier sequence, as according to - * the ANSI C++ spec. declSpecifier : "auto" | "register" | "static" | - * "extern" | "mutable" | "inline" | "virtual" | "explicit" | "char" | - * "wchar_t" | "bool" | "short" | "int" | "long" | "signed" | "unsigned" | - * "float" | "double" | "void" | "const" | "volatile" | "friend" | "typedef" | - * ("typename")? name | {"class"|"struct"|"union"} classSpecifier | {"enum"} - * enumSpecifier Notes: - folded in storageClassSpecifier, typeSpecifier, - * functionSpecifier - folded elaboratedTypeSpecifier into classSpecifier - * and enumSpecifier - find template names in name - * - * @param parm - * Is this for a parameter declaration (true) or simple - * declaration (false) - * @param forTypeId - * TODO - * @return TODO - * @throws BacktrackException - * request a backtrack - * @throws FoundDeclaratorException + * the ANSI C++ specification. + * declSpecifier : + * "auto" | "register" | "static" | "extern" | "mutable" | + * "inline" | "virtual" | "explicit" | + * "typedef" | "friend" | + * "const" | "volatile" | + * "short" | "long" | "signed" | "unsigned" | "int" | + * "char" | "wchar_t" | "bool" | "float" | "double" | "void" | + * ("typename")? name | + * { "class" | "struct" | "union" } classSpecifier | + * {"enum"} enumSpecifier */ - protected ICPPASTDeclSpecifier declSpecifierSeq(boolean parm, - boolean forTypeId) throws BacktrackException, EndOfFileException, FoundDeclaratorException { - IToken firstToken = LA(1); - Flags flags = new Flags(parm, false, forTypeId); - IToken last = null; - - boolean isInline = false, isVirtual = false, isExplicit = false, isFriend = false; - boolean isConst = false, isVolatile = false, isRestrict = false; - boolean isLong = false, isShort = false, isUnsigned = false, isSigned = false, isLongLong = false; - boolean isComplex = false, isImaginary = false; - boolean isTypename = false; - + protected ICPPASTDeclSpecifier declSpecifierSeq(final DeclarationOptions option) + throws BacktrackException, EndOfFileException, FoundDeclaratorException { int storageClass = IASTDeclSpecifier.sc_unspecified; int simpleType = IASTSimpleDeclSpecifier.t_unspecified; - ITokenDuple duple = null; + int options= 0; + int isLong= 0; - ICPPASTCompositeTypeSpecifier classSpec = null; - ICPPASTElaboratedTypeSpecifier elabSpec = null; - IASTEnumerationSpecifier enumSpec = null; - IASTExpression typeofExpression = null; - int startOffset = firstToken.getOffset(); + ITokenDuple identifier= null; + ICPPASTDeclSpecifier result= null; + IASTExpression typeofExpression= null; + + boolean isTypename = false; + boolean encounteredRawType= false; + boolean encounteredTypename= false; + + final int offset = LA(1).getOffset(); + int endOffset= offset; declSpecifiers: for (;;) { - switch (LT(1)) { - case IToken.t_inline: - last = consume(); - isInline = true; - break; - case IToken.t_typedef: - storageClass = IASTDeclSpecifier.sc_typedef; - last = consume(); - break; + final IToken token= LA(1); + final int lt1= token.getType(); + switch (lt1) { + // storage class specifiers case IToken.t_auto: - last = consume(); storageClass = IASTDeclSpecifier.sc_auto; + endOffset= consume().getEndOffset(); break; case IToken.t_register: - last = consume(); storageClass = IASTDeclSpecifier.sc_register; + endOffset= consume().getEndOffset(); break; case IToken.t_static: storageClass = IASTDeclSpecifier.sc_static; - last = consume(); + endOffset= consume().getEndOffset(); break; case IToken.t_extern: storageClass = IASTDeclSpecifier.sc_extern; - last = consume(); + endOffset= consume().getEndOffset(); break; case IToken.t_mutable: storageClass = ICPPASTDeclSpecifier.sc_mutable; - last = consume(); + endOffset= consume().getEndOffset(); + break; + case IToken.t_typedef: + storageClass = IASTDeclSpecifier.sc_typedef; + endOffset= consume().getEndOffset(); + break; + // function specifiers + case IToken.t_inline: + options |= INLINE; + endOffset= consume().getEndOffset(); break; case IToken.t_virtual: - isVirtual = true; - last = consume(); + options |= VIRTUAL; + endOffset= consume().getEndOffset(); break; case IToken.t_explicit: - isExplicit = true; - last = consume(); + options |= EXPLICIT; + endOffset= consume().getEndOffset(); break; case IToken.t_friend: - isFriend = true; - last = consume(); + options |= FRIEND; + endOffset= consume().getEndOffset(); break; + // type specifier case IToken.t_const: - isConst = true; - last = consume(); + options |= CONST; + endOffset= consume().getEndOffset(); break; case IToken.t_volatile: - isVolatile = true; - last = consume(); + options |= VOLATILE; + endOffset= consume().getEndOffset(); break; case IToken.t_restrict: - isRestrict = true; - last = consume(); + options |= RESTRICT; + endOffset= consume().getEndOffset(); break; case IToken.t_signed: - isSigned = true; - flags.setEncounteredRawType(true); - last = consume(); + options |= SIGNED; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_unsigned: - isUnsigned = true; - flags.setEncounteredRawType(true); - last = consume(); + options |= UNSIGNED; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_short: - isShort = true; - flags.setEncounteredRawType(true); - last = consume(); + options |= SHORT; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_long: - if (isLong && supportLongLong) { - isLong = false; - isLongLong = true; - } else - isLong = true; - flags.setEncounteredRawType(true); - last = consume(); + isLong++; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t__Complex: - if (!supportComplex) { - IToken la = LA(1); - throwBacktrack(la.getOffset(), la.getEndOffset() - la.getOffset()); - } - last = consume(); - isComplex=true; + options |= COMPLEX; + endOffset= consume().getEndOffset(); break; case IToken.t__Imaginary: - if (!supportComplex) { - IToken la = LA(1); - throwBacktrack(la.getOffset(), la.getLength()); - } - last = consume(); - isImaginary=true; + options |= IMAGINARY; + endOffset= consume().getEndOffset(); break; case IToken.t_char: simpleType = IASTSimpleDeclSpecifier.t_char; - flags.setEncounteredRawType(true); - last = consume(); + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_wchar_t: simpleType = ICPPASTSimpleDeclSpecifier.t_wchar_t; - flags.setEncounteredRawType(true); - last = consume(); + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_bool: simpleType = ICPPASTSimpleDeclSpecifier.t_bool; - flags.setEncounteredRawType(true); - last = consume(); + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_int: - flags.setEncounteredRawType(true); - last = consume(); simpleType = IASTSimpleDeclSpecifier.t_int; + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_float: simpleType = IASTSimpleDeclSpecifier.t_float; - flags.setEncounteredRawType(true); - last = consume(); + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_double: simpleType = IASTSimpleDeclSpecifier.t_double; - flags.setEncounteredRawType(true); - last = consume(); + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_void: simpleType = IASTSimpleDeclSpecifier.t_void; - flags.setEncounteredRawType(true); - last = consume(); + encounteredRawType= true; + endOffset= consume().getEndOffset(); break; case IToken.t_typename: + consume(); + identifier= name(); + endOffset= identifier.getLastToken().getEndOffset(); isTypename = true; - last = consume(); - duple = name(); - last = duple.getLastToken(); - flags.setEncounteredTypename(true); + encounteredTypename= true; break; + case IToken.tBITCOMPLEMENT: case IToken.tCOLONCOLON: case IToken.tIDENTIFIER: case IToken.tCOMPLETION: - if (flags.haveEncounteredRawType()) + if (encounteredRawType || encounteredTypename) break declSpecifiers; - if (flags.haveEncounteredTypename()) - break declSpecifiers; - - try - { - lookAheadForDeclarator(flags); - } - catch( FoundDeclaratorException fde ) - { - ICPPASTSimpleDeclSpecifier simpleDeclSpec = null; - if (isLongLong) { - simpleDeclSpec = createGPPSimpleDeclSpecifier(); - ((IGPPASTSimpleDeclSpecifier) simpleDeclSpec).setLongLong(isLongLong); - } else - simpleDeclSpec = createSimpleDeclSpecifier(); - - int l = last != null ? last.getEndOffset() - firstToken.getOffset() : 0; - ((ASTNode) simpleDeclSpec).setOffsetAndLength(firstToken.getOffset(), l); - - simpleDeclSpec.setConst(isConst); - simpleDeclSpec.setVolatile(isVolatile); - if (simpleDeclSpec instanceof IGPPASTDeclSpecifier) - ((IGPPASTDeclSpecifier) simpleDeclSpec).setRestrict(isRestrict); - - simpleDeclSpec.setFriend(isFriend); - simpleDeclSpec.setInline(isInline); - simpleDeclSpec.setStorageClass(storageClass); - simpleDeclSpec.setVirtual(isVirtual); - simpleDeclSpec.setExplicit(isExplicit); - - simpleDeclSpec.setType(simpleType); - simpleDeclSpec.setLong(isLong); - simpleDeclSpec.setShort(isShort); - simpleDeclSpec.setUnsigned(isUnsigned); - simpleDeclSpec.setSigned(isSigned); - fde.declSpec = simpleDeclSpec; - throw fde; + try { + if (option.fAllowEmptySpecifier && lt1 != IToken.tCOMPLETION) { + lookAheadForDeclarator(option); + } + } catch (FoundDeclaratorException e) { + if (e.currToken.getType() == IToken.tEOC || canBeConstructorDestructorOrConversion(option, storageClass, options, e.declarator)) { + e.declSpec= createSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); + throw e; + } } - duple = name(); - last = duple.getLastToken(); - flags.setEncounteredTypename(true); + identifier= name(); + endOffset= identifier.getLastToken().getEndOffset(); + encounteredTypename= true; break; case IToken.t_class: case IToken.t_struct: case IToken.t_union: - if (flags.haveEncounteredTypename()) - throwBacktrack(LA(1)); + if (encounteredTypename || encounteredRawType) + throwBacktrack(token); try { - classSpec = classSpecifier(); - flags.setEncounteredTypename(true); - break; + result= classSpecifier(); } catch (BacktrackException bt) { - elabSpec = elaboratedTypeSpecifier(); - flags.setEncounteredTypename(true); - break; + result= elaboratedTypeSpecifier(); } + endOffset= calculateEndOffset(result); + encounteredTypename= true; + break; + case IToken.t_enum: - if (flags.haveEncounteredTypename()) - throwBacktrack(LA(1)); + if (encounteredTypename || encounteredRawType) + throwBacktrack(token); try { - enumSpec = enumSpecifier(); - flags.setEncounteredTypename(true); - break; + result= (ICPPASTDeclSpecifier) enumSpecifier(); } catch (BacktrackException bt) { - // this is an elaborated class specifier - elabSpec = elaboratedTypeSpecifier(); - flags.setEncounteredTypename(true); - break; + result= elaboratedTypeSpecifier(); } + endOffset= calculateEndOffset(result); + encounteredTypename= true; + break; + case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec - if (supportAttributeSpecifiers) - __attribute_decl_seq(true, false); - else - throwBacktrack(LA(1).getOffset(), LA(1).getLength()); + if (!supportAttributeSpecifiers) + throwBacktrack(token); + __attribute_decl_seq(true, false); break; - case IGCCToken.t__declspec: // if __declspec appears before identifier - if (duple == null && supportDeclspecSpecifiers) - __attribute_decl_seq(false, true); - else - throwBacktrack(LA(1).getOffset(), LA(1).getLength()); + case IGCCToken.t__declspec: // __declspec precedes the identifier + if (identifier != null || !supportDeclspecSpecifiers) + throwBacktrack(token); + __attribute_decl_seq(false, true); break; - + default: if (LT(1) >= IExtensionToken.t__otherDeclSpecModifierFirst && LT(1) <= IExtensionToken.t__otherDeclSpecModifierLast) { handleOtherDeclSpecModifier(); + endOffset= LA(1).getOffset(); break; } - if (supportTypeOfUnaries && LT(1) == IGCCToken.t_typeof) { + if (LT(1) == IGCCToken.t_typeof) { + if (encounteredRawType || encounteredTypename) + throwBacktrack(token); + typeofExpression = unaryTypeofExpression(); - if (typeofExpression != null) { - flags.setEncounteredTypename(true); - } + encounteredTypename= true; + endOffset= calculateEndOffset(typeofExpression); + break; } break declSpecifiers; } + + if (encounteredRawType && encounteredTypename) + throwBacktrack(token); } - if (elabSpec != null) { - elabSpec.setConst(isConst); - elabSpec.setVolatile(isVolatile); - if (elabSpec instanceof IGPPASTDeclSpecifier) - ((IGPPASTDeclSpecifier) elabSpec).setRestrict(isRestrict); - elabSpec.setFriend(isFriend); - elabSpec.setInline(isInline); - elabSpec.setStorageClass(storageClass); - elabSpec.setVirtual(isVirtual); - elabSpec.setExplicit(isExplicit); - ((ASTNode) elabSpec).setOffsetAndLength(startOffset, calculateEndOffset(elabSpec) - startOffset); - return elabSpec; + // check for empty specification + if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !option.fAllowEmptySpecifier) { + throwBacktrack(LA(1)); } - if (enumSpec != null) { - enumSpec.setConst(isConst); - enumSpec.setVolatile(isVolatile); - if (enumSpec instanceof IGPPASTDeclSpecifier) - ((IGPPASTDeclSpecifier) enumSpec).setRestrict(isRestrict); - ((ICPPASTDeclSpecifier) enumSpec).setFriend(isFriend); - ((ICPPASTDeclSpecifier) enumSpec).setVirtual(isVirtual); - ((ICPPASTDeclSpecifier) enumSpec).setExplicit(isExplicit); - enumSpec.setInline(isInline); - enumSpec.setStorageClass(storageClass); - ((ASTNode) enumSpec).setOffsetAndLength(startOffset, calculateEndOffset(enumSpec) - startOffset); - return (ICPPASTDeclSpecifier) enumSpec; - } - if (classSpec != null) { - classSpec.setConst(isConst); - classSpec.setVolatile(isVolatile); - if (classSpec instanceof IGPPASTDeclSpecifier) - ((IGPPASTDeclSpecifier) classSpec).setRestrict(isRestrict); - classSpec.setFriend(isFriend); - classSpec.setInline(isInline); - classSpec.setStorageClass(storageClass); - classSpec.setVirtual(isVirtual); - classSpec.setExplicit(isExplicit); - ((ASTNode) classSpec).setOffsetAndLength(startOffset, calculateEndOffset(classSpec) - startOffset); - return classSpec; - } - if (duple != null) { - ICPPASTNamedTypeSpecifier nameSpec = (ICPPASTNamedTypeSpecifier) createNamedTypeSpecifier(); - nameSpec.setIsTypename(isTypename); - IASTName name = createName(duple); - nameSpec.setName(name); - nameSpec.setConst(isConst); - nameSpec.setVolatile(isVolatile); - if (nameSpec instanceof IGPPASTDeclSpecifier) - ((IGPPASTDeclSpecifier) nameSpec).setRestrict(isRestrict); - nameSpec.setFriend(isFriend); - nameSpec.setInline(isInline); - nameSpec.setStorageClass(storageClass); - nameSpec.setVirtual(isVirtual); - nameSpec.setExplicit(isExplicit); - if (last != null) { - ((ASTNode) nameSpec).setOffsetAndLength(startOffset, last.getEndOffset() - startOffset); - } - else { - ((ASTNode) nameSpec).setOffsetAndLength(startOffset, duple.getLastToken().getEndOffset() - startOffset); - } - return nameSpec; - } - ICPPASTSimpleDeclSpecifier simpleDeclSpec = null; - if (isComplex || isImaginary || isLongLong || typeofExpression != null) { - simpleDeclSpec = createGPPSimpleDeclSpecifier(); - ((IGPPASTSimpleDeclSpecifier) simpleDeclSpec).setLongLong(isLongLong); - ((IGPPASTSimpleDeclSpecifier) simpleDeclSpec).setComplex(isComplex); - ((IGPPASTSimpleDeclSpecifier) simpleDeclSpec).setImaginary(isImaginary); - if (typeofExpression != null) { - ((IGPPASTSimpleDeclSpecifier) simpleDeclSpec).setTypeofExpression(typeofExpression); - } - } else - simpleDeclSpec = createSimpleDeclSpecifier(); - - if( last == null && typeofExpression != null ){ - ((ASTNode) simpleDeclSpec).setOffsetAndLength((ASTNode) typeofExpression); - } else { - int l = last != null ? last.getEndOffset() - firstToken.getOffset() : 0; - ((ASTNode) simpleDeclSpec).setOffsetAndLength(firstToken.getOffset(), l); - } - simpleDeclSpec.setConst(isConst); - simpleDeclSpec.setVolatile(isVolatile); - if (simpleDeclSpec instanceof IGPPASTDeclSpecifier) - ((IGPPASTDeclSpecifier) simpleDeclSpec).setRestrict(isRestrict); - - simpleDeclSpec.setFriend(isFriend); - simpleDeclSpec.setInline(isInline); - simpleDeclSpec.setStorageClass(storageClass); - simpleDeclSpec.setVirtual(isVirtual); - simpleDeclSpec.setExplicit(isExplicit); - - simpleDeclSpec.setType(simpleType); - simpleDeclSpec.setLong(isLong); - simpleDeclSpec.setShort(isShort); - simpleDeclSpec.setUnsigned(isUnsigned); - simpleDeclSpec.setSigned(isSigned); - return simpleDeclSpec; + if (result != null) { + configureDeclSpec(result, storageClass, options); + if ((options & RESTRICT) != 0) { + if (result instanceof ICASTCompositeTypeSpecifier) { + ((ICASTCompositeTypeSpecifier) result).setRestrict(true); + } else if (result instanceof CASTEnumerationSpecifier) { + ((CASTEnumerationSpecifier) result).setRestrict(true); + } else if (result instanceof CASTElaboratedTypeSpecifier) { + ((CASTElaboratedTypeSpecifier) result).setRestrict(true); + } + } + ((ASTNode) result).setOffsetAndLength(offset, endOffset - offset); + return result; + } + + if (identifier != null) + return createNamedTypeSpecifier(identifier, isTypename, storageClass, options, offset, endOffset); + + return createSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); } + private boolean canBeConstructorDestructorOrConversion(DeclarationOptions declOption, int storageClass, int options, IASTDeclarator dtor) { + final int forbid= CONST | RESTRICT | VOLATILE | SHORT | UNSIGNED | SIGNED | COMPLEX | IMAGINARY | FRIEND; + if (storageClass == IASTDeclSpecifier.sc_unspecified && (options & forbid) == 0) { + if (CPPVisitor.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) { + IASTName name= CPPVisitor.findInnermostDeclarator(dtor).getName(); + if (name instanceof ICPPASTQualifiedName) { + final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) name; + final IASTName names[]= qname.getNames(); + final int len = names.length; + if (len > 1 && CharArrayUtils.equals(names[len-2].toCharArray(), names[len-1].toCharArray())) + return true; // constructor + + name= qname.getLastName(); + } + if (name instanceof ICPPASTConversionName) + return true; // conversion + if (name instanceof ICPPASTTemplateId) { + if (((ICPPASTTemplateId) name).getTemplateName() instanceof ICPPASTConversionName) { + return true; + } + + } + final char[] nchars= name.toCharArray(); + if (nchars.length > 0 && nchars[0] == '~') + return true; // destructor + + if (declOption == DeclarationOptions.CPP_MEMBER && CharArrayUtils.equals(nchars, currentClassName)) + return true; + } + } + return false; + } - protected ICPPASTSimpleDeclSpecifier createGPPSimpleDeclSpecifier() { + private ICPPASTNamedTypeSpecifier createNamedTypeSpecifier(ITokenDuple identifier, boolean isTypename, + int storageClass, int options, int offset, int endOffset) { + ICPPASTNamedTypeSpecifier declSpec = (ICPPASTNamedTypeSpecifier)createNamedTypeSpecifier(); + IASTName name = createName(identifier); + declSpec.setName(name); + declSpec.setIsTypename(isTypename); + configureDeclSpec(declSpec, storageClass, options); + ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset - offset); + return declSpec; + } + + private ICPPASTSimpleDeclSpecifier createSimpleDeclSpec(int storageClass, int simpleType, + int options, int isLong, IASTExpression typeofExpression, int offset, int endOffset) { + + if (isLong > 1 && !supportLongLong) + isLong= 1; + + ICPPASTSimpleDeclSpecifier declSpec= null; + if (isLong > 1 || (options & (RESTRICT|COMPLEX|IMAGINARY)) != 0 || typeofExpression != null) { + final IGPPASTSimpleDeclSpecifier gppDeclSpec= createGPPSimpleDeclSpecifier(); + gppDeclSpec.setLongLong(isLong > 1); + gppDeclSpec.setRestrict((options & RESTRICT) != 0); + gppDeclSpec.setComplex((options & COMPLEX) != 0); + gppDeclSpec.setImaginary((options & IMAGINARY) != 0); + gppDeclSpec.setTypeofExpression(typeofExpression); + + declSpec= gppDeclSpec; + } else { + declSpec = createSimpleDeclSpecifier(); + } + + configureDeclSpec(declSpec, storageClass, options); + + declSpec.setType(simpleType); + declSpec.setLong(isLong == 1); + declSpec.setShort((options & SHORT) != 0); + declSpec.setUnsigned((options & UNSIGNED) != 0); + declSpec.setSigned((options & SIGNED) != 0); + + ((ASTNode) declSpec).setOffsetAndLength(offset, endOffset-offset); + return declSpec; + } + + private void configureDeclSpec(ICPPASTDeclSpecifier declSpec, int storageClass, int options) { + declSpec.setStorageClass(storageClass); + declSpec.setConst((options & CONST) != 0); + declSpec.setVolatile((options & VOLATILE) != 0); + declSpec.setInline((options & INLINE) != 0); + declSpec.setFriend((options & FRIEND) != 0); + declSpec.setVirtual((options & VIRTUAL) != 0); + declSpec.setExplicit((options & EXPLICIT) != 0); + } + + @Override + protected boolean verifyLookaheadDeclarator(DeclarationOptions option, IASTDeclarator dtor, IToken nextToken) { + switch (nextToken.getType()) { + case IToken.tCOMMA: + return true; + + case IToken.tCOLON: + case IToken.t_try: + case IToken.t_catch: + case IToken.tLBRACE: + case IToken.t_const: + case IToken.t_volatile: + if (option == DeclarationOptions.GLOBAL || option == DeclarationOptions.CPP_MEMBER) { + if (CVisitor.findTypeRelevantDeclarator(dtor) instanceof IASTFunctionDeclarator) { + return true; + } + } + break; + case IToken.tSEMI: + return option == DeclarationOptions.GLOBAL || option == DeclarationOptions.CPP_MEMBER || + option == DeclarationOptions.LOCAL; + + case IToken.tRPAREN: + return option == DeclarationOptions.PARAMETER; + + case IToken.tEOC: + return true; + } + return false; + } + + protected IGPPASTSimpleDeclSpecifier createGPPSimpleDeclSpecifier() { return new GPPASTSimpleDeclSpecifier(); } @@ -3356,11 +3146,88 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } @Override - protected IASTDeclarator initDeclarator() throws EndOfFileException, BacktrackException { - return initDeclarator(SimpleDeclarationStrategy.TRY_FUNCTION); + protected IASTDeclarator initDeclarator(DeclarationOptions option) throws EndOfFileException, BacktrackException { + // called from the lookahead, only. + return initDeclarator(DtorStrategy.PREFER_FUNCTION, option); + } + + protected IASTDeclarator initDeclarator(IASTDeclSpecifier declspec, DeclarationOptions option) throws EndOfFileException, BacktrackException { + final IToken mark= mark(); + IASTDeclarator dtor1= null; + IToken end1= null; + IASTDeclarator dtor2= null; + BacktrackException bt= null; + try { + dtor1= initDeclarator(DtorStrategy.PREFER_FUNCTION, option); + if (dtor1 instanceof IASTFunctionDeclarator == false) + return dtor1; + + // optimization outside of function bodies and inside of templates + if (functionBodyCount == 0 || templateCount != 0) + return dtor1; + + // avoid second option for function definitions + end1= LA(1); + switch(end1.getType()) { + case IToken.tLBRACE: case IToken.tCOLON: + case IToken.t_throw: case IToken.t_try: + case IToken.t_const: case IToken.t_volatile: + return dtor1; + } + } catch (BacktrackException e) { + bt= e; + } + + if (!option.fAllowConstructorInitializer || !canHaveConstructorInitializer(declspec)) { + if (bt != null) + throw bt; + return dtor1; + } + + backup(mark); + try { + dtor2= initDeclarator(DtorStrategy.PREFER_NESTED, option); + if (dtor1 == null) { + return dtor2; + } + } catch (BacktrackException e) { + if (dtor1 != null) { + backup(end1); + return dtor1; + } + throw e; + } + + // we have an ambiguity + if (LA(1) != end1) { + backup(end1); + return dtor1; + } + + CPPASTAmbiguousDeclarator dtor= new CPPASTAmbiguousDeclarator(dtor2, dtor1); + dtor.setOffsetAndLength((ASTNode) dtor1); + return dtor; } - /** + private boolean canHaveConstructorInitializer(IASTDeclSpecifier declspec) { + if (declspec instanceof ICPPASTSimpleDeclSpecifier) { + ICPPASTSimpleDeclSpecifier simpleSpecifier= (ICPPASTSimpleDeclSpecifier) declspec; + switch(simpleSpecifier.getType()) { + case IASTSimpleDeclSpecifier.t_unspecified: + case IASTSimpleDeclSpecifier.t_void: + return false; + } + if (simpleSpecifier.isFriend()) { + return false; + } + if (simpleSpecifier.getStorageClass() == IASTDeclSpecifier.sc_typedef) { + return false; + } + } + return true; + } + + /** * Parses the initDeclarator construct of the ANSI C++ spec. initDeclarator : * declarator ("=" initializerClause | "(" expressionList ")")? * @@ -3368,16 +3235,18 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * @throws BacktrackException * request a backtrack */ - protected IASTDeclarator initDeclarator(SimpleDeclarationStrategy strategy) + protected IASTDeclarator initDeclarator(DtorStrategy strategy, DeclarationOptions option) throws EndOfFileException, BacktrackException { - IASTDeclarator d = declarator(strategy, false); - IASTInitializer initializer = optionalCPPInitializer(d); - if (initializer != null) { - d.setInitializer(initializer); - ((ASTNode) d).setLength(calculateEndOffset(initializer) - ((ASTNode) d).getOffset()); + final IASTDeclarator dtor= declarator(strategy, option); + if (option.fAllowInitializer) { + IASTInitializer initializer= optionalCPPInitializer(dtor); + if (initializer != null) { + dtor.setInitializer(initializer); + adjustLength(dtor, initializer); + } } - return d; + return dtor; } protected IASTInitializer optionalCPPInitializer(IASTDeclarator d) @@ -3476,346 +3345,359 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { /** * Parse a declarator, as according to the ANSI C++ specification. - * declarator : (ptrOperator)* directDeclarator directDeclarator : - * declaratorId | directDeclarator "(" parameterDeclarationClause ")" - * (cvQualifier)* (exceptionSpecification)* | directDeclarator "[" - * (constantExpression)? "]" | "(" declarator")" | directDeclarator "(" - * parameterDeclarationClause ")" (oldKRParameterDeclaration)* declaratorId : - * name - * + * declarator : (ptrOperator)* directDeclarator + * directDeclarator : + * declaratorId | + * directDeclarator "(" parameterDeclarationClause ")" (cvQualifier)* (exceptionSpecification)* | + * directDeclarator "[" (constantExpression)? "]" | + * "(" declarator")" | + * directDeclarator "(" parameterDeclarationClause ")" (oldKRParameterDeclaration)* + * + * declaratorId : name * @return declarator that this parsing produced. * @throws BacktrackException * request a backtrack */ - protected IASTDeclarator declarator(SimpleDeclarationStrategy strategy, - boolean forNewTypeId) throws EndOfFileException, BacktrackException { + protected IASTDeclarator declarator(DtorStrategy strategy, DeclarationOptions option) + throws EndOfFileException, BacktrackException { + + final int startingOffset = LA(1).getOffset(); + int endOffset = startingOffset; - IToken la = LA(1); - int startingOffset = la.getOffset(); - la = null; - IASTDeclarator innerDecl = null; - IASTName declaratorName = null; List pointerOps = new ArrayList(DEFAULT_POINTEROPS_LIST_SIZE); - List parameters = Collections.emptyList(); - List arrayMods = Collections.emptyList(); - List exceptionSpecIds = Collections.emptyList(); - boolean encounteredVarArgs = false; - boolean tryEncountered = false; - IASTExpression bitField = null; - boolean isFunction = false; - boolean isPureVirtual = false, isConst = false, isVolatile = false; - int finalOffset = startingOffset; - overallLoop: do { - - consumePointerOperators(pointerOps); + consumePointerOperators(pointerOps); + if (!pointerOps.isEmpty()) { + endOffset = calculateEndOffset(pointerOps.get(pointerOps.size() - 1)); + } - // if __attribute__ is after the pointer ops and before the declarator ex: void * __attribute__((__cdecl__)) foo(); - __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + // Accept __attribute__ or __declspec between pointer operators and declarator. + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + + // Look for identifier or nested declarator + final int lt1= LT(1); + switch (lt1) { + case IToken.tBITCOMPLEMENT: + case IToken.t_operator: + case IToken.tCOLONCOLON: + case IToken.tIDENTIFIER: + case IToken.tCOMPLETION: + if (option.fRequireAbstract) + throwBacktrack(LA(1)); + + final IASTName declaratorName= consumeTemplatedOperatorName(); + endOffset= calculateEndOffset(declaratorName); + return declarator(pointerOps, declaratorName, null, startingOffset, endOffset, strategy, option); + } - if (!pointerOps.isEmpty()) - finalOffset = calculateEndOffset(pointerOps.get(pointerOps.size() - 1)); + if (lt1 == IToken.tLPAREN) { + IASTDeclarator cand1= null; + IToken cand1End= null; + // try an abstract function declarator + if (option.fAllowAbstract && option.fAllowFunctions) { + final IToken mark= mark(); + try { + cand1= declarator(pointerOps, createName(), null, startingOffset, endOffset, strategy, option); + if (option.fRequireAbstract || !option.fAllowNested) + return cand1; - if (!forNewTypeId && LT(1) == IToken.tLPAREN) { - IToken mark = mark(); - try { - consume(); - innerDecl = declarator(strategy, forNewTypeId); - finalOffset = consume(IToken.tRPAREN).getEndOffset(); - } catch (BacktrackException bte) { - backup(mark); - innerDecl = null; - } - declaratorName = createName(); - } else { - try { - declaratorName = consumeTemplatedOperatorName(); - finalOffset = calculateEndOffset(declaratorName); - if (declaratorName instanceof ICPPASTQualifiedName - && ((ICPPASTQualifiedName) declaratorName).isConversionOrOperator()) - isFunction = true; - } catch (BacktrackException bt) { - declaratorName = createName(); - } - } + cand1End= LA(1); + } catch (BacktrackException e) { + } + backup(mark); + } + + // type-ids for new or operator-id: + if (!option.fAllowNested) { + if (option.fAllowAbstract) { + return declarator(pointerOps, createName(), null, startingOffset, endOffset, strategy, option); + } + throwBacktrack(LA(1)); + } + + // try a nested declarator + try { + consume(); + if (LT(1) == IToken.tRPAREN) + throwBacktrack(LA(1)); - for (;;) { - switch (LT(1)) { - case IToken.tLPAREN: - IToken markityMark = mark(); - boolean success = false; - try - { - consume(); // tLPAREN - expression(); - consume( IToken.tRPAREN ); - success = true; - backup( markityMark ); - } - catch( BacktrackException bte ) - { - backup( markityMark ); - } - catch( EndOfFileException eof ) - { - backup( markityMark ); - } - if( success ) - { - switch( LT(1) ) - { - case IToken.tSEMI: - case IToken.tCOMMA: - break overallLoop; - } - } + final IASTDeclarator nested= declarator(strategy, option); + endOffset= consume(IToken.tRPAREN).getEndOffset(); + final IASTDeclarator cand2= declarator(pointerOps, null, nested, startingOffset, endOffset, DtorStrategy.PREFER_FUNCTION, option); + if (cand1 == null || cand1End == null) + return cand2; + final IToken cand2End= LA(1); + if (cand1End == cand2End) { + CPPASTAmbiguousDeclarator result= new CPPASTAmbiguousDeclarator(cand1, cand2); + ((ASTNode) result).setOffsetAndLength((ASTNode) cand1); + return result; + } + // use the longer variant + if (cand1End.getOffset() < cand2End.getOffset()) + return cand2; - if( strategy == SimpleDeclarationStrategy.TRY_VARIABLE ) - break overallLoop; - - - if (!looksLikeExpression(LA(2))&& !forNewTypeId) { - // parameterDeclarationClause - isFunction = true; - // TODO need to create a temporary scope object here - IToken last = consume(IToken.tLPAREN); - finalOffset = last.getEndOffset(); - boolean seenParameter = false; - parameterDeclarationLoop: for (;;) { - switch (LT(1)) { - case IToken.tRPAREN: - last = consume(); - finalOffset = last.getEndOffset(); - break parameterDeclarationLoop; - case IToken.tEOC: - break parameterDeclarationLoop; - case IToken.tELLIPSIS: - last = consume(); - encounteredVarArgs = true; - finalOffset = last.getEndOffset(); - break; - case IToken.tCOMMA: - last = consume(); - seenParameter = false; - finalOffset = last.getEndOffset(); - break; - default: - int endOffset = (last != null) ? last.getEndOffset() : LA(1).getEndOffset(); - if (seenParameter) - throwBacktrack(startingOffset, endOffset - startingOffset); - IASTParameterDeclaration p = parameterDeclaration(); - finalOffset = calculateEndOffset(p); - if (parameters == Collections.EMPTY_LIST) - parameters = new ArrayList(DEFAULT_PARM_LIST_SIZE); - parameters.add(p); - seenParameter = true; - } - } - } - - if (LT(1) == IToken.tCOLON) - break overallLoop; - - if (LT(1) == IToken.t_try) { - tryEncountered = true; - break overallLoop; - } - - // Consume any number of __attribute__ tokens after the parameters - __attribute_decl_seq(supportAttributeSpecifiers, false); - - - IToken beforeCVModifier = mark(); - IToken[] cvModifiers = new IToken[2]; - int numCVModifiers = 0; - IToken afterCVModifier = beforeCVModifier; - // const-volatile - // 2 options: either this is a marker for the method, - // or it might be the beginning of old K&R style - // parameter declaration, see - // void getenv(name) const char * name; {} - // This will be determined further below - while ((LT(1) == IToken.t_const || LT(1) == IToken.t_volatile) && numCVModifiers < 2) { - IToken t = consume(); - finalOffset = t.getEndOffset(); - cvModifiers[numCVModifiers++] = t; - afterCVModifier = mark(); - } - // check for throws clause here - - if (LT(1) == IToken.t_throw) { - exceptionSpecIds = new ArrayList(DEFAULT_SIZE_EXCEPTIONS_LIST); - consume(); // throw - consume(IToken.tLPAREN); // ( - boolean done = false; - while (!done) { - switch (LT(1)) { - case IToken.tRPAREN: - finalOffset = consume().getEndOffset(); - done = true; - break; - case IToken.tCOMMA: - consume(); - break; - default: - IToken before = LA(1); - IASTTypeId typeId = typeId(false); - if (typeId != null) { - exceptionSpecIds.add(typeId); - } else { - IASTProblem p = createProblem(IProblem.SYNTAX_ERROR, - before.getOffset(), before.getLength()); - IASTProblemTypeId typeIdProblem = createTypeIDProblem(); - typeIdProblem.setProblem(p); - ((ASTNode) typeIdProblem).setOffsetAndLength(((ASTNode) p)); - exceptionSpecIds.add(typeIdProblem); - if (before == LA(1)) - done = true; - } - break; - } - } - - // more __attribute__ after throws - __attribute_decl_seq(supportAttributeSpecifiers, false); - } - // check for optional pure virtual - if (LT(1) == IToken.tASSIGN && LT(2) == IToken.tINTEGER) { - char[] image = LA(2).getCharImage(); - if (image.length == 1 && image[0] == '0') { - consume(); // tASSIGN - finalOffset = consume().getEndOffset(); // tINTEGER - isPureVirtual = true; - } - } - if (afterCVModifier != LA(1) || LT(1) == IToken.tSEMI - || LT(1) == IToken.tLBRACE) { - // There were C++-specific clauses after - // const/volatile modifier - // Then it is a marker for the method - if (numCVModifiers > 0) { - for (int i = 0; i < numCVModifiers; i++) { - if (cvModifiers[i].getType() == IToken.t_const) - isConst = true; - if (cvModifiers[i].getType() == IToken.t_volatile) - isVolatile = true; - } - } - afterCVModifier = mark(); - // In this case (method) we can't expect K&R - // parameter declarations, - // but we'll check anyway, for errorhandling - } - break; - case IToken.tLBRACKET: - if (forNewTypeId) - break; - arrayMods = new ArrayList(DEFAULT_POINTEROPS_LIST_SIZE); - consumeArrayModifiers(arrayMods); - if (!arrayMods.isEmpty()) - finalOffset = calculateEndOffset(arrayMods.get(arrayMods.size() - 1)); - continue; - case IToken.tCOLON: - if (forNewTypeId) - break; - consume(); - bitField = constantExpression(); - finalOffset = calculateEndOffset(bitField); - break; - case IGCCToken.t__attribute__: // if __attribute__ is after the declarator - if(supportAttributeSpecifiers) - __attribute_decl_seq(supportAttributeSpecifiers, false); - else - throwBacktrack(LA(1).getOffset(), LA(1).getLength()); - break; - default: - break; - } - break; - } - - } while (false); - - if (LT(1) == IToken.t_asm) { // asm labels bug 226121 - consume(); - finalOffset= asmExpression(null).getEndOffset(); - } - if(supportAttributeSpecifiers) - __attribute_decl_seq(supportAttributeSpecifiers, false); - - IASTDeclarator d = null; - if (isFunction) { - - ICPPASTFunctionDeclarator fc = null; - if (tryEncountered) - fc = createTryBlockDeclarator(); - else - fc = createFunctionDeclarator(); - fc.setVarArgs(encounteredVarArgs); - for (int i = 0; i < parameters.size(); ++i) { - IASTParameterDeclaration p = (IASTParameterDeclaration) parameters.get(i); - fc.addParameterDeclaration(p); - } - fc.setConst(isConst); - fc.setVolatile(isVolatile); - fc.setPureVirtual(isPureVirtual); - for (int i = 0; i < exceptionSpecIds.size(); ++i) { - IASTTypeId typeId = (IASTTypeId) exceptionSpecIds.get(i); - fc.addExceptionSpecificationTypeId(typeId); - } - d = fc; - } else if (arrayMods != Collections.EMPTY_LIST) { - d = createArrayDeclarator(); - for (int i = 0; i < arrayMods.size(); ++i) { - IASTArrayModifier m = (IASTArrayModifier) arrayMods.get(i); - ((IASTArrayDeclarator) d).addArrayModifier(m); - } - } else if (bitField != null) { - IASTFieldDeclarator fl = createFieldDeclarator(); - fl.setBitFieldSize(bitField); - d = fl; - } else { - d = createDeclarator(); - } - for (int i = 0; i < pointerOps.size(); ++i) { - IASTPointerOperator po = pointerOps.get(i); - d.addPointerOperator(po); - } - if (innerDecl != null) { - d.setNestedDeclarator(innerDecl); - } - if (declaratorName != null) { - d.setName(declaratorName); + } catch (BacktrackException e) { + if (cand1 == null) + throw e; + } + backup(cand1End); + return cand1; } - ((ASTNode) d).setOffsetAndLength(startingOffset, finalOffset - startingOffset); - return d; - + // try abstract declarator + if (!option.fAllowAbstract) { + // bit-fields may be abstract + if (!option.fAllowBitField || LT(1) != IToken.tCOLON) + throwBacktrack(LA(1)); + } + return declarator(pointerOps, createName(), null, startingOffset, endOffset, strategy, option); } - private boolean looksLikeExpression(IToken t) { - switch (t.getType()) { - case IToken.tINTEGER: - case IToken.t_false: - case IToken.t_true: - case IToken.tSTRING: - case IToken.tLSTRING: - case IToken.tFLOATINGPT: - case IToken.tCHAR: - case IToken.tAMPER: - case IToken.tDOT: - case IToken.tLPAREN: - case IToken.tMINUS: - case IToken.tSTAR: - case IToken.tPLUS: - case IToken.tNOT: - case IToken.tBITCOMPLEMENT: - return true; - default: + private IASTDeclarator declarator(List pointerOps, + IASTName declaratorName, IASTDeclarator nestedDeclarator, int startingOffset, int endOffset, + DtorStrategy strategy, DeclarationOptions option) + throws EndOfFileException, BacktrackException { + IASTDeclarator result= null; + loop: while(true) { + final int lt1= LT(1); + switch (lt1) { + case IToken.tLPAREN: + if (option.fAllowFunctions && strategy == DtorStrategy.PREFER_FUNCTION) { + result= functionDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + } + break loop; + + case IToken.tLBRACKET: + result= arrayDeclarator(option); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IToken.tCOLON: + if (!option.fAllowBitField) + break loop; // no backtrack because typeid can be followed by colon + + result= bitFieldDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + break loop; + + case IGCCToken.t__attribute__: // if __attribute__ is after a declarator + if (!supportAttributeSpecifiers) + throwBacktrack(LA(1)); + __attribute_decl_seq(true, supportDeclspecSpecifiers); + break; + case IGCCToken.t__declspec: + if (!supportDeclspecSpecifiers) + throwBacktrack(LA(1)); + __attribute_decl_seq(supportAttributeSpecifiers, true); + break; + default: + break loop; + } + } + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + + if (result == null) { + result= createDeclarator(); + setDeclaratorID(result, declaratorName, nestedDeclarator); + } else { + endOffset= calculateEndOffset(result); + } + + if (LT(1) == IToken.t_asm) { // asm labels bug 226121 + consume(); + endOffset= asmExpression(null).getEndOffset(); + + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + } + + for (IASTPointerOperator po : pointerOps) { + result.addPointerOperator(po); + } + + ((ASTNode) result).setOffsetAndLength(startingOffset, endOffset - startingOffset); + return result; + } + + private void setDeclaratorID(IASTDeclarator declarator, IASTName declaratorName, IASTDeclarator nestedDeclarator) { + if (nestedDeclarator != null) { + declarator.setNestedDeclarator(nestedDeclarator); + declarator.setName(createName()); + } else { + declarator.setName(declaratorName); + } + } + + /** + * Parse a function declarator starting with the left parenthesis. + */ + private IASTDeclarator functionDeclarator() throws EndOfFileException, BacktrackException { + IToken last = consume(IToken.tLPAREN); + int startOffset= last.getOffset(); + boolean seenParameter= false; + boolean encounteredVarArgs= false; + List parameters= null; + int endOffset= last.getEndOffset(); + + paramLoop: while(true) { + switch (LT(1)) { + case IToken.tRPAREN: + case IToken.tEOC: + endOffset= consume().getEndOffset(); + break paramLoop; + case IToken.tELLIPSIS: + endOffset= consume().getEndOffset(); + encounteredVarArgs = true; break; - } - return false; + case IToken.tCOMMA: + endOffset= consume().getEndOffset(); + seenParameter = false; + break; + default: + if (seenParameter) + throwBacktrack(startOffset, endOffset - startOffset); + + IASTParameterDeclaration pd = parameterDeclaration(); + endOffset = calculateEndOffset(pd); + if (parameters == null) + parameters = new ArrayList(DEFAULT_PARAMETER_LIST_SIZE); + parameters.add(pd); + seenParameter = true; + break; + } + } + + // Consume any number of __attribute__ tokens after the parameters + __attribute_decl_seq(supportAttributeSpecifiers, false); + + boolean isTryCatch= false; + boolean isConst= false; + boolean isVolatile= false; + boolean isPureVirtual= false; + ArrayList exceptionSpecIds= null; + + if (LT(1) == IToken.t_try) { + isTryCatch= true; + } else { + // cv-qualifiers + cvloop: while(true) { + switch(LT(1)) { + case IToken.t_const: + isConst= true; + endOffset= consume().getEndOffset(); + break; + case IToken.t_volatile: + isVolatile= true; + endOffset= consume().getEndOffset(); + break; + default: + break cvloop; + } + } + + // throws clause + if (LT(1) == IToken.t_throw) { + exceptionSpecIds = new ArrayList(DEFAULT_SIZE_EXCEPTIONS_LIST); + consume(); // throw + consume(IToken.tLPAREN); + + thloop: while(true) { + switch (LT(1)) { + case IToken.tRPAREN: + case IToken.tEOC: + endOffset= consume().getEndOffset(); + break thloop; + case IToken.tCOMMA: + consume(); + break; + default: + int thoffset= LA(1).getOffset(); + IASTTypeId typeId= typeId(DeclarationOptions.TYPEID); + if (typeId != null) { + exceptionSpecIds.add(typeId); + } else { + int thendoffset= LA(1).getOffset(); + if (thoffset == thendoffset) { + thendoffset= consume().getEndOffset(); + } + IASTProblem p= createProblem(IProblem.SYNTAX_ERROR, thoffset, thendoffset-thoffset); + IASTProblemTypeId typeIdProblem = createTypeIDProblem(); + typeIdProblem.setProblem(p); + ((ASTNode) typeIdProblem).setOffsetAndLength(((ASTNode) p)); + exceptionSpecIds.add(typeIdProblem); + } + break; + } + } + + // more __attribute__ after throws + __attribute_decl_seq(supportAttributeSpecifiers, false); + } + + // pure virtual + if (LT(1) == IToken.tASSIGN && LT(2) == IToken.tINTEGER) { + char[] image = LA(2).getCharImage(); + if (image.length == 1 && image[0] == '0') { + consume(); // tASSIGN + endOffset= consume().getEndOffset(); // tINTEGER + isPureVirtual= true; + } + } + } + + final ICPPASTFunctionDeclarator fc= isTryCatch ? createTryBlockDeclarator() : createFunctionDeclarator(); + fc.setVarArgs(encounteredVarArgs); + fc.setConst(isConst); + fc.setVolatile(isVolatile); + fc.setPureVirtual(isPureVirtual); + if (parameters != null) { + for (IASTParameterDeclaration param : parameters) { + fc.addParameterDeclaration(param); + } + } + if (exceptionSpecIds != null) + for (IASTTypeId exception : exceptionSpecIds) { + fc.addExceptionSpecificationTypeId(exception); + } + ((ASTNode) fc).setOffsetAndLength(startOffset, endOffset-startOffset); + return fc; } + /** + * Parse an array declarator starting at the square bracket. + */ + private IASTArrayDeclarator arrayDeclarator(DeclarationOptions option) throws EndOfFileException, BacktrackException { + ArrayList arrayMods = new ArrayList(DEFAULT_POINTEROPS_LIST_SIZE); + int start= LA(1).getOffset(); + consumeArrayModifiers(option, arrayMods); + if (arrayMods.isEmpty()) + throwBacktrack(LA(1)); + + final int endOffset = calculateEndOffset(arrayMods.get(arrayMods.size() - 1)); + final IASTArrayDeclarator d = createArrayDeclarator(); + for (IASTArrayModifier m : arrayMods) { + d.addArrayModifier(m); + } + + ((ASTNode) d).setOffsetAndLength(start, endOffset-start); + return d; + } + + + /** + * Parses for a bit field declarator starting with the colon + */ + private IASTFieldDeclarator bitFieldDeclarator() throws EndOfFileException, BacktrackException { + int start= consume(IToken.tCOLON).getOffset(); + + final IASTExpression bitField = constantExpression(); + final int endOffset = calculateEndOffset(bitField); + + IASTFieldDeclarator d = createFieldDeclarator(); + d.setBitFieldSize(bitField); + + ((ASTNode) d).setOffsetAndLength(start, endOffset-start); + return d; + } protected IASTProblemTypeId createTypeIDProblem() { return new CPPASTProblemTypeId(); @@ -3837,7 +3719,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } - protected IASTDeclarator createArrayDeclarator() { + protected IASTArrayDeclarator createArrayDeclarator() { return new CPPASTArrayDeclarator(); } @@ -3957,49 +3839,65 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (LT(1) == IToken.tLBRACE) { consume(); + final char[] outerName= currentClassName; + if (name instanceof ICPPASTQualifiedName) { + currentClassName= ((ICPPASTQualifiedName)name).getLastName().toCharArray(); + } else { + currentClassName= name.toCharArray(); + } + try { + memberDeclarationLoop: while (true) { + int checkToken = LA(1).hashCode(); + switch (LT(1)) { + case IToken.t_public: + case IToken.t_protected: + case IToken.t_private: { + IToken key = consume(); + int l = consume(IToken.tCOLON).getEndOffset(); + ICPPASTVisibilityLabel label = createVisibilityLabel(); + ((ASTNode) label).setOffsetAndLength(key.getOffset(), l - key.getOffset()); + label.setVisibility(token2Visibility(key.getType())); + astClassSpecifier.addMemberDeclaration(label); + label.setParent(astClassSpecifier); + // this overrides the MEMBER_DECLARATION property + label.setPropertyInParent(ICPPASTCompositeTypeSpecifier.VISIBILITY_LABEL); + break; + } + case IToken.tRBRACE: { + int l = consume().getEndOffset(); + ((ASTNode) astClassSpecifier).setLength(l - classKey.getOffset()); + break memberDeclarationLoop; + } + case IToken.tEOC: + // Don't care about the offsets + break memberDeclarationLoop; + default: + try { + final IToken m= mark(); + try { + IASTDeclaration d= declaration(DeclarationOptions.CPP_MEMBER); + astClassSpecifier.addMemberDeclaration(d); + } catch (BacktrackException e) { + backup(m); + IASTDeclaration d= usingDeclaration(m.getOffset()); + astClassSpecifier.addMemberDeclaration(d); + } + } catch (BacktrackException bt) { + IASTProblem p = failParse(bt); + IASTProblemDeclaration pd = createProblemDeclaration(); + pd.setProblem(p); + ((ASTNode) pd).setOffsetAndLength(((ASTNode) p)); + astClassSpecifier.addMemberDeclaration(pd); + if (checkToken == LA(1).hashCode()) + errorHandling(); + } - memberDeclarationLoop: while (true) { - int checkToken = LA(1).hashCode(); - switch (LT(1)) { - case IToken.t_public: - case IToken.t_protected: - case IToken.t_private: { - IToken key = consume(); - int l = consume(IToken.tCOLON).getEndOffset(); - ICPPASTVisibilityLabel label = createVisibilityLabel(); - ((ASTNode) label).setOffsetAndLength(key.getOffset(), l - key.getOffset()); - label.setVisibility(token2Visibility(key.getType())); - astClassSpecifier.addMemberDeclaration(label); - label.setParent(astClassSpecifier); - // this overrides the MEMBER_DECLARATION property - label.setPropertyInParent(ICPPASTCompositeTypeSpecifier.VISIBILITY_LABEL); - break; - } - case IToken.tRBRACE: { - int l = consume().getEndOffset(); - ((ASTNode) astClassSpecifier).setLength(l - classKey.getOffset()); - break memberDeclarationLoop; - } - case IToken.tEOC: - // Don't care about the offsets - break memberDeclarationLoop; - default: - try { - IASTDeclaration d = declaration(); - astClassSpecifier.addMemberDeclaration(d); - } catch (BacktrackException bt) { - IASTProblem p = failParse(bt); - IASTProblemDeclaration pd = createProblemDeclaration(); - pd.setProblem(p); - ((ASTNode) pd).setOffsetAndLength(((ASTNode) p)); - astClassSpecifier.addMemberDeclaration(pd); - if (checkToken == LA(1).hashCode()) - errorHandling(); - } - - if (checkToken == LA(1).hashCode()) - failParseWithErrorHandling(); - } + if (checkToken == LA(1).hashCode()) + failParseWithErrorHandling(); + } + } + } finally { + currentClassName= outerName; } } return astClassSpecifier; @@ -4154,7 +4052,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { consume(IToken.tELLIPSIS); isEllipsis = true; } else { - decl = simpleDeclaration(SimpleDeclarationStrategy.TRY_VARIABLE, true); + decl= simpleSingleDeclaration(DeclarationOptions.EXCEPTION); } if (LT(1) != IToken.tEOC) consume(IToken.tRPAREN); @@ -4193,6 +4091,29 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } } + private IASTSimpleDeclaration simpleSingleDeclaration(DeclarationOptions options) throws BacktrackException, EndOfFileException { + final int startOffset= LA(1).getOffset(); + IASTDeclSpecifier declSpec; + IASTDeclarator declarator; + + try { + declSpec= declSpecifierSeq(options); + declarator= initDeclarator(declSpec, options); + } catch (FoundDeclaratorException e) { + declSpec= e.declSpec; + declarator= e.declarator; + backup(e.currToken); + } + + final int endOffset = figureEndOffset(declSpec, declarator); + final IASTSimpleDeclaration decl= createSimpleDeclaration(); + decl.setDeclSpecifier(declSpec); + decl.addDeclarator(declarator); + ((ASTNode) decl).setOffsetAndLength(startOffset, endOffset - startOffset); + + return decl; + } + protected ICPPASTCatchHandler createCatchHandler() { return new CPPASTCatchHandler(); } @@ -4249,7 +4170,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (LT(1) == IToken.tEOC) break; int checkOffset = LA(1).hashCode(); - IASTDeclaration declaration = declaration(); + IASTDeclaration declaration = declaration(DeclarationOptions.GLOBAL); translationUnit.addDeclaration(declaration); if (LA(1).hashCode() == checkOffset) @@ -4299,14 +4220,16 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return new CPPASTTranslationUnit(); } - protected void consumeArrayModifiers(List collection) + protected void consumeArrayModifiers(DeclarationOptions option, List collection) throws EndOfFileException, BacktrackException { + boolean allowExpression= option == DeclarationOptions.TYPEID_NEW; while (LT(1) == IToken.tLBRACKET) { int o = consume().getOffset(); // eat the '[' IASTExpression exp = null; if (LT(1) != IToken.tRBRACKET && LT(1) != IToken.tEOC) { - exp = constantExpression(); + exp = allowExpression ? expression() : constantExpression(); + allowExpression= false; } int l; switch (LT(1)) { @@ -4546,7 +4469,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return parseLabelStatement(); } - return parseDeclarationOrExpressionStatement(); + return parseDeclarationOrExpressionStatement(DeclarationOptions.LOCAL); } } @@ -4642,7 +4565,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } catch (BacktrackException bt) { backup(mark); try { - return simpleDeclaration(SimpleDeclarationStrategy.TRY_VARIABLE, true); + return simpleSingleDeclaration(DeclarationOptions.CONDITION); } catch (BacktrackException b) { failParse(); throw b; @@ -4651,8 +4574,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return null; } - private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() { - }; @Override protected ASTVisitor createAmbiguityNodeVisitor() { @@ -4768,16 +4689,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return result; } - @Override - protected void checkTokenVsDeclarator(IToken la, IASTDeclarator d) throws FoundDeclaratorException { - switch (la.getType()) { - case IToken.tCOLON: - case IToken.t_try: - throw new FoundDeclaratorException( d, la ); - default: - super.checkTokenVsDeclarator(la, d); - } - } @Override protected IASTStatement functionBody() throws EndOfFileException, BacktrackException { @@ -4787,11 +4698,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return s; } - @Override - protected IASTDeclaration simpleDeclaration() throws BacktrackException, EndOfFileException { - return simpleDeclarationStrategyUnion(); - } - protected IASTExpression unaryOperatorCastExpression(int operator) throws EndOfFileException, BacktrackException { IToken mark = mark(); int offset = consume().getOffset(); @@ -4850,7 +4756,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { int startOffset; startOffset = consume().getOffset(); consume(IToken.tLPAREN); - IASTStatement init = forInitStatement(); + IASTStatement init = forInitStatement(DeclarationOptions.LOCAL); IASTNode for_condition = null; switch (LT(1)) { case IToken.tSEMI: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 5ba2156b968..06fc8e70fe3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -39,6 +39,7 @@ 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.IASTFieldReference; import org.eclipse.cdt.core.dom.ast.IASTForStatement; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; @@ -2439,4 +2440,54 @@ public class CPPVisitor { } return e1; } + + /** + * Returns the outermost declarator the given declarator nests within, or + * declarator itself. + * @since 5.0 + */ + public static IASTDeclarator findOutermostDeclarator(IASTDeclarator declarator) { + while(true) { + IASTNode parent= declarator.getParent(); + if (parent instanceof IASTDeclarator) { + declarator= (IASTDeclarator) parent; + } else { + return declarator; + } + } + } + + /** + * Returns the innermost declarator nested within the given declarator, or + * declarator itself. + * @since 5.1 + */ + public static IASTDeclarator findInnermostDeclarator(IASTDeclarator declarator) { + IASTDeclarator innermost= null; + while(declarator != null) { + innermost= declarator; + declarator= declarator.getNestedDeclarator(); + } + return innermost; + } + + /** + * Searches for the innermost declarator that contributes the the type declared. + * @since 5.1 + */ + public static IASTDeclarator findTypeRelevantDeclarator(IASTDeclarator declarator) { + IASTDeclarator result= findInnermostDeclarator(declarator); + while (result.getPointerOperators().length == 0 + && result instanceof IASTFieldDeclarator == false + && result instanceof IASTFunctionDeclarator == false + && result instanceof IASTArrayModifier == false) { + final IASTNode parent= result.getParent(); + if (parent instanceof IASTDeclarator) { + result= (IASTDeclarator) parent; + } else { + return result; + } + } + return result; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java index 22b013232f2..4205875e45b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModificationStore; import org.eclipse.cdt.internal.core.dom.rewrite.changegenerator.ChangeGeneratorWriterVisitor; @@ -78,7 +80,16 @@ public class ASTWriter { */ public String write(IASTNode rootNode, String fileScope, NodeCommentMap commentMap) throws ProblemRuntimeException { transformationVisitor = new ChangeGeneratorWriterVisitor(modificationStore, givenIndentation, fileScope, commentMap); - rootNode.accept(transformationVisitor); + + // mstodo: workaround for + if (rootNode instanceof IASTArrayModifier) { + int result= transformationVisitor.visit((IASTArrayModifier) rootNode); + if (result == ASTVisitor.PROCESS_CONTINUE) { + rootNode.accept(transformationVisitor); + } + } else { + rootNode.accept(transformationVisitor); + } String str = transformationVisitor.toString(); transformationVisitor.cleanCache(); return str; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java index edb2af11c73..d87b5f93334 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java @@ -7,11 +7,13 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -200,6 +202,12 @@ public class ASTWriterVisitor extends CPPASTVisitor { return ASTVisitor.PROCESS_SKIP; } + public int visit(IASTArrayModifier amod) { + if(!macroHandler.checkisMacroExpansionNode(amod)) { + declaratorWriter.writeArrayModifier(amod); + } + return ASTVisitor.PROCESS_SKIP; + } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java index 5fe4820ca77..d6b248ca4da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/DeclaratorWriter.java @@ -7,7 +7,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.astwriter; @@ -15,6 +16,7 @@ import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator; import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTName; @@ -254,12 +256,18 @@ public class DeclaratorWriter extends NodeWriter { protected void writeArrayModifiers(IASTArrayDeclarator arrDecl, IASTArrayModifier[] arrMods) { for (IASTArrayModifier modifier : arrMods) { - scribe.print('['); - modifier.accept(visitor); - scribe.print(']'); + writeArrayModifier(modifier); } } + protected void writeArrayModifier(IASTArrayModifier modifier) { + scribe.print('['); + IASTExpression ex= modifier.getConstantExpression(); + if (ex != null) { + ex.accept(visitor); + } + scribe.print(']'); + } private void writeFieldDeclarator(IASTFieldDeclarator fieldDecl) { IASTPointerOperator[] pointOps = fieldDecl.getPointerOperators(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java index 17556e7af79..241cb58a802 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java @@ -353,25 +353,14 @@ public class ExpressionWriter extends NodeWriter{ IASTTypeId typeId = newExp.getTypeId(); visitNodeIfNotNull(typeId); - IASTExpression[] arraySizeExpressions = getNewTypeIdArrayExpressions(newExp, newExp.getNewTypeIdArrayExpressions()); - for (IASTExpression expression : arraySizeExpressions) { - scribe.print('['); - expression.accept(visitor); - scribe.print(']'); - } - if (arraySizeExpressions.length == 0 ) { + IASTExpression initExp= getNewInitializer(newExp); + if (initExp != null) { scribe.print('('); - IASTExpression initExp = getNewInitializer(newExp); - visitNodeIfNotNull(initExp); + initExp.accept(visitor); scribe.print(')'); } } - protected IASTExpression[] getNewTypeIdArrayExpressions( - ICPPASTNewExpression newExp, IASTExpression[] expressions) { - return newExp.getNewTypeIdArrayExpressions(); - } - protected IASTExpression getNewInitializer(ICPPASTNewExpression newExp) { return newExp.getNewInitializer(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGenerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGenerator.java index 8901a868856..78ac97b3102 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGenerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGenerator.java @@ -7,7 +7,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.changegenerator; @@ -16,6 +17,8 @@ import java.util.LinkedHashMap; import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; @@ -26,10 +29,13 @@ import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModification; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModificationMap; import org.eclipse.cdt.internal.core.dom.rewrite.ASTModificationStore; @@ -77,7 +83,7 @@ public class ChangeGenerator extends CPPASTVisitor { shouldVisitDeclSpecifiers = true; shouldVisitDeclarators = true; - + shouldVisitInitializers = true; shouldVisitBaseSpecifiers = true; @@ -132,7 +138,7 @@ public class ChangeGenerator extends CPPASTVisitor { private IASTNode determineParentToBeRewritten(IASTNode modifiedNode, List modificationsForNode) { IASTNode modifiedNodeParent = modifiedNode; for(ASTModification currentModification : modificationsForNode){ - if(currentModification.getKind() != ASTModification.ModificationKind.APPEND_CHILD){ + if(currentModification.getKind() == ASTModification.ModificationKind.REPLACE){ modifiedNodeParent = modifiedNode.getParent(); break; } @@ -385,9 +391,51 @@ public class ChangeGenerator extends CPPASTVisitor { synthTreatment(declarator); return ASTVisitor.PROCESS_SKIP; } + + // mstodo workaround + if (declarator instanceof IASTArrayDeclarator) { + IASTPointerOperator [] ptrOps = declarator.getPointerOperators(); + for ( int i = 0; i < ptrOps.length; i++ ) { + if( !ptrOps[i].accept( this ) ) return PROCESS_ABORT; + } + + IASTDeclarator nestedDeclarator= declarator.getNestedDeclarator(); + IASTName name= declarator.getName(); + if (nestedDeclarator == null && name != null) { + IASTDeclarator outermost= CPPVisitor.findOutermostDeclarator(declarator); + if (outermost.getPropertyInParent() != IASTTypeId.ABSTRACT_DECLARATOR) { + if (!name.accept(this)) return PROCESS_ABORT; + } + } + + if (nestedDeclarator != null) { + if (!nestedDeclarator.accept(this)) return PROCESS_ABORT; + } + + IASTArrayModifier [] mods = ((IASTArrayDeclarator) declarator).getArrayModifiers(); + for ( int i = 0; i < mods.length; i++ ) { + int result= visit(mods[i]); + if (result != PROCESS_CONTINUE) + return result; + + if( !mods[i].accept( this ) ) return PROCESS_ABORT; + } + IASTInitializer initializer = declarator.getInitializer(); + if( initializer != null ) if( !initializer.accept( this ) ) return PROCESS_ABORT; + return PROCESS_CONTINUE; + } + return super.visit(declarator); } - + + public int visit(IASTArrayModifier mod) { + if (hasChangedChild(mod)) { + synthTreatment(mod); + return ASTVisitor.PROCESS_SKIP; + } + return PROCESS_CONTINUE; + } + @Override public int visit(ICPPASTNamespaceDefinition namespaceDefinition) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGeneratorWriterVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGeneratorWriterVisitor.java index 69b3ce6edd7..c60da015169 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGeneratorWriterVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ChangeGeneratorWriterVisitor.java @@ -7,10 +7,12 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.changegenerator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; @@ -270,6 +272,14 @@ public class ChangeGeneratorWriterVisitor extends ASTWriterVisitor { return PROCESS_SKIP; } + @Override + public int visit(IASTArrayModifier arrayModifier) { + if (doBeforeEveryNode(arrayModifier) == PROCESS_CONTINUE) { + return super.visit(arrayModifier); + } + return PROCESS_SKIP; + } + @Override public int visit(IASTExpression expression) { if (doBeforeEveryNode(expression) == PROCESS_CONTINUE) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ModifiedASTExpressionWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ModifiedASTExpressionWriter.java index 00eb6ddcf81..7a5fb5c5459 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ModifiedASTExpressionWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/changegenerator/ModifiedASTExpressionWriter.java @@ -7,7 +7,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Institute for Software - initial API and implementation + * Institute for Software - initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.rewrite.changegenerator; @@ -76,13 +77,4 @@ public class ModifiedASTExpressionWriter extends ExpressionWriter { } return initializer; } - - @Override - protected IASTExpression[] getNewTypeIdArrayExpressions( - ICPPASTNewExpression newExp, IASTExpression[] expressions) { - IASTExpression[] modifiedExpressions = modificationHelper.createModifiedChildArray(newExp, expressions, IASTExpression.class); - return modifiedExpressions; - } - - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java index 7ad3c74dc81..f9cb9681f41 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorName.java @@ -71,6 +71,9 @@ class ASTPreprocessorName extends ASTPreprocessorNode implements IASTName { public int getRoleOfName(boolean allowResolution) { return IASTNameOwner.r_unclear; } + public IASTName getLastName() { + return this; + } } class ASTPreprocessorDefinition extends ASTPreprocessorName { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java index f1757552a10..cbbb61e826f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/BasicTokenDuple.java @@ -33,8 +33,7 @@ public class BasicTokenDuple implements ITokenDuple { lastToken = last; } - //TODO - move numSegments to a subclass - private int numSegments = -1; + protected int numSegments = -1; BasicTokenDuple( ITokenDuple firstDuple, ITokenDuple secondDuple ){ this( firstDuple.getFirstToken(), secondDuple.getLastToken() ); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TemplateTokenDuple.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TemplateTokenDuple.java index d6dd032080b..0b16a583eb6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TemplateTokenDuple.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TemplateTokenDuple.java @@ -23,7 +23,6 @@ import org.eclipse.cdt.core.parser.ITokenDuple; public class TemplateTokenDuple extends BasicTokenDuple { protected final List [] argLists; - private final int numSegments; /** * @param first diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java index d8a2446c38c..8940be12267 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java @@ -167,6 +167,10 @@ public class PDOMASTAdapter { public String toString() { return fDelegate.toString(); } + + public IASTName getLastName() { + return this; + } } private static class AnonymousEnumeration implements IEnumeration { diff --git a/core/org.eclipse.cdt.ui.tests/resources/contentassist/CompletionTestStart40.h b/core/org.eclipse.cdt.ui.tests/resources/contentassist/CompletionTestStart40.h index 1593d53835a..757ff51ee8e 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/contentassist/CompletionTestStart40.h +++ b/core/org.eclipse.cdt.ui.tests/resources/contentassist/CompletionTestStart40.h @@ -41,7 +41,7 @@ public: void anotherMethod(); }; -class { +class xOtherClass { public: xOtherClass(char*); xOtherClass(int); diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractExpression.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractExpression.rts index 4e64c610fb2..d1980ee2ec8 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractExpression.rts +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractExpression.rts @@ -267,7 +267,7 @@ struct helper {}; helper *new_helper() { - return new helper(); + return new helper; } int main(int argc, char** argv) diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java index 1b8be4f28d4..d5112a1a3d7 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java @@ -17,15 +17,18 @@ package org.eclipse.cdt.ui.tests.refactoring.rename; import java.io.StringWriter; -import junit.framework.*; +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; -import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.tests.FailingTest; import org.eclipse.core.resources.IFile; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.participants.RenameArguments; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.tests.FailingTest; + /** * @author aniefer */ @@ -63,7 +66,7 @@ public class RenameRegressionTests extends RenameTests { public void testSimpleRename() throws Exception { StringWriter writer = new StringWriter(); writer.write( "int boo; // boo \n" ); //$NON-NLS-1$ - writer.write( "#ifdef 0 \n" ); //$NON-NLS-1$ + writer.write( "#if 0 \n" ); //$NON-NLS-1$ writer.write( "boo \n" ); //$NON-NLS-1$ writer.write( "#endif \n" ); //$NON-NLS-1$ writer.write( "void f() { \n" ); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AbstractSemanticHighlightingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AbstractSemanticHighlightingTest.java index c8c9730c0da..96760d52c80 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AbstractSemanticHighlightingTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/AbstractSemanticHighlightingTest.java @@ -43,6 +43,7 @@ import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; + import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.index.provider.IndexProviderManager; import org.eclipse.cdt.internal.core.index.provider.ReadOnlyPDOMProviderBridge; @@ -77,7 +78,7 @@ public class AbstractSemanticHighlightingTest extends TestCase { String sdkCode= "void SDKFunction();\n"+ - "class SDKClass { public: SDKMethod(); };\n\n"; + "class SDKClass { public: void SDKMethod(); };\n\n"; fSdkFile= createExternalSDK(sdkCode); assertNotNull(fSdkFile); @@ -148,8 +149,8 @@ public class AbstractSemanticHighlightingTest extends TestCase { store.setToDefault(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED); SemanticHighlighting[] semanticHighlightings= SemanticHighlightings.getSemanticHighlightings(); - for (int i= 0, n= semanticHighlightings.length; i < n; i++) { - String enabledPreferenceKey= SemanticHighlightings.getEnabledPreferenceKey(semanticHighlightings[i]); + for (SemanticHighlighting semanticHighlighting : semanticHighlightings) { + String enabledPreferenceKey= SemanticHighlightings.getEnabledPreferenceKey(semanticHighlighting); if (!store.isDefault(enabledPreferenceKey)) store.setToDefault(enabledPreferenceKey); } @@ -215,8 +216,7 @@ public class AbstractSemanticHighlightingTest extends TestCase { buf.append("// "+fCurrentHighlighting+'\n'); IDocument document= fSourceViewer.getDocument(); buf.append("Position[] expected= new Position[] {\n"); - for (int i= 0, n= positions.length; i < n; i++) { - Position position= positions[i]; + for (Position position : positions) { int line= document.getLineOfOffset(position.getOffset()); int column= position.getOffset() - document.getLineOffset(line); buf.append("\tcreatePosition(" + line + ", " + column + ", " + position.getLength() + "),\n"); @@ -253,8 +253,7 @@ public class AbstractSemanticHighlightingTest extends TestCase { IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); store.setValue(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED, true); SemanticHighlighting[] semanticHilightings= SemanticHighlightings.getSemanticHighlightings(); - for (int i= 0, n= semanticHilightings.length; i < n; i++) { - SemanticHighlighting semanticHilighting= semanticHilightings[i]; + for (SemanticHighlighting semanticHilighting : semanticHilightings) { if (store.getBoolean(SemanticHighlightings.getEnabledPreferenceKey(semanticHilighting))) store.setValue(SemanticHighlightings.getEnabledPreferenceKey(semanticHilighting), false); } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java index 0b0da03c3b2..213474c6472 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java @@ -289,10 +289,10 @@ public class CodeFormatterTest extends BaseUITestCase { assertFormatterResult(); } - //main + //int main //( // int argc, - // char const * argv[] + // char const int* argv[] //) //try //{ @@ -310,7 +310,7 @@ public class CodeFormatterTest extends BaseUITestCase { // return 2; //} - //main(int argc, char const * argv[]) + //int main(int argc, char const int* argv[]) //try { // for (int i = 1; i < argc; ++i) { // } @@ -326,9 +326,9 @@ public class CodeFormatterTest extends BaseUITestCase { assertFormatterResult(); } - //main(int argc, char const * argv[]) { try { for (int i = 1; i < argc; ++i) { } return 0; } catch (float e) { return 1; } catch (...) { return 2; } } + //int main(int argc, char const int * argv[]) { try { for (int i = 1; i < argc; ++i) { } return 0; } catch (float e) { return 1; } catch (...) { return 2; } } - //main(int argc, char const * argv[]) { + //int main(int argc, char const int * argv[]) { // try { // for (int i = 1; i < argc; ++i) { // } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_AnonymousTypes.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_AnonymousTypes.java index af70b7672a9..9ba7cfd6e8c 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_AnonymousTypes.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/contentassist2/CompletionTest_AnonymousTypes.java @@ -22,7 +22,7 @@ public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{ private final String headerFileName = "CompletionTestStart40.h"; private final String headerFileFullPath ="resources/contentassist/" + headerFileName; private final String expectedPrefix = ""; - private final String[] expectedResults = {"notAnonymousEnum", "notAnonymousClass"}; + private final String[] expectedResults = {"notAnonymousEnum", "notAnonymousClass", "xOtherClass"}; public CompletionTest_AnonymousTypes(String name) { super(name); @@ -39,6 +39,7 @@ public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{ /* (non-Javadoc) * @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getCompletionPosition() */ + @Override protected int getCompletionPosition() { return getBuffer().indexOf(" x "); } @@ -46,6 +47,7 @@ public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{ /* (non-Javadoc) * @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getExpectedPrefix() */ + @Override protected String getExpectedPrefix() { return expectedPrefix; } @@ -53,6 +55,7 @@ public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{ /* (non-Javadoc) * @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getExpectedResultsValues() */ + @Override protected String[] getExpectedResultsValues() { return expectedResults; } @@ -60,6 +63,7 @@ public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{ /* (non-Javadoc) * @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getFileName() */ + @Override protected String getFileName() { return fileName; } @@ -67,12 +71,14 @@ public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{ /* (non-Javadoc) * @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getFileFullPath() */ + @Override protected String getFileFullPath() { return fileFullPath; } /* (non-Javadoc) * @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getHeaderFileFullPath() */ + @Override protected String getHeaderFileFullPath() { return headerFileFullPath; } @@ -80,6 +86,7 @@ public class CompletionTest_AnonymousTypes extends CompletionProposalsBaseTest{ /* (non-Javadoc) * @see org.eclipse.cdt.core.codeassist.tests.CompletionProposalsTest#getHeaderFileName() */ + @Override protected String getHeaderFileName() { return headerFileName; } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java index 873e8d076b9..7c56e9aa05d 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsAnyIndexer.java @@ -46,6 +46,7 @@ public abstract class CPPSelectionTestsAnyIndexer extends BaseSelectionTestsInde sourceIndexerID= indexerID; } + @Override protected void setUp() throws Exception { super.setUp(); @@ -60,6 +61,7 @@ public abstract class CPPSelectionTestsAnyIndexer extends BaseSelectionTestsInde index= CCorePlugin.getIndexManager().getIndex(fCProject); } + @Override protected void tearDown() throws Exception { closeAllEditors(); CProjectHelper.delete(fCProject); @@ -732,7 +734,7 @@ public abstract class CPPSelectionTestsAnyIndexer extends BaseSelectionTestsInde // typedef int TestTypeTwo; // #include "testBug78354.h" - // main() + // int main() // { // TestTypeOne myFirstLink = 5; // TestTypeTwo mySecondLink = 6; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java index 9db50c1c939..03627e33148 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java @@ -141,27 +141,29 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { } } - protected void setUp() throws Exception { + @Override + protected void setUp() throws Exception { super.setUp(); initProject(); OpenDeclarationsAction.sIsJUnitTest= true; OpenDeclarationsAction.sAllowFallback= false; } - protected void tearDown() throws Exception { + @Override + protected void tearDown() throws Exception { if( project == null || !project.exists() ) return; closeAllEditors(); IResource [] members = project.members(); - for( int i = 0; i < members.length; i++ ){ - if( members[i].getName().equals( ".project" ) || members[i].getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ + for (IResource member : members) { + if( member.getName().equals( ".project" ) || member.getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ continue; - if (members[i].getName().equals(".settings")) + if (member.getName().equals(".settings")) continue; try{ - members[i].delete( false, monitor ); + member.delete( false, monitor ); } catch( Throwable e ){ /*boo*/ } @@ -922,7 +924,7 @@ public class CPPSelectionTestsNoIndexer extends BaseUITestCase { StringBuffer buffer = new StringBuffer(); buffer.append("typedef int TestTypeOne;\n"); //$NON-NLS-1$ buffer.append("typedef int TestTypeTwo;\n"); //$NON-NLS-1$ - buffer.append("main()\n"); //$NON-NLS-1$ + buffer.append("int main()\n"); //$NON-NLS-1$ buffer.append("{\n"); //$NON-NLS-1$ buffer.append("TestTypeOne myFirstLink = 5;\n"); //$NON-NLS-1$ buffer.append("TestTypeTwo mySecondLink = 6;\n"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java index c1986578c03..5d39ccbd23d 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CSelectionTestsNoIndexer.java @@ -115,7 +115,8 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { return suite; } - protected void setUp() throws Exception { + @Override + protected void setUp() throws Exception { super.setUp(); OpenDeclarationsAction.sIsJUnitTest= true; OpenDeclarationsAction.sAllowFallback= false; @@ -133,20 +134,21 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { } } - protected void tearDown() throws Exception { + @Override + protected void tearDown() throws Exception { if( project == null || !project.exists() ) return; closeAllEditors(); IResource [] members = project.members(); - for( int i = 0; i < members.length; i++ ){ - if( members[i].getName().equals( ".project" ) || members[i].getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ + for (IResource member : members) { + if( member.getName().equals( ".project" ) || member.getName().equals( ".cproject" ) ) //$NON-NLS-1$ //$NON-NLS-2$ continue; - if (members[i].getName().equals(".settings")) + if (member.getName().equals(".settings")) continue; try{ - members[i].delete( true, monitor ); + member.delete( true, monitor ); } catch( Throwable e ){ /*boo*/ } @@ -667,7 +669,7 @@ public class CSelectionTestsNoIndexer extends BaseUITestCase { StringBuffer buffer = new StringBuffer(); buffer.append("typedef int TestTypeOne;\n"); //$NON-NLS-1$ buffer.append("typedef int TestTypeTwo;\n"); //$NON-NLS-1$ - buffer.append("main()\n"); //$NON-NLS-1$ + buffer.append("int main()\n"); //$NON-NLS-1$ buffer.append("{\n"); //$NON-NLS-1$ buffer.append("TestTypeOne myFirstLink = 5;\n"); //$NON-NLS-1$ buffer.append("TestTypeTwo mySecondLink = 6;\n"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java index 26d60dddb1d..34fd7b4e50d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java @@ -49,10 +49,6 @@ import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclaration; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression; -import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement; - import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper; /** @@ -165,46 +161,6 @@ public abstract class CRefactoring extends Refactoring { } - private class AmbiguityFinder extends ASTVisitor{ - - private boolean ambiguityFound = false; - - { - shouldVisitDeclarations = true; - shouldVisitExpressions = true; - shouldVisitStatements= true; - } - - @Override - public int visit(IASTDeclaration declaration) { - if (declaration instanceof IASTAmbiguousDeclaration) { - ambiguityFound = true; - } - return ASTVisitor.PROCESS_CONTINUE; - } - - @Override - public int visit(IASTExpression expression) { - if (expression instanceof IASTAmbiguousExpression) { - ambiguityFound = true; - } - return ASTVisitor.PROCESS_CONTINUE; - } - - @Override - public int visit(IASTStatement statement) { - if (statement instanceof IASTAmbiguousStatement) { - ambiguityFound = true; - } - return ASTVisitor.PROCESS_CONTINUE; - } - - public boolean ambiguityFound() { - return ambiguityFound; - } - - } - @Override public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { @@ -302,9 +258,8 @@ public abstract class CRefactoring extends Refactoring { } protected boolean translationUnitIsAmbiguous() { - AmbiguityFinder af = new AmbiguityFinder(); - unit.accept(af); - return af.ambiguityFound(); + // ambiguities are resolved before the tu is passed to the refactoring. + return false; } public void lockIndex() throws CoreException, InterruptedException {