Remove Tokenizer::simplifyNull()

This commit is contained in:
Daniel Marjamäki 2016-10-18 21:44:02 +02:00
parent 9cea2d6dfa
commit efa3aba32a
10 changed files with 47 additions and 67 deletions

View File

@ -83,6 +83,15 @@ std::string astCanonicalType(const Token *expr)
return "";
}
static bool match(const Token *tok, const std::string &rhs)
{
if (tok->str() == rhs)
return true;
if (tok->isName() && !tok->varId() && tok->values.size() == 1U && tok->values.front().isKnown() && MathLib::toString(tok->values.front().intvalue) == rhs)
return true;
return false;
}
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
{
if (!tok)
@ -90,7 +99,7 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
const Token *ret = nullptr;
if (tok->isComparisonOp()) {
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {
if (tok->astOperand1() && match(tok->astOperand1(), rhs)) {
// Invert comparator
std::string s = tok->str();
if (s[0] == '>')
@ -100,7 +109,7 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
if (s == comp) {
ret = tok->astOperand2();
}
} else if (tok->str() == comp && tok->astOperand2() && tok->astOperand2()->str() == rhs) {
} else if (tok->str() == comp && tok->astOperand2() && match(tok->astOperand2(), rhs)) {
ret = tok->astOperand1();
}
} else if (comp == "!=" && rhs == std::string("0")) {

View File

@ -983,6 +983,13 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
variables.write(varid1, tok);
} else if (varid1 && Token::Match(tok, "%varid% .", varid1)) {
variables.use(varid1, tok);
} else if (var &&
var->_type == Variables::pointer &&
Token::Match(tok, "%name% ;") &&
tok->varId() == 0 &&
tok->hasKnownIntValue() &&
tok->values.front().intvalue == 0) {
variables.use(varid1, tok);
} else {
variables.write(varid1, tok);
}

View File

@ -748,6 +748,10 @@ public:
/** Values of token */
std::list<ValueFlow::Value> values;
bool hasKnownIntValue() const {
return values.size() == 1U && values.front().isKnown() && values.front().tokvalue == nullptr;
}
const ValueFlow::Value * getValue(const MathLib::bigint val) const {
std::list<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it) {

View File

@ -1889,26 +1889,6 @@ void Tokenizer::combineStringAndCharLiterals()
}
}
void Tokenizer::simplifyNull()
{
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->str() == "NULL" && (!Token::Match(tok->previous(), "[(,] NULL [,)]") || tok->strAt(-2) == "="))
tok->str("0");
else if (tok->str() == "__null") {
tok->originalName(tok->str());
tok->str("0");
}
}
// nullptr..
if (isCPP() && _settings->standards.cpp == Standards::CPP11) {
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (tok->str() == "nullptr")
tok->str("0");
}
}
}
void Tokenizer::concatenateNegativeNumberAndAnyPositive()
{
for (Token *tok = list.front(); tok; tok = tok->next()) {
@ -3362,9 +3342,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// Simplify the C alternative tokens (and, or, etc.)
simplifyCAlternativeTokens();
// replace 'NULL' and similar '0'-defined macros with '0'
simplifyNull();
// replace 'sin(0)' to '0' and other similar math expressions
simplifyMathExpressions();

View File

@ -468,8 +468,6 @@ public:
void combineStringAndCharLiterals();
void simplifyNull();
void concatenateNegativeNumberAndAnyPositive();
void simplifyExternC();

View File

@ -604,7 +604,7 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value)
// Handle various constants..
static Token * valueFlowSetConstantValue(const Token *tok, const Settings *settings)
static Token * valueFlowSetConstantValue(const Token *tok, const Settings *settings, bool cpp)
{
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
ValueFlow::Value value(MathLib::toLongNumber(tok->str()));
@ -614,6 +614,10 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
ValueFlow::Value value(tok->enumerator()->value);
value.setKnown();
setTokenValue(const_cast<Token *>(tok), value);
} else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
ValueFlow::Value value(0);
value.setKnown();
setTokenValue(const_cast<Token *>(tok), value);
} else if (Token::simpleMatch(tok, "sizeof (") && tok->tokAt(2)) {
const Token *tok2 = tok->tokAt(2);
if (tok2->enumerator() && tok2->enumerator()->scope) {
@ -655,7 +659,7 @@ static Token * valueFlowSetConstantValue(const Token *tok, const Settings *setti
static void valueFlowNumber(TokenList *tokenlist)
{
for (Token *tok = tokenlist->front(); tok;) {
tok = valueFlowSetConstantValue(tok, tokenlist->getSettings());
tok = valueFlowSetConstantValue(tok, tokenlist->getSettings(), tokenlist->isCPP());
}
if (tokenlist->isCPP()) {
@ -983,12 +987,12 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, SymbolDatabase *symbo
MathLib::bigint num = 0;
const Token *vartok = nullptr;
if (tok->isComparisonOp() && tok->astOperand1() && tok->astOperand2()) {
if (tok->astOperand1()->isName() && tok->astOperand2()->isNumber()) {
if (tok->astOperand1()->isName() && tok->astOperand2()->hasKnownIntValue()) {
vartok = tok->astOperand1();
num = MathLib::toLongNumber(tok->astOperand2()->str());
} else if (tok->astOperand1()->isNumber() && tok->astOperand2()->isName()) {
num = tok->astOperand2()->values.front().intvalue;
} else if (tok->astOperand1()->hasKnownIntValue() && tok->astOperand2()->isName()) {
vartok = tok->astOperand2();
num = MathLib::toLongNumber(tok->astOperand1()->str());
num = tok->astOperand1()->values.front().intvalue;
} else {
continue;
}
@ -1708,7 +1712,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
if (Token::Match(tok, "==|!=|>=|<=")) {
if (!tok->astOperand1() || !tok->astOperand2())
continue;
if (tok->astOperand1()->isNumber()) {
if (tok->astOperand1()->hasKnownIntValue()) {
numtok = tok->astOperand1();
vartok = tok->astOperand2();
} else {
@ -1717,7 +1721,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
}
if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2())
vartok = vartok->astOperand1();
if (!vartok->isName() || !numtok->isNumber() || !MathLib::isInt(numtok->str()))
if (!vartok->isName() || !numtok->hasKnownIntValue())
continue;
} else if (tok->str() == "!") {
vartok = tok->astOperand1();
@ -1742,7 +1746,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symbol
if (!var || !(var->isLocal() || var->isArgument()))
continue;
std::list<ValueFlow::Value> values;
values.push_back(ValueFlow::Value(tok, numtok ? MathLib::toLongNumber(numtok->str()) : 0LL));
values.push_back(ValueFlow::Value(tok, numtok ? numtok->values.front().intvalue : 0LL));
if (Token::Match(tok->astParent(), "%oror%|&&")) {
Token *parent = const_cast<Token*>(tok->astParent());
@ -2549,7 +2553,7 @@ const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(const Token *expr, c
if (expr && expr->values.empty()) {
valueFlowConstantFoldAST(expr->astOperand1(), settings);
valueFlowConstantFoldAST(expr->astOperand2(), settings);
valueFlowSetConstantValue(expr, settings);
valueFlowSetConstantValue(expr, settings, true /* TODO: this is a guess */);
}
return expr && expr->values.size() == 1U && expr->values.front().isKnown() ? &expr->values.front() : nullptr;
}

View File

@ -1669,7 +1669,7 @@ private:
" return;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (warning) Either the condition 'p==NULL' is redundant or there is possible null pointer dereference: p.\n", errout.str());
// check, and use
check("void f(struct X *p, int x) {\n"
@ -1689,7 +1689,7 @@ private:
ASSERT_EQUALS("", errout.str());
check(code, true); // inconclusive
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'fred==0' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'fred==NULL' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
}
check("void f(char *s) {\n" // #3358

View File

@ -1592,7 +1592,7 @@ private:
"{ "
"FILE * f ; "
"f = fopen ( \"foo\" , \"r\" ) ; "
"if ( f == 0 ) "
"if ( f == NULL ) "
"{ "
"return -1 ; "
"} "
@ -1669,7 +1669,7 @@ private:
ASSERT_EQUALS("char * s ; do { s = new char [ 10 ] ; } while ( ! s ) ;",
tok("char *s; do { } while (0 == (s=new char[10]));"));
// #4911
ASSERT_EQUALS("; do { current = f ( ) ; } while ( ( current ) != 0 ) ;", simplifyIfAndWhileAssign(";do { } while((current=f()) != NULL);"));
ASSERT_EQUALS("; do { current = f ( ) ; } while ( ( current ) != NULL ) ;", simplifyIfAndWhileAssign(";do { } while((current=f()) != NULL);"));
}
void not1() {

View File

@ -1707,7 +1707,7 @@ private:
{
const char code[] = "typedef int RexxFunctionHandler();\n"
"RexxFunctionHandler *(efuncs[]) = { NULL, NULL };";
const char expected[] = "int ( * ( efuncs [ ] ) ) ( ) = { 0 , 0 } ;";
const char expected[] = "int ( * ( efuncs [ ] ) ) ( ) = { NULL , NULL } ;";
ASSERT_EQUALS(expected, tok(code));
ASSERT_EQUALS("", errout.str());
}

View File

@ -241,7 +241,6 @@ private:
TEST_CASE(simplify_constants4);
TEST_CASE(simplify_constants5);
TEST_CASE(simplify_constants6); // Ticket #5625: Ternary operator as template parameter
TEST_CASE(simplifyNull);
TEST_CASE(simplifyMulAndParens); // Ticket #2784 + #3184
TEST_CASE(simplifyStructDecl);
@ -2675,7 +2674,7 @@ private:
" nr = (last = list->prev)->nr;\n" // <- don't replace "last" with 0
"}\n";
const char expected[] = "void f ( struct ABC * list ) {\n"
"struct ABC * last ; last = 0 ;\n"
"struct ABC * last ; last = NULL ;\n"
"nr = ( last = list . prev ) . nr ;\n"
"}";
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true));
@ -3394,24 +3393,6 @@ private:
}
}
void simplifyNull() {
{
const char code[] =
"int * p = NULL;\n"
"int * q = __null;\n";
const char expected[] =
"int * p ; p = 0 ;\nint * q ; q = 0 ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code,true));
}
ASSERT_EQUALS("( a == nullptr )", tokenizeAndStringify("(a==nullptr)", false, false, Settings::Native, "test.c"));
ASSERT_EQUALS("( a == 0 )", tokenizeAndStringify("(a==nullptr)", false, false, Settings::Native, "test.cpp"));
ASSERT_EQUALS("if ( p == 0 )", tokenizeAndStringify("if (p==NULL)"));
ASSERT_EQUALS("f ( NULL ) ;", tokenizeAndStringify("f(NULL);"));
ASSERT_EQUALS("char * i ; i = 0 ;", tokenizeAndStringify("char* i = (NULL);"));
}
void simplifyMulAndParens() {
// (error) Resource leak
const char code[] = "void f() {"
@ -3482,19 +3463,19 @@ private:
// ticket #346
const char code1[] = "void *p = NULL;";
const char res1[] = "void * p ; p = 0 ;";
const char res1[] = "void * p ; p = NULL ;";
ASSERT_EQUALS(res1, tokenizeAndStringify(code1));
const char code2[] = "const void *p = NULL;";
const char res2[] = "const void * p ; p = 0 ;";
const char res2[] = "const void * p ; p = NULL ;";
ASSERT_EQUALS(res2, tokenizeAndStringify(code2));
const char code3[] = "void * const p = NULL;";
const char res3[] = "void * const p ; p = 0 ;";
const char res3[] = "void * const p ; p = NULL ;";
ASSERT_EQUALS(res3, tokenizeAndStringify(code3));
const char code4[] = "const void * const p = NULL;";
const char res4[] = "const void * const p ; p = 0 ;";
const char res4[] = "const void * const p ; p = NULL ;";
ASSERT_EQUALS(res4, tokenizeAndStringify(code4));
}
@ -3562,7 +3543,7 @@ private:
// ticket #3927
const char code3[] = "union xy *p = NULL;";
ASSERT_EQUALS("union xy * p ; p = 0 ;", tokenizeAndStringify(code3));
ASSERT_EQUALS("union xy * p ; p = NULL ;", tokenizeAndStringify(code3));
}
void vardecl_par() {