From 710e066a9aa50e92895a5db82cb93ca856549454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 22 May 2016 21:18:52 +0200 Subject: [PATCH] Fixed #6406 (VarId: struct member initialization) --- lib/tokenize.cpp | 28 ++++++++++++++++++++++++++++ test/testother.cpp | 10 ---------- test/testvarid.cpp | 19 +++++++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 7a3633b60..99df1c98d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2460,6 +2460,34 @@ static void setVarIdStructMembers(Token **tok1, unsigned int *_varId) { Token *tok = *tok1; + + if (Token::Match(tok, "%name% = { . %name% =")) { + const unsigned int struct_varid = tok->varId(); + if (struct_varid == 0) + return; + + std::map& members = structMembers[struct_varid]; + + tok = tok->tokAt(3); + while (tok->str() != "}") { + while (Token::Match(tok, "{|[|(")) + tok = tok->link()->next(); + if (Token::Match(tok->previous(), "[,{] . %name% =")) { + tok = tok->next(); + const std::map::iterator it = members.find(tok->str()); + if (it == members.end()) { + members[tok->str()] = ++(*_varId); + tok->varId(*_varId); + } else { + tok->varId(it->second); + } + } + tok = tok->next(); + } + + return; + } + while (Token::Match(tok->next(), ". %name% !!(")) { const unsigned int struct_varid = tok->varId(); tok = tok->tokAt(2); diff --git a/test/testother.cpp b/test/testother.cpp index eda8f208c..6ad7afd83 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -3007,16 +3007,6 @@ private: "}"); ASSERT_EQUALS("", errout.str()); - // #6406 - false positive for struct with designated initializer - check("struct callbacks {\n" - " void (*something)(void);\n" - "};\n" - "void something(void) {}\n" - "void f() {\n" - " struct callbacks ops = { .something = something };\n" - "}\n"); - TODO_ASSERT_EQUALS("", "[test.cpp:6]: (warning) Redundant assignment of 'something' to itself.\n", errout.str()); - // #6406 - designated initializer doing bogus self assignment check("struct callbacks {\n" " void (*something)(void);\n" diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 19c4be3ad..d260dc2f9 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -148,6 +148,7 @@ private: TEST_CASE(varid_inheritedMembers); // #4101 TEST_CASE(varid_header); // #6386 TEST_CASE(varid_rangeBasedFor); + TEST_CASE(varid_structinit); // #6406 TEST_CASE(varidclass1); TEST_CASE(varidclass2); @@ -2442,6 +2443,24 @@ private: "}", false, "test.c")); } + void varid_structinit() { // #6406 + ASSERT_EQUALS("\n\n##file 0\n" + "1: void foo ( ) {\n" + "2: struct ABC abc@1 ; abc@1 = { . a@2 = 0 , . b@3 = 1 } ;\n" + "3: }\n", + tokenize("void foo() {\n" + " struct ABC abc = {.a=0,.b=1};\n" + "}")); + + ASSERT_EQUALS("\n\n##file 0\n" + "1: void foo ( ) {\n" + "2: struct ABC abc@1 ; abc@1 = { . a@2 = abc@1 . a@2 , . b@3 = abc@1 . b@3 } ;\n" + "3: }\n", + tokenize("void foo() {\n" + " struct ABC abc = {.a=abc.a,.b=abc.b};\n" + "}")); + } + void varidclass1() { const std::string actual = tokenize( "class Fred\n"