forked from qt-creator/qt-creator
[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>
This commit is contained in:
27
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
27
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -766,8 +766,33 @@ bool Parser::parseNamespace(DeclarationAST *&node)
|
|||||||
parseAttributeSpecifier(*attr_ptr);
|
parseAttributeSpecifier(*attr_ptr);
|
||||||
attr_ptr = &(*attr_ptr)->next;
|
attr_ptr = &(*attr_ptr)->next;
|
||||||
}
|
}
|
||||||
if (LA() == T_LBRACE)
|
if (LA() == T_LBRACE) {
|
||||||
parseLinkageBody(ast->linkage_body);
|
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;
|
node = ast;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -99,6 +99,8 @@ private slots:
|
|||||||
void initTestCase();
|
void initTestCase();
|
||||||
// declarations
|
// declarations
|
||||||
void gcc_attributes_1();
|
void gcc_attributes_1();
|
||||||
|
void gcc_attributes_2();
|
||||||
|
void gcc_attributes_3();
|
||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
void simple_name_1();
|
void simple_name_1();
|
||||||
@@ -159,7 +161,55 @@ void tst_AST::gcc_attributes_1()
|
|||||||
{
|
{
|
||||||
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
|
QSharedPointer<TranslationUnit> unit(parseDeclaration("\n"
|
||||||
"static inline void *__attribute__((__always_inline__)) _mm_malloc(size_t size, size_t align);"
|
"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()
|
void tst_AST::simple_declaration_1()
|
||||||
|
@@ -43,6 +43,7 @@ Q_OBJECT
|
|||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void unfinished_function_like_macro_call();
|
void unfinished_function_like_macro_call();
|
||||||
void nasty_macro_expansion();
|
void nasty_macro_expansion();
|
||||||
|
void tstst();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_Preprocessor::unfinished_function_like_macro_call()
|
void tst_Preprocessor::unfinished_function_like_macro_call()
|
||||||
@@ -111,5 +112,28 @@ void tst_Preprocessor::nasty_macro_expansion()
|
|||||||
QVERIFY(!preprocessed.contains("FIELD32"));
|
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)
|
QTEST_APPLESS_MAIN(tst_Preprocessor)
|
||||||
#include "tst_preprocessor.moc"
|
#include "tst_preprocessor.moc"
|
||||||
|
Reference in New Issue
Block a user