diff --git a/lib/astutils.cpp b/lib/astutils.cpp index fce631511..c5ea05689 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -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 &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 &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 &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 &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) diff --git a/lib/astutils.h b/lib/astutils.h index 4e5ece12d..c4d9254fc 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -22,10 +22,10 @@ #define astutilsH //--------------------------------------------------------------------------- -#include #include 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 &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 &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 &constFunctions); +bool isConstExpression(const Token *tok, const Library& library, bool pure); bool isWithoutSideEffects(bool cpp, const Token* tok); diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 98312cd62..5a517194f 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -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 &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; diff --git a/lib/checkcondition.h b/lib/checkcondition.h index ec8ca1885..32aca0e58 100644 --- a/lib/checkcondition.h +++ b/lib/checkcondition.h @@ -103,7 +103,7 @@ public: private: - bool isOverlappingCond(const Token * const cond1, const Token * const cond2, const std::set &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); diff --git a/lib/checkio.cpp b/lib/checkio.cpp index e57bbbcad..ab9f97b27 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -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())) { diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 987a0717a..1619eb234 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -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; diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 11cb732b7..7876256d2 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -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::listastParent(); 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; } } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 9d22b6bca..1dec196cb 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -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 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::const_iterator scope; std::list constFunctions; - const std::set 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; } } diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index a3a460813..564ccb12f 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -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; } diff --git a/lib/library.cpp b/lib/library.cpp index 45262bb3a..e4fd6e283 100644 --- a/lib/library.cpp +++ b/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 >::const_iterator it = _formatstr.find(funcname); - if (it != _formatstr.end() && it->second.first) + std::map::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 >::const_iterator it = _formatstr.find(funcname); - if (it != _formatstr.end() && !it->second.first) + std::map::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 >::const_iterator it1; - it1 = argumentChecks.find(getFunctionName(ftok)); - if (it1 == argumentChecks.end()) + std::map::const_iterator it1 = functions.find(getFunctionName(ftok)); + if (it1 == functions.cend()) return nullptr; - const std::map::const_iterator it2 = it1->second.find(argnr); - if (it2 != it1->second.end()) + const std::map::const_iterator it2 = it1->second.argumentChecks.find(argnr); + if (it2 != it1->second.argumentChecks.cend()) return &it2->second; - const std::map::const_iterator it3 = it1->second.find(-1); - if (it3 != it1->second.end()) + const std::map::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 >::const_iterator it = argumentChecks.find(functionName); - if (it == argumentChecks.end()) + const std::map::const_iterator it = functions.find(functionName); + if (it == functions.cend()) return (callargs == 0); int args = 0; int firstOptionalArg = -1; - for (std::map::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { + for (std::map::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::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& argumentChecksFunc = argumentChecks.at(getFunctionName(ftok)); + const std::map& argumentChecksFunc = functions.at(getFunctionName(ftok)).argumentChecks; for (std::map::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::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::const_iterator it1 = functions.find(functionName); + if (it1 == functions.cend()) + return false; + for (std::map::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::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::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::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::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()) diff --git a/lib/library.h b/lib/library.h index 170799ac8..fb42fc9ec 100644 --- a/lib/library.h +++ b/lib/library.h @@ -31,7 +31,6 @@ #include #include #include -#include 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 + 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 use; - std::set leakignore; - std::set functionconst; - std::set 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 minsizes; }; - // function name, argument nr => argument data - std::map > argumentChecks; + + struct Function { + std::map 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 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 >::const_iterator it1; - it1 = argumentChecks.find(functionName); - if (it1 == argumentChecks.end()) - return false; - std::map::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 *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::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::const_iterator it2 = platform_types.find(name); - return (it2 != platform_types.end()) ? &(it2->second) : nullptr; } @@ -504,7 +488,6 @@ private: }; int allocid; std::set _files; - std::set _useretval; std::map _alloc; // allocation functions std::map _dealloc; // deallocation functions std::set _functions; @@ -512,7 +495,6 @@ private: std::map _returnValue; std::map _returnValueType; std::map _returnValueContainer; - std::set _ignorefunction; // ignore functions/macros from a library (gtk, qt etc) std::map _reporterrors; std::map _processAfterCode; std::set _markupExtensions; // file extensions of markup files @@ -520,8 +502,7 @@ private: std::map _executableblocks; // keywords for blocks of executable code std::map _exporters; // keywords that export variables/functions to libraries (meta-code/macros) std::map > _importers; // keywords that import variables/functions - std::map _reflection; // invocation of reflection - std::map > _formatstr; // Parameters for format string checking + std::map _reflection; // invocation of reflection std::map podtypes; // pod types std::map platform_types; // platform independent typedefs std::map platforms; // platform dependent typedefs diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4d674bb8f..672af36a8 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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()) { diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index a774beb2f..245ac9cff 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -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(cond2), value, settings); diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index 93188f601..1be1b58ac 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -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")); diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 8839b37db..ffa510d79 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -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 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 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 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 null,uninit; CheckNullPointer::parseFunctionCall(*xtok, null, &library, 0U); diff --git a/test/testother.cpp b/test/testother.cpp index 166f4ccf6..ffbdeaa8d 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -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"