clarify calculation: Fixed FP for 'a = (*p ? 1 : 2)'
This commit is contained in:
parent
4a46029ba6
commit
4b72f01e99
|
@ -180,7 +180,7 @@ void CheckOther::clarifyCalculation()
|
|||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
// ? operator where lhs is arithmetical expression
|
||||
if (tok->str() != "?" || !tok->astOperand1() || !tok->astOperand1()->isArithmeticalOp())
|
||||
if (tok->str() != "?" || !tok->astOperand1() || !tok->astOperand1()->isArithmeticalOp() || !tok->astOperand1()->isCalculation())
|
||||
continue;
|
||||
|
||||
// Is code clarified by parentheses already?
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "symboldatabase.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <stack>
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Register this check class (by creating a static instance of it)
|
||||
|
@ -219,45 +218,6 @@ void CheckSizeof::sizeofsizeofError(const Token *tok)
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isCalculation(const Token *op)
|
||||
{
|
||||
if (!op)
|
||||
return false;
|
||||
|
||||
if (!Token::Match(op, "%cop%|++|--"))
|
||||
return false;
|
||||
|
||||
if (Token::Match(op, "*|&")) {
|
||||
// dereference or address-of?
|
||||
if (!op->astOperand2())
|
||||
return false;
|
||||
|
||||
if (op->astOperand2()->str() == "[")
|
||||
return false;
|
||||
|
||||
// type specification?
|
||||
std::stack<const Token *> operands;
|
||||
operands.push(op);
|
||||
while (!operands.empty()) {
|
||||
const Token *item = operands.top();
|
||||
operands.pop();
|
||||
if (item->isNumber() || item->varId() > 0)
|
||||
return true;
|
||||
if (item->astOperand1())
|
||||
operands.push(item->astOperand1());
|
||||
if (item->astOperand2())
|
||||
operands.push(item->astOperand2());
|
||||
else if (Token::Match(item, "*|&"))
|
||||
return false;
|
||||
}
|
||||
|
||||
// type specification => return false
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CheckSizeof::sizeofCalculation()
|
||||
{
|
||||
|
@ -267,7 +227,7 @@ void CheckSizeof::sizeofCalculation()
|
|||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "sizeof (")) {
|
||||
const Token *argument = tok->next()->astOperand2();
|
||||
if (isCalculation(argument) && (!argument->isExpandedMacro() || _settings->inconclusive))
|
||||
if (argument && argument->isCalculation() && (!argument->isExpandedMacro() || _settings->inconclusive))
|
||||
sizeofCalculationError(argument, argument->isExpandedMacro());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <cctype>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
Token::Token(Token **t) :
|
||||
tokensBack(t),
|
||||
|
@ -1143,6 +1144,42 @@ void Token::astOperand2(Token *tok)
|
|||
_astOperand2 = tok;
|
||||
}
|
||||
|
||||
bool Token::isCalculation() const
|
||||
{
|
||||
if (!Token::Match(this, "%cop%|++|--"))
|
||||
return false;
|
||||
|
||||
if (Token::Match(this, "*|&")) {
|
||||
// dereference or address-of?
|
||||
if (!this->astOperand2())
|
||||
return false;
|
||||
|
||||
if (this->astOperand2()->str() == "[")
|
||||
return false;
|
||||
|
||||
// type specification?
|
||||
std::stack<const Token *> operands;
|
||||
operands.push(this);
|
||||
while (!operands.empty()) {
|
||||
const Token *op = operands.top();
|
||||
operands.pop();
|
||||
if (op->isNumber() || op->varId() > 0)
|
||||
return true;
|
||||
if (op->astOperand1())
|
||||
operands.push(op->astOperand1());
|
||||
if (op->astOperand2())
|
||||
operands.push(op->astOperand2());
|
||||
else if (Token::Match(op, "*|&"))
|
||||
return false;
|
||||
}
|
||||
|
||||
// type specification => return false
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Token::printAst() const
|
||||
{
|
||||
bool title = false;
|
||||
|
|
|
@ -672,6 +672,15 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is current token a calculation? Only true for operands.
|
||||
* For '*' and '&' tokens it is looked up if this is a
|
||||
* dereference or address-of. A dereference or address-of is not
|
||||
* counted as a calculation.
|
||||
* @return returns true if current token is a calculation
|
||||
*/
|
||||
bool isCalculation() const;
|
||||
|
||||
void clearAst() {
|
||||
_astOperand1 = _astOperand2 = _astParent = NULL;
|
||||
}
|
||||
|
|
|
@ -4174,6 +4174,9 @@ private:
|
|||
" return shift < sizeof(int64_t)*8 ? 1 : 2;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f() { a = *p ? 1 : 2; }");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void clarifyStatement() {
|
||||
|
|
Loading…
Reference in New Issue