From cfa7b4906eadf25c900e869ed0c63fe244d5d565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 18 Aug 2010 22:42:04 +0200 Subject: [PATCH] Symbol database: bug fixes. Ticket: #1895 --- lib/checkclass.cpp | 69 ++++++++++++-- lib/checkclass.h | 8 +- lib/tokenize.cpp | 40 +++++++-- lib/tokenize.h | 5 ++ test/testclass.cpp | 16 ++++ test/testsimplifytokens.cpp | 3 +- test/testtokenize.cpp | 175 ++++++++++++++++++++++++++++++++++-- 7 files changed, 289 insertions(+), 27 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2231359e8..ceb29e735 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -112,6 +112,17 @@ void CheckClass::createSymbolDatabase() info->access = Protected; else if (tok->str() == "public:") info->access = Public; + else if (Token::Match(tok, "public|protected|private %var% :")) + { + if (tok->str() == "private") + info->access = Private; + else if (tok->str() == "protected") + info->access = Protected; + else if (tok->str() == "public") + info->access = Public; + + tok = tok->tokAt(2); + } // function? else if (((Token::Match(tok, "%var% (") || Token::Match(tok, "operator %any% (")) && tok->previous()->str() != "::") && @@ -411,8 +422,7 @@ void CheckClass::SpaceInfo::getVarList() // Get variable list.. const Token *tok1 = classDef; unsigned int indentlevel = 0; - bool isStruct = tok1->str() == "struct"; - bool priv = !isStruct; + AccessControl varaccess = tok1->str() == "struct" ? Public : Private; for (const Token *tok = tok1; tok; tok = tok->next()) { if (!tok->next()) @@ -434,7 +444,6 @@ void CheckClass::SpaceInfo::getVarList() // These are automaticly initialized. if (tok->str() == "__published:") { - priv = false; for (; tok; tok = tok->next()) { if (tok->str() == "{") @@ -449,10 +458,33 @@ void CheckClass::SpaceInfo::getVarList() } // "private:" "public:" "protected:" etc - const bool b((tok->str()[0] != ':') && tok->str().find(":") != std::string::npos); - - if (b) - priv = bool(tok->str() == "private:"); + bool b = false; + if (tok->str() == "public:") + { + varaccess = Public; + b = true; + } + else if (tok->str() == "protected:") + { + varaccess = Protected; + b = true; + } + else if (tok->str() == "private:") + { + varaccess = Private; + b = true; + } + else if (Token::Match(tok, "public|protected|private %var% :")) + { + if (tok->str() == "public") + varaccess = Public; + else if (tok->str() == "protected") + varaccess = Protected; + else if (tok->str() == "private") + varaccess = Private; + tok = tok->tokAt(2); + b = true; + } // Search for start of statement.. if (! Token::Match(tok, "[;{}]") && ! b) @@ -466,6 +498,25 @@ void CheckClass::SpaceInfo::getVarList() if (next->str().find(":") != std::string::npos) continue; + if (Token::Match(next, "public|protected|private %var% :")) + { + if (next->str() == "public") + varaccess = Public; + else if (next->str() == "protected") + varaccess = Protected; + else if (next->str() == "private") + varaccess = Private; + tok = tok->tokAt(2); + continue; + } + + // Is it a forward declaration? + if (Token::Match(next, "class|struct|union %var% ;")) + { + tok = tok->tokAt(2); + continue; + } + // Borland C++: Ignore properties.. if (next->str() == "__property") continue; @@ -583,7 +634,7 @@ void CheckClass::SpaceInfo::getVarList() check->reportError(vartok, Severity::error, "cppcheckError", "Internal error. CheckClass::SpaceInfo::getVarList found variable \'" + vartok->str() + "\' with varid 0."); } - varlist.push_back(Var(vartok, false, priv, isMutable, isStatic, isClass)); + varlist.push_back(Var(vartok, false, varaccess, isMutable, isStatic, isClass)); } } } @@ -954,7 +1005,7 @@ void CheckClass::constructors() std::list::const_iterator var; for (var = info->varlist.begin(); var != info->varlist.end(); ++var) { - if (var->priv && !var->isClass && !var->isStatic) + if (var->access == Private && !var->isClass && !var->isStatic) { noConstructorError(info->classDef, info->className, info->classDef->str() == "struct"); break; diff --git a/lib/checkclass.h b/lib/checkclass.h index b1e82e4f5..d1d3e2653 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -132,10 +132,10 @@ private: class Var { public: - Var(const Token *token_, bool init_ = false, bool priv_ = false, bool mutable_ = false, bool static_ = false, bool class_ = false) + Var(const Token *token_, bool init_ = false, AccessControl access_ = Public, bool mutable_ = false, bool static_ = false, bool class_ = false) : token(token_), init(init_), - priv(priv_), + access(access_), isMutable(mutable_), isStatic(static_), isClass(class_) @@ -148,8 +148,8 @@ private: /** @brief has this variable been initialized? */ bool init; - /** @brief is this variable declared in the private section? */ - bool priv; + /** @brief what section is this variable declared in? */ + AccessControl access; // public/protected/private /** @brief is this variable mutable? */ bool isMutable; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index ebdb3afc8..c8b8adf05 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1679,9 +1679,6 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s // specify array size.. arraySize(); - // simplify bit fields.. - simplifyBitfields(); - // simplify labels.. labels(); @@ -1792,6 +1789,9 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s } } + // simplify bit fields.. + simplifyBitfields(); + // Remove __declspec() simplifyDeclspec(); @@ -1801,6 +1801,9 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s // remove __attribute__((?)) simplifyAttribute(); + // remove Microsoft MFC.. + simplifyMicrosoftMFC(); + // typedef.. simplifyTypedef(); @@ -1935,7 +1938,10 @@ void Tokenizer::labels() // simplify label.. if (Token::Match(tok, "[;{}] %var% : %var%")) - tok->tokAt(2)->insertToken(";"); + { + if (!Token::Match(tok->next(), "public|protected|private")) + tok->tokAt(2)->insertToken(";"); + } } } } @@ -2769,7 +2775,7 @@ void Tokenizer::setVarId() if (Token::Match(tok, "else|return|typedef|delete|sizeof")) continue; - if (Token::Match(tok, "const|static|extern|public:|private:|protected:")) + while (Token::Match(tok, "const|static|extern|public:|private:|protected:|;|mutable")) tok = tok->next(); while (Token::Match(tok, "%var% ::")) @@ -7913,10 +7919,14 @@ void Tokenizer::simplifyBitfields() { for (Token *tok = _tokens; tok; tok = tok->next()) { - if (Token::Match(tok, "[;{] signed|unsigned|int|long %var% : %num% ;")) + if (Token::Match(tok, ";|{|public:|protected:|private: signed|unsigned|int|long|bool|char|short %var% : %num% ;")) Token::eraseTokens(tok->tokAt(2), tok->tokAt(5)); - if (Token::Match(tok, "[;{] signed|unsigned int|long %var% : %num% ;")) + else if (Token::Match(tok, ";|{|public:|protected:|private: signed|unsigned int|long|char|short %var% : %num% ;")) Token::eraseTokens(tok->tokAt(3), tok->tokAt(6)); + else if (Token::Match(tok, ";|{|public:|protected:|private: const signed|unsigned|int|long|bool|char|short %var% : %num% ;")) + Token::eraseTokens(tok->tokAt(3), tok->tokAt(6)); + else if (Token::Match(tok, ";|{|public:|protected:|private: const signed|unsigned int|long|char|short %var% : %num% ;")) + Token::eraseTokens(tok->tokAt(4), tok->tokAt(7)); } } @@ -7963,4 +7973,20 @@ void Tokenizer::simplifyBuiltinExpect() } +// Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()' +void Tokenizer::simplifyMicrosoftMFC() +{ + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (Token::simpleMatch(tok->next(), "DECLARE_MESSAGE_MAP ( )")) + { + tok->deleteNext(); + tok->deleteNext(); + tok->deleteNext(); + } + } +} + + + diff --git a/lib/tokenize.h b/lib/tokenize.h index 207632cf6..31c8d8f99 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -473,6 +473,11 @@ public: */ void simplifyBuiltinExpect(); + /** + * Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()' + */ + void simplifyMicrosoftMFC(); + /** * This will return a short name describing function parameters * e.g. parameters: (int a, char b) should get name "int,char,". diff --git a/test/testclass.cpp b/test/testclass.cpp index 167ebb9e9..ab5b3e38c 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -149,6 +149,7 @@ private: TEST_CASE(constFriend); // ticket #1921 - fp for friend function TEST_CASE(symboldatabase1); + TEST_CASE(symboldatabase2); } // Check the operator Equal @@ -4210,6 +4211,21 @@ private: "};"); ASSERT_EQUALS("", errout.str()); } + + void symboldatabase2() + { + checkConst("class foo {\n" + "public slots :\n" + "foo() { }\n" + "};"); + ASSERT_EQUALS("", errout.str()); + + checkConst("class foo {\n" + "class bar;\n" + "foo() { }\n" + "};"); + ASSERT_EQUALS("", errout.str()); + } }; REGISTER_TEST(TestClass) diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index a2f6135d7..2f3dcfb74 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -2585,7 +2585,8 @@ private: { const char code[] = "class NoLabels { bool varOne : 1 ; bool varTwo : 1 ; } ;"; - ASSERT_EQUALS(code, tok(code)); + const char expect[] = "class NoLabels { bool varOne ; bool varTwo ; } ;"; + ASSERT_EQUALS(expect, tok(code)); } { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 488a74498..74786a12a 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -144,6 +144,10 @@ private: TEST_CASE(varid19); TEST_CASE(varid20); TEST_CASE(varid21); + TEST_CASE(varid22); + TEST_CASE(varid23); + TEST_CASE(varid24); + TEST_CASE(varid25); TEST_CASE(varidStl); TEST_CASE(varid_delete); TEST_CASE(varid_functions); @@ -238,7 +242,11 @@ private: TEST_CASE(labels); TEST_CASE(simplifyInitVar); - TEST_CASE(bitfields); + TEST_CASE(bitfields1); + TEST_CASE(bitfields2); + TEST_CASE(bitfields3); + + TEST_CASE(microsoftMFC); } @@ -2304,6 +2312,86 @@ private: ASSERT_EQUALS(expected, tokenizeDebugListing(code)); } + void varid22() + { + const std::string code("class foo()\n" + "{\n" + "public:\n" + " vector x;\n" + "};\n"); + + const std::string expected("\n\n##file 0\n" + "1: class foo ( )\n" + "2: {\n" + "3: public:\n" + "4: vector < const std :: string & > x@1 ;\n" + "5: } ;\n"); + + ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + } + + void varid23() + { + const std::string code("class foo()\n" + "{\n" + "public:\n" + " static vector x;\n" + "};\n"); + + const std::string expected("\n\n##file 0\n" + "1: class foo ( )\n" + "2: {\n" + "3: public:\n" + "4: static vector < const std :: string & > x@1 ;\n" + "5: } ;\n"); + + ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + } + + void varid24() + { + const std::string code("class foo()\n" + "{\n" + "public:\n" + " ;\n" + "private:\n" + " static int i;\n" + "};\n"); + + const std::string expected("\n\n##file 0\n" + "1: class foo ( )\n" + "2: {\n" + "3: public:\n" + "4: ;\n" + "5: private:\n" + "6: static int i@1 ;\n" + "7: } ;\n"); + + ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + } + + void varid25() + { + const std::string code("class foo()\n" + "{\n" + "public:\n" + " ;\n" + "private:\n" + " mutable int i;\n" + "};\n"); + + const std::string expected("\n\n##file 0\n" + "1: class foo ( )\n" + "2: {\n" + "3: public:\n" + "4: ;\n" + "5: private:\n" + "6: mutable int i@1 ;\n" + "7: } ;\n"); + + ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + } + void varidStl() { @@ -4170,13 +4258,88 @@ private: } } - void bitfields() + void bitfields1() { - const char code1[] = "struct A { int x : 3; };"; - ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringify(code1,false)); + const char code1[] = "struct A { bool x : 1; };"; + ASSERT_EQUALS("struct A { bool x ; } ;", tokenizeAndStringify(code1,false)); - const char code2[] = "struct A { unsigned long x : 3; };"; - ASSERT_EQUALS("struct A { unsigned long x ; } ;", tokenizeAndStringify(code2,false)); + const char code2[] = "struct A { char x : 3; };"; + ASSERT_EQUALS("struct A { char x ; } ;", tokenizeAndStringify(code2,false)); + + const char code3[] = "struct A { short x : 3; };"; + ASSERT_EQUALS("struct A { short x ; } ;", tokenizeAndStringify(code3,false)); + + const char code4[] = "struct A { int x : 3; };"; + ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringify(code4,false)); + + const char code5[] = "struct A { long x : 3; };"; + ASSERT_EQUALS("struct A { long x ; } ;", tokenizeAndStringify(code5,false)); + + const char code6[] = "struct A { unsigned char x : 3; };"; + ASSERT_EQUALS("struct A { unsigned char x ; } ;", tokenizeAndStringify(code6,false)); + + const char code7[] = "struct A { unsigned short x : 3; };"; + ASSERT_EQUALS("struct A { unsigned short x ; } ;", tokenizeAndStringify(code7,false)); + + const char code8[] = "struct A { unsigned int x : 3; };"; + ASSERT_EQUALS("struct A { unsigned int x ; } ;", tokenizeAndStringify(code8,false)); + + const char code9[] = "struct A { unsigned long x : 3; };"; + ASSERT_EQUALS("struct A { unsigned long x ; } ;", tokenizeAndStringify(code9,false)); + + const char code10[] = "struct A { signed char x : 3; };"; + ASSERT_EQUALS("struct A { signed char x ; } ;", tokenizeAndStringify(code10,false)); + + const char code11[] = "struct A { signed short x : 3; };"; + ASSERT_EQUALS("struct A { signed short x ; } ;", tokenizeAndStringify(code11,false)); + + const char code12[] = "struct A { signed int x : 3; };"; + ASSERT_EQUALS("struct A { signed int x ; } ;", tokenizeAndStringify(code12,false)); + + const char code13[] = "struct A { signed long x : 3; };"; + ASSERT_EQUALS("struct A { signed long x ; } ;", tokenizeAndStringify(code13,false)); + } + + void bitfields2() + { + const char code1[] = "struct A { public: int x : 3; };"; + ASSERT_EQUALS("struct A { public: int x ; } ;", tokenizeAndStringify(code1,false)); + + const char code2[] = "struct A { public: unsigned long x : 3; };"; + ASSERT_EQUALS("struct A { public: unsigned long x ; } ;", tokenizeAndStringify(code2,false)); + + const char code3[] = "struct A { protected: int x : 3; };"; + ASSERT_EQUALS("struct A { protected: int x ; } ;", tokenizeAndStringify(code3,false)); + + const char code4[] = "struct A { protected: unsigned long x : 3; };"; + ASSERT_EQUALS("struct A { protected: unsigned long x ; } ;", tokenizeAndStringify(code4,false)); + + const char code5[] = "struct A { private: int x : 3; };"; + ASSERT_EQUALS("struct A { private: int x ; } ;", tokenizeAndStringify(code5,false)); + + const char code6[] = "struct A { private: unsigned long x : 3; };"; + ASSERT_EQUALS("struct A { private: unsigned long x ; } ;", tokenizeAndStringify(code6,false)); + } + + void bitfields3() + { + const char code1[] = "struct A { const int x : 3; };"; + ASSERT_EQUALS("struct A { const int x ; } ;", tokenizeAndStringify(code1,false)); + + const char code2[] = "struct A { const unsigned long x : 3; };"; + ASSERT_EQUALS("struct A { const unsigned long x ; } ;", tokenizeAndStringify(code2,false)); + + const char code3[] = "struct A { public: const int x : 3; };"; + ASSERT_EQUALS("struct A { public: const int x ; } ;", tokenizeAndStringify(code3,false)); + + const char code4[] = "struct A { public: const unsigned long x : 3; };"; + ASSERT_EQUALS("struct A { public: const unsigned long x ; } ;", tokenizeAndStringify(code4,false)); + } + + void microsoftMFC() + { + const char code1[] = "class MyDialog : public CDialog { DECLARE_MESSAGE_MAP() private: CString text; };"; + ASSERT_EQUALS("class MyDialog : public CDialog { private: CString text ; } ;", tokenizeAndStringify(code1,false)); } };