From a621c99a0f986bece17713ad7ffd23a8f6af4345 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Fri, 24 Feb 2012 13:06:21 +0100 Subject: [PATCH] [C++] Add error recovery for namespace declarations. Change-Id: I884ff9901c95467524e5eba38e91f75992d30e14 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com> Reviewed-by: Flex Ferrum <flexferrum@gmail.com> --- src/libs/3rdparty/cplusplus/Parser.cpp | 27 +++++++++- tests/auto/cplusplus/ast/tst_ast.cpp | 52 ++++++++++++++++++- .../preprocessor/tst_preprocessor.cpp | 24 +++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index f9d2802fc25..77d7a5e2006 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 844f19f1a8b..13f90d2a292 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 8056b5b0636..1add2726168 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" -- GitLab