Improved cast detection in AST:
-> Make use of it in checkother.cpp Use tokenizer simplification instead of reimplementation for test suite
This commit is contained in:
parent
b0b0562247
commit
b78131cfcf
|
@ -185,22 +185,6 @@ static bool isOppositeCond(const Token * const cond1, const Token * const cond2,
|
||||||
(comp1 == ">=" && comp2 == "<"));
|
(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.
|
// 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
|
// If this return value is stored in a character variable and then compared
|
||||||
|
@ -2068,8 +2052,8 @@ void CheckOther::checkCharVariable()
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// (x) & y => if x is a possible type then assume & is a address-of operator
|
// Don't care about address-of operator
|
||||||
if (Token::simpleMatch(tok->previous(), ") &") && isPossibleCast(tok->linkAt(-1)))
|
if (!tok->astOperand2())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
// it's ok with a bitwise and where the other operand is 0xff or less..
|
||||||
|
|
|
@ -382,12 +382,18 @@ static bool iscast(const Token *tok)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
||||||
|
if (tok2->link() && tok2->str() == "<")
|
||||||
|
tok2 = tok2->link()->next();
|
||||||
|
|
||||||
if (tok2->str() == ")")
|
if (tok2->str() == ")")
|
||||||
return tok2->previous()->str() == "*" ||
|
return tok2->previous()->str() == "*" ||
|
||||||
(Token::Match(tok2, ") %any%") &&
|
(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%|*|&|::"))
|
if (!Token::Match(tok2, "%var%|*|&|::"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (tok2->isStandardType())
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -585,6 +585,7 @@ private:
|
||||||
TEST_CASE(astunaryop);
|
TEST_CASE(astunaryop);
|
||||||
TEST_CASE(astfunction);
|
TEST_CASE(astfunction);
|
||||||
TEST_CASE(asttemplate);
|
TEST_CASE(asttemplate);
|
||||||
|
TEST_CASE(astcast);
|
||||||
|
|
||||||
TEST_CASE(startOfExecutableScope);
|
TEST_CASE(startOfExecutableScope);
|
||||||
}
|
}
|
||||||
|
@ -10384,55 +10385,31 @@ private:
|
||||||
static std::string testAst(const char code[],bool verbose=false) {
|
static std::string testAst(const char code[],bool verbose=false) {
|
||||||
// tokenize given code..
|
// tokenize given code..
|
||||||
const Settings settings;
|
const Settings settings;
|
||||||
TokenList tokenList(&settings);
|
Tokenizer tokenList(&settings, nullptr);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
if (!tokenList.createTokens(istr,"test.cpp"))
|
if (!tokenList.list.createTokens(istr,"test.cpp"))
|
||||||
return "ERROR";
|
return "ERROR";
|
||||||
|
|
||||||
for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
tokenList.combineOperators();
|
||||||
if (Token::Match(tok, "%or%|<<|>>|+|-|*|/|%|&|^ =")) {
|
tokenList.createLinks();
|
||||||
tok->str(tok->str() + "=");
|
tokenList.createLinks2();
|
||||||
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<Token *> 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create AST..
|
// Create AST..
|
||||||
tokenList.createAst();
|
tokenList.list.createAst();
|
||||||
|
|
||||||
// Basic AST validation
|
// 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() != ":")
|
if (tok->astOperand2() && !tok->astOperand1() && tok->str() != ";" && tok->str() != ":")
|
||||||
return "Op2 but no Op1 for token: " + tok->str();
|
return "Op2 but no Op1 for token: " + tok->str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return stringified AST
|
// Return stringified AST
|
||||||
if (verbose)
|
if (verbose)
|
||||||
return tokenList.front()->astTop()->astStringVerbose(0,0);
|
return tokenList.list.front()->astTop()->astStringVerbose(0, 0);
|
||||||
|
|
||||||
std::string ret;
|
std::string ret;
|
||||||
std::set<const Token *> astTop;
|
std::set<const Token *> 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()) {
|
if (tok->astOperand1() && astTop.find(tok->astTop()) == astTop.end()) {
|
||||||
astTop.insert(tok->astTop());
|
astTop.insert(tok->astTop());
|
||||||
if (!ret.empty())
|
if (!ret.empty())
|
||||||
|
@ -10504,7 +10481,7 @@ private:
|
||||||
ASSERT_EQUALS("ax( whilex(", testAst("a(x) while (x)"));
|
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( 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("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);"));
|
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<C*> { void f() { a=b+c; } };"));
|
ASSERT_EQUALS("AB: f( abc+=", testAst("struct A : public B<C*> { 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<strange, type>)c;"));
|
||||||
|
}
|
||||||
|
|
||||||
void compileLimits() {
|
void compileLimits() {
|
||||||
const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n"
|
const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n"
|
||||||
"#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n"
|
"#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n"
|
||||||
|
|
Loading…
Reference in New Issue