Moved functions to astutils
This commit is contained in:
parent
b8bb939e32
commit
e598b07a6d
10
Makefile
10
Makefile
|
@ -283,7 +283,7 @@ endif
|
|||
|
||||
###### Build
|
||||
|
||||
$(SRCDIR)/astutils.o: lib/astutils.cpp lib/cxx11emu.h lib/astutils.h lib/symboldatabase.h lib/config.h lib/token.h lib/valueflow.h lib/mathlib.h lib/utils.h
|
||||
$(SRCDIR)/astutils.o: lib/astutils.cpp lib/cxx11emu.h lib/astutils.h lib/symboldatabase.h lib/config.h lib/token.h lib/valueflow.h lib/mathlib.h lib/utils.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/astutils.o $(SRCDIR)/astutils.cpp
|
||||
|
||||
$(SRCDIR)/check.o: lib/check.cpp lib/cxx11emu.h lib/check.h lib/config.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h
|
||||
|
@ -310,7 +310,7 @@ $(SRCDIR)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp lib/cxx11emu.h lib/ch
|
|||
$(SRCDIR)/checkclass.o: lib/checkclass.cpp lib/cxx11emu.h lib/checkclass.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checkclass.o $(SRCDIR)/checkclass.cpp
|
||||
|
||||
$(SRCDIR)/checkcondition.o: lib/checkcondition.cpp lib/cxx11emu.h lib/checkcondition.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/astutils.h lib/symboldatabase.h lib/utils.h lib/checkother.h
|
||||
$(SRCDIR)/checkcondition.o: lib/checkcondition.cpp lib/cxx11emu.h lib/checkcondition.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/astutils.h lib/checkother.h lib/symboldatabase.h lib/utils.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checkcondition.o $(SRCDIR)/checkcondition.cpp
|
||||
|
||||
$(SRCDIR)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/cxx11emu.h lib/checkexceptionsafety.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h
|
||||
|
@ -322,10 +322,10 @@ $(SRCDIR)/checkinternal.o: lib/checkinternal.cpp lib/cxx11emu.h lib/checkinterna
|
|||
$(SRCDIR)/checkio.o: lib/checkio.cpp lib/cxx11emu.h lib/checkio.h lib/check.h lib/config.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checkio.o $(SRCDIR)/checkio.cpp
|
||||
|
||||
$(SRCDIR)/checkleakautovar.o: lib/checkleakautovar.cpp lib/cxx11emu.h lib/checkleakautovar.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/checkmemoryleak.h lib/symboldatabase.h lib/utils.h
|
||||
$(SRCDIR)/checkleakautovar.o: lib/checkleakautovar.cpp lib/cxx11emu.h lib/checkleakautovar.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/checkmemoryleak.h lib/symboldatabase.h lib/utils.h lib/astutils.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checkleakautovar.o $(SRCDIR)/checkleakautovar.cpp
|
||||
|
||||
$(SRCDIR)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/cxx11emu.h lib/checkmemoryleak.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h
|
||||
$(SRCDIR)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/cxx11emu.h lib/checkmemoryleak.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h lib/astutils.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checkmemoryleak.o $(SRCDIR)/checkmemoryleak.cpp
|
||||
|
||||
$(SRCDIR)/checknonreentrantfunctions.o: lib/checknonreentrantfunctions.cpp lib/cxx11emu.h lib/checknonreentrantfunctions.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h
|
||||
|
@ -355,7 +355,7 @@ $(SRCDIR)/checkstring.o: lib/checkstring.cpp lib/cxx11emu.h lib/checkstring.h li
|
|||
$(SRCDIR)/checktype.o: lib/checktype.cpp lib/cxx11emu.h lib/checktype.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checktype.o $(SRCDIR)/checktype.cpp
|
||||
|
||||
$(SRCDIR)/checkuninitvar.o: lib/checkuninitvar.cpp lib/cxx11emu.h lib/checkuninitvar.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/checknullpointer.h lib/symboldatabase.h lib/utils.h
|
||||
$(SRCDIR)/checkuninitvar.o: lib/checkuninitvar.cpp lib/cxx11emu.h lib/checkuninitvar.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/astutils.h lib/checknullpointer.h lib/symboldatabase.h lib/utils.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -std=c++0x -c -o $(SRCDIR)/checkuninitvar.o $(SRCDIR)/checkuninitvar.cpp
|
||||
|
||||
$(SRCDIR)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp lib/cxx11emu.h lib/checkunusedfunctions.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/timer.h lib/symboldatabase.h lib/utils.h
|
||||
|
|
232
lib/astutils.cpp
232
lib/astutils.cpp
|
@ -19,6 +19,36 @@
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
#include "astutils.h"
|
||||
#include "symboldatabase.h"
|
||||
#include "token.h"
|
||||
#include "tokenize.h"
|
||||
#include <set>
|
||||
|
||||
static bool isChar(const Variable* var)
|
||||
{
|
||||
return (var && !var->isPointer() && !var->isArray() && var->typeStartToken()->str() == "char");
|
||||
}
|
||||
|
||||
static bool isSignedChar(const Variable* var)
|
||||
{
|
||||
return (isChar(var) && !var->typeStartToken()->isUnsigned());
|
||||
}
|
||||
|
||||
bool astIsSignedChar(const Token *tok)
|
||||
{
|
||||
if (!tok)
|
||||
return false;
|
||||
if (tok->str() == "*" && tok->astOperand1() && !tok->astOperand2()) {
|
||||
const Variable *var = tok->astOperand1()->variable();
|
||||
if (!var || !var->isPointer())
|
||||
return false;
|
||||
const Token *type = var->typeStartToken();
|
||||
while (type && type->str() == "const")
|
||||
type = type->next();
|
||||
return (type && type->str() == "char" && !type->isUnsigned());
|
||||
}
|
||||
return isSignedChar(tok->variable());
|
||||
}
|
||||
|
||||
bool astIsIntegral(const Token *tok, bool unknown)
|
||||
{
|
||||
|
@ -100,3 +130,205 @@ bool astIsFloat(const Token *tok, bool unknown)
|
|||
|
||||
return unknown;
|
||||
}
|
||||
|
||||
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
|
||||
{
|
||||
if (!tok)
|
||||
return nullptr;
|
||||
|
||||
const Token *ret = nullptr;
|
||||
if (tok->isComparisonOp()) {
|
||||
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {
|
||||
// Invert comparator
|
||||
std::string s = tok->str();
|
||||
if (s[0] == '>')
|
||||
s[0] = '<';
|
||||
else if (s[0] == '<')
|
||||
s[0] = '>';
|
||||
if (s == comp) {
|
||||
ret = tok->astOperand2();
|
||||
}
|
||||
} else if (tok->str() == comp && tok->astOperand2() && tok->astOperand2()->str() == rhs) {
|
||||
ret = tok->astOperand1();
|
||||
}
|
||||
} else if (comp == "!=" && rhs == std::string("0")) {
|
||||
ret = tok;
|
||||
} else if (comp == "==" && rhs == std::string("0")) {
|
||||
if (tok->str() == "!")
|
||||
ret = tok->astOperand1();
|
||||
}
|
||||
while (ret && ret->str() == ".")
|
||||
ret = ret->astOperand2();
|
||||
if (ret && ret->varId() == 0U)
|
||||
ret = nullptr;
|
||||
if (vartok)
|
||||
*vartok = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isSameExpression(bool cpp, const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions)
|
||||
{
|
||||
if (tok1 == nullptr && tok2 == nullptr)
|
||||
return true;
|
||||
if (tok1 == nullptr || tok2 == nullptr)
|
||||
return false;
|
||||
if (cpp) {
|
||||
if (tok1->str() == "." && tok1->astOperand1() && tok1->astOperand1()->str() == "this")
|
||||
tok1 = tok1->astOperand2();
|
||||
if (tok2->str() == "." && tok2->astOperand1() && tok2->astOperand1()->str() == "this")
|
||||
tok2 = tok2->astOperand2();
|
||||
}
|
||||
if (tok1->varId() != tok2->varId() || tok1->str() != tok2->str()) {
|
||||
if ((Token::Match(tok1,"<|>") && Token::Match(tok2,"<|>")) ||
|
||||
(Token::Match(tok1,"<=|>=") && Token::Match(tok2,"<=|>="))) {
|
||||
return isSameExpression(cpp, tok1->astOperand1(), tok2->astOperand2(), constFunctions) &&
|
||||
isSameExpression(cpp, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (tok1->str() == "." && tok1->originalName() != tok2->originalName())
|
||||
return false;
|
||||
if (tok1->isExpandedMacro() || tok2->isExpandedMacro())
|
||||
return false;
|
||||
if (tok1->isName() && tok1->next()->str() == "(" && tok1->str() != "sizeof") {
|
||||
if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && constFunctions.find(tok1->str()) == constFunctions.end() && !tok1->isAttributeConst() && !tok1->isAttributePure())
|
||||
return false;
|
||||
else if (tok1->function() && !tok1->function()->isConst() && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
|
||||
return false;
|
||||
}
|
||||
// templates/casts
|
||||
if ((Token::Match(tok1, "%name% <") && tok1->next()->link()) ||
|
||||
(Token::Match(tok2, "%name% <") && tok2->next()->link())) {
|
||||
|
||||
// non-const template function that is not a dynamic_cast => return false
|
||||
if (Token::simpleMatch(tok1->next()->link(), "> (") &&
|
||||
!(tok1->function() && tok1->function()->isConst()) &&
|
||||
tok1->str() != "dynamic_cast")
|
||||
return false;
|
||||
|
||||
// some template/cast stuff.. check that the template arguments are same
|
||||
const Token *t1 = tok1->next();
|
||||
const Token *t2 = tok2->next();
|
||||
const Token *end1 = t1->link();
|
||||
const Token *end2 = t2->link();
|
||||
while (t1 && t2 && t1 != end1 && t2 != end2) {
|
||||
if (t1->str() != t2->str())
|
||||
return false;
|
||||
t1 = t1->next();
|
||||
t2 = t2->next();
|
||||
}
|
||||
if (t1 != end1 || t2 != end2)
|
||||
return false;
|
||||
}
|
||||
if (tok1->type() == Token::eIncDecOp || tok1->isAssignmentOp())
|
||||
return false;
|
||||
// bailout when we see ({..})
|
||||
if (tok1->str() == "{")
|
||||
return false;
|
||||
if (tok1->str() == "(" && tok1->previous() && !tok1->previous()->isName()) { // cast => assert that the casts are equal
|
||||
const Token *t1 = tok1->next();
|
||||
const Token *t2 = tok2->next();
|
||||
while (t1 && t2 && t1->str() == t2->str() && (t1->isName() || t1->str() == "*")) {
|
||||
t1 = t1->next();
|
||||
t2 = t2->next();
|
||||
}
|
||||
if (!t1 || !t2 || t1->str() != ")" || t2->str() != ")")
|
||||
return false;
|
||||
}
|
||||
bool noncommuative_equals =
|
||||
isSameExpression(cpp, tok1->astOperand1(), tok2->astOperand1(), constFunctions);
|
||||
noncommuative_equals = noncommuative_equals &&
|
||||
isSameExpression(cpp, tok1->astOperand2(), tok2->astOperand2(), constFunctions);
|
||||
|
||||
if (noncommuative_equals)
|
||||
return true;
|
||||
|
||||
const bool commutative = tok1->astOperand1() && tok1->astOperand2() && Token::Match(tok1, "%or%|%oror%|+|*|&|&&|^|==|!=");
|
||||
bool commuative_equals = commutative &&
|
||||
isSameExpression(cpp, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
|
||||
commuative_equals = commuative_equals &&
|
||||
isSameExpression(cpp, tok1->astOperand1(), tok2->astOperand2(), constFunctions);
|
||||
|
||||
return commuative_equals;
|
||||
}
|
||||
|
||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions)
|
||||
{
|
||||
if (!cond1 || !cond2)
|
||||
return false;
|
||||
|
||||
if (cond1->str() == "!") {
|
||||
if (cond2->str() == "!=") {
|
||||
if (cond2->astOperand1() && cond2->astOperand1()->str() == "0")
|
||||
return isSameExpression(cpp, cond1->astOperand1(), cond2->astOperand2(), constFunctions);
|
||||
if (cond2->astOperand2() && cond2->astOperand2()->str() == "0")
|
||||
return isSameExpression(cpp, cond1->astOperand1(), cond2->astOperand1(), constFunctions);
|
||||
}
|
||||
return isSameExpression(cpp, cond1->astOperand1(), cond2, constFunctions);
|
||||
}
|
||||
|
||||
if (cond2->str() == "!")
|
||||
return isOppositeCond(isNot, cpp, cond2, cond1, constFunctions);
|
||||
|
||||
if (!cond1->isComparisonOp() || !cond2->isComparisonOp())
|
||||
return false;
|
||||
|
||||
const std::string &comp1 = cond1->str();
|
||||
|
||||
// condition found .. get comparator
|
||||
std::string comp2;
|
||||
if (isSameExpression(cpp, cond1->astOperand1(), cond2->astOperand1(), constFunctions) &&
|
||||
isSameExpression(cpp, cond1->astOperand2(), cond2->astOperand2(), constFunctions)) {
|
||||
comp2 = cond2->str();
|
||||
} else if (isSameExpression(cpp, cond1->astOperand1(), cond2->astOperand2(), constFunctions) &&
|
||||
isSameExpression(cpp, cond1->astOperand2(), cond2->astOperand1(), constFunctions)) {
|
||||
comp2 = cond2->str();
|
||||
if (comp2[0] == '>')
|
||||
comp2[0] = '<';
|
||||
else if (comp2[0] == '<')
|
||||
comp2[0] = '>';
|
||||
}
|
||||
|
||||
// is condition opposite?
|
||||
return ((comp1 == "==" && comp2 == "!=") ||
|
||||
(comp1 == "!=" && comp2 == "==") ||
|
||||
(comp1 == "<" && comp2 == ">=") ||
|
||||
(comp1 == "<=" && comp2 == ">") ||
|
||||
(comp1 == ">" && comp2 == "<=") ||
|
||||
(comp1 == ">=" && comp2 == "<") ||
|
||||
(!isNot && ((comp1 == "<" && comp2 == ">") ||
|
||||
(comp1 == ">" && comp2 == "<"))));
|
||||
}
|
||||
|
||||
bool isConstExpression(const Token *tok, const std::set<std::string> &constFunctions)
|
||||
{
|
||||
if (!tok)
|
||||
return true;
|
||||
if (tok->isName() && tok->next()->str() == "(") {
|
||||
if (!tok->function() && !Token::Match(tok->previous(), ".|::") && constFunctions.find(tok->str()) == constFunctions.end())
|
||||
return false;
|
||||
else if (tok->function() && !tok->function()->isConst())
|
||||
return false;
|
||||
}
|
||||
if (tok->type() == Token::eIncDecOp)
|
||||
return false;
|
||||
// bailout when we see ({..})
|
||||
if (tok->str() == "{")
|
||||
return false;
|
||||
return isConstExpression(tok->astOperand1(),constFunctions) && isConstExpression(tok->astOperand2(),constFunctions);
|
||||
}
|
||||
|
||||
bool isWithoutSideEffects(bool cpp, const Token* tok)
|
||||
{
|
||||
if (!cpp)
|
||||
return true;
|
||||
|
||||
while (tok && tok->astOperand2() && tok->astOperand2()->str() != "(")
|
||||
tok = tok->astOperand2();
|
||||
if (tok && tok->varId()) {
|
||||
const Variable* var = tok->variable();
|
||||
return var && (!var->isClass() || var->isPointer() || var->isStlType());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,35 @@
|
|||
#define astutilsH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "symboldatabase.h"
|
||||
#include "token.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
class Token;
|
||||
class Tokenizer;
|
||||
|
||||
/** Is expression a 'signed char' if no promotion is used */
|
||||
bool astIsSignedChar(const Token *tok);
|
||||
/** Is expression of integral type? */
|
||||
bool astIsIntegral(const Token *tok, bool unknown);
|
||||
/** Is expression of floating point type? */
|
||||
bool astIsFloat(const Token *tok, bool unknown);
|
||||
|
||||
/** Is given syntax tree a variable comparison against value */
|
||||
const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
|
||||
|
||||
bool isSameExpression(bool cpp, const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions);
|
||||
|
||||
/**
|
||||
* Are two conditions opposite
|
||||
* @param isNot do you want to know if cond1 is !cond2 or if cond1 and cond2 are non-overlapping. true: cond1==!cond2 false: cond1==true => cond2==false
|
||||
* @param cpp c++ file
|
||||
* @param cond1 condition1
|
||||
* @param cond2 condition2
|
||||
*/
|
||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions);
|
||||
|
||||
bool isConstExpression(const Token *tok, const std::set<std::string> &constFunctions);
|
||||
|
||||
bool isWithoutSideEffects(bool cpp, const Token* tok);
|
||||
|
||||
#endif // astutilsH
|
||||
|
|
|
@ -301,7 +301,7 @@ bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token *
|
|||
return false;
|
||||
|
||||
// same expressions
|
||||
if (isSameExpression(_tokenizer, cond1,cond2,constFunctions))
|
||||
if (isSameExpression(_tokenizer->isCPP(), cond1,cond2,constFunctions))
|
||||
return true;
|
||||
|
||||
// bitwise overlap for example 'x&7' and 'x==1'
|
||||
|
@ -324,7 +324,7 @@ bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token *
|
|||
if (!num2->isNumber() || MathLib::isNegative(num2->str()))
|
||||
return false;
|
||||
|
||||
if (!isSameExpression(_tokenizer, expr1,expr2,constFunctions))
|
||||
if (!isSameExpression(_tokenizer->isCPP(), expr1,expr2,constFunctions))
|
||||
return false;
|
||||
|
||||
const MathLib::bigint value1 = MathLib::toLongNumber(num1->str());
|
||||
|
@ -377,54 +377,6 @@ void CheckCondition::multiConditionError(const Token *tok, unsigned int line1)
|
|||
// Detect oppositing inner and outer conditions
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool CheckCondition::isOppositeCond(bool isNot, const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions) const
|
||||
{
|
||||
if (!cond1 || !cond2)
|
||||
return false;
|
||||
|
||||
if (cond1->str() == "!") {
|
||||
if (cond2->str() == "!=") {
|
||||
if (cond2->astOperand1() && cond2->astOperand1()->str() == "0")
|
||||
return isSameExpression(_tokenizer, cond1->astOperand1(), cond2->astOperand2(), constFunctions);
|
||||
if (cond2->astOperand2() && cond2->astOperand2()->str() == "0")
|
||||
return isSameExpression(_tokenizer, cond1->astOperand1(), cond2->astOperand1(), constFunctions);
|
||||
}
|
||||
return isSameExpression(_tokenizer, cond1->astOperand1(), cond2, constFunctions);
|
||||
}
|
||||
|
||||
if (cond2->str() == "!")
|
||||
return isOppositeCond(isNot, cond2, cond1, constFunctions);
|
||||
|
||||
if (!cond1->isComparisonOp() || !cond2->isComparisonOp())
|
||||
return false;
|
||||
|
||||
const std::string &comp1 = cond1->str();
|
||||
|
||||
// condition found .. get comparator
|
||||
std::string comp2;
|
||||
if (isSameExpression(_tokenizer, cond1->astOperand1(), cond2->astOperand1(), constFunctions) &&
|
||||
isSameExpression(_tokenizer, cond1->astOperand2(), cond2->astOperand2(), constFunctions)) {
|
||||
comp2 = cond2->str();
|
||||
} else if (isSameExpression(_tokenizer, cond1->astOperand1(), cond2->astOperand2(), constFunctions) &&
|
||||
isSameExpression(_tokenizer, cond1->astOperand2(), cond2->astOperand1(), constFunctions)) {
|
||||
comp2 = cond2->str();
|
||||
if (comp2[0] == '>')
|
||||
comp2[0] = '<';
|
||||
else if (comp2[0] == '<')
|
||||
comp2[0] = '>';
|
||||
}
|
||||
|
||||
// is condition opposite?
|
||||
return ((comp1 == "==" && comp2 == "!=") ||
|
||||
(comp1 == "!=" && comp2 == "==") ||
|
||||
(comp1 == "<" && comp2 == ">=") ||
|
||||
(comp1 == "<=" && comp2 == ">") ||
|
||||
(comp1 == ">" && comp2 == "<=") ||
|
||||
(comp1 == ">=" && comp2 == "<") ||
|
||||
(!isNot && ((comp1 == "<" && comp2 == ">") ||
|
||||
(comp1 == ">" && comp2 == "<"))));
|
||||
}
|
||||
|
||||
void CheckCondition::oppositeInnerCondition()
|
||||
{
|
||||
if (!_settings->isEnabled("warning"))
|
||||
|
@ -494,7 +446,7 @@ void CheckCondition::oppositeInnerCondition()
|
|||
const Token *cond1 = scope->classDef->next()->astOperand2();
|
||||
const Token *cond2 = ifToken->next()->astOperand2();
|
||||
|
||||
if (isOppositeCond(false, cond1, cond2, _settings->library.functionpure))
|
||||
if (isOppositeCond(false, _tokenizer->isCPP(), cond1, cond2, _settings->library.functionpure))
|
||||
oppositeInnerConditionError(scope->classDef, cond2);
|
||||
}
|
||||
}
|
||||
|
@ -682,7 +634,7 @@ void CheckCondition::checkIncorrectLogicOperator()
|
|||
|
||||
// Opposite comparisons around || or && => always true or always false
|
||||
if ((tok->astOperand1()->isName() || tok->astOperand2()->isName()) &&
|
||||
isOppositeCond(true, tok->astOperand1(), tok->astOperand2(), _settings->library.functionpure)) {
|
||||
isOppositeCond(true, _tokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), _settings->library.functionpure)) {
|
||||
|
||||
const bool alwaysTrue(tok->str() == "||");
|
||||
incorrectLogicOperatorError(tok, tok->expressionString(), alwaysTrue);
|
||||
|
@ -693,7 +645,7 @@ void CheckCondition::checkIncorrectLogicOperator()
|
|||
// 'A && (!A || B)' is equivalent with 'A || B'
|
||||
if (printStyle && (tok->str() == "||") && tok->astOperand1() && tok->astOperand2() && tok->astOperand2()->str() == "&&") {
|
||||
const Token* tok2 = tok->astOperand2()->astOperand1();
|
||||
if (isOppositeCond(true, tok->astOperand1(), tok2, _settings->library.functionpure)) {
|
||||
if (isOppositeCond(true, _tokenizer->isCPP(), tok->astOperand1(), tok2, _settings->library.functionpure)) {
|
||||
redundantConditionError(tok, tok2->expressionString() + ". 'A && (!A || B)' is equivalent to 'A || B'");
|
||||
continue;
|
||||
}
|
||||
|
@ -721,9 +673,9 @@ void CheckCondition::checkIncorrectLogicOperator()
|
|||
if (!parseComparison(comp2, ¬2, &op2, &value2, &expr2))
|
||||
continue;
|
||||
|
||||
if (isSameExpression(_tokenizer, comp1, comp2, _settings->library.functionpure))
|
||||
if (isSameExpression(_tokenizer->isCPP(), comp1, comp2, _settings->library.functionpure))
|
||||
continue; // same expressions => only report that there are same expressions
|
||||
if (!isSameExpression(_tokenizer, expr1, expr2, _settings->library.functionpure))
|
||||
if (!isSameExpression(_tokenizer->isCPP(), expr1, expr2, _settings->library.functionpure))
|
||||
continue;
|
||||
|
||||
const bool isfloat = astIsFloat(expr1, true) || MathLib::isFloat(value1) || astIsFloat(expr2, true) || MathLib::isFloat(value2);
|
||||
|
|
|
@ -100,13 +100,6 @@ public:
|
|||
private:
|
||||
|
||||
bool isOverlappingCond(const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions) const;
|
||||
/**
|
||||
* Are two conditions opposite
|
||||
* @param isNot do you want to know if cond1 is !cond2 or if cond1 and cond2 are non-overlapping. true: cond1==!cond2 false: cond1==true => cond2==false
|
||||
* @param cond1 condition1
|
||||
* @param cond2 condition2
|
||||
*/
|
||||
bool isOppositeCond(bool isNot, const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions) const;
|
||||
void assignIfError(const Token *tok1, const Token *tok2, const std::string &condition, bool result);
|
||||
void mismatchingBitAndError(const Token *tok1, const MathLib::bigint num1, const Token *tok2, const MathLib::bigint num2);
|
||||
void badBitmaskCheckError(const Token *tok);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "checkmemoryleak.h" // <- CheckMemoryLeak::memoryLeak
|
||||
#include "tokenize.h"
|
||||
#include "symboldatabase.h"
|
||||
#include "astutils.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
|
@ -307,17 +308,17 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
}
|
||||
|
||||
const Token *vartok = nullptr;
|
||||
if (Token::isVariableComparison(tok3, "!=", "0", &vartok)) {
|
||||
if (astIsVariableComparison(tok3, "!=", "0", &vartok)) {
|
||||
varInfo2.erase(vartok->varId());
|
||||
if (notzero.find(vartok->varId()) != notzero.end())
|
||||
varInfo2.clear();
|
||||
} else if (Token::isVariableComparison(tok3, "==", "0", &vartok)) {
|
||||
} else if (astIsVariableComparison(tok3, "==", "0", &vartok)) {
|
||||
varInfo1.erase(vartok->varId());
|
||||
} else if (Token::isVariableComparison(tok3, "<", "0", &vartok)) {
|
||||
} else if (astIsVariableComparison(tok3, "<", "0", &vartok)) {
|
||||
varInfo1.erase(vartok->varId());
|
||||
} else if (Token::isVariableComparison(tok3, ">", "0", &vartok)) {
|
||||
} else if (astIsVariableComparison(tok3, ">", "0", &vartok)) {
|
||||
varInfo2.erase(vartok->varId());
|
||||
} else if (Token::isVariableComparison(tok3, "==", "-1", &vartok)) {
|
||||
} else if (astIsVariableComparison(tok3, "==", "-1", &vartok)) {
|
||||
varInfo1.erase(vartok->varId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "symboldatabase.h"
|
||||
#include "mathlib.h"
|
||||
#include "tokenize.h"
|
||||
#include "astutils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
@ -525,7 +526,7 @@ static bool notvar(const Token *tok, unsigned int varid)
|
|||
return notvar(tok->astOperand1(),varid) || notvar(tok->astOperand2(),varid);
|
||||
if (tok->str() == "(" && Token::Match(tok->astOperand1(), "UNLIKELY|LIKELY"))
|
||||
return notvar(tok->astOperand2(), varid);
|
||||
const Token *vartok = Token::isVariableComparison(tok, "==", "0");
|
||||
const Token *vartok = astIsVariableComparison(tok, "==", "0");
|
||||
return vartok && (vartok->varId() == varid);
|
||||
}
|
||||
|
||||
|
@ -539,7 +540,7 @@ static bool ifvar(const Token *tok, unsigned int varid, const std::string &comp,
|
|||
if (!condition || condition->str() == "&&")
|
||||
return false;
|
||||
|
||||
const Token *vartok = Token::isVariableComparison(condition, comp, rhs);
|
||||
const Token *vartok = astIsVariableComparison(condition, comp, rhs);
|
||||
return (vartok && vartok->varId() == varid);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,109 +34,6 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
bool isConstExpression(const Token *tok, const std::set<std::string> &constFunctions)
|
||||
{
|
||||
if (!tok)
|
||||
return true;
|
||||
if (tok->isName() && tok->next()->str() == "(") {
|
||||
if (!tok->function() && !Token::Match(tok->previous(), ".|::") && constFunctions.find(tok->str()) == constFunctions.end())
|
||||
return false;
|
||||
else if (tok->function() && !tok->function()->isConst())
|
||||
return false;
|
||||
}
|
||||
if (tok->type() == Token::eIncDecOp)
|
||||
return false;
|
||||
// bailout when we see ({..})
|
||||
if (tok->str() == "{")
|
||||
return false;
|
||||
return isConstExpression(tok->astOperand1(),constFunctions) && isConstExpression(tok->astOperand2(),constFunctions);
|
||||
}
|
||||
|
||||
bool isSameExpression(const Tokenizer *tokenizer, const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions)
|
||||
{
|
||||
if (tok1 == nullptr && tok2 == nullptr)
|
||||
return true;
|
||||
if (tok1 == nullptr || tok2 == nullptr)
|
||||
return false;
|
||||
if (tokenizer->isCPP()) {
|
||||
if (tok1->str() == "." && tok1->astOperand1() && tok1->astOperand1()->str() == "this")
|
||||
tok1 = tok1->astOperand2();
|
||||
if (tok2->str() == "." && tok2->astOperand1() && tok2->astOperand1()->str() == "this")
|
||||
tok2 = tok2->astOperand2();
|
||||
}
|
||||
if (tok1->varId() != tok2->varId() || tok1->str() != tok2->str()) {
|
||||
if ((Token::Match(tok1,"<|>") && Token::Match(tok2,"<|>")) ||
|
||||
(Token::Match(tok1,"<=|>=") && Token::Match(tok2,"<=|>="))) {
|
||||
return isSameExpression(tokenizer, tok1->astOperand1(), tok2->astOperand2(), constFunctions) &&
|
||||
isSameExpression(tokenizer, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (tok1->str() == "." && tok1->originalName() != tok2->originalName())
|
||||
return false;
|
||||
if (tok1->isExpandedMacro() || tok2->isExpandedMacro())
|
||||
return false;
|
||||
if (tok1->isName() && tok1->next()->str() == "(" && tok1->str() != "sizeof") {
|
||||
if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && constFunctions.find(tok1->str()) == constFunctions.end() && !tok1->isAttributeConst() && !tok1->isAttributePure())
|
||||
return false;
|
||||
else if (tok1->function() && !tok1->function()->isConst() && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
|
||||
return false;
|
||||
}
|
||||
// templates/casts
|
||||
if ((Token::Match(tok1, "%name% <") && tok1->next()->link()) ||
|
||||
(Token::Match(tok2, "%name% <") && tok2->next()->link())) {
|
||||
|
||||
// non-const template function that is not a dynamic_cast => return false
|
||||
if (Token::simpleMatch(tok1->next()->link(), "> (") &&
|
||||
!(tok1->function() && tok1->function()->isConst()) &&
|
||||
tok1->str() != "dynamic_cast")
|
||||
return false;
|
||||
|
||||
// some template/cast stuff.. check that the template arguments are same
|
||||
const Token *t1 = tok1->next();
|
||||
const Token *t2 = tok2->next();
|
||||
const Token *end1 = t1->link();
|
||||
const Token *end2 = t2->link();
|
||||
while (t1 && t2 && t1 != end1 && t2 != end2) {
|
||||
if (t1->str() != t2->str())
|
||||
return false;
|
||||
t1 = t1->next();
|
||||
t2 = t2->next();
|
||||
}
|
||||
if (t1 != end1 || t2 != end2)
|
||||
return false;
|
||||
}
|
||||
if (tok1->type() == Token::eIncDecOp || tok1->isAssignmentOp())
|
||||
return false;
|
||||
// bailout when we see ({..})
|
||||
if (tok1->str() == "{")
|
||||
return false;
|
||||
if (tok1->str() == "(" && tok1->previous() && !tok1->previous()->isName()) { // cast => assert that the casts are equal
|
||||
const Token *t1 = tok1->next();
|
||||
const Token *t2 = tok2->next();
|
||||
while (t1 && t2 && t1->str() == t2->str() && (t1->isName() || t1->str() == "*")) {
|
||||
t1 = t1->next();
|
||||
t2 = t2->next();
|
||||
}
|
||||
if (!t1 || !t2 || t1->str() != ")" || t2->str() != ")")
|
||||
return false;
|
||||
}
|
||||
bool noncommuative_equals =
|
||||
isSameExpression(tokenizer, tok1->astOperand1(), tok2->astOperand1(), constFunctions);
|
||||
noncommuative_equals = noncommuative_equals &&
|
||||
isSameExpression(tokenizer, tok1->astOperand2(), tok2->astOperand2(), constFunctions);
|
||||
|
||||
if (noncommuative_equals)
|
||||
return true;
|
||||
|
||||
const bool commutative = tok1->astOperand1() && tok1->astOperand2() && Token::Match(tok1, "%or%|%oror%|+|*|&|&&|^|==|!=");
|
||||
bool commuative_equals = commutative &&
|
||||
isSameExpression(tokenizer, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
|
||||
commuative_equals = commuative_equals &&
|
||||
isSameExpression(tokenizer, tok1->astOperand1(), tok2->astOperand2(), constFunctions);
|
||||
|
||||
return commuative_equals;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// The return value of fgetc(), getc(), ungetc(), getchar() etc. is an integer value.
|
||||
|
@ -1572,31 +1469,6 @@ void CheckOther::passedByValueError(const Token *tok, const std::string &parname
|
|||
//---------------------------------------------------------------------------
|
||||
// Check usage of char variables..
|
||||
//---------------------------------------------------------------------------
|
||||
static bool isChar(const Variable* var)
|
||||
{
|
||||
return (var && !var->isPointer() && !var->isArray() && var->typeStartToken()->str() == "char");
|
||||
}
|
||||
|
||||
static bool isSignedChar(const Variable* var)
|
||||
{
|
||||
return (isChar(var) && !var->typeStartToken()->isUnsigned());
|
||||
}
|
||||
|
||||
static bool astIsSignedChar(const Token *tok)
|
||||
{
|
||||
if (!tok)
|
||||
return false;
|
||||
if (tok->str() == "*" && tok->astOperand1() && !tok->astOperand2()) {
|
||||
const Variable *var = tok->astOperand1()->variable();
|
||||
if (!var || !var->isPointer())
|
||||
return false;
|
||||
const Token *type = var->typeStartToken();
|
||||
while (type && type->str() == "const")
|
||||
type = type->next();
|
||||
return (type && type->str() == "char" && !type->isUnsigned());
|
||||
}
|
||||
return isSignedChar(tok->variable());
|
||||
}
|
||||
|
||||
void CheckOther::checkCharVariable()
|
||||
{
|
||||
|
@ -2134,20 +2006,6 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
bool isWithoutSideEffects(const Tokenizer *tokenizer, const Token* tok)
|
||||
{
|
||||
if (!tokenizer->isCPP())
|
||||
return true;
|
||||
|
||||
while (tok && tok->astOperand2() && tok->astOperand2()->str() != "(")
|
||||
tok = tok->astOperand2();
|
||||
if (tok && tok->varId()) {
|
||||
const Variable* var = tok->variable();
|
||||
return var && (!var->isClass() || var->isPointer() || var->isStlType());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CheckOther::checkDuplicateExpression()
|
||||
{
|
||||
if (!_settings->isEnabled("style"))
|
||||
|
@ -2170,8 +2028,8 @@ void CheckOther::checkDuplicateExpression()
|
|||
if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>")) {
|
||||
if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1(), true))
|
||||
continue;
|
||||
if (isSameExpression(_tokenizer, tok->astOperand1(), tok->astOperand2(), _settings->library.functionpure)) {
|
||||
if (isWithoutSideEffects(_tokenizer, tok->astOperand1())) {
|
||||
if (isSameExpression(_tokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), _settings->library.functionpure)) {
|
||||
if (isWithoutSideEffects(_tokenizer->isCPP(), tok->astOperand1())) {
|
||||
const bool assignment = tok->str() == "=";
|
||||
if (assignment)
|
||||
selfAssignmentError(tok, tok->astOperand1()->expressionString());
|
||||
|
@ -2189,16 +2047,16 @@ void CheckOther::checkDuplicateExpression()
|
|||
}
|
||||
}
|
||||
} else if (!Token::Match(tok, "[-/%]")) { // These operators are not associative
|
||||
if (tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(_tokenizer, tok->astOperand2(), tok->astOperand1()->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer, tok->astOperand2()))
|
||||
if (tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(_tokenizer->isCPP(), tok->astOperand2(), tok->astOperand1()->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer->isCPP(), tok->astOperand2()))
|
||||
duplicateExpressionError(tok->astOperand2(), tok->astOperand2(), tok->str());
|
||||
else if (tok->astOperand2()) {
|
||||
const Token *ast1 = tok->astOperand1();
|
||||
while (ast1 && tok->str() == ast1->str()) {
|
||||
if (isSameExpression(_tokenizer, ast1->astOperand1(), tok->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer, ast1->astOperand1()))
|
||||
if (isSameExpression(_tokenizer->isCPP(), ast1->astOperand1(), tok->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer->isCPP(), ast1->astOperand1()))
|
||||
// TODO: warn if variables are unchanged. See #5683
|
||||
// Probably the message should be changed to 'duplicate expressions X in condition or something like that'.
|
||||
;//duplicateExpressionError(ast1->astOperand1(), tok->astOperand2(), tok->str());
|
||||
else if (isSameExpression(_tokenizer, ast1->astOperand2(), tok->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer, ast1->astOperand2()))
|
||||
else if (isSameExpression(_tokenizer->isCPP(), ast1->astOperand2(), tok->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer->isCPP(), ast1->astOperand2()))
|
||||
duplicateExpressionError(ast1->astOperand2(), tok->astOperand2(), tok->str());
|
||||
if (!isConstExpression(ast1->astOperand2(), _settings->library.functionpure))
|
||||
break;
|
||||
|
@ -2207,7 +2065,7 @@ void CheckOther::checkDuplicateExpression()
|
|||
}
|
||||
}
|
||||
} else if (tok->astOperand1() && tok->astOperand2() && tok->str() == ":" && tok->astParent() && tok->astParent()->str() == "?") {
|
||||
if (isSameExpression(_tokenizer, tok->astOperand1(), tok->astOperand2(), temp))
|
||||
if (isSameExpression(_tokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), temp))
|
||||
duplicateExpressionTernaryError(tok);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,6 @@
|
|||
class Function;
|
||||
class Variable;
|
||||
|
||||
bool isConstExpression(const Token *tok, const std::set<std::string> &constFunctions);
|
||||
|
||||
/** Is expressions same? */
|
||||
bool isSameExpression(const Tokenizer *tokenizer, const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions);
|
||||
|
||||
bool isWithoutSideEffects(const Tokenizer *tokenizer, const Token* tok);
|
||||
|
||||
/// @addtogroup Checks
|
||||
/// @{
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
#include "checkuninitvar.h"
|
||||
#include "astutils.h"
|
||||
#include "mathlib.h"
|
||||
#include "checknullpointer.h" // CheckNullPointer::parseFunctionCall
|
||||
#include "symboldatabase.h"
|
||||
|
@ -280,7 +281,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
|
|||
unsigned int condVarId = 0, condVarValue = 0;
|
||||
const Token *condVarTok = nullptr;
|
||||
if (Token::simpleMatch(tok, "if (") &&
|
||||
Token::isVariableComparison(tok->next()->astOperand2(), "!=", "0", &condVarTok)) {
|
||||
astIsVariableComparison(tok->next()->astOperand2(), "!=", "0", &condVarTok)) {
|
||||
std::map<unsigned int,int>::const_iterator it = variableValue.find(condVarTok->varId());
|
||||
if (it != variableValue.end() && it->second == NOT_ZERO)
|
||||
return true; // this scope is not fully analysed => return true
|
||||
|
|
|
@ -1468,42 +1468,6 @@ const Token *Token::getValueTokenDeadPointer() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const Token * Token::isVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
|
||||
{
|
||||
if (!tok)
|
||||
return nullptr;
|
||||
|
||||
const Token *ret = nullptr;
|
||||
if (tok->isComparisonOp()) {
|
||||
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {
|
||||
// Invert comparator
|
||||
std::string s = tok->str();
|
||||
if (s[0] == '>')
|
||||
s[0] = '<';
|
||||
else if (s[0] == '<')
|
||||
s[0] = '>';
|
||||
if (s == comp) {
|
||||
ret = tok->astOperand2();
|
||||
}
|
||||
} else if (tok->str() == comp && tok->astOperand2() && tok->astOperand2()->str() == rhs) {
|
||||
ret = tok->astOperand1();
|
||||
}
|
||||
} else if (comp == "!=" && rhs == std::string("0")) {
|
||||
ret = tok;
|
||||
} else if (comp == "==" && rhs == std::string("0")) {
|
||||
if (tok->str() == "!")
|
||||
ret = tok->astOperand1();
|
||||
}
|
||||
while (ret && ret->str() == ".")
|
||||
ret = ret->astOperand2();
|
||||
if (ret && ret->varId() == 0U)
|
||||
ret = nullptr;
|
||||
if (vartok)
|
||||
*vartok = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Token::assignProgressValues(Token *tok)
|
||||
{
|
||||
unsigned int total_count = 0;
|
||||
|
|
|
@ -717,9 +717,6 @@ public:
|
|||
|
||||
const Token *getValueTokenDeadPointer() const;
|
||||
|
||||
/** Is given syntax tree a variable comparison against value */
|
||||
static const Token * isVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
|
||||
|
||||
private:
|
||||
|
||||
void next(Token *nextToken) {
|
||||
|
|
Loading…
Reference in New Issue