From b78131cfcf9c2951c4b5624922a7889582415335 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Sat, 24 May 2014 11:28:43 +0200 Subject: [PATCH] Improved cast detection in AST: -> Make use of it in checkother.cpp Use tokenizer simplification instead of reimplementation for test suite --- lib/checkother.cpp | 20 ++--------------- lib/tokenlist.cpp | 8 ++++++- test/testtokenize.cpp | 52 +++++++++++++++---------------------------- 3 files changed, 27 insertions(+), 53 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index f9a90e61a..ed511838b 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -185,22 +185,6 @@ static bool isOppositeCond(const Token * const cond1, const Token * const cond2, (comp1 == ">=" && comp2 == "<")); } -static bool isPossibleCast(const Token * const startPar) -{ - if (!Token::Match(startPar, "( %type%")) - return false; - const Token *tok; - for (tok = startPar->tokAt(2); tok; tok = tok->next()) { - if (tok->str() == ")") - return true; - if (tok->varId()>0) - return false; - if (!Token::Match(tok,"%type%|*|&")) - return false; - } - return tok != nullptr; -} - //---------------------------------------------------------------------------------- // The return value of fgetc(), getc(), ungetc(), getchar() etc. is an integer value. // If this return value is stored in a character variable and then compared @@ -2068,8 +2052,8 @@ void CheckOther::checkCharVariable() else continue; - // (x) & y => if x is a possible type then assume & is a address-of operator - if (Token::simpleMatch(tok->previous(), ") &") && isPossibleCast(tok->linkAt(-1))) + // Don't care about address-of operator + if (!tok->astOperand2()) continue; // it's ok with a bitwise and where the other operand is 0xff or less.. diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 59c7ef884..24a1e9eb1 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -382,12 +382,18 @@ static bool iscast(const Token *tok) return true; for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { + if (tok2->link() && tok2->str() == "<") + tok2 = tok2->link()->next(); + if (tok2->str() == ")") return tok2->previous()->str() == "*" || (Token::Match(tok2, ") %any%") && - (!tok2->next()->isOp() && !Token::Match(tok2->next(), "[[]);,?:.]"))); + (tok2->strAt(1) == "&" || (!tok2->next()->isOp() && !Token::Match(tok2->next(), "[[]);,?:.]")))); if (!Token::Match(tok2, "%var%|*|&|::")) return false; + + if (tok2->isStandardType()) + return true; } return false; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index f95460d9c..885c09237 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -585,6 +585,7 @@ private: TEST_CASE(astunaryop); TEST_CASE(astfunction); TEST_CASE(asttemplate); + TEST_CASE(astcast); TEST_CASE(startOfExecutableScope); } @@ -10384,55 +10385,31 @@ private: static std::string testAst(const char code[],bool verbose=false) { // tokenize given code.. const Settings settings; - TokenList tokenList(&settings); + Tokenizer tokenList(&settings, nullptr); std::istringstream istr(code); - if (!tokenList.createTokens(istr,"test.cpp")) + if (!tokenList.list.createTokens(istr,"test.cpp")) return "ERROR"; - for (Token *tok = tokenList.front(); tok; tok = tok->next()) { - if (Token::Match(tok, "%or%|<<|>>|+|-|*|/|%|&|^ =")) { - tok->str(tok->str() + "="); - tok->deleteNext(); - } else if (Token::simpleMatch(tok, ": :")) { - tok->str("::"); - tok->deleteNext(); - } else if (Token::Match(tok, ">|<|= =")) { - tok->str(tok->str() + tok->strAt(1)); - tok->deleteNext(); - } - } - - // Set links.. - std::stack links; - for (Token *tok = tokenList.front(); tok; tok = tok->next()) { - if (Token::Match(tok, "(|[|{")) - links.push(tok); - else if (!links.empty() && Token::Match(tok,")|]|}")) { - Token::createMutualLinks(links.top(), tok); - links.pop(); - } else if (Token::Match(tok, "< %type% >")) { - Token::createMutualLinks(tok, tok->tokAt(2)); - } else if (Token::Match(tok, "< %type% * >")) { - Token::createMutualLinks(tok, tok->tokAt(3)); - } - } + tokenList.combineOperators(); + tokenList.createLinks(); + tokenList.createLinks2(); // Create AST.. - tokenList.createAst(); + tokenList.list.createAst(); // Basic AST validation - for (const Token *tok = tokenList.front(); tok; tok = tok->next()) { + for (const Token *tok = tokenList.list.front(); tok; tok = tok->next()) { if (tok->astOperand2() && !tok->astOperand1() && tok->str() != ";" && tok->str() != ":") return "Op2 but no Op1 for token: " + tok->str(); } // Return stringified AST if (verbose) - return tokenList.front()->astTop()->astStringVerbose(0,0); + return tokenList.list.front()->astTop()->astStringVerbose(0, 0); std::string ret; std::set astTop; - for (const Token *tok = tokenList.front(); tok; tok = tok->next()) { + for (const Token *tok = tokenList.list.front(); tok; tok = tok->next()) { if (tok->astOperand1() && astTop.find(tok->astTop()) == astTop.end()) { astTop.insert(tok->astTop()); if (!ret.empty()) @@ -10504,7 +10481,7 @@ private: ASSERT_EQUALS("ax( whilex(", testAst("a(x) while (x)")); ASSERT_EQUALS("ifx( i0= whilei(", testAst("if (x) { ({ int i = 0; while(i); }) };")); ASSERT_EQUALS("ifx( BUG_ON{!( i0= whilei(", testAst("if (x) { BUG_ON(!({int i=0; while(i);})); }")); - ASSERT_EQUALS("v0= while{( v0= while{( v0=", testAst("({ v = 0; }); while (({ v = 0; }) != 0); while (({ v = 0; }) != 0);")); + ASSERT_EQUALS("v0= while{0!=( v0= while{0!=( v0=", testAst("({ v = 0; }); while (({ v = 0; }) != 0); while (({ v = 0; }) != 0);")); ASSERT_EQUALS("abc.1:?1+bd.1:?+=", testAst("a =(b.c ? : 1) + 1 + (b.d ? : 1);")); @@ -10607,6 +10584,13 @@ private: ASSERT_EQUALS("AB: f( abc+=", testAst("struct A : public B { void f() { a=b+c; } };")); } + void astcast() const { + ASSERT_EQUALS("ac&(=", testAst("a = (long)&c;")); + ASSERT_EQUALS("ac*(=", testAst("a = (Foo*)*c;")); + ASSERT_EQUALS("ac-(=", testAst("a = (long)-c;")); + ASSERT_EQUALS("ac(=", testAst("a = (some)c;")); + } + void compileLimits() { const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n" "#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n"