diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 5c97528372b..56cdbee83d0 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -46,8 +46,8 @@ namespace { struct ForwardTraversal { enum class Progress : std::uint8_t { Continue, Break, Skip }; - ForwardTraversal(const ValuePtr& analyzer, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) - : analyzer(analyzer), tokenList(tokenList), errorLogger(errorLogger), settings(settings) + ForwardTraversal(ValuePtr analyzer, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) + : analyzer(std::move(analyzer)), tokenList(tokenList), errorLogger(errorLogger), settings(settings) {} ValuePtr analyzer; const TokenList& tokenList; @@ -316,7 +316,7 @@ namespace { } ForwardTraversal fork(bool analyze = false) const { - ForwardTraversal ft = *this; + ForwardTraversal ft = *this; // copy if (analyze) { ft.analyzeOnly = true; ft.analyzeTerminate = true; @@ -937,24 +937,24 @@ namespace { }; } -Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) +Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, ValuePtr a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) { if (a->invalid()) return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail}; - ForwardTraversal ft{a, tokenList, errorLogger, settings}; + ForwardTraversal ft{std::move(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 TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) +Analyzer::Result valueFlowGenericForward(Token* start, ValuePtr a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings) { if (Settings::terminated()) throw TerminateException(); if (a->invalid()) return Analyzer::Result{Analyzer::Action::None, Analyzer::Terminate::Bail}; - ForwardTraversal ft{a, tokenList, errorLogger, settings}; + ForwardTraversal ft{std::move(a), tokenList, errorLogger, settings}; (void)ft.updateRecursive(start); return Analyzer::Result{ ft.actions, ft.terminate }; } diff --git a/lib/forwardanalyzer.h b/lib/forwardanalyzer.h index 7b722f48c35..82dce539f11 100644 --- a/lib/forwardanalyzer.h +++ b/lib/forwardanalyzer.h @@ -29,11 +29,11 @@ template class ValuePtr; Analyzer::Result valueFlowGenericForward(Token* start, const Token* end, - const ValuePtr& a, + ValuePtr a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings); -Analyzer::Result valueFlowGenericForward(Token* start, const ValuePtr& a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings); +Analyzer::Result valueFlowGenericForward(Token* start, ValuePtr a, const TokenList& tokenList, ErrorLogger& errorLogger, const Settings& settings); #endif diff --git a/lib/reverseanalyzer.cpp b/lib/reverseanalyzer.cpp index 50aad01fdd9..eeea8cf6b66 100644 --- a/lib/reverseanalyzer.cpp +++ b/lib/reverseanalyzer.cpp @@ -37,8 +37,8 @@ namespace { struct ReverseTraversal { - ReverseTraversal(const ValuePtr& analyzer, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) - : analyzer(analyzer), tokenlist(tokenlist), errorLogger(errorLogger), settings(settings) + ReverseTraversal(ValuePtr analyzer, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) + : analyzer(std::move(analyzer)), tokenlist(tokenlist), errorLogger(errorLogger), settings(settings) {} ValuePtr analyzer; const TokenList& tokenlist; @@ -254,7 +254,7 @@ namespace { if (a) { valueFlowGenericForward(nextAfterAstRightmostLeaf(assignTok->astOperand2()), assignTok->astOperand2()->scope()->bodyEnd, - a, + std::move(a), tokenlist, errorLogger, settings); @@ -268,11 +268,11 @@ namespace { if (a) { valueFlowGenericForward(nextAfterAstRightmostLeaf(assignTok->astOperand2()), assignTok->astOperand2()->scope()->bodyEnd, - a, + a, // copy tokenlist, errorLogger, settings); - valueFlowGenericReverse(assignTok->astOperand1()->previous(), end, a, tokenlist, errorLogger, settings); + valueFlowGenericReverse(assignTok->astOperand1()->previous(), end, std::move(a), tokenlist, errorLogger, settings); } } } @@ -305,7 +305,7 @@ namespace { if (inLoop) { if (Token::findmatch(tok->link(), "goto|break", tok)) break; - valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); + valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); // copy of analyzer } Token* thenEnd; const bool hasElse = Token::simpleMatch(tok->link()->tokAt(-2), "} else {"); @@ -334,7 +334,7 @@ namespace { break; if (!thenAction.isModified() && !elseAction.isModified()) - valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); + valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); // copy of analyzer else if (condAction.isRead()) break; // If the condition modifies the variable then bail @@ -353,7 +353,7 @@ namespace { } Token* condTok = getCondTokFromEnd(tok->link()); if (condTok) { - Analyzer::Result r = valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); + Analyzer::Result r = valueFlowGenericForward(condTok, analyzer, tokenlist, errorLogger, settings); // copy of analyzer if (r.action.isModified()) break; } @@ -406,10 +406,10 @@ namespace { }; } -void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) +void valueFlowGenericReverse(Token* start, const Token* end, ValuePtr a, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings) { if (a->invalid()) return; - ReverseTraversal rt{a, tokenlist, errorLogger, settings}; + ReverseTraversal rt{std::move(a), tokenlist, errorLogger, settings}; rt.traverse(start, end); } diff --git a/lib/reverseanalyzer.h b/lib/reverseanalyzer.h index 2a9877fb337..a7cf5575349 100644 --- a/lib/reverseanalyzer.h +++ b/lib/reverseanalyzer.h @@ -27,6 +27,6 @@ class TokenList; template class ValuePtr; -void valueFlowGenericReverse(Token* start, const Token* end, const ValuePtr& a, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings); +void valueFlowGenericReverse(Token* start, const Token* end, ValuePtr a, const TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings); #endif diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 83f183643e6..c4bdbe3d4a1 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3432,14 +3432,14 @@ static void valueFlowConditionExpressions(const TokenList& tokenlist, condTok2, makeConditionValue(1, condTok2, /*assume*/ true, !isBool, settings), settings); // don't set '1' for non-boolean expressions - valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings); + valueFlowGenericForward(startTok, startTok->link(), std::move(a1), tokenlist, errorLogger, settings); } auto a2 = makeOppositeExpressionAnalyzer(true, condTok2, makeConditionValue(0, condTok2, true, false, settings), settings); - valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings); + valueFlowGenericForward(startTok, startTok->link(), std::move(a2), tokenlist, errorLogger, settings); } } @@ -3454,7 +3454,7 @@ static void valueFlowConditionExpressions(const TokenList& tokenlist, auto a1 = makeSameExpressionAnalyzer(condTok2, makeConditionValue(0, condTok2, false, false, settings), settings); - valueFlowGenericForward(startTok, startTok->link(), a1, tokenlist, errorLogger, settings); + valueFlowGenericForward(startTok, startTok->link(), std::move(a1), tokenlist, errorLogger, settings); if (is1) { auto a2 = @@ -3462,7 +3462,7 @@ static void valueFlowConditionExpressions(const TokenList& tokenlist, condTok2, makeConditionValue(isOp, condTok2, false, false, settings), settings); - valueFlowGenericForward(startTok, startTok->link(), a2, tokenlist, errorLogger, settings); + valueFlowGenericForward(startTok, startTok->link(), std::move(a2), tokenlist, errorLogger, settings); } } } @@ -3480,7 +3480,7 @@ static void valueFlowConditionExpressions(const TokenList& tokenlist, auto a1 = makeSameExpressionAnalyzer(condTok2, makeConditionValue(0, condTok2, false, false, settings), settings); - valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, a1, tokenlist, errorLogger, settings); + valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, std::move(a1), tokenlist, errorLogger, settings); if (is1) { auto a2 = makeOppositeExpressionAnalyzer(true, @@ -3489,7 +3489,7 @@ static void valueFlowConditionExpressions(const TokenList& tokenlist, settings); valueFlowGenericForward(startTok->link()->next(), scope2->bodyEnd, - a2, + std::move(a2), tokenlist, errorLogger, settings); @@ -5476,7 +5476,7 @@ static void valueFlowInjectParameter(const TokenList& tokenlist, auto a = makeMultiValueFlowAnalyzer(arg, settings); valueFlowGenericForward(const_cast(functionScope->bodyStart), functionScope->bodyEnd, - a, + std::move(a), tokenlist, errorLogger, settings); @@ -6026,7 +6026,7 @@ static void valueFlowUninit(TokenList& tokenlist, ErrorLogger& errorLogger, cons } auto partialReadsAnalyzer = std::make_shared(); auto analyzer = makeMemberExpressionAnalyzer(memVar.nameToken()->str(), tok, uninitValue, partialReadsAnalyzer, settings); - valueFlowGenericForward(start, tok->scope()->bodyEnd, analyzer, tokenlist, errorLogger, settings); + valueFlowGenericForward(start, tok->scope()->bodyEnd, std::move(analyzer), tokenlist, errorLogger, settings); for (auto&& p : *partialReadsAnalyzer) { Token* tok2 = p.first; diff --git a/lib/valueptr.h b/lib/valueptr.h index 270b5f58fc6..68a1aeac76c 100644 --- a/lib/valueptr.h +++ b/lib/valueptr.h @@ -26,12 +26,15 @@ #include template -class CPPCHECKLIB ValuePtr { +class ValuePtr { template struct cloner { static T* apply(const T* x) { return new U(*static_cast(x)); } + static T* move(T* x) { + return new U(std::move(*static_cast(x))); + } }; public: @@ -42,12 +45,16 @@ class CPPCHECKLIB ValuePtr { ValuePtr() : mPtr(nullptr), mClone() {} - template + template)> // cppcheck-suppress noExplicitConstructor // NOLINTNEXTLINE(google-explicit-constructor) ValuePtr(const U& value) : mPtr(cloner::apply(&value)), mClone(&cloner::apply) {} + template), REQUIRES("Must not be ValuePtr", !std::is_base_of)> + explicit ValuePtr(U&& value) : mPtr(cloner::move(&value)), mClone(&cloner::apply) + {} + ValuePtr(const ValuePtr& rhs) : mPtr(nullptr), mClone(rhs.mClone) { if (rhs) { mPtr.reset(mClone(rhs.get())); @@ -62,10 +69,10 @@ class CPPCHECKLIB ValuePtr { return mPtr.get(); } - T& operator*() { + T& operator*() noexcept { return *get(); } - const T& operator*() const { + const T& operator*() const noexcept { return *get(); }