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 18bf08f6a51..187cded860d 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 @@ -628,7 +628,7 @@ public class AST2BaseTest extends BaseTestCase { final protected IASTTranslationUnit parseAndCheckBindings(String code, ParserLanguage lang, boolean useGnuExtensions, boolean skipTrivialInitializers) throws Exception { - IASTTranslationUnit tu = parse(code, lang, useGnuExtensions, skipTrivialInitializers); + IASTTranslationUnit tu = parse(code, lang, useGnuExtensions, true, skipTrivialInitializers); CNameCollector col = new CNameCollector(); tu.accept(col); assertNoProblemBindings(col); 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 378cacfce27..a09d97679de 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 @@ -7270,4 +7270,10 @@ public class AST2Tests extends AST2BaseTest { } } + // void f () __attribute__ ((int)); + public void testAttributeSyntax_298841() throws Exception { + final String code = getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.C, true); + parseAndCheckBindings(code, ParserLanguage.CPP, true); + } } 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 67ce8eb3dfb..ba03031274d 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 @@ -2300,92 +2300,72 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } } - protected void __attribute__() throws BacktrackException, EndOfFileException { - IToken token = LA(1); + protected void __attribute__() throws BacktrackException, EndOfFileException { + if (LT(1) != IGCCToken.t__attribute__) + return; - if (token.getType() == IGCCToken.t__attribute__) { - consume(); - - token = LA(1); - - if (token.getType() == IToken.tLPAREN) { + consume(); + if (LT(1) == IToken.tLPAREN) { + consume(); + consume(IToken.tLPAREN); + + for (;;) { + final int lt1= LT(1); + if (lt1 == IToken.tRPAREN || lt1 == IToken.tEOC) + break; + + // Allow empty attribute + if (lt1 != IToken.tCOMMA) { + singelAttribute(); + } + + // Require comma + if (LT(1) != IToken.tCOMMA) + break; consume(); - while(true) { - token = LA(1); - switch(token.getType()) { - case IToken.tLPAREN: - consume(); - boolean ident=false; - boolean comma1=false; - boolean first=true; - whileLoop: while(true) { - token = LA(1); - switch(token.getType()) { - case IToken.tIDENTIFIER: - if (comma1 || first) { - ident=true; - first=false; - } else { - throwBacktrack(token.getOffset(), token.getLength()); - } - consume(); - break; - case IToken.tLPAREN: - consume(); - if (ident) { - token = LA(1); - // consume the parameters - whileLoop2: while(true) { - try { - expression(); - } catch (BacktrackException be) { - switch(LT(1)) { - case IToken.tCOMMA: - consume(); - break; - case IToken.tRPAREN: - consume(); - break whileLoop2; - default: - throw be; - } - } - } - } else { - throwBacktrack(token.getOffset(), token.getLength()); // can't have __attribute((())) - } - break; - case IToken.tRPAREN: - consume(); - break whileLoop; - case IToken.tCOMMA: - if (ident) { - ident=false; - comma1=true; - } - consume(); - break; - case IToken.t_const: - consume(); - break; - default: - throwBacktrack(token.getOffset(), token.getLength()); - break; - } - } - break; - case IToken.tRPAREN: // finished - consume(); - return; - default: - throwBacktrack(token.getOffset(), token.getLength()); - } - } } + + consumeOrEOC(IToken.tRPAREN); + consumeOrEOC(IToken.tRPAREN); } } + + private void singelAttribute() throws EndOfFileException, BacktrackException { + // Check if we have an identifier including keywords + if (!isIdentifier(LA(1))) + throw backtrack; + consume(); + + // Check for parameters + if (LT(1) == IToken.tLPAREN) { + consume(); + for(;;) { + final int lt2= LT(1); + if (lt2 == IToken.tRPAREN || lt2 == IToken.tEOC) + break; + + // Allow empty parameter + if (lt2 != IToken.tCOMMA) { + expression(); + } + // Require comma + if (LT(1) != IToken.tCOMMA) + break; + consume(); + } + consumeOrEOC(IToken.tRPAREN); + } + } - protected void __declspec() throws BacktrackException, EndOfFileException { + private boolean isIdentifier(IToken t) { + char[] image= t.getCharImage(); + if (image.length == 0) + return false; + char firstChar= image[0]; + return Character.isLetter(firstChar) || firstChar == '_'; + } + + protected void __declspec() throws BacktrackException, EndOfFileException { IToken token = LA(1); if (token.getType() == IGCCToken.t__declspec) { consume();