From 51baca03594e44bca454dcdad79613b537e77546 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Mon, 2 May 2011 22:42:52 -0400 Subject: [PATCH] fix #1982 (simplifyTypedef: scope info is lost) --- lib/tokenize.cpp | 35 +++++++++++++++++++++ test/testsimplifytokens.cpp | 61 +++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 82d9c8881..cd421666a 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1395,6 +1395,7 @@ void Tokenizer::simplifyTypedef() bool simplifyType = false; bool inMemberFunc = false; int memberScope = 0; + bool globalScope = false; std::size_t classLevel = spaceInfo.size(); for (Token *tok2 = tok; tok2; tok2 = tok2->next()) @@ -1517,6 +1518,12 @@ void Tokenizer::simplifyTypedef() if (pattern1.find("::") != std::string::npos) // has a "something ::" { + if (Token::simpleMatch(tok2->previous(), "::")) + { + tok2->previous()->previous()->deleteNext(); + globalScope = true; + } + for (std::size_t i = classLevel; i < spaceInfo.size(); i++) { tok2->deleteNext(); @@ -1615,11 +1622,39 @@ void Tokenizer::simplifyTypedef() inOperator = true; // skip over class or struct in derived class declaration + bool structRemoved = false; if (isDerived && Token::Match(typeStart, "class|struct")) + { + if (typeStart->str() == "struct") + structRemoved = true; typeStart = typeStart->next(); + } // start substituting at the typedef name by replacing it with the type tok2->str(typeStart->str()); + + // restore qualification if it was removed + if (typeStart->str() == "struct" || structRemoved) + { + if (structRemoved) + tok2 = tok2->previous(); + + if (globalScope) + { + tok2->insertToken("::"); + tok2 = tok2->next(); + } + + for (std::size_t i = classLevel; i < spaceInfo.size(); i++) + { + tok2->insertToken(spaceInfo[i].className); + tok2 = tok2->next(); + tok2->insertToken("::"); + tok2 = tok2->next(); + } + } + + // add remainder of type tok2 = copyTokens(tok2, typeStart->next(), typeEnd); if (!pointers.empty()) diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 9b2be60f3..4401663a6 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -258,6 +258,7 @@ private: TEST_CASE(simplifyTypedef91); // ticket #2716 TEST_CASE(simplifyTypedef92); // ticket #2736 TEST_CASE(simplifyTypedef93); // ticket #2738 + TEST_CASE(simplifyTypedef94); // ticket #1982 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -5255,6 +5256,66 @@ private: ASSERT_EQUALS("", errout.str()); } + void simplifyTypedef94() // ticket #1982 + { + const char code1[] = "class A {\n" + "public:\n" + " typedef struct {\n" + " int a[4];\n" + " } data;\n" + "};\n" + "A::data d;\n"; + const char expected1[] = "class A { " + "public: " + "struct data { " + "int a [ 4 ] ; " + "} ; " + "} ; " + "struct A :: data d ;"; + + checkSimplifyTypedef(code1); + ASSERT_EQUALS(expected1, sizeof_(code1)); + TODO_ASSERT_EQUALS("[test.cpp:7]: (debug) Scope::checkVariable found variable 'd' with varid 0.\n", "", errout.str()); + + const char code2[] = "class A {\n" + "public:\n" + " typedef struct {\n" + " int a[4];\n" + " } data;\n" + "};\n" + "::A::data d;\n"; + const char expected2[] = "class A { " + "public: " + "struct data { " + "int a [ 4 ] ; " + "} ; " + "} ; " + "struct :: A :: data d ;"; + + checkSimplifyTypedef(code2); + ASSERT_EQUALS(expected2, sizeof_(code2)); + TODO_ASSERT_EQUALS("[test.cpp:7]: (debug) Scope::checkVariable found variable 'd' with varid 0.\n", "", errout.str()); + + const char code3[] = "class A {\n" + "public:\n" + " typedef struct {\n" + " int a[4];\n" + " } data;\n" + "};\n" + "class B : public ::A::data { };\n"; + const char expected3[] = "class A { " + "public: " + "struct data { " + "int a [ 4 ] ; " + "} ; " + "} ; " + "class B : public :: A :: data { } ;"; + + checkSimplifyTypedef(code3); + ASSERT_EQUALS(expected3, sizeof_(code3)); + ASSERT_EQUALS("", errout.str()); + } + void simplifyTypedefFunction1() { {