Fixed #3964 (False positive: Expressions in array declarations are not simplified 'char mac[17+1];')
This commit is contained in:
parent
a243983242
commit
9ffc7f4c2d
|
@ -705,6 +705,74 @@ static bool isLowerEqualThanMulDiv(const Token* lower)
|
|||
return isLowerThanMulDiv(lower) || Token::Match(lower, "[*/%]");
|
||||
}
|
||||
|
||||
|
||||
bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
|
||||
{
|
||||
bool ret = false;
|
||||
// (1-2)
|
||||
while (tok->tokAt(4) && tok->next()->isNumber() && tok->tokAt(3)->isNumber()) { // %any% %num% %any% %num% %any%
|
||||
const Token* op = tok->tokAt(2);
|
||||
const Token* after = tok->tokAt(4);
|
||||
if (Token::Match(tok, "* %num% /") && tok->next()->str() == MathLib::multiply(tok->strAt(3), MathLib::divide(tok->next()->str(), tok->strAt(3)))) {
|
||||
// Division where result is a whole number
|
||||
} else if (!((op->str() == "*" && (isLowerThanMulDiv(tok) || tok->str() == "*") && isLowerEqualThanMulDiv(after)) || // associative
|
||||
(Token::Match(op, "[/%]") && isLowerThanMulDiv(tok) && isLowerEqualThanMulDiv(after)) || // NOT associative
|
||||
(Token::Match(op, "[+-]") && isLowerThanMulDiv(tok) && isLowerThanMulDiv(after)) || // Only partially (+) associative, but handled later
|
||||
(Token::Match(op, ">>|<<") && isLowerThanShift(tok) && isLowerThanPlusMinus(after)) || // NOT associative
|
||||
(op->str() == "&" && isLowerThanShift(tok) && isLowerThanShift(after)) || // associative
|
||||
(op->str() == "^" && isLowerThanAnd(tok) && isLowerThanAnd(after)) || // associative
|
||||
(op->str() == "|" && isLowerThanXor(tok) && isLowerThanXor(after)))) // associative
|
||||
break;
|
||||
|
||||
tok = tok->next();
|
||||
|
||||
// Don't simplify "%num% / 0"
|
||||
if (Token::Match(op, "[/%] 0"))
|
||||
continue;
|
||||
|
||||
// Integer operations
|
||||
if (Token::Match(op, ">>|<<|&|^|%or%")) {
|
||||
const char cop = op->str()[0];
|
||||
const MathLib::bigint leftInt(MathLib::toLongNumber(tok->str()));
|
||||
const MathLib::bigint rightInt(MathLib::toLongNumber(tok->strAt(2)));
|
||||
std::string result;
|
||||
|
||||
if (cop == '&' || cop == '|' || cop == '^')
|
||||
result = MathLib::calculate(tok->str(), tok->strAt(2), cop);
|
||||
else if (cop == '<') {
|
||||
if (tok->previous()->str() != "<<") // Ensure that its not a shift operator as used for streams
|
||||
result = MathLib::toString<MathLib::bigint>(leftInt << rightInt);
|
||||
} else
|
||||
result = MathLib::toString<MathLib::bigint>(leftInt >> rightInt);
|
||||
|
||||
if (!result.empty()) {
|
||||
ret = true;
|
||||
tok->str(result);
|
||||
tok->deleteNext(2);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
else if (Token::Match(tok->previous(), "- %num% - %num%"))
|
||||
tok->str(MathLib::add(tok->str(), tok->strAt(2)));
|
||||
else if (Token::Match(tok->previous(), "- %num% + %num%"))
|
||||
tok->str(MathLib::subtract(tok->str(), tok->strAt(2)));
|
||||
else {
|
||||
try {
|
||||
tok->str(MathLib::calculate(tok->str(), tok->strAt(2), op->str()[0]));
|
||||
} catch (InternalError &e) {
|
||||
e.token = tok;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
tok->deleteNext(2);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO: This is not the correct class for simplifyCalculations(), so it
|
||||
// should be moved away.
|
||||
bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
|
||||
|
@ -882,67 +950,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
|
|||
}
|
||||
|
||||
else {
|
||||
// (1-2)
|
||||
while (tok->tokAt(4) && tok->next()->isNumber() && tok->tokAt(3)->isNumber()) { // %any% %num% %any% %num% %any%
|
||||
const Token* op = tok->tokAt(2);
|
||||
const Token* after = tok->tokAt(4);
|
||||
if (Token::Match(tok, "* %num% /") && tok->next()->str() == MathLib::multiply(tok->strAt(3), MathLib::divide(tok->next()->str(), tok->strAt(3)))) {
|
||||
// Division where result is a whole number
|
||||
} else if (!((op->str() == "*" && (isLowerThanMulDiv(tok) || tok->str() == "*") && isLowerEqualThanMulDiv(after)) || // associative
|
||||
(Token::Match(op, "[/%]") && isLowerThanMulDiv(tok) && isLowerEqualThanMulDiv(after)) || // NOT associative
|
||||
(Token::Match(op, "[+-]") && isLowerThanMulDiv(tok) && isLowerThanMulDiv(after)) || // Only partially (+) associative, but handled later
|
||||
(Token::Match(op, ">>|<<") && isLowerThanShift(tok) && isLowerThanPlusMinus(after)) || // NOT associative
|
||||
(op->str() == "&" && isLowerThanShift(tok) && isLowerThanShift(after)) || // associative
|
||||
(op->str() == "^" && isLowerThanAnd(tok) && isLowerThanAnd(after)) || // associative
|
||||
(op->str() == "|" && isLowerThanXor(tok) && isLowerThanXor(after)))) // associative
|
||||
break;
|
||||
|
||||
tok = tok->next();
|
||||
|
||||
// Don't simplify "%num% / 0"
|
||||
if (Token::Match(op, "[/%] 0"))
|
||||
continue;
|
||||
|
||||
// Integer operations
|
||||
if (Token::Match(op, ">>|<<|&|^|%or%")) {
|
||||
const char cop = op->str()[0];
|
||||
const MathLib::bigint leftInt(MathLib::toLongNumber(tok->str()));
|
||||
const MathLib::bigint rightInt(MathLib::toLongNumber(tok->strAt(2)));
|
||||
std::string result;
|
||||
|
||||
if (cop == '&' || cop == '|' || cop == '^')
|
||||
result = MathLib::calculate(tok->str(), tok->strAt(2), cop);
|
||||
else if (cop == '<') {
|
||||
if (tok->previous()->str() != "<<") // Ensure that its not a shift operator as used for streams
|
||||
result = MathLib::toString<MathLib::bigint>(leftInt << rightInt);
|
||||
} else
|
||||
result = MathLib::toString<MathLib::bigint>(leftInt >> rightInt);
|
||||
|
||||
if (!result.empty()) {
|
||||
ret = true;
|
||||
tok->str(result);
|
||||
tok->deleteNext(2);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
else if (Token::Match(tok->previous(), "- %num% - %num%"))
|
||||
tok->str(MathLib::add(tok->str(), tok->strAt(2)));
|
||||
else if (Token::Match(tok->previous(), "- %num% + %num%"))
|
||||
tok->str(MathLib::subtract(tok->str(), tok->strAt(2)));
|
||||
else {
|
||||
try {
|
||||
tok->str(MathLib::calculate(tok->str(), tok->strAt(2), op->str()[0]));
|
||||
} catch (InternalError &e) {
|
||||
e.token = tok;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
tok->deleteNext(2);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
ret |= simplifyNumericCalculations(tok);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
|
|
@ -151,6 +151,15 @@ public:
|
|||
|
||||
/**
|
||||
* Simplify constant calculations such as "1+2" => "3"
|
||||
* @param tok start token
|
||||
* @return true if modifications to token-list are done.
|
||||
* false if no modifications are done.
|
||||
*/
|
||||
static bool simplifyNumericCalculations(Token *tok);
|
||||
|
||||
/**
|
||||
* Simplify constant calculations such as "1+2" => "3".
|
||||
* This also perform simple cleanup of parantheses etc.
|
||||
* @param _tokens start token
|
||||
* @return true if modifications to token-list are done.
|
||||
* false if no modifications are done.
|
||||
|
|
|
@ -1624,6 +1624,12 @@ bool Tokenizer::tokenize(std::istream &code,
|
|||
// combine "- %num%"
|
||||
concatenateNegativeNumber();
|
||||
|
||||
// simplify simple calculations
|
||||
for (Token *tok = list.front() ? list.front()->next() : NULL; tok; tok = tok->next()) {
|
||||
if (tok->isNumber())
|
||||
TemplateSimplifier::simplifyNumericCalculations(tok->previous());
|
||||
}
|
||||
|
||||
// remove extern "C" and extern "C" {}
|
||||
if (isCPP())
|
||||
simplifyExternC();
|
||||
|
|
|
@ -4513,7 +4513,7 @@ private:
|
|||
std::istringstream istr(code);
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
|
||||
ASSERT_EQUALS("void f ( ) { double a ; a = 4.2 ; float b ; b = 4.2f ; double c ; c = 4.2e+10 ; double d ; d = 4.2e-10 ; int e ; e = 4 + 2 ; }", tokenizer.tokens()->stringifyList(0, false));
|
||||
ASSERT_EQUALS("void f ( ) { double a ; a = 4.2 ; float b ; b = 4.2f ; double c ; c = 4.2e+10 ; double d ; d = 4.2e-10 ; int e ; e = 6 ; }", tokenizer.tokens()->stringifyList(0, false));
|
||||
}
|
||||
|
||||
void tokenize_strings() {
|
||||
|
@ -4719,7 +4719,7 @@ private:
|
|||
void vardecl_template_1() {
|
||||
// ticket #1046
|
||||
const char code1[] = "b<(1<<24),10,24> u, v;";
|
||||
const char res1[] = "b < ( 1 << 24 ) , 10 , 24 > u ; b < ( 1 << 24 ) , 10 , 24 > v ;";
|
||||
const char res1[] = "b < ( 16777216 ) , 10 , 24 > u ; b < ( 16777216 ) , 10 , 24 > v ;";
|
||||
ASSERT_EQUALS(res1, tokenizeAndStringify(code1));
|
||||
// ticket #3571 (segmentation fault)
|
||||
tokenizeAndStringify("template <int i = (3>4) > class X4 {};");
|
||||
|
@ -6468,6 +6468,9 @@ private:
|
|||
// ticket #3723 - Simplify condition (0 && a < 123)
|
||||
ASSERT_EQUALS("( 0 )",
|
||||
tokenizeAndStringify("( 0 && a < 123 )", true));
|
||||
|
||||
// ticket #3964 - simplify numeric calculations in tokenization
|
||||
ASSERT_EQUALS("char a [ 10 ] ;", tokenizeAndStringify("char a[9+1];"));
|
||||
}
|
||||
|
||||
void simplifyCompoundAssignment() {
|
||||
|
|
Loading…
Reference in New Issue