From b90452e309dfeb308fd9b82b4fce8f32588caeb4 Mon Sep 17 00:00:00 2001 From: Przemyslaw Gorszkowski Date: Thu, 5 Jun 2014 09:05:41 +0200 Subject: [PATCH] C++: fix nested anonymous with __attribute__ Task-number: QTCREATORBUG-12345 Change-Id: Ib2316ebdc81393b38185b9cb659fb85b78753e7b Reviewed-by: Nikolai Kosjar Reviewed-by: Eike Ziller --- src/libs/3rdparty/cplusplus/Parser.cpp | 12 +++---- src/plugins/cpptools/cppcompletion_test.cpp | 14 ++++++++ tests/auto/cplusplus/ast/tst_ast.cpp | 38 +++++++++++++++++++++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index bf19628fd23..dfdc260f6e7 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -1988,12 +1988,6 @@ bool Parser::parseClassSpecifier(SpecifierListAST *&node) NameAST *name = 0; parseName(name); - if (! name && LA() == T_LBRACE && (LA(0) == T_CLASS || LA(0) == T_STRUCT || LA(0) == T_UNION || LA(0) == T_ENUM)) { - AnonymousNameAST *ast = new (_pool) AnonymousNameAST; - ast->class_token = classkey_token; - name = ast; - } - bool parsed = false; const bool previousInFunctionBody = _inFunctionBody; @@ -2010,6 +2004,12 @@ bool Parser::parseClassSpecifier(SpecifierListAST *&node) } if (LA() == T_COLON || LA() == T_LBRACE) { + if (!name) { + AnonymousNameAST *ast = new (_pool) AnonymousNameAST; + ast->class_token = classkey_token; + name = ast; + } + BaseSpecifierListAST *base_clause_list = 0; if (LA() == T_COLON) { diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 8679d3120a1..0dde60e9f92 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -1856,6 +1856,20 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("val2") << QLatin1String("val3")); + QTest::newRow("nested_anonymous_with___attribute__") << _( + "struct Enclosing\n" + "{\n" + " struct __attribute__((aligned(8)))\n" + " {\n" + " int i;\n" + " };\n" + "};\n" + "Enclosing e;\n" + "@\n" + ) << _("e.") << (QStringList() + << QLatin1String("Enclosing") + << QLatin1String("i")); + QTest::newRow("enum_inside_namespace") << _( "namespace Ns\n" "{\n" diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index c1f7c914562..4010ba1e26d 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -183,6 +183,8 @@ private slots: void q_enum_1(); void incomplete_ast(); + void unnamed_class(); + void unnamed_class_data(); }; void tst_AST::gcc_attributes_1() @@ -1743,6 +1745,42 @@ void tst_AST::incomplete_ast() QVERIFY(ast); } +static ClassSpecifierAST *classSpecifierInSimpleDeclaration(SimpleDeclarationAST *simpleDeclaration) +{ + Q_ASSERT(simpleDeclaration); + SpecifierListAST *specifier = simpleDeclaration->decl_specifier_list; + Q_ASSERT(specifier); + Q_ASSERT(specifier->value); + return specifier->value->asClassSpecifier(); +} + +void tst_AST::unnamed_class() +{ + QFETCH(QByteArray, source); + QVERIFY(!source.isEmpty()); + + QSharedPointer unit(parseDeclaration(source)); + QVERIFY(unit->ast()); + SimpleDeclarationAST *simpleDeclaration = unit->ast()->asSimpleDeclaration(); + QVERIFY(simpleDeclaration); + ClassSpecifierAST *clazz = classSpecifierInSimpleDeclaration(simpleDeclaration); + + QVERIFY(clazz); + QVERIFY(clazz->name); + QVERIFY(clazz->name->asAnonymousName()); + + QCOMPARE(diag.errorCount, 0); +} + +void tst_AST::unnamed_class_data() +{ + QTest::addColumn("source"); + + typedef QByteArray _; + QTest::newRow("unnamed-only") << _("class {};"); + QTest::newRow("unnamed-derived") << _("class : B {};"); +} + void tst_AST::initTestCase() { control.setDiagnosticClient(&diag);