diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index f9d2802fc2579bdcd0fb129526089693e857029f..77d7a5e20068ab751482b7ee7944abc725c474a1 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -766,8 +766,33 @@ bool Parser::parseNamespace(DeclarationAST *&node) parseAttributeSpecifier(*attr_ptr); attr_ptr = &(*attr_ptr)->next; } - if (LA() == T_LBRACE) + if (LA() == T_LBRACE) { parseLinkageBody(ast->linkage_body); + } else { // attempt to do error recovery + unsigned pos = cursor(); + for (;LA() != T_EOF_SYMBOL; consumeToken()) { + switch (LA()) { + case T_IDENTIFIER: + case T_POUND: + case T_POUND_POUND: + case T___ATTRIBUTE__: + case T_LPAREN: + case T_RPAREN: + case T_DEFAULT: + case T_PUBLIC: + case T_PRIVATE: + case T_PROTECTED: + continue; + } + if (tok().isLiteral()) + continue; + break; + } + if (LA() == T_LBRACE && parseLinkageBody(ast->linkage_body)) + warning(pos, "expected '{' before '%s'", _translationUnit->tokenAt(pos).spell()); + else + rewind(pos); + } node = ast; return true; } diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 844f19f1a8b7579345239b7a6a2f9e1932b5a2e9..13f90d2a292f79f1e8dad7772139f08150df8799 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -99,6 +99,8 @@ private slots: void initTestCase(); // declarations void gcc_attributes_1(); + void gcc_attributes_2(); + void gcc_attributes_3(); // expressions void simple_name_1(); @@ -159,7 +161,55 @@ void tst_AST::gcc_attributes_1() { QSharedPointer<TranslationUnit> unit(parseDeclaration("\n" "static inline void *__attribute__((__always_inline__)) _mm_malloc(size_t size, size_t align);" - )); + )); +} + +void tst_AST::gcc_attributes_2() +{ + QSharedPointer<TranslationUnit> unit(parseDeclaration( + "\nnamespace std __attribute__ ((__visibility__ (\"default\"))) {\n}\n" + )); + AST *ast = unit->ast(); + QVERIFY(ast); + NamespaceAST* ns = ast->asNamespace(); + QVERIFY(ns); + QCOMPARE(unit->spell(ns->identifier_token), "std"); + QVERIFY(ns->attribute_list); + QVERIFY(!ns->attribute_list->next); + QVERIFY(ns->attribute_list->value); + AttributeSpecifierAST *attrSpec = ns->attribute_list->value->asAttributeSpecifier(); + QVERIFY(attrSpec); + QVERIFY(attrSpec->attribute_list); + QVERIFY(!attrSpec->attribute_list->next); + QVERIFY(attrSpec->attribute_list->value); + AttributeAST *attr = attrSpec->attribute_list->value->asAttribute(); + QVERIFY(attr); + QCOMPARE(unit->spell(attr->identifier_token), "__visibility__"); + QVERIFY(attr->expression_list); + QVERIFY(!attr->expression_list->next); + QVERIFY(attr->expression_list->value); + StringLiteralAST *e = attr->expression_list->value->asStringLiteral(); + QVERIFY(e); + QVERIFY(!e->next); + QCOMPARE(unit->spell(e->literal_token), "default"); +} + +void tst_AST::gcc_attributes_3() +{ + const char *inp = "\nnamespace std X {\n}\n"; + QSharedPointer<TranslationUnit> unit(parseDeclaration(inp)); + AST *ast = unit->ast(); + QVERIFY(ast); + NamespaceAST* ns = ast->asNamespace(); + QVERIFY(ns); + QCOMPARE(unit->spell(ns->identifier_token), "std"); + QVERIFY(!ns->attribute_list); + QVERIFY(ns->linkage_body); + LinkageBodyAST *link = ns->linkage_body->asLinkageBody(); + QVERIFY(link); + QCOMPARE(unit->tokenKind(link->lbrace_token), (int) T_LBRACE); + QVERIFY(!link->declaration_list); + QCOMPARE(unit->tokenKind(link->rbrace_token), (int) T_RBRACE); } void tst_AST::simple_declaration_1() diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 8056b5b06363713f6acc3ade15d2735b46385e77..1add27261681729e2761f2b50fcad3fc06cd7368 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -43,6 +43,7 @@ Q_OBJECT private Q_SLOTS: void unfinished_function_like_macro_call(); void nasty_macro_expansion(); + void tstst(); }; void tst_Preprocessor::unfinished_function_like_macro_call() @@ -111,5 +112,28 @@ void tst_Preprocessor::nasty_macro_expansion() QVERIFY(!preprocessed.contains("FIELD32")); } +void tst_Preprocessor::tstst() +{ + Client *client = 0; // no client. + Environment env; + + Preprocessor preprocess(client, &env); + QByteArray preprocessed = preprocess( + QLatin1String("<stdin>"), + QByteArray("\n" + "# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V)))\n" + "namespace std _GLIBCXX_VISIBILITY(default) {\n" + "}\n" + )); + + qDebug() << preprocessed; + + /* +# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V))) +namespace std _GLIBCXX_VISIBILITY(default) + + */ +} + QTEST_APPLESS_MAIN(tst_Preprocessor) #include "tst_preprocessor.moc"