Refactorized Library
This commit is contained in:
parent
af1398900c
commit
2f6350a0d0
|
@ -128,7 +128,7 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions)
|
||||
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure)
|
||||
{
|
||||
if (tok1 == nullptr && tok2 == nullptr)
|
||||
return true;
|
||||
|
@ -143,15 +143,15 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
|||
if (tok1->varId() != tok2->varId() || tok1->str() != tok2->str() || tok1->originalName() != tok2->originalName()) {
|
||||
if ((Token::Match(tok1,"<|>") && Token::Match(tok2,"<|>")) ||
|
||||
(Token::Match(tok1,"<=|>=") && Token::Match(tok2,"<=|>="))) {
|
||||
return isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), constFunctions) &&
|
||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
|
||||
return isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), library, pure) &&
|
||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), library, pure);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (macro && (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())
|
||||
if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && pure && !library.isFunctionConst(tok1->str(), true) && !tok1->isAttributeConst() && !tok1->isAttributePure())
|
||||
return false;
|
||||
else if (tok1->function() && !tok1->function()->isConst() && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
|
||||
return false;
|
||||
|
@ -201,18 +201,18 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
|||
return false;
|
||||
}
|
||||
bool noncommutativeEquals =
|
||||
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand1(), constFunctions);
|
||||
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand1(), library, pure);
|
||||
noncommutativeEquals = noncommutativeEquals &&
|
||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand2(), constFunctions);
|
||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand2(), library, pure);
|
||||
|
||||
if (noncommutativeEquals)
|
||||
return true;
|
||||
|
||||
const bool commutative = tok1->astOperand1() && tok1->astOperand2() && Token::Match(tok1, "%or%|%oror%|+|*|&|&&|^|==|!=");
|
||||
bool commutativeEquals = commutative &&
|
||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), constFunctions);
|
||||
isSameExpression(cpp, macro, tok1->astOperand2(), tok2->astOperand1(), library, pure);
|
||||
commutativeEquals = commutativeEquals &&
|
||||
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), constFunctions);
|
||||
isSameExpression(cpp, macro, tok1->astOperand1(), tok2->astOperand2(), library, pure);
|
||||
|
||||
// in c++, "a"+b might be different to b+"a"
|
||||
if (cpp && commutativeEquals && tok1->str() == "+" &&
|
||||
|
@ -224,7 +224,7 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
|||
return commutativeEquals;
|
||||
}
|
||||
|
||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions)
|
||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const Library& library, bool pure)
|
||||
{
|
||||
if (!cond1 || !cond2)
|
||||
return false;
|
||||
|
@ -232,15 +232,15 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
|||
if (cond1->str() == "!") {
|
||||
if (cond2->str() == "!=") {
|
||||
if (cond2->astOperand1() && cond2->astOperand1()->str() == "0")
|
||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), constFunctions);
|
||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), library, pure);
|
||||
if (cond2->astOperand2() && cond2->astOperand2()->str() == "0")
|
||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), constFunctions);
|
||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure);
|
||||
}
|
||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2, constFunctions);
|
||||
return isSameExpression(cpp, true, cond1->astOperand1(), cond2, library, pure);
|
||||
}
|
||||
|
||||
if (cond2->str() == "!")
|
||||
return isOppositeCond(isNot, cpp, cond2, cond1, constFunctions);
|
||||
return isOppositeCond(isNot, cpp, cond2, cond1, library, pure);
|
||||
|
||||
if (!cond1->isComparisonOp() || !cond2->isComparisonOp())
|
||||
return false;
|
||||
|
@ -249,11 +249,11 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
|||
|
||||
// condition found .. get comparator
|
||||
std::string comp2;
|
||||
if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), constFunctions) &&
|
||||
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand2(), constFunctions)) {
|
||||
if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand1(), library, pure) &&
|
||||
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand2(), library, pure)) {
|
||||
comp2 = cond2->str();
|
||||
} else if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), constFunctions) &&
|
||||
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand1(), constFunctions)) {
|
||||
} else if (isSameExpression(cpp, true, cond1->astOperand1(), cond2->astOperand2(), library, pure) &&
|
||||
isSameExpression(cpp, true, cond1->astOperand2(), cond2->astOperand1(), library, pure)) {
|
||||
comp2 = cond2->str();
|
||||
if (comp2[0] == '>')
|
||||
comp2[0] = '<';
|
||||
|
@ -272,12 +272,12 @@ bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token
|
|||
(comp1 == ">" && comp2 == "<"))));
|
||||
}
|
||||
|
||||
bool isConstExpression(const Token *tok, const std::set<std::string> &constFunctions)
|
||||
bool isConstExpression(const Token *tok, const Library& library, bool pure)
|
||||
{
|
||||
if (!tok)
|
||||
return true;
|
||||
if (tok->isName() && tok->next()->str() == "(") {
|
||||
if (!tok->function() && !Token::Match(tok->previous(), ".|::") && constFunctions.find(tok->str()) == constFunctions.end())
|
||||
if (!tok->function() && !Token::Match(tok->previous(), ".|::") && !library.isFunctionConst(tok->str(), pure))
|
||||
return false;
|
||||
else if (tok->function() && !tok->function()->isConst())
|
||||
return false;
|
||||
|
@ -287,7 +287,7 @@ bool isConstExpression(const Token *tok, const std::set<std::string> &constFunct
|
|||
// bailout when we see ({..})
|
||||
if (tok->str() == "{")
|
||||
return false;
|
||||
return isConstExpression(tok->astOperand1(),constFunctions) && isConstExpression(tok->astOperand2(),constFunctions);
|
||||
return isConstExpression(tok->astOperand1(), library, pure) && isConstExpression(tok->astOperand2(), library, pure);
|
||||
}
|
||||
|
||||
bool isWithoutSideEffects(bool cpp, const Token* tok)
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
#define astutilsH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
class Settings;
|
||||
class Library;
|
||||
class Token;
|
||||
|
||||
/** Is expression a 'signed char' if no promotion is used */
|
||||
|
@ -53,7 +53,7 @@ std::string astCanonicalType(const Token *expr);
|
|||
/** 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, bool macro, const Token *tok1, const Token *tok2, const std::set<std::string> &constFunctions);
|
||||
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure);
|
||||
|
||||
/**
|
||||
* Are two conditions opposite
|
||||
|
@ -63,9 +63,9 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
|||
* @param cond2 condition2
|
||||
* @param constFunctions constFunctions
|
||||
*/
|
||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions);
|
||||
bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const Library& library, bool pure);
|
||||
|
||||
bool isConstExpression(const Token *tok, const std::set<std::string> &constFunctions);
|
||||
bool isConstExpression(const Token *tok, const Library& library, bool pure);
|
||||
|
||||
bool isWithoutSideEffects(bool cpp, const Token* tok);
|
||||
|
||||
|
|
|
@ -351,13 +351,13 @@ void CheckCondition::comparisonError(const Token *tok, const std::string &bitop,
|
|||
reportError(tok, Severity::style, "comparisonError", errmsg, CWE398, false);
|
||||
}
|
||||
|
||||
bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions) const
|
||||
bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token * const cond2, bool pure) const
|
||||
{
|
||||
if (!cond1 || !cond2)
|
||||
return false;
|
||||
|
||||
// same expressions
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, cond1, cond2, constFunctions))
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, cond1, cond2, _settings->library, pure))
|
||||
return true;
|
||||
|
||||
// bitwise overlap for example 'x&7' and 'x==1'
|
||||
|
@ -380,7 +380,7 @@ bool CheckCondition::isOverlappingCond(const Token * const cond1, const Token *
|
|||
if (!num2->isNumber() || MathLib::isNegative(num2->str()))
|
||||
return false;
|
||||
|
||||
if (!isSameExpression(_tokenizer->isCPP(), true, expr1, expr2, constFunctions))
|
||||
if (!isSameExpression(_tokenizer->isCPP(), true, expr1, expr2, _settings->library, pure))
|
||||
return false;
|
||||
|
||||
const MathLib::bigint value1 = MathLib::toLongNumber(num1->str());
|
||||
|
@ -414,7 +414,7 @@ void CheckCondition::multiCondition()
|
|||
break;
|
||||
tok2 = tok2->tokAt(4);
|
||||
|
||||
if (isOverlappingCond(cond1, tok2->astOperand2(), _settings->library.functionpure))
|
||||
if (isOverlappingCond(cond1, tok2->astOperand2(), true))
|
||||
multiConditionError(tok2, cond1->linenr());
|
||||
}
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ void CheckCondition::oppositeInnerCondition()
|
|||
const Token *cond1 = scope->classDef->next()->astOperand2();
|
||||
const Token *cond2 = ifToken->next()->astOperand2();
|
||||
|
||||
if (isOppositeCond(false, _tokenizer->isCPP(), cond1, cond2, _settings->library.functionpure))
|
||||
if (isOppositeCond(false, _tokenizer->isCPP(), cond1, cond2, _settings->library, true))
|
||||
oppositeInnerConditionError(scope->classDef, cond2);
|
||||
}
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ void CheckCondition::checkIncorrectLogicOperator()
|
|||
|
||||
// Opposite comparisons around || or && => always true or always false
|
||||
if ((tok->astOperand1()->isName() || tok->astOperand2()->isName()) &&
|
||||
isOppositeCond(true, _tokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), _settings->library.functionpure)) {
|
||||
isOppositeCond(true, _tokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), _settings->library, true)) {
|
||||
|
||||
const bool alwaysTrue(tok->str() == "||");
|
||||
incorrectLogicOperatorError(tok, tok->expressionString(), alwaysTrue, false);
|
||||
|
@ -691,7 +691,7 @@ void CheckCondition::checkIncorrectLogicOperator()
|
|||
((tok->str() == "||" && tok->astOperand2()->str() == "&&") ||
|
||||
(tok->str() == "&&" && tok->astOperand2()->str() == "||"))) {
|
||||
const Token* tok2 = tok->astOperand2()->astOperand1();
|
||||
if (isOppositeCond(true, _tokenizer->isCPP(), tok->astOperand1(), tok2, _settings->library.functionpure)) {
|
||||
if (isOppositeCond(true, _tokenizer->isCPP(), tok->astOperand1(), tok2, _settings->library, true)) {
|
||||
std::string expr1(tok->astOperand1()->expressionString());
|
||||
std::string expr2(tok->astOperand2()->astOperand1()->expressionString());
|
||||
std::string expr3(tok->astOperand2()->astOperand2()->expressionString());
|
||||
|
@ -752,9 +752,9 @@ void CheckCondition::checkIncorrectLogicOperator()
|
|||
if (inconclusive && !printInconclusive)
|
||||
continue;
|
||||
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, comp1, comp2, _settings->library.functionpure))
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, comp1, comp2, _settings->library, true))
|
||||
continue; // same expressions => only report that there are same expressions
|
||||
if (!isSameExpression(_tokenizer->isCPP(), true, expr1, expr2, _settings->library.functionpure))
|
||||
if (!isSameExpression(_tokenizer->isCPP(), true, expr1, expr2, _settings->library, true))
|
||||
continue;
|
||||
|
||||
const bool isfloat = astIsFloat(expr1, true) || MathLib::isFloat(value1) || astIsFloat(expr2, true) || MathLib::isFloat(value2);
|
||||
|
@ -1082,9 +1082,9 @@ void CheckCondition::checkInvalidTestForOverflow()
|
|||
continue;
|
||||
|
||||
const Token *termToken;
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, exprToken, calcToken->astOperand1(), _settings->library.functionpure))
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, exprToken, calcToken->astOperand1(), _settings->library, true))
|
||||
termToken = calcToken->astOperand2();
|
||||
else if (isSameExpression(_tokenizer->isCPP(), true, exprToken, calcToken->astOperand2(), _settings->library.functionpure))
|
||||
else if (isSameExpression(_tokenizer->isCPP(), true, exprToken, calcToken->astOperand2(), _settings->library, true))
|
||||
termToken = calcToken->astOperand1();
|
||||
else
|
||||
continue;
|
||||
|
|
|
@ -103,7 +103,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
bool isOverlappingCond(const Token * const cond1, const Token * const cond2, const std::set<std::string> &constFunctions) const;
|
||||
bool isOverlappingCond(const Token * const cond1, const Token * const cond2, bool pure) 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);
|
||||
|
|
|
@ -233,7 +233,7 @@ void CheckIO::checkFileUsage()
|
|||
if ((tok->str() == "ungetc" || tok->str() == "ungetwc") && fileTok)
|
||||
fileTok = fileTok->nextArgument();
|
||||
operation = Filepointer::UNIMPORTANT;
|
||||
} else if (!Token::Match(tok, "if|for|while|catch|switch") && _settings->library.functionpure.find(tok->str()) == _settings->library.functionpure.end()) {
|
||||
} else if (!Token::Match(tok, "if|for|while|catch|switch") && !_settings->library.isFunctionConst(tok->str(), true)) {
|
||||
const Token* const end2 = tok->linkAt(1);
|
||||
if (scope->functionOf && scope->functionOf->isClassOrStruct() && !scope->function->isStatic() && ((tok->strAt(-1) != "::" && tok->strAt(-1) != ".") || tok->strAt(-2) == "this")) {
|
||||
if (!tok->function() || (tok->function()->nestedIn && tok->function()->nestedIn->isClassOrStruct())) {
|
||||
|
|
|
@ -460,8 +460,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
if (_tokenizer->IsScopeNoReturn(tok->tokAt(2), &unknown)) {
|
||||
if (!unknown)
|
||||
varInfo->clear();
|
||||
else if (_settings->library.leakignore.find(functionName) == _settings->library.leakignore.end() &&
|
||||
_settings->library.use.find(functionName) == _settings->library.use.end())
|
||||
else if (!_settings->library.isLeakIgnore(functionName) && !_settings->library.isUse(functionName))
|
||||
varInfo->possibleUsageAll(functionName);
|
||||
}
|
||||
}
|
||||
|
@ -526,8 +525,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo *varInfo, const VarInfo::AllocI
|
|||
void CheckLeakAutoVar::functionCall(const Token *tok, VarInfo *varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af)
|
||||
{
|
||||
// Ignore function call?
|
||||
const bool ignore = bool(_settings->library.leakignore.find(tok->str()) != _settings->library.leakignore.end());
|
||||
if (ignore)
|
||||
if (_settings->library.isLeakIgnore(tok->str()))
|
||||
return;
|
||||
|
||||
int argNr = 1;
|
||||
|
|
|
@ -494,7 +494,7 @@ static bool alwaysTrue(const Token *tok)
|
|||
|
||||
bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname, const Settings *settings, bool cpp)
|
||||
{
|
||||
return ((call_func_white_list.find(funcname)!=call_func_white_list.end()) || (settings->library.leakignore.find(funcname) != settings->library.leakignore.end()) || (cpp && funcname == "delete"));
|
||||
return ((call_func_white_list.find(funcname)!=call_func_white_list.end()) || settings->library.isLeakIgnore(funcname) || (cpp && funcname == "delete"));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -1318,7 +1318,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
|||
parent = parent->astParent();
|
||||
if (parent && parent->astOperand1() && parent->astOperand1()->isName()) {
|
||||
const std::string &functionName = parent->astOperand1()->str();
|
||||
if (_settings->library.leakignore.find(functionName) != _settings->library.leakignore.end())
|
||||
if (_settings->library.isLeakIgnore(functionName))
|
||||
leakignore = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -574,7 +574,7 @@ void CheckOther::checkRedundantAssignment()
|
|||
}
|
||||
|
||||
// Ensure that LHS in assignments are the same
|
||||
bool error = oldeq && eq->astOperand1() && isSameExpression(_tokenizer->isCPP(), true, eq->astOperand1(), oldeq->astOperand1(), _settings->library.functionpure);
|
||||
bool error = oldeq && eq->astOperand1() && isSameExpression(_tokenizer->isCPP(), true, eq->astOperand1(), oldeq->astOperand1(), _settings->library, true);
|
||||
|
||||
// Ensure that variable is not used on right side
|
||||
std::stack<const Token *> tokens;
|
||||
|
@ -635,7 +635,7 @@ void CheckOther::checkRedundantAssignment()
|
|||
if (!writtenArgumentsEnd) // Indicates that we are in the first argument of strcpy/memcpy/... function
|
||||
memAssignments.erase(tok->varId());
|
||||
}
|
||||
} else if (Token::Match(tok, "%name% (") && _settings->library.functionpure.find(tok->str()) == _settings->library.functionpure.end()) { // Function call. Global variables might be used. Reset their status
|
||||
} else if (Token::Match(tok, "%name% (") && !_settings->library.isFunctionConst(tok->str(), true)) { // Function call. Global variables might be used. Reset their status
|
||||
const bool memfunc = Token::Match(tok, "memcpy|memmove|memset|strcpy|strncpy|sprintf|snprintf|strcat|strncat|wcscpy|wcsncpy|swprintf|wcscat|wcsncat");
|
||||
if (tok->varId()) // operator() or function pointer
|
||||
varAssignments.erase(tok->varId());
|
||||
|
@ -1936,7 +1936,7 @@ void CheckOther::checkInvalidFree()
|
|||
// If the previously-allocated variable is passed in to another function
|
||||
// as a parameter, it might be modified, so we shouldn't report an error
|
||||
// if it is later used to free memory
|
||||
else if (Token::Match(tok, "%name% (") && _settings->library.functionpure.find(tok->str()) == _settings->library.functionpure.end()) {
|
||||
else if (Token::Match(tok, "%name% (") && !_settings->library.isFunctionConst(tok->str(), true)) {
|
||||
const Token* tok2 = Token::findmatch(tok->next(), "%var%", tok->linkAt(1));
|
||||
while (tok2 != nullptr) {
|
||||
allocatedVariables.erase(tok2->varId());
|
||||
|
@ -2001,7 +2001,6 @@ void CheckOther::checkDuplicateExpression()
|
|||
|
||||
std::list<Scope>::const_iterator scope;
|
||||
std::list<const Function*> constFunctions;
|
||||
const std::set<std::string> temp; // Can be used as dummy for isSameExpression()
|
||||
getConstFunctions(symbolDatabase, constFunctions);
|
||||
|
||||
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
|
@ -2013,7 +2012,7 @@ void CheckOther::checkDuplicateExpression()
|
|||
if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>|+=|*=|<<=|>>=")) {
|
||||
if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1(), true))
|
||||
continue;
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), _settings->library.functionpure)) {
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), _settings->library, true)) {
|
||||
if (isWithoutSideEffects(_tokenizer->isCPP(), tok->astOperand1())) {
|
||||
const bool assignment = tok->str() == "=";
|
||||
if (assignment && warningEnabled)
|
||||
|
@ -2033,25 +2032,25 @@ void CheckOther::checkDuplicateExpression()
|
|||
}
|
||||
}
|
||||
} else if (!Token::Match(tok, "[-/%]")) { // These operators are not associative
|
||||
if (styleEnabled && tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(_tokenizer->isCPP(), true, tok->astOperand2(), tok->astOperand1()->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer->isCPP(), tok->astOperand2()))
|
||||
if (styleEnabled && tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(_tokenizer->isCPP(), true, tok->astOperand2(), tok->astOperand1()->astOperand2(), _settings->library, true) && 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->isCPP(), true, ast1->astOperand1(), tok->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer->isCPP(), ast1->astOperand1()))
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, ast1->astOperand1(), tok->astOperand2(), _settings->library, true) && 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 (styleEnabled && isSameExpression(_tokenizer->isCPP(), true, ast1->astOperand2(), tok->astOperand2(), _settings->library.functionpure) && isWithoutSideEffects(_tokenizer->isCPP(), ast1->astOperand2()))
|
||||
else if (styleEnabled && isSameExpression(_tokenizer->isCPP(), true, ast1->astOperand2(), tok->astOperand2(), _settings->library, true) && isWithoutSideEffects(_tokenizer->isCPP(), ast1->astOperand2()))
|
||||
duplicateExpressionError(ast1->astOperand2(), tok->astOperand2(), tok->str());
|
||||
if (!isConstExpression(ast1->astOperand2(), _settings->library.functionpure))
|
||||
if (!isConstExpression(ast1->astOperand2(), _settings->library, true))
|
||||
break;
|
||||
ast1 = ast1->astOperand1();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (styleEnabled && tok->astOperand1() && tok->astOperand2() && tok->str() == ":" && tok->astParent() && tok->astParent()->str() == "?") {
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), temp))
|
||||
if (isSameExpression(_tokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), _settings->library, false))
|
||||
duplicateExpressionTernaryError(tok);
|
||||
}
|
||||
}
|
||||
|
@ -2655,9 +2654,9 @@ void CheckOther::checkEvaluationOrder()
|
|||
if (tok2 == tok &&
|
||||
tok->str() == "=" &&
|
||||
parent->str() == "=" &&
|
||||
isSameExpression(_tokenizer->isCPP(), false, tok->astOperand1(), parent->astOperand1(), _settings->library.functionpure)) {
|
||||
isSameExpression(_tokenizer->isCPP(), false, tok->astOperand1(), parent->astOperand1(), _settings->library, true)) {
|
||||
if (_settings->isEnabled("warning") &&
|
||||
isSameExpression(_tokenizer->isCPP(), true, tok->astOperand1(), parent->astOperand1(), _settings->library.functionpure))
|
||||
isSameExpression(_tokenizer->isCPP(), true, tok->astOperand1(), parent->astOperand1(), _settings->library, true))
|
||||
selfAssignmentError(parent, tok->astOperand1()->expressionString());
|
||||
break;
|
||||
}
|
||||
|
@ -2677,7 +2676,7 @@ void CheckOther::checkEvaluationOrder()
|
|||
continue; // don't care about sizeof usage
|
||||
tokens.push(tok3->astOperand1());
|
||||
tokens.push(tok3->astOperand2());
|
||||
if (isSameExpression(_tokenizer->isCPP(), false, tok->astOperand1(), tok3, _settings->library.functionpure)) {
|
||||
if (isSameExpression(_tokenizer->isCPP(), false, tok->astOperand1(), tok3, _settings->library, true)) {
|
||||
foundError = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -888,7 +888,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, Alloc al
|
|||
break;
|
||||
}
|
||||
if (alloc != NO_ALLOC && parent->str() == "(") {
|
||||
if (_settings->library.functionpure.find(parent->strAt(-1)) == _settings->library.functionpure.end()) {
|
||||
if (!_settings->library.isFunctionConst(parent->strAt(-1), true)) {
|
||||
assignment = true;
|
||||
break;
|
||||
}
|
||||
|
|
123
lib/library.cpp
123
lib/library.cpp
|
@ -187,7 +187,7 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
|
|||
temp.arg = 1;
|
||||
_dealloc[memorynode->GetText()] = temp;
|
||||
} else if (memorynodename == "use")
|
||||
use.insert(memorynode->GetText());
|
||||
functions[memorynode->GetText()].use = true;
|
||||
else
|
||||
unknown_elements.insert(memorynodename);
|
||||
}
|
||||
|
@ -537,14 +537,14 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
|||
if (functionnodename == "noreturn")
|
||||
_noreturn[name] = (strcmp(functionnode->GetText(), "true") == 0);
|
||||
else if (functionnodename == "pure")
|
||||
functionpure.insert(name);
|
||||
functions[name].ispure = true;
|
||||
else if (functionnodename == "const") {
|
||||
functionconst.insert(name);
|
||||
functionpure.insert(name); // a constant function is pure
|
||||
functions[name].ispure = true;
|
||||
functions[name].isconst = true; // a constant function is pure
|
||||
} else if (functionnodename == "leak-ignore")
|
||||
leakignore.insert(name);
|
||||
functions[name].leakignore = true;
|
||||
else if (functionnodename == "use-retval")
|
||||
_useretval.insert(name);
|
||||
functions[name].useretval = true;
|
||||
else if (functionnodename == "returnValue") {
|
||||
if (const char *expr = functionnode->GetText())
|
||||
_returnValue[name] = expr;
|
||||
|
@ -558,7 +558,7 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
|||
return Error(MISSING_ATTRIBUTE, "nr");
|
||||
const bool bAnyArg = strcmp(argNrString, "any")==0;
|
||||
const int nr = bAnyArg ? -1 : std::atoi(argNrString);
|
||||
ArgumentChecks &ac = argumentChecks[name][nr];
|
||||
ArgumentChecks &ac = functions[name].argumentChecks[nr];
|
||||
ac.optional = functionnode->Attribute("default") != nullptr;
|
||||
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
|
||||
const std::string argnodename = argnode->Name();
|
||||
|
@ -633,19 +633,25 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
|||
}
|
||||
|
||||
else if (argnodename == "iterator") {
|
||||
ac.iteratorInfo.setType(argnode->Attribute("type"));
|
||||
ac.iteratorInfo.setContainer(argnode->Attribute("container"));
|
||||
ac.iteratorInfo.it = true;
|
||||
const char* str = argnode->Attribute("type");
|
||||
ac.iteratorInfo.first = str ? (std::strcmp(str, "first") == 0) : false;
|
||||
ac.iteratorInfo.last = str ? (std::strcmp(str, "last") == 0) : false;
|
||||
str = argnode->Attribute("container");
|
||||
ac.iteratorInfo.container = str ? std::atoi(str) : 0;
|
||||
}
|
||||
|
||||
else
|
||||
unknown_elements.insert(argnodename);
|
||||
}
|
||||
} else if (functionnodename == "ignorefunction") {
|
||||
_ignorefunction.insert(name);
|
||||
functions[name].ignore = true;
|
||||
} else if (functionnodename == "formatstr") {
|
||||
functions[name].formatstr = true;
|
||||
const tinyxml2::XMLAttribute* scan = functionnode->FindAttribute("scan");
|
||||
const tinyxml2::XMLAttribute* secure = functionnode->FindAttribute("secure");
|
||||
_formatstr[name] = std::make_pair(scan && scan->BoolValue(), secure && secure->BoolValue());
|
||||
functions[name].formatstr_scan = scan && scan->BoolValue();
|
||||
functions[name].formatstr_secure = secure && secure->BoolValue();
|
||||
} else if (functionnodename == "warn") {
|
||||
WarnInfo wi;
|
||||
const char* const severity = functionnode->Attribute("severity");
|
||||
|
@ -788,8 +794,8 @@ bool Library::isnullargbad(const Token *ftok, int argnr) const
|
|||
if (!arg) {
|
||||
// scan format string argument should not be null
|
||||
const std::string funcname = getFunctionName(ftok);
|
||||
std::map<std::string, std::pair<bool, bool> >::const_iterator it = _formatstr.find(funcname);
|
||||
if (it != _formatstr.end() && it->second.first)
|
||||
std::map<std::string, Function>::const_iterator it = functions.find(funcname);
|
||||
if (it != functions.cend() && it->second.formatstr && it->second.formatstr_scan)
|
||||
return true;
|
||||
}
|
||||
return arg && arg->notnull;
|
||||
|
@ -801,8 +807,8 @@ bool Library::isuninitargbad(const Token *ftok, int argnr) const
|
|||
if (!arg) {
|
||||
// non-scan format string argument should not be uninitialized
|
||||
const std::string funcname = getFunctionName(ftok);
|
||||
std::map<std::string, std::pair<bool, bool> >::const_iterator it = _formatstr.find(funcname);
|
||||
if (it != _formatstr.end() && !it->second.first)
|
||||
std::map<std::string, Function>::const_iterator it = functions.find(funcname);
|
||||
if (it != functions.cend() && it->second.formatstr && !it->second.formatstr_scan)
|
||||
return true;
|
||||
}
|
||||
return arg && arg->notuninit;
|
||||
|
@ -813,14 +819,14 @@ bool Library::isuninitargbad(const Token *ftok, int argnr) const
|
|||
const Library::AllocFunc* Library::alloc(const Token *tok) const
|
||||
{
|
||||
const std::string funcname = getFunctionName(tok);
|
||||
return isNotLibraryFunction(tok) && argumentChecks.find(funcname) != argumentChecks.end() ? 0 : getAllocDealloc(_alloc, funcname);
|
||||
return isNotLibraryFunction(tok) && functions.find(funcname) != functions.end() ? 0 : getAllocDealloc(_alloc, funcname);
|
||||
}
|
||||
|
||||
/** get deallocation info for function */
|
||||
const Library::AllocFunc* Library::dealloc(const Token *tok) const
|
||||
{
|
||||
const std::string funcname = getFunctionName(tok);
|
||||
return isNotLibraryFunction(tok) && argumentChecks.find(funcname) != argumentChecks.end() ? 0 : getAllocDealloc(_dealloc, funcname);
|
||||
return isNotLibraryFunction(tok) && functions.find(funcname) != functions.end() ? 0 : getAllocDealloc(_dealloc, funcname);
|
||||
}
|
||||
|
||||
/** get allocation id for function */
|
||||
|
@ -842,15 +848,14 @@ const Library::ArgumentChecks * Library::getarg(const Token *ftok, int argnr) co
|
|||
{
|
||||
if (isNotLibraryFunction(ftok))
|
||||
return nullptr;
|
||||
std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it1;
|
||||
it1 = argumentChecks.find(getFunctionName(ftok));
|
||||
if (it1 == argumentChecks.end())
|
||||
std::map<std::string, Function>::const_iterator it1 = functions.find(getFunctionName(ftok));
|
||||
if (it1 == functions.cend())
|
||||
return nullptr;
|
||||
const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.find(argnr);
|
||||
if (it2 != it1->second.end())
|
||||
const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.find(argnr);
|
||||
if (it2 != it1->second.argumentChecks.cend())
|
||||
return &it2->second;
|
||||
const std::map<int,ArgumentChecks>::const_iterator it3 = it1->second.find(-1);
|
||||
if (it3 != it1->second.end())
|
||||
const std::map<int,ArgumentChecks>::const_iterator it3 = it1->second.argumentChecks.find(-1);
|
||||
if (it3 != it1->second.argumentChecks.cend())
|
||||
return &it3->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -926,12 +931,12 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
|
|||
bool Library::matchArguments(const Token *ftok, const std::string &functionName) const
|
||||
{
|
||||
int callargs = numberOfArguments(ftok);
|
||||
const std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it = argumentChecks.find(functionName);
|
||||
if (it == argumentChecks.end())
|
||||
const std::map<std::string, Function>::const_iterator it = functions.find(functionName);
|
||||
if (it == functions.cend())
|
||||
return (callargs == 0);
|
||||
int args = 0;
|
||||
int firstOptionalArg = -1;
|
||||
for (std::map<int, ArgumentChecks>::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) {
|
||||
for (std::map<int, ArgumentChecks>::const_iterator it2 = it->second.argumentChecks.cbegin(); it2 != it->second.argumentChecks.cend(); ++it2) {
|
||||
if (it2->first > args)
|
||||
args = it2->first;
|
||||
if (it2->second.optional && (firstOptionalArg == -1 || firstOptionalArg > it2->first))
|
||||
|
@ -955,13 +960,18 @@ const Library::WarnInfo* Library::getWarnInfo(const Token* ftok) const
|
|||
|
||||
bool Library::formatstr_function(const Token* ftok) const
|
||||
{
|
||||
return (!isNotLibraryFunction(ftok) &&
|
||||
_formatstr.find(getFunctionName(ftok)) != _formatstr.cend());
|
||||
if (isNotLibraryFunction(ftok))
|
||||
return false;
|
||||
|
||||
std::map<std::string, Library::Function>::const_iterator it = functions.find(getFunctionName(ftok));
|
||||
if (it != functions.cend())
|
||||
return it->second.formatstr;
|
||||
return false;
|
||||
}
|
||||
|
||||
int Library::formatstr_argno(const Token* ftok) const
|
||||
{
|
||||
const std::map<int, Library::ArgumentChecks>& argumentChecksFunc = argumentChecks.at(getFunctionName(ftok));
|
||||
const std::map<int, Library::ArgumentChecks>& argumentChecksFunc = functions.at(getFunctionName(ftok)).argumentChecks;
|
||||
for (std::map<int, Library::ArgumentChecks>::const_iterator i = argumentChecksFunc.cbegin(); i != argumentChecksFunc.cend(); ++i) {
|
||||
if (i->second.formatstr) {
|
||||
return i->first - 1;
|
||||
|
@ -972,18 +982,22 @@ int Library::formatstr_argno(const Token* ftok) const
|
|||
|
||||
bool Library::formatstr_scan(const Token* ftok) const
|
||||
{
|
||||
return _formatstr.at(getFunctionName(ftok)).first;
|
||||
return functions.at(getFunctionName(ftok)).formatstr_scan;
|
||||
}
|
||||
|
||||
bool Library::formatstr_secure(const Token* ftok) const
|
||||
{
|
||||
return _formatstr.at(getFunctionName(ftok)).second;
|
||||
return functions.at(getFunctionName(ftok)).formatstr_secure;
|
||||
}
|
||||
|
||||
bool Library::isUseRetVal(const Token* ftok) const
|
||||
{
|
||||
return (!isNotLibraryFunction(ftok) &&
|
||||
_useretval.find(getFunctionName(ftok)) != _useretval.end());
|
||||
if (isNotLibraryFunction(ftok))
|
||||
return false;
|
||||
std::map<std::string, Library::Function>::const_iterator it = functions.find(getFunctionName(ftok));
|
||||
if (it != functions.cend())
|
||||
return it->second.useretval;
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string& Library::returnValue(const Token *ftok) const
|
||||
|
@ -1010,6 +1024,47 @@ int Library::returnValueContainer(const Token *ftok) const
|
|||
return it != _returnValueContainer.end() ? it->second : -1;
|
||||
}
|
||||
|
||||
bool Library::hasminsize(const std::string &functionName) const
|
||||
{
|
||||
std::map<std::string, Function>::const_iterator it1 = functions.find(functionName);
|
||||
if (it1 == functions.cend())
|
||||
return false;
|
||||
for (std::map<int, ArgumentChecks>::const_iterator it2 = it1->second.argumentChecks.cbegin(); it2 != it1->second.argumentChecks.cend(); ++it2) {
|
||||
if (!it2->second.minsizes.empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Library::ignorefunction(const std::string& functionName) const
|
||||
{
|
||||
std::map<std::string, Library::Function>::const_iterator it = functions.find(functionName);
|
||||
if (it != functions.cend())
|
||||
return it->second.ignore;
|
||||
return false;
|
||||
}
|
||||
bool Library::isUse(const std::string& functionName) const
|
||||
{
|
||||
std::map<std::string, Library::Function>::const_iterator it = functions.find(functionName);
|
||||
if (it != functions.cend())
|
||||
return it->second.use;
|
||||
return false;
|
||||
}
|
||||
bool Library::isLeakIgnore(const std::string& functionName) const
|
||||
{
|
||||
std::map<std::string, Library::Function>::const_iterator it = functions.find(functionName);
|
||||
if (it != functions.cend())
|
||||
return it->second.leakignore;
|
||||
return false;
|
||||
}
|
||||
bool Library::isFunctionConst(const std::string& functionName, bool pure) const
|
||||
{
|
||||
std::map<std::string, Library::Function>::const_iterator it = functions.find(functionName);
|
||||
if (it != functions.cend())
|
||||
return pure ? it->second.ispure : it->second.isconst;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Library::isnoreturn(const Token *ftok) const
|
||||
{
|
||||
if (ftok->function() && ftok->function()->isAttributeNoreturn())
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLDocument;
|
||||
|
@ -54,9 +53,10 @@ public:
|
|||
|
||||
class Error {
|
||||
public:
|
||||
Error() : errorcode(OK) , reason("") {}
|
||||
explicit Error(ErrorCode e) : errorcode(e) , reason("") {}
|
||||
Error(ErrorCode e, const std::string &r) : errorcode(e), reason(r) {}
|
||||
Error() : errorcode(OK) {}
|
||||
explicit Error(ErrorCode e) : errorcode(e) {}
|
||||
template<typename T>
|
||||
Error(ErrorCode e, T&& r) : errorcode(e), reason(r) {}
|
||||
ErrorCode errorcode;
|
||||
std::string reason;
|
||||
};
|
||||
|
@ -139,18 +139,10 @@ public:
|
|||
}
|
||||
|
||||
bool formatstr_function(const Token* ftok) const;
|
||||
|
||||
int formatstr_argno(const Token* ftok) const;
|
||||
|
||||
bool formatstr_scan(const Token* ftok) const;
|
||||
|
||||
bool formatstr_secure(const Token* ftok) const;
|
||||
|
||||
std::set<std::string> use;
|
||||
std::set<std::string> leakignore;
|
||||
std::set<std::string> functionconst;
|
||||
std::set<std::string> functionpure;
|
||||
|
||||
struct WarnInfo {
|
||||
std::string message;
|
||||
Standards standards;
|
||||
|
@ -245,15 +237,6 @@ public:
|
|||
class IteratorInfo {
|
||||
public:
|
||||
IteratorInfo() : it(false), container(0), first(false), last(false) {}
|
||||
void setContainer(const char *str) {
|
||||
it = true;
|
||||
container = str ? std::atoi(str) : 0;
|
||||
}
|
||||
void setType(const char *str) {
|
||||
it = true;
|
||||
first = str ? (std::strcmp(str,"first") == 0) : false;
|
||||
last = str ? (std::strcmp(str,"last") == 0) : false;
|
||||
}
|
||||
|
||||
bool it;
|
||||
int container;
|
||||
|
@ -264,7 +247,7 @@ public:
|
|||
|
||||
class MinSize {
|
||||
public:
|
||||
enum Type {NONE,STRLEN,ARGVALUE,SIZEOF,MUL};
|
||||
enum Type { NONE, STRLEN, ARGVALUE, SIZEOF, MUL };
|
||||
MinSize(Type t, int a) : type(t), arg(a), arg2(0) {}
|
||||
Type type;
|
||||
int arg;
|
||||
|
@ -273,8 +256,25 @@ public:
|
|||
std::list<MinSize> minsizes;
|
||||
};
|
||||
|
||||
// function name, argument nr => argument data
|
||||
std::map<std::string, std::map<int, ArgumentChecks> > argumentChecks;
|
||||
|
||||
struct Function {
|
||||
std::map<int, ArgumentChecks> argumentChecks; // argument nr => argument data
|
||||
bool use;
|
||||
bool leakignore;
|
||||
bool isconst;
|
||||
bool ispure;
|
||||
bool useretval;
|
||||
bool ignore; // ignore functions/macros from a library (gtk, qt etc)
|
||||
bool formatstr;
|
||||
bool formatstr_scan;
|
||||
bool formatstr_secure;
|
||||
Function() : use(false), leakignore(false), isconst(false), ispure(false), useretval(false), ignore(false), formatstr(false), formatstr_scan(false), formatstr_secure(false) {}
|
||||
};
|
||||
|
||||
std::map<std::string, Function> functions;
|
||||
bool isUse(const std::string& functionName) const;
|
||||
bool isLeakIgnore(const std::string& functionName) const;
|
||||
bool isFunctionConst(const std::string& functionName, bool pure) const;
|
||||
|
||||
bool isboolargbad(const Token *ftok, int argnr) const {
|
||||
const ArgumentChecks *arg = getarg(ftok, argnr);
|
||||
|
@ -306,18 +306,7 @@ public:
|
|||
return arg && arg->iteratorInfo.it ? &arg->iteratorInfo : nullptr;
|
||||
}
|
||||
|
||||
bool hasminsize(const std::string &functionName) const {
|
||||
std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it1;
|
||||
it1 = argumentChecks.find(functionName);
|
||||
if (it1 == argumentChecks.end())
|
||||
return false;
|
||||
std::map<int,ArgumentChecks>::const_iterator it2;
|
||||
for (it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) {
|
||||
if (!it2->second.minsizes.empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool hasminsize(const std::string &functionName) const;
|
||||
|
||||
const std::list<ArgumentChecks::MinSize> *argminsizes(const Token *ftok, int argnr) const {
|
||||
const ArgumentChecks *arg = getarg(ftok, argnr);
|
||||
|
@ -334,9 +323,7 @@ public:
|
|||
|
||||
bool reportErrors(const std::string &path) const;
|
||||
|
||||
bool ignorefunction(const std::string &function) const {
|
||||
return (_ignorefunction.find(function) != _ignorefunction.end());
|
||||
}
|
||||
bool ignorefunction(const std::string &function) const;
|
||||
|
||||
bool isexecutableblock(const std::string &file, const std::string &token) const;
|
||||
|
||||
|
@ -401,13 +388,13 @@ public:
|
|||
, _const_ptr(false) {
|
||||
}
|
||||
bool operator == (const PlatformType & type) const {
|
||||
return (_type == type._type &&
|
||||
_signed == type._signed &&
|
||||
return (_signed == type._signed &&
|
||||
_unsigned == type._unsigned &&
|
||||
_long == type._long &&
|
||||
_pointer == type._pointer &&
|
||||
_ptr_ptr == type._ptr_ptr &&
|
||||
_const_ptr == type._const_ptr);
|
||||
_const_ptr == type._const_ptr &&
|
||||
_type == type._type);
|
||||
}
|
||||
bool operator != (const PlatformType & type) const {
|
||||
return !(*this == type);
|
||||
|
@ -431,16 +418,13 @@ public:
|
|||
|
||||
const PlatformType *platform_type(const std::string &name, const std::string & platform) const {
|
||||
const std::map<std::string, Platform>::const_iterator it = platforms.find(platform);
|
||||
|
||||
if (it != platforms.end()) {
|
||||
const PlatformType * const type = it->second.platform_type(name);
|
||||
|
||||
if (type)
|
||||
return type;
|
||||
}
|
||||
|
||||
const std::map<std::string, PlatformType>::const_iterator it2 = platform_types.find(name);
|
||||
|
||||
return (it2 != platform_types.end()) ? &(it2->second) : nullptr;
|
||||
}
|
||||
|
||||
|
@ -504,7 +488,6 @@ private:
|
|||
};
|
||||
int allocid;
|
||||
std::set<std::string> _files;
|
||||
std::set<std::string> _useretval;
|
||||
std::map<std::string, AllocFunc> _alloc; // allocation functions
|
||||
std::map<std::string, AllocFunc> _dealloc; // deallocation functions
|
||||
std::set<std::string> _functions;
|
||||
|
@ -512,7 +495,6 @@ private:
|
|||
std::map<std::string, std::string> _returnValue;
|
||||
std::map<std::string, std::string> _returnValueType;
|
||||
std::map<std::string, int> _returnValueContainer;
|
||||
std::set<std::string> _ignorefunction; // ignore functions/macros from a library (gtk, qt etc)
|
||||
std::map<std::string, bool> _reporterrors;
|
||||
std::map<std::string, bool> _processAfterCode;
|
||||
std::set<std::string> _markupExtensions; // file extensions of markup files
|
||||
|
@ -520,8 +502,7 @@ private:
|
|||
std::map<std::string, CodeBlock> _executableblocks; // keywords for blocks of executable code
|
||||
std::map<std::string, ExportedFunctions> _exporters; // keywords that export variables/functions to libraries (meta-code/macros)
|
||||
std::map<std::string, std::set<std::string> > _importers; // keywords that import variables/functions
|
||||
std::map<std::string,int> _reflection; // invocation of reflection
|
||||
std::map<std::string, std::pair<bool, bool> > _formatstr; // Parameters for format string checking
|
||||
std::map<std::string, int> _reflection; // invocation of reflection
|
||||
std::map<std::string, struct PodType> podtypes; // pod types
|
||||
std::map<std::string, PlatformType> platform_types; // platform independent typedefs
|
||||
std::map<std::string, Platform> platforms; // platform dependent typedefs
|
||||
|
|
|
@ -8420,9 +8420,9 @@ void Tokenizer::simplifyAttribute()
|
|||
{
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, "%type% (") && !_settings->library.isNotLibraryFunction(tok)) {
|
||||
if (_settings->library.functionpure.find(tok->str()) != _settings->library.functionpure.end())
|
||||
if (_settings->library.isFunctionConst(tok->str(), true))
|
||||
tok->isAttributePure(true);
|
||||
if (_settings->library.functionconst.find(tok->str()) != _settings->library.functionconst.end())
|
||||
if (_settings->library.isFunctionConst(tok->str(), false))
|
||||
tok->isAttributeConst(true);
|
||||
}
|
||||
while (Token::Match(tok, "__attribute__|__attribute (") && tok->next()->link() && tok->next()->link()->next()) {
|
||||
|
|
|
@ -856,7 +856,7 @@ static void valueFlowOppositeCondition(SymbolDatabase *symboldatabase, const Set
|
|||
const Token *cond2 = tok2->tokAt(4)->astOperand2();
|
||||
if (!cond2 || !cond2->isComparisonOp())
|
||||
continue;
|
||||
if (isOppositeCond(true, cpp, cond1, cond2, settings->library.functionpure)) {
|
||||
if (isOppositeCond(true, cpp, cond1, cond2, settings->library, true)) {
|
||||
ValueFlow::Value value(1);
|
||||
value.setKnown();
|
||||
setTokenValue(const_cast<Token*>(cond2), value, settings);
|
||||
|
|
|
@ -66,9 +66,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT(library.use.empty());
|
||||
ASSERT(library.leakignore.empty());
|
||||
ASSERT(library.argumentChecks.empty());
|
||||
ASSERT(library.functions.empty());
|
||||
}
|
||||
|
||||
void function() const {
|
||||
|
@ -86,9 +84,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT(library.use.empty());
|
||||
ASSERT(library.leakignore.empty());
|
||||
ASSERT(library.argumentChecks.empty());
|
||||
ASSERT(library.functions.empty());
|
||||
ASSERT(library.isnotnoreturn(tokenList.front()));
|
||||
}
|
||||
|
||||
|
@ -222,13 +218,13 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT_EQUALS(true, library.argumentChecks["foo"][1].notuninit);
|
||||
ASSERT_EQUALS(true, library.argumentChecks["foo"][2].notnull);
|
||||
ASSERT_EQUALS(true, library.argumentChecks["foo"][3].formatstr);
|
||||
ASSERT_EQUALS(true, library.argumentChecks["foo"][4].strz);
|
||||
ASSERT_EQUALS(false, library.argumentChecks["foo"][4].optional);
|
||||
ASSERT_EQUALS(true, library.argumentChecks["foo"][5].notbool);
|
||||
ASSERT_EQUALS(true, library.argumentChecks["foo"][5].optional);
|
||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[1].notuninit);
|
||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[2].notnull);
|
||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[3].formatstr);
|
||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[4].strz);
|
||||
ASSERT_EQUALS(false, library.functions["foo"].argumentChecks[4].optional);
|
||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[5].notbool);
|
||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[5].optional);
|
||||
}
|
||||
|
||||
void function_arg_any() const {
|
||||
|
@ -241,7 +237,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT_EQUALS(true, library.argumentChecks["foo"][-1].notuninit);
|
||||
ASSERT_EQUALS(true, library.functions["foo"].argumentChecks[-1].notuninit);
|
||||
}
|
||||
|
||||
void function_arg_valid() const {
|
||||
|
@ -346,9 +342,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT(library.use.empty());
|
||||
ASSERT(library.leakignore.empty());
|
||||
ASSERT(library.argumentChecks.empty());
|
||||
ASSERT(library.functions.empty());
|
||||
|
||||
{
|
||||
TokenList tokenList(nullptr);
|
||||
|
@ -375,9 +369,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT(library.use.empty());
|
||||
ASSERT(library.leakignore.empty());
|
||||
ASSERT(library.argumentChecks.empty());
|
||||
ASSERT(library.functions.empty());
|
||||
|
||||
{
|
||||
Settings settings;
|
||||
|
@ -471,9 +463,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT(library.use.empty());
|
||||
ASSERT(library.leakignore.empty());
|
||||
ASSERT(library.argumentChecks.empty());
|
||||
ASSERT(library.functions.empty());
|
||||
|
||||
ASSERT(Library::ismemory(library.alloc("CreateX")));
|
||||
ASSERT_EQUALS(library.allocId("CreateX"), library.deallocId("DeleteX"));
|
||||
|
@ -516,9 +506,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT(library.use.empty());
|
||||
ASSERT(library.leakignore.empty());
|
||||
ASSERT(library.argumentChecks.empty());
|
||||
ASSERT(library.functions.empty());
|
||||
|
||||
const Library::AllocFunc* af = library.alloc("CreateX");
|
||||
ASSERT(af && af->arg == 5);
|
||||
|
@ -539,9 +527,7 @@ private:
|
|||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
ASSERT(library.use.empty());
|
||||
ASSERT(library.leakignore.empty());
|
||||
ASSERT(library.argumentChecks.empty());
|
||||
ASSERT(library.functions.empty());
|
||||
|
||||
ASSERT(Library::isresource(library.allocId("CreateX")));
|
||||
ASSERT_EQUALS(library.allocId("CreateX"), library.deallocId("DeleteX"));
|
||||
|
|
|
@ -2254,9 +2254,9 @@ private:
|
|||
{
|
||||
Library library;
|
||||
Library::ArgumentChecks arg;
|
||||
library.argumentChecks["x"][1] = arg;
|
||||
library.argumentChecks["x"][2] = arg;
|
||||
library.argumentChecks["x"][3] = arg;
|
||||
library.functions["x"].argumentChecks[1] = arg;
|
||||
library.functions["x"].argumentChecks[2] = arg;
|
||||
library.functions["x"].argumentChecks[3] = arg;
|
||||
|
||||
std::list<const Token *> null, uninit;
|
||||
CheckNullPointer::parseFunctionCall(*xtok, null, &library, 0U);
|
||||
|
@ -2269,10 +2269,10 @@ private:
|
|||
{
|
||||
Library library;
|
||||
Library::ArgumentChecks arg;
|
||||
library.argumentChecks["x"][1] = arg;
|
||||
library.argumentChecks["x"][2] = arg;
|
||||
library.argumentChecks["x"][3] = arg;
|
||||
library.argumentChecks["x"][1].notnull = true;
|
||||
library.functions["x"].argumentChecks[1] = arg;
|
||||
library.functions["x"].argumentChecks[2] = arg;
|
||||
library.functions["x"].argumentChecks[3] = arg;
|
||||
library.functions["x"].argumentChecks[1].notnull = true;
|
||||
|
||||
std::list<const Token *> null,uninit;
|
||||
CheckNullPointer::parseFunctionCall(*xtok, null, &library, 0U);
|
||||
|
@ -2286,10 +2286,10 @@ private:
|
|||
{
|
||||
Library library;
|
||||
Library::ArgumentChecks arg;
|
||||
library.argumentChecks["x"][1] = arg;
|
||||
library.argumentChecks["x"][2] = arg;
|
||||
library.argumentChecks["x"][3] = arg;
|
||||
library.argumentChecks["x"][2].notuninit = true;
|
||||
library.functions["x"].argumentChecks[1] = arg;
|
||||
library.functions["x"].argumentChecks[2] = arg;
|
||||
library.functions["x"].argumentChecks[3] = arg;
|
||||
library.functions["x"].argumentChecks[2].notuninit = true;
|
||||
|
||||
std::list<const Token *> null,uninit;
|
||||
CheckNullPointer::parseFunctionCall(*xtok, null, &library, 0U);
|
||||
|
@ -2303,10 +2303,10 @@ private:
|
|||
{
|
||||
Library library;
|
||||
Library::ArgumentChecks arg;
|
||||
library.argumentChecks["x"][1] = arg;
|
||||
library.argumentChecks["x"][2] = arg;
|
||||
library.argumentChecks["x"][3] = arg;
|
||||
library.argumentChecks["x"][3].notuninit = true;
|
||||
library.functions["x"].argumentChecks[1] = arg;
|
||||
library.functions["x"].argumentChecks[2] = arg;
|
||||
library.functions["x"].argumentChecks[3] = arg;
|
||||
library.functions["x"].argumentChecks[3].notuninit = true;
|
||||
|
||||
std::list<const Token *> null,uninit;
|
||||
CheckNullPointer::parseFunctionCall(*xtok, null, &library, 0U);
|
||||
|
|
|
@ -2291,7 +2291,7 @@ private:
|
|||
|
||||
Settings settings;
|
||||
settings.library.setnoreturn("exit", true);
|
||||
settings.library.argumentChecks["exit"][1] = Library::ArgumentChecks();
|
||||
settings.library.functions["exit"].argumentChecks[1] = Library::ArgumentChecks();
|
||||
check("void foo() {\n"
|
||||
" exit(0);\n"
|
||||
" break;\n"
|
||||
|
|
Loading…
Reference in New Issue