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];
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
// ? operator where lhs is arithmetical expression
|
// ? 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;
|
continue;
|
||||||
|
|
||||||
// Is code clarified by parentheses already?
|
// Is code clarified by parentheses already?
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <stack>
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Register this check class (by creating a static instance of it)
|
// 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()
|
void CheckSizeof::sizeofCalculation()
|
||||||
{
|
{
|
||||||
|
@ -267,7 +227,7 @@ void CheckSizeof::sizeofCalculation()
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "sizeof (")) {
|
if (Token::simpleMatch(tok, "sizeof (")) {
|
||||||
const Token *argument = tok->next()->astOperand2();
|
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());
|
sizeofCalculationError(argument, argument->isExpandedMacro());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
Token::Token(Token **t) :
|
Token::Token(Token **t) :
|
||||||
tokensBack(t),
|
tokensBack(t),
|
||||||
|
@ -1143,6 +1144,42 @@ void Token::astOperand2(Token *tok)
|
||||||
_astOperand2 = 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
|
void Token::printAst() const
|
||||||
{
|
{
|
||||||
bool title = false;
|
bool title = false;
|
||||||
|
|
|
@ -672,6 +672,15 @@ public:
|
||||||
return ret;
|
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() {
|
void clearAst() {
|
||||||
_astOperand1 = _astOperand2 = _astParent = NULL;
|
_astOperand1 = _astOperand2 = _astParent = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4174,6 +4174,9 @@ private:
|
||||||
" return shift < sizeof(int64_t)*8 ? 1 : 2;\n"
|
" return shift < sizeof(int64_t)*8 ? 1 : 2;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() { a = *p ? 1 : 2; }");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void clarifyStatement() {
|
void clarifyStatement() {
|
||||||
|
|
Loading…
Reference in New Issue