diff --git a/Makefile b/Makefile index 8aef517b7a8..a4d33f18c67 100644 --- a/Makefile +++ b/Makefile @@ -578,7 +578,7 @@ $(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h li $(libcppdir)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/errortypes.cpp -$(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/valueptr.h lib/vfvalue.h +$(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/forwardanalyzer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueptr.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/forwardanalyzer.cpp $(libcppdir)/fwdanalysis.o: lib/fwdanalysis.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index ee391b1a5fa..2d2abfe036e 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -21,11 +21,13 @@ #include "analyzer.h" #include "astutils.h" #include "config.h" +#include "errorlogger.h" #include "errortypes.h" #include "mathlib.h" #include "settings.h" #include "symboldatabase.h" #include "token.h" +#include "tokenlist.h" #include "utils.h" #include "valueptr.h" #include "vfvalue.h" @@ -45,16 +47,19 @@ namespace { struct ForwardTraversal { enum class Progress { Continue, Break, Skip }; enum class Terminate { None, Bail, Inconclusive }; - ForwardTraversal(const ValuePtr& analyzer, const Settings& settings) - : analyzer(analyzer), settings(settings) + ForwardTraversal(const ValuePtr& analyzer, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings) + : analyzer(analyzer), tokenList(tokenList), errorLogger(errorLogger), settings(settings) {} ValuePtr analyzer; + const TokenList& tokenList; + ErrorLogger* const errorLogger; const Settings& settings; Analyzer::Action actions; bool analyzeOnly{}; bool analyzeTerminate{}; Analyzer::Terminate terminate = Analyzer::Terminate::None; std::vector loopEnds; + int branchCount = 0; Progress Break(Analyzer::Terminate t = Analyzer::Terminate::None) { if ((!analyzeOnly || analyzeTerminate) && t != Analyzer::Terminate::None) @@ -648,6 +653,10 @@ namespace { } } else if (tok->isControlFlowKeyword() && Token::Match(tok, "if|while|for (") && Token::simpleMatch(tok->next()->link(), ") {")) { + if (settings.checkLevel == Settings::CheckLevel::normal && ++branchCount > 4) { + reportError(Severity::information, "normalCheckLevelMaxBranches", "Limit analysis of branches. Use --check-level=exhausive to analyze all branches."); + return Break(Analyzer::Terminate::Bail); + } Token* endCond = tok->next()->link(); Token* endBlock = endCond->next()->link(); Token* condTok = getCondTok(tok); @@ -828,6 +837,15 @@ namespace { return Progress::Continue; } + void reportError(Severity severity, const std::string& id, const std::string& msg) { + if (errorLogger) { + const ErrorMessage::FileLocation loc(tokenList.getSourceFilePath(), 1, 1); + const std::list callstack{loc}; + const ErrorMessage errmsg(callstack, tokenList.getSourceFilePath(), severity, msg, id, Certainty::normal); + errorLogger->reportErr(errmsg); + } + } + static bool isFunctionCall(const Token* tok) { if (!Token::simpleMatch(tok, "(")) @@ -886,24 +904,24 @@ namespace { }; } -Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& a, const Settings& settings) +Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings) { if (a->invalid()) return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail}; - ForwardTraversal ft{a, settings}; + ForwardTraversal ft{a, tokenList, errorLogger, settings}; if (start) ft.analyzer->updateState(start); ft.updateRange(start, end); return Analyzer::Result{ ft.actions, ft.terminate }; } -Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const Settings& settings) +Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings) { if (Settings::terminated()) throw TerminateException(); if (a->invalid()) return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail}; - ForwardTraversal ft{a, settings}; + ForwardTraversal ft{a, tokenList, errorLogger, settings}; ft.updateRecursive(start); return Analyzer::Result{ ft.actions, ft.terminate }; } diff --git a/lib/forwardanalyzer.h b/lib/forwardanalyzer.h index 16c01011dac..f378d852d57 100644 --- a/lib/forwardanalyzer.h +++ b/lib/forwardanalyzer.h @@ -21,15 +21,19 @@ #include "analyzer.h" +class ErrorLogger; class Settings; class Token; +class TokenList; template class ValuePtr; Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& a, + const TokenList& tokenList, + ErrorLogger* const errorLogger, const Settings& settings); -Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const Settings& settings); +Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const TokenList& tokenList, ErrorLogger* const errorLogger, const Settings& settings); #endif diff --git a/lib/reverseanalyzer.cpp b/lib/reverseanalyzer.cpp index 83ed6ed7309..213061e5044 100644 --- a/lib/reverseanalyzer.cpp +++ b/lib/reverseanalyzer.cpp @@ -37,10 +37,12 @@ namespace { struct ReverseTraversal { - ReverseTraversal(const ValuePtr& analyzer, const Settings& settings) - : analyzer(analyzer), settings(settings) + ReverseTraversal(const ValuePtr& analyzer, const TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings) + : analyzer(analyzer), tokenlist(tokenlist), errorLogger(errorLogger), settings(settings) {} ValuePtr analyzer; + const TokenList& tokenlist; + ErrorLogger* const errorLogger; const Settings& settings; std::pair evalCond(const Token* tok) const { @@ -239,6 +241,8 @@ namespace { valueFlowGenericForward(nextAfterAstRightmostLeaf(assignTok->astOperand2()), assignTok->astOperand2()->scope()->bodyEnd, a, + tokenlist, + errorLogger, settings); } // Assignment to @@ -251,8 +255,10 @@ namespace { valueFlowGenericForward(nextAfterAstRightmostLeaf(assignTok->astOperand2()), assignTok->astOperand2()->scope()->bodyEnd, a, + tokenlist, + errorLogger, settings); - valueFlowGenericReverse(assignTok->astOperand1()->previous(), end, a, settings); + valueFlowGenericReverse(assignTok->astOperand1()->previous(), end, a, tokenlist, errorLogger, settings); } } } @@ -285,7 +291,7 @@ namespace { break; if (condAction.isModified()) break; - valueFlowGenericForward(condTok, analyzer, settings); + valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); } Token* thenEnd; const bool hasElse = Token::simpleMatch(tok->link()->tokAt(-2), "} else {"); @@ -314,7 +320,7 @@ namespace { break; if (!thenAction.isModified() && !elseAction.isModified()) - valueFlowGenericForward(condTok, analyzer, settings); + valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); else if (condAction.isRead()) break; // If the condition modifies the variable then bail @@ -333,7 +339,7 @@ namespace { } Token* condTok = getCondTokFromEnd(tok->link()); if (condTok) { - Analyzer::Result r = valueFlowGenericForward(condTok, analyzer, settings); + Analyzer::Result r = valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); if (r.action.isModified()) break; } @@ -389,10 +395,10 @@ namespace { }; } -void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const Settings& settings) +void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings) { if (a->invalid()) return; - ReverseTraversal rt{a, settings}; + ReverseTraversal rt{a, tokenlist, errorLogger, settings}; rt.traverse(start, end); } diff --git a/lib/reverseanalyzer.h b/lib/reverseanalyzer.h index 801b6276c86..c35315de0d9 100644 --- a/lib/reverseanalyzer.h +++ b/lib/reverseanalyzer.h @@ -20,11 +20,13 @@ #define reverseanalyzerH struct Analyzer; +class ErrorLogger; class Settings; class Token; +class TokenList; template class ValuePtr; -void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const Settings& settings); +void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings); #endif diff --git a/lib/settings.cpp b/lib/settings.cpp index 15dc9b41044..0fd99ace212 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -243,6 +243,7 @@ void Settings::loadSummaries() void Settings::setCheckLevelExhaustive() { // Checking can take a little while. ~ 10 times slower than normal analysis is OK. + checkLevel = CheckLevel::exhaustive; performanceValueFlowMaxIfCount = -1; performanceValueFlowMaxSubFunctionArgs = 256; } @@ -250,6 +251,7 @@ void Settings::setCheckLevelExhaustive() void Settings::setCheckLevelNormal() { // Checking should finish in reasonable time. + checkLevel = CheckLevel::normal; performanceValueFlowMaxSubFunctionArgs = 8; performanceValueFlowMaxIfCount = 100; } diff --git a/lib/settings.h b/lib/settings.h index 3c4fade32e2..81de9a36d89 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -444,6 +444,12 @@ class CPPCHECKLIB WARN_UNUSED Settings { void setCheckLevelExhaustive(); void setCheckLevelNormal(); + enum class CheckLevel { + exhaustive, + normal + }; + CheckLevel checkLevel = CheckLevel::normal; + private: static std::string parseEnabled(const std::string &str, std::tuple, SimpleEnableGroup> &groups); std::string applyEnabled(const std::string &str, bool enable); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 030b0699452..3acacf4b65a 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2047,6 +2047,7 @@ static Analyzer::Result valueFlowForward(Token* startToken, const Token* exprTok, ValueFlow::Value value, const TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2055,6 +2056,8 @@ static Analyzer::Result valueFlowForward(Token* startToken, return valueFlowGenericForward(startToken, endToken, makeAnalyzer(exprTok, std::move(value), tokenlist, settings), + tokenlist, + errorLogger, settings); } @@ -2063,12 +2066,13 @@ static Analyzer::Result valueFlowForward(Token* startToken, const Token* exprTok, std::list values, const TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { Analyzer::Result result{}; for (ValueFlow::Value& v : values) { - result.update(valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, settings, loc)); + result.update(valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, errorLogger, settings, loc)); } return result; } @@ -2078,6 +2082,7 @@ static Analyzer::Result valueFlowForward(Token* startToken, const Token* exprTok, ValueOrValues v, TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2085,13 +2090,14 @@ static Analyzer::Result valueFlowForward(Token* startToken, const Function* f = Scope::nestedInFunction(startToken->scope()); if (f && f->functionScope) endToken = f->functionScope->bodyEnd; - return valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, settings, loc); + return valueFlowForward(startToken, endToken, exprTok, std::move(v), tokenlist, errorLogger, settings, loc); } static Analyzer::Result valueFlowForwardRecursive(Token* top, const Token* exprTok, std::list values, const TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { @@ -2100,7 +2106,7 @@ static Analyzer::Result valueFlowForwardRecursive(Token* top, if (settings.debugnormal) setSourceLocation(v, loc, top); result.update( - valueFlowGenericForward(top, makeAnalyzer(exprTok, std::move(v), tokenlist, settings), settings)); + valueFlowGenericForward(top, makeAnalyzer(exprTok, std::move(v), tokenlist, settings), tokenlist, errorLogger, settings)); } return result; } @@ -2110,13 +2116,14 @@ static void valueFlowReverse(Token* tok, const Token* const varToken, std::list values, const TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { for (ValueFlow::Value& v : values) { if (settings.debugnormal) setSourceLocation(v, loc, tok); - valueFlowGenericReverse(tok, endToken, makeReverseAnalyzer(varToken, std::move(v), tokenlist, settings), settings); + valueFlowGenericReverse(tok, endToken, makeReverseAnalyzer(varToken, std::move(v), tokenlist, settings), tokenlist, errorLogger, settings); } } @@ -2126,14 +2133,14 @@ static void valueFlowReverse(const TokenList& tokenlist, const Token* const varToken, ValueFlow::Value val, const ValueFlow::Value& val2, - ErrorLogger* /*errorLogger*/, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) { std::list values = {std::move(val)}; if (val2.varId != 0) values.push_back(val2); - valueFlowReverse(tok, nullptr, varToken, std::move(values), tokenlist, settings, loc); + valueFlowReverse(tok, nullptr, varToken, std::move(values), tokenlist, errorLogger, settings, loc); } static bool isConditionKnown(const Token* tok, bool then) @@ -3886,7 +3893,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLog if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) { std::list values = tok->values(); values.remove_if(&isNotLifetimeValue); - valueFlowForward(nextAfterAstRightmostLeaf(tok), ValueFlow::getEndOfExprScope(tok), tok->previous(), values, tokenlist, settings); + valueFlowForward(nextAfterAstRightmostLeaf(tok), ValueFlow::getEndOfExprScope(tok), tok->previous(), values, tokenlist, errorLogger, settings); return; } Token *parent = tok->astParent(); @@ -3926,7 +3933,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLog Token* nextExpression = nextAfterAstRightmostLeaf(parent); if (expr->exprId() > 0) { - valueFlowForward(nextExpression, endOfVarScope->next(), expr, values, tokenlist, settings); + valueFlowForward(nextExpression, endOfVarScope->next(), expr, values, tokenlist, errorLogger, settings); for (ValueFlow::Value& val : values) { if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address) @@ -3937,7 +3944,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLog const Token* parentLifetime = getParentLifetime(tokenlist.isCPP(), parent->astOperand1()->astOperand2(), &settings.library); if (parentLifetime && parentLifetime->exprId() > 0) { - valueFlowForward(nextExpression, endOfVarScope, parentLifetime, values, tokenlist, settings); + valueFlowForward(nextExpression, endOfVarScope, parentLifetime, values, tokenlist, errorLogger, settings); } } } @@ -3958,7 +3965,7 @@ static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLog Token *nextExpression = nextAfterAstRightmostLeaf(parent); // Only forward lifetime values values.remove_if(&isNotLifetimeValue); - valueFlowForward(nextExpression, endOfVarScope, tok, values, tokenlist, settings); + valueFlowForward(nextExpression, endOfVarScope, tok, values, tokenlist, errorLogger, settings); // Cast } else if (parent->isCast()) { std::list values = tok->values(); @@ -5106,7 +5113,7 @@ static Token* findEndOfFunctionCallForParameter(Token* parameterToken) return nextAfterAstRightmostLeaf(parent); } -static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings& settings) +static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings) { if (!tokenlist.isCPP() || settings.standards.cpp < Standards::CPP11) return; @@ -5138,7 +5145,7 @@ static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symbo setTokenValue(tok, value, settings); if (var->scope()) { const Token* const endOfVarScope = var->scope()->bodyEnd; - valueFlowForward(tok->next(), endOfVarScope, tok, std::move(value), tokenlist, settings); + valueFlowForward(tok->next(), endOfVarScope, tok, std::move(value), tokenlist, errorLogger, settings); } continue; } @@ -5171,7 +5178,7 @@ static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symbo value.errorPath.emplace_back(tok, "Calling std::forward(" + varTok->str() + ")"); value.setKnown(); - valueFlowForward(endOfFunctionCall, endOfVarScope, varTok, std::move(value), tokenlist, settings); + valueFlowForward(endOfFunctionCall, endOfVarScope, varTok, std::move(value), tokenlist, errorLogger, settings); } } } @@ -5247,6 +5254,9 @@ static const Scope* getLoopScope(const Token* tok) // static void valueFlowConditionExpressions(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) { + if (settings.checkLevel == Settings::CheckLevel::normal) + return; + for (const Scope * scope : symboldatabase.functionScopes) { if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) { if (settings.debugwarnings) @@ -5277,11 +5287,11 @@ static void valueFlowConditionExpressions(const TokenList &tokenlist, const Symb if (is1) { const bool isBool = astIsBool(condTok2) || Token::Match(condTok2, "%comp%|%oror%|&&"); SameExpressionAnalyzer a1(condTok2, makeConditionValue(1, condTok2, /*assume*/ true, !isBool), tokenlist, settings); // don't set '1' for non-boolean expressions - valueFlowGenericForward(startTok, startTok->link(), a1, settings); + valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings); } OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(0, condTok2, true), tokenlist, settings); - valueFlowGenericForward(startTok, startTok->link(), a2, settings); + valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings); } } @@ -5292,11 +5302,11 @@ static void valueFlowConditionExpressions(const TokenList &tokenlist, const Symb startTok = startTok->link()->tokAt(2); for (const Token* condTok2:conds) { SameExpressionAnalyzer a1(condTok2, makeConditionValue(0, condTok2, false), tokenlist, settings); - valueFlowGenericForward(startTok, startTok->link(), a1, settings); + valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings); if (is1) { OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(1, condTok2, false), tokenlist, settings); - valueFlowGenericForward(startTok, startTok->link(), a2, settings); + valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings); } } } @@ -5312,11 +5322,11 @@ static void valueFlowConditionExpressions(const TokenList &tokenlist, const Symb } for (const Token* condTok2:conds) { SameExpressionAnalyzer a1(condTok2, makeConditionValue(0, condTok2, false), tokenlist, settings); - valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a1, settings); + valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a1, tokenlist, errorLogger, settings); if (is1) { OppositeExpressionAnalyzer a2(true, condTok2, makeConditionValue(1, condTok2, false), tokenlist, settings); - valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a2, settings); + valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a2, tokenlist, errorLogger, settings); } } } @@ -5373,7 +5383,7 @@ static std::set getVarIds(const Token* tok) return result; } -static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings& settings) +static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings) { for (const Scope* scope : symboldatabase.functionScopes) { for (auto* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { @@ -5425,13 +5435,13 @@ static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& rhs.errorPath.emplace_back(tok, tok->astOperand1()->expressionString() + " is assigned '" + tok->astOperand2()->expressionString() + "' here."); - valueFlowForward(start, end, tok->astOperand1(), rhs, tokenlist, settings); + valueFlowForward(start, end, tok->astOperand1(), rhs, tokenlist, errorLogger, settings); ValueFlow::Value lhs = makeSymbolic(tok->astOperand1()); lhs.errorPath.emplace_back(tok, tok->astOperand1()->expressionString() + " is assigned '" + tok->astOperand2()->expressionString() + "' here."); - valueFlowForward(start, end, tok->astOperand2(), lhs, tokenlist, settings); + valueFlowForward(start, end, tok->astOperand2(), lhs, tokenlist, errorLogger, settings); } } } @@ -5831,7 +5841,7 @@ static void valueFlowForwardAssign(Token* const tok, } } } - valueFlowForward(nextExpression, endOfVarScope, expr, values, tokenlist, settings); + valueFlowForward(nextExpression, endOfVarScope, expr, values, tokenlist, errorLogger, settings); } static void valueFlowForwardAssign(Token* const tok, @@ -6039,7 +6049,7 @@ static void valueFlowAfterAssign(TokenList &tokenlist, value.errorPath.emplace_back(tok, tok->astOperand1()->expressionString() + " is assigned '" + tok->astOperand2()->expressionString() + "' here."); - valueFlowForward(start, end, expr, value, tokenlist, settings); + valueFlowForward(start, end, expr, value, tokenlist, errorLogger, settings); } } } @@ -6202,20 +6212,22 @@ struct ConditionHandler { const Token* exprTok, const std::list& values, TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { - return valueFlowForward(start->next(), stop, exprTok, values, tokenlist, settings, loc); + return valueFlowForward(start->next(), stop, exprTok, values, tokenlist, errorLogger, settings, loc); } virtual Analyzer::Result forward(Token* top, const Token* exprTok, const std::list& values, TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { - return valueFlowForwardRecursive(top, exprTok, values, tokenlist, settings, loc); + return valueFlowForwardRecursive(top, exprTok, values, tokenlist, errorLogger, settings, loc); } virtual void reverse(Token* start, @@ -6223,10 +6235,11 @@ struct ConditionHandler { const Token* exprTok, const std::list& values, TokenList& tokenlist, + ErrorLogger* errorLogger, const Settings& settings, SourceLocation loc = SourceLocation::current()) const { - return valueFlowReverse(start, endToken, exprTok, values, tokenlist, settings, loc); + return valueFlowReverse(start, endToken, exprTok, values, tokenlist, errorLogger, settings, loc); } void traverseCondition(const TokenList& tokenlist, @@ -6353,7 +6366,7 @@ struct ConditionHandler { })) { // Start at the end of the loop body Token* bodyTok = top->link()->next(); - reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist, settings); + reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist, errorLogger, settings); } if (settings.debugwarnings) bailout(tokenlist, @@ -6372,7 +6385,7 @@ struct ConditionHandler { if (!startTok) startTok = tok->previous(); - reverse(startTok, nullptr, cond.vartok, values, tokenlist, settings); + reverse(startTok, nullptr, cond.vartok, values, tokenlist, errorLogger, settings); }); } @@ -6465,7 +6478,7 @@ struct ConditionHandler { return v.isImpossible(); }); for (Token* start:nextExprs) { - Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, settings); + Analyzer::Result r = forward(start, cond.vartok, values, tokenlist, errorLogger, settings); if (r.terminate != Analyzer::Terminate::None || r.action.isModified()) return; } @@ -6525,8 +6538,8 @@ struct ConditionHandler { if (Token::simpleMatch(condTop, "?")) { Token* colon = condTop->astOperand2(); - forward(colon->astOperand1(), cond.vartok, thenValues, tokenlist, settings); - forward(colon->astOperand2(), cond.vartok, elseValues, tokenlist, settings); + forward(colon->astOperand1(), cond.vartok, thenValues, tokenlist, errorLogger, settings); + forward(colon->astOperand2(), cond.vartok, elseValues, tokenlist, errorLogger, settings); // TODO: Handle after condition return; } @@ -6613,7 +6626,7 @@ struct ConditionHandler { if (allowKnown) valueFlowSetConditionToKnown(condTok, values, i == 0); - Analyzer::Result r = forward(startTokens[i], startTokens[i]->link(), cond.vartok, values, tokenlist, settings); + Analyzer::Result r = forward(startTokens[i], startTokens[i]->link(), cond.vartok, values, tokenlist, errorLogger, settings); deadBranch[i] = r.terminate == Analyzer::Terminate::Escape; if (r.action.isModified() && !deadBranch[i]) changeBlock = i; @@ -6722,7 +6735,7 @@ struct ConditionHandler { if (isKnown && isBreakOrContinueScope(after)) { const Scope* loopScope = getLoopScope(cond.vartok); if (loopScope) { - Analyzer::Result r = forward(after, loopScope->bodyEnd, cond.vartok, values, tokenlist, settings); + Analyzer::Result r = forward(after, loopScope->bodyEnd, cond.vartok, values, tokenlist, errorLogger, settings); if (r.terminate != Analyzer::Terminate::None) return; if (r.action.isModified()) @@ -6730,14 +6743,14 @@ struct ConditionHandler { auto* start = const_cast(loopScope->bodyEnd); if (Token::simpleMatch(start, "} while (")) { start = start->tokAt(2); - forward(start, start->link(), cond.vartok, values, tokenlist, settings); + forward(start, start->link(), cond.vartok, values, tokenlist, errorLogger, settings); start = start->link(); } values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible)); changeKnownToPossible(values); } } - forward(after, ValueFlow::getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, settings); + forward(after, ValueFlow::getEndOfExprScope(cond.vartok, scope), cond.vartok, values, tokenlist, errorLogger, settings); } }); } @@ -7146,7 +7159,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart, } } -static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, const Settings& settings) +static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, ErrorLogger * const errorLogger, const Settings& settings) { const Token *vartok = nullptr; for (const Token *tok = fortok; tok; tok = tok->next()) { @@ -7170,7 +7183,7 @@ static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const ValueFlow::Value v{num}; v.errorPath.emplace_back(fortok,"After for loop, " + var->name() + " has value " + v.infoString()); - valueFlowForward(blockTok->next(), endToken, vartok, v, tokenlist, settings); + valueFlowForward(blockTok->next(), endToken, vartok, v, tokenlist, errorLogger, settings); } } @@ -7198,7 +7211,7 @@ static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symbold std::list initValues; initValues.emplace_back(initValue, ValueFlow::Value::Bound::Lower); initValues.push_back(ValueFlow::asImpossible(initValues.back())); - Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, initValues, tokenlist, settings); + Analyzer::Result result = valueFlowForward(bodyStart, bodyStart->link(), vartok, initValues, tokenlist, errorLogger, settings); if (!result.action.isModified()) { std::list lastValues; @@ -7207,11 +7220,11 @@ static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symbold lastValues.push_back(ValueFlow::asImpossible(lastValues.back())); if (stepValue != 1) lastValues.pop_front(); - valueFlowForward(bodyStart, bodyStart->link(), vartok, lastValues, tokenlist, settings); + valueFlowForward(bodyStart, bodyStart->link(), vartok, lastValues, tokenlist, errorLogger, settings); } } const MathLib::bigint afterValue = executeBody ? lastValue + stepValue : initValue; - valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, settings); + valueFlowForLoopSimplifyAfter(tok, varid, afterValue, tokenlist, errorLogger, settings); } else { ProgramMemory mem1, mem2, memAfter; if (valueFlowForLoop2(tok, &mem1, &mem2, &memAfter)) { @@ -7240,7 +7253,7 @@ static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symbold continue; if (p.first.tok->varId() == 0) continue; - valueFlowForLoopSimplifyAfter(tok, p.first.getExpressionId(), p.second.intvalue, tokenlist, settings); + valueFlowForLoopSimplifyAfter(tok, p.first.getExpressionId(), p.second.intvalue, tokenlist, errorLogger, settings); } } } @@ -7461,7 +7474,7 @@ static void valueFlowInjectParameter(TokenList& tokenlist, { const bool r = productParams(settings, vars, [&](const std::unordered_map& arg) { MultiValueFlowAnalyzer a(arg, tokenlist, settings); - valueFlowGenericForward(const_cast(functionScope->bodyStart), functionScope->bodyEnd, a, settings); + valueFlowGenericForward(const_cast(functionScope->bodyStart), functionScope->bodyEnd, a, tokenlist, errorLogger, settings); }); if (!r) { std::string fname = ""; @@ -7473,6 +7486,7 @@ static void valueFlowInjectParameter(TokenList& tokenlist, } static void valueFlowInjectParameter(const TokenList& tokenlist, + ErrorLogger* const errorLogger, const Settings& settings, const Variable* arg, const Scope* functionScope, @@ -7492,6 +7506,7 @@ static void valueFlowInjectParameter(const TokenList& tokenlist, arg->nameToken(), argvalues, tokenlist, + errorLogger, settings); } @@ -7713,7 +7728,7 @@ static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase& symboldat } } -static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings& settings) +static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings) { if (!tokenlist.isCPP()) return; @@ -7735,7 +7750,7 @@ static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const argvalues.push_back(std::move(v)); } if (!argvalues.empty()) - valueFlowInjectParameter(tokenlist, settings, var, scope, argvalues); + valueFlowInjectParameter(tokenlist, errorLogger, settings, var, scope, argvalues); } } } @@ -7950,7 +7965,7 @@ static Token* findStartToken(const Variable* var, Token* start, const Library* l return tok; } -static void valueFlowUninit(TokenList& tokenlist, const Settings& settings) +static void valueFlowUninit(TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings) { for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (!tok->scope()->isExecutable()) @@ -7993,7 +8008,7 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings& settings) continue; } MemberExpressionAnalyzer analyzer(memVar.nameToken()->str(), tok, uninitValue, tokenlist, settings); - valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, settings); + valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, tokenlist, errorLogger, settings); for (auto&& p : *analyzer.partialReads) { Token* tok2 = p.first; @@ -8023,7 +8038,7 @@ static void valueFlowUninit(TokenList& tokenlist, const Settings& settings) if (partial) continue; - valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist, settings); + valueFlowForward(start, tok->scope()->bodyEnd, var->nameToken(), uninitValue, tokenlist, errorLogger, settings); } } @@ -8660,7 +8675,7 @@ static std::vector getContainerSizeFromConstructor(const Token return getContainerSizeFromConstructorArgs(args, valueType->container, known); } -static void valueFlowContainerSetTokValue(TokenList& tokenlist, const Settings& settings, const Token* tok, Token* initList) +static void valueFlowContainerSetTokValue(TokenList& tokenlist, ErrorLogger* const errorLogger, const Settings& settings, const Token* tok, Token* initList) { ValueFlow::Value value; value.valueType = ValueFlow::Value::ValueType::TOK; @@ -8673,7 +8688,7 @@ static void valueFlowContainerSetTokValue(TokenList& tokenlist, const Settings& if (tok->variable() && tok->variable()->isConst()) { valueFlowForwardConst(start, tok->variable()->scope()->bodyEnd, tok->variable(), {value}, settings); } else { - valueFlowForward(start, tok, value, tokenlist, settings); + valueFlowForward(start, tok, value, tokenlist, errorLogger, settings); } } @@ -8700,7 +8715,7 @@ static MathLib::bigint valueFlowGetStrLength(const Token* tok) static void valueFlowContainerSize(TokenList& tokenlist, const SymbolDatabase& symboldatabase, - ErrorLogger* /*errorLogger*/, + ErrorLogger* const errorLogger, const Settings& settings, const std::set& skippedFunctions) { @@ -8757,7 +8772,7 @@ static void valueFlowContainerSize(TokenList& tokenlist, if (!staticSize) { if (Token::simpleMatch(nameToken->next(), "{")) { Token* initList = nameToken->next(); - valueFlowContainerSetTokValue(tokenlist, settings, nameToken, initList); + valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, nameToken, initList); values = getInitListSize(initList, var->valueType(), settings, known); } else if (Token::simpleMatch(nameToken->next(), "(")) { const Token* constructorArgs = nameToken->next(); @@ -8771,7 +8786,7 @@ static void valueFlowContainerSize(TokenList& tokenlist, } for (const ValueFlow::Value& value : values) { - valueFlowForward(nameToken->next(), var->nameToken(), value, tokenlist, settings); + valueFlowForward(nameToken->next(), var->nameToken(), value, tokenlist, errorLogger, settings); } } @@ -8784,11 +8799,11 @@ static void valueFlowContainerSize(TokenList& tokenlist, continue; if (containerTok->valueType() && containerTok->valueType()->container && containerTok->valueType()->container->stdStringLike) { - valueFlowContainerSetTokValue(tokenlist, settings, containerTok, containerTok->tokAt(2)); + valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, containerTok, containerTok->tokAt(2)); ValueFlow::Value value(Token::getStrLength(containerTok->tokAt(2))); value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; value.setKnown(); - valueFlowForward(containerTok->next(), containerTok, value, tokenlist, settings); + valueFlowForward(containerTok->next(), containerTok, value, tokenlist, errorLogger, settings); } } else if (Token::Match(tok->previous(), ">|return (|{") && astIsContainer(tok) && getLibraryContainer(tok)->size_templateArgNo < 0) { std::vector values; @@ -8812,9 +8827,9 @@ static void valueFlowContainerSize(TokenList& tokenlist, if (astIsContainer(containerTok) && containerTok->valueType()->container->size_templateArgNo < 0) { std::vector values = getInitListSize(tok->tokAt(3), containerTok->valueType(), settings); - valueFlowContainerSetTokValue(tokenlist, settings, containerTok, tok->tokAt(3)); + valueFlowContainerSetTokValue(tokenlist, errorLogger, settings, containerTok, tok->tokAt(3)); for (const ValueFlow::Value& value : values) - valueFlowForward(containerTok->next(), containerTok, value, tokenlist, settings); + valueFlowForward(containerTok->next(), containerTok, value, tokenlist, errorLogger, settings); } } else if (Token::Match(tok, ". %name% (") && tok->astOperand1() && tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->container) { @@ -8826,18 +8841,18 @@ static void valueFlowContainerSize(TokenList& tokenlist, ValueFlow::Value value(0); value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; value.setKnown(); - valueFlowForward(tok->next(), containerTok, value, tokenlist, settings); + valueFlowForward(tok->next(), containerTok, value, tokenlist, errorLogger, settings); } else if (action == Library::Container::Action::RESIZE && tok->tokAt(2)->astOperand2() && tok->tokAt(2)->astOperand2()->hasKnownIntValue()) { ValueFlow::Value value(tok->tokAt(2)->astOperand2()->values().front()); value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; value.setKnown(); - valueFlowForward(tok->linkAt(2), containerTok, value, tokenlist, settings); + valueFlowForward(tok->linkAt(2), containerTok, value, tokenlist, errorLogger, settings); } else if (action == Library::Container::Action::PUSH && !isIteratorPair(getArguments(tok->tokAt(2)))) { ValueFlow::Value value(0); value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; value.setImpossible(); - valueFlowForward(tok->linkAt(2), containerTok, value, tokenlist, settings); + valueFlowForward(tok->linkAt(2), containerTok, value, tokenlist, errorLogger, settings); } } else if (Token::simpleMatch(tok, "+=") && astIsContainer(tok->astOperand1())) { const Token* containerTok = tok->astOperand1(); @@ -8852,7 +8867,7 @@ static void valueFlowContainerSize(TokenList& tokenlist, Token* next = nextAfterAstRightmostLeaf(tok); if (!next) next = tok->next(); - valueFlowForward(next, containerTok, value, tokenlist, settings); + valueFlowForward(next, containerTok, value, tokenlist, errorLogger, settings); } } } @@ -8927,7 +8942,7 @@ struct ContainerConditionHandler : ConditionHandler { } }; -static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings& settings) +static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings) { auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint { MathLib::bigint sizeValue = -1; @@ -9024,7 +9039,7 @@ static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolD value.errorPath.emplace_back(tok->tokAt(2), "Assign " + tok->strAt(1) + ", buffer with size " + std::to_string(sizeValue)); value.valueType = ValueFlow::Value::ValueType::BUFFER_SIZE; value.setKnown(); - valueFlowForward(const_cast(rhs), functionScope->bodyEnd, tok->next(), std::move(value), tokenlist, settings); + valueFlowForward(const_cast(rhs), functionScope->bodyEnd, tok->next(), std::move(value), tokenlist, errorLogger, settings); } } } @@ -9096,7 +9111,7 @@ static bool getMinMaxValues(const std::string &typestr, const Settings &settings return getMinMaxValues(&vt, settings.platform, minvalue, maxvalue); } -static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings& settings) +static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger* const errorLogger, const Settings& settings) { for (const Scope *functionScope : symboldatabase.functionScopes) { if (!functionScope->bodyStart) @@ -9125,7 +9140,7 @@ static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& s argValues.back().errorPath.emplace_back(arg.nameToken(), "Assuming " + arg.name() + " size is 1000000"); argValues.back().safe = true; for (const ValueFlow::Value &value : argValues) - valueFlowForward(const_cast(functionScope->bodyStart), arg.nameToken(), value, tokenlist, settings); + valueFlowForward(const_cast(functionScope->bodyStart), arg.nameToken(), value, tokenlist, errorLogger, settings); continue; } @@ -9164,6 +9179,7 @@ static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& s arg.nameToken(), argValues, tokenlist, + errorLogger, settings); continue; } @@ -9187,6 +9203,7 @@ static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& s arg.nameToken(), argValues, tokenlist, + errorLogger, settings); } } @@ -9470,7 +9487,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowGlobalStaticVar(tokenlist, settings)), VFA(valueFlowPointerAlias(tokenlist, settings)), VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), - VFA(valueFlowSymbolic(tokenlist, symboldatabase, settings)), + VFA(valueFlowSymbolic(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowBitAnd(tokenlist, settings)), VFA(valueFlowSameExpressions(tokenlist, settings)), VFA(valueFlowConditionExpressions(tokenlist, symboldatabase, errorLogger, settings)), @@ -9493,9 +9510,9 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)), VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), - VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, settings)), - VFA(valueFlowUninit(tokenlist, settings)), - VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, settings)), + VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings)), + VFA(valueFlowUninit(tokenlist, errorLogger, settings)), + VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, errorLogger, settings)), VFA_CPP(valueFlowSmartPointer(tokenlist, errorLogger, settings)), VFA_CPP(valueFlowIterators(tokenlist, settings)), VFA_CPP( @@ -9504,11 +9521,11 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA_CPP(valueFlowContainerSize(tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), VFA_CPP( valueFlowCondition(ContainerConditionHandler{}, tokenlist, symboldatabase, errorLogger, settings, skippedFunctions)), - VFA(valueFlowSafeFunctions(tokenlist, symboldatabase, settings)), + VFA(valueFlowSafeFunctions(tokenlist, symboldatabase, errorLogger, settings)), }); runner.run_once({ - VFA(valueFlowDynamicBufferSize(tokenlist, symboldatabase, settings)), + VFA(valueFlowDynamicBufferSize(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowDebug(tokenlist, errorLogger, settings)), }); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 81fd6458cdb..328217b8896 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -118,6 +118,7 @@ if (BUILD_TESTS) COMMAND $ --library=${LIBRARY} --check-library + --check-level=exhaustive --platform=${PLATFORM} --enable=style,information --inconclusive diff --git a/test/cfg/runtests.sh b/test/cfg/runtests.sh index 4a51f7c6d1a..71b865e3ee1 100755 --- a/test/cfg/runtests.sh +++ b/test/cfg/runtests.sh @@ -27,7 +27,7 @@ CFG="$DIR"../../cfg/ # TODO: remove missingInclude disabling when it no longer is implied by --enable=information # Cppcheck options # need to suppress unmatchedSuppression in case valueFlowBailout is not reported -CPPCHECK_OPT='--check-library --platform=unix64 --enable=style,information --inconclusive --force --error-exitcode=-1 --disable=missingInclude --inline-suppr --template="{file}:{line}:{severity}:{id}:{message}" --debug-warnings --suppress=valueFlowBailout --suppress=purgedConfiguration --suppress=unmatchedSuppression' +CPPCHECK_OPT='--check-library --platform=unix64 --enable=style,information --inconclusive --force --check-level=exhaustive --error-exitcode=-1 --disable=missingInclude --inline-suppr --template="{file}:{line}:{severity}:{id}:{message}" --debug-warnings --suppress=valueFlowBailout --suppress=purgedConfiguration --suppress=unmatchedSuppression' # Compiler settings CXX=g++ diff --git a/test/fixture.cpp b/test/fixture.cpp index 6318dc151b3..f8a433d66e7 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -402,6 +402,8 @@ void TestFixture::reportErr(const ErrorMessage &msg) { if (msg.severity == Severity::internal) return; + if (msg.severity == Severity::information && msg.id == "normalCheckLevelMaxBranches") + return; const std::string errormessage(msg.toString(mVerbose, mTemplateFormat, mTemplateLocation)); errout << errormessage << std::endl; } @@ -422,6 +424,11 @@ void TestFixture::setTemplateFormat(const std::string &templateFormat) } } +TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::exhaustive() { + settings.setCheckLevelExhaustive(); + return *this; +} + TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::library(const char lib[]) { if (REDUNDANT_CHECK && std::find(settings.libraries.cbegin(), settings.libraries.cend(), lib) != settings.libraries.cend()) throw std::runtime_error("redundant setting: libraries (" + std::string(lib) + ")"); diff --git a/test/fixture.h b/test/fixture.h index f5d94cd026a..1a8b3878db4 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -198,6 +198,8 @@ class TestFixture : public ErrorLogger { return *this; } + SettingsBuilder& exhaustive(); + SettingsBuilder& library(const char lib[]); SettingsBuilder& libraryxml(const char xmldata[], std::size_t len); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index ab40dd5e817..df48369c6cc 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -142,7 +142,7 @@ class TestCondition : public TestFixture { } void check_(const char* file, int line, const char code[], const char* filename = "test.cpp", bool inconclusive = false) { - const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive, inconclusive).build(); + const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive, inconclusive).exhaustive().build(); check_(file, line, code, settings, filename); } diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 3f68230420f..b3096edffcb 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -237,7 +237,7 @@ class TestSimplifyTypedef : public TestFixture { errout.str(""); // show warnings about unhandled typedef - const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive).debugwarnings(debugwarnings).platform(type).build(); + const Settings settings = settingsBuilder(settings0).exhaustive().certainty(Certainty::inconclusive).debugwarnings(debugwarnings).platform(type).build(); Tokenizer tokenizer(settings, this); std::istringstream istr(code); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index f4a313171fe..0bd82aacc5a 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -2438,7 +2438,7 @@ class TestSymbolDatabase : public TestFixture { errout.str(""); // Check.. - const Settings settings = settingsBuilder(pSettings ? *pSettings : settings1).debugwarnings(debug).build(); + const Settings settings = settingsBuilder(pSettings ? *pSettings : settings1).debugwarnings(debug).exhaustive().build(); // Tokenize.. Tokenizer tokenizer(settings, this); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index bf97ca1ced3..ddca3275906 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -42,7 +42,7 @@ class TestValueFlow : public TestFixture { TestValueFlow() : TestFixture("TestValueFlow") {} private: - Settings settings = settingsBuilder().library("std.cfg").build(); + Settings settings = settingsBuilder().library("std.cfg").exhaustive().build(); void run() override { // strcpy, abort cfg @@ -485,7 +485,7 @@ class TestValueFlow : public TestFixture { #define bailout(...) bailout_(__FILE__, __LINE__, __VA_ARGS__) void bailout_(const char* file, int line, const char code[]) { - const Settings s = settingsBuilder().debugwarnings().build(); + const Settings s = settingsBuilder().debugwarnings().exhaustive().build(); errout.str(""); std::vector files(1, "test.cpp"); @@ -6867,7 +6867,7 @@ class TestValueFlow : public TestFixture { void valueFlowSafeFunctionParameterValues() { const char *code; std::list values; - Settings s = settingsBuilder().library("std.cfg").build(); + Settings s = settingsBuilder().exhaustive().library("std.cfg").build(); s.safeChecks.classes = s.safeChecks.externalFunctions = s.safeChecks.internalFunctions = true; code = "short f(short x) {\n" @@ -6918,7 +6918,7 @@ class TestValueFlow : public TestFixture { void valueFlowUnknownFunctionReturn() { const char *code; std::list values; - Settings s = settingsBuilder().library("std.cfg").build(); + Settings s = settingsBuilder().exhaustive().library("std.cfg").build(); s.checkUnknownFunctionReturn.insert("rand"); code = "x = rand();";