From 9e513774b112baaac1414eccc07c50661ce76452 Mon Sep 17 00:00:00 2001 From: Przemyslaw Gorszkowski Date: Mon, 9 Feb 2015 09:44:00 +0100 Subject: [PATCH] C++: resolved self-value reference for enum Added support for resolving case: enum E { val1, val2 = val1, // val2-4 are not resolved val3, val4 }; Task-number: QTCREATORBUG-13932 Change-Id: I122c5eb0b0397d6c02bc3db0a5c1ea1c28c5c6e7 Reviewed-by: Nikolai Kosjar --- src/libs/3rdparty/cplusplus/Bind.cpp | 35 ++++++++++++++++--- .../auto/cplusplus/semantic/tst_semantic.cpp | 26 ++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 58e3815a8f6..a0a0e1a0659 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -510,6 +510,24 @@ void calculateConstantValue(const Symbol *symbol, EnumeratorDeclaration *e, Cont } } +const StringLiteral *valueOfEnumerator(const Enum *e, const Identifier *value) { + const int enumMemberCount = e->memberCount(); + for (int i = 0; i < enumMemberCount; ++i) { + const Symbol *member = e->memberAt(i); + if (const Declaration *decl = member->asDeclaration()) { + if (const EnumeratorDeclaration *enumDecl = decl->asEnumeratorDeclarator()) { + if (const Name *enumDeclName = enumDecl->name()) { + if (const Identifier *enumDeclIdentifier = enumDeclName->identifier()) { + if (enumDeclIdentifier->equalTo(value)) + return enumDecl->constantValue(); + } + } + } + } + } + return 0; +} + } // anonymous namespace void Bind::enumerator(EnumeratorAST *ast, Enum *symbol) @@ -528,12 +546,21 @@ void Bind::enumerator(EnumeratorAST *ast, Enum *symbol) EnumeratorDeclaration *e = control()->newEnumeratorDeclaration(ast->identifier_token, name); e->setType(control()->integerType(IntegerType::Int)); // ### introduce IntegerType::Enumerator - if (ExpressionAST *expr = ast->expression) - e->setConstantValue(asStringLiteral(expr->firstToken(), expr->lastToken())); - else if (!symbol->isEmpty()) + if (ExpressionAST *expr = ast->expression) { + const int firstToken = expr->firstToken(); + const int lastToken = expr->lastToken(); + const StringLiteral *constantValue = asStringLiteral(firstToken, lastToken); + const StringLiteral *resolvedValue = 0; + if (lastToken - firstToken == 1) { + if (const Identifier *constantId = identifier(firstToken)) + resolvedValue = valueOfEnumerator(symbol, constantId); + } + e->setConstantValue(resolvedValue ? resolvedValue : constantValue); + } else if (!symbol->isEmpty()) { calculateConstantValue(*(symbol->memberEnd()-1), e, control()); - else + } else { e->setConstantValue(control()->stringLiteral("0", 1)); + } symbol->addMember(e); } diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 579c70d2ab5..c11226240a8 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -189,6 +189,7 @@ private slots: void enum_constantValue2(); void enum_constantValue3(); void enum_constantValue4(); + void enum_constantValue5(); }; void tst_Semantic::function_declaration_1() @@ -890,5 +891,30 @@ void tst_Semantic::enum_constantValue4() testEnumaratorDeclarator(e, 4, "11"); } +void tst_Semantic::enum_constantValue5() +{ + QSharedPointer doc = document("\n" + "enum {\n" + "E1,\n" + "E2=E1,\n" + "E3,\n" + "E4=E3,\n" + "E5\n" + "};\n" + ); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->memberCount(), 1U); + Enum *e = doc->globals->memberAt(0)->asEnum(); + QVERIFY(e); + QCOMPARE(e->memberCount(), 5U); + + testEnumaratorDeclarator(e, 0, "0"); + testEnumaratorDeclarator(e, 1, "0"); + testEnumaratorDeclarator(e, 2, "1"); + testEnumaratorDeclarator(e, 3, "1"); + testEnumaratorDeclarator(e, 4, "2"); +} + QTEST_MAIN(tst_Semantic) #include "tst_semantic.moc"