From 26ba29c303c19ca957047312f281642f29019177 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 21 Oct 2023 12:41:39 +0200 Subject: [PATCH] Fix #12086 FN passedByValue with index operator and namespaced function call (#5574) --- lib/astutils.cpp | 2 +- lib/astutils.h | 2 +- lib/checkother.cpp | 20 ++------------------ lib/valueflow.cpp | 2 +- test/testother.cpp | 8 ++++++++ 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 949d79b70..e735a078f 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3052,7 +3052,7 @@ const Token* getIteratorExpression(const Token* tok) return nullptr; } -bool isIteratorPair(std::vector args) +bool isIteratorPair(const std::vector& args) { if (args.size() != 2) return false; diff --git a/lib/astutils.h b/lib/astutils.h index dd56b4cb5..c5fe9e095 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -393,7 +393,7 @@ const Token* getIteratorExpression(const Token* tok); /** * Are the arguments a pair of iterators/pointers? */ -bool isIteratorPair(std::vector args); +bool isIteratorPair(const std::vector& args); CPPCHECKLIB const Token *findLambdaStartToken(const Token *last); diff --git a/lib/checkother.cpp b/lib/checkother.cpp index a8120b59c..d937e625b 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1281,27 +1281,11 @@ static bool canBeConst(const Variable *var, const Settings* settings) if (parent->str() == ">>" && parent->astOperand2() == tok2) return false; } else if (parent->str() == "," || parent->str() == "(") { // function argument - const Token* tok3 = tok2->previous(); - int argNr = 0; - while (tok3 && tok3->str() != "(") { - if (tok3->link() && Token::Match(tok3, ")|]|}|>")) - tok3 = tok3->link(); - else if (tok3->link()) - break; - else if (tok3->str() == ";") - break; - else if (tok3->str() == ",") - argNr++; - tok3 = tok3->previous(); - } - if (!tok3 || tok3->str() != "(") - return false; - const Token* functionTok = tok3->astOperand1(); + int argNr = -1; + const Token* functionTok = getTokenArgumentFunction(tok2, argNr); if (!functionTok) return false; const Function* tokFunction = functionTok->function(); - if (!tokFunction && functionTok->str() == "." && (functionTok = functionTok->astOperand2())) - tokFunction = functionTok->function(); if (tokFunction) { const Variable* argVar = tokFunction->getArgumentVar(argNr); if (!argVar || (!argVar->isConst() && argVar->isReference())) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index eebe52fd2..ff8279d99 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4280,7 +4280,7 @@ static bool hasBorrowingVariables(const std::list& vars, const std::ve static void valueFlowLifetimeUserConstructor(Token* tok, const Function* constructor, const std::string& name, - std::vector args, + const std::vector& args, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings* settings) diff --git a/test/testother.cpp b/test/testother.cpp index 2912b1d59..b3d0fc0d2 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2159,6 +2159,14 @@ private: "T::T(std::string s) noexcept(true) : m(std::move(s)) {}\n"); ASSERT_EQUALS("", errout.str()); + check("namespace N {\n" // #12086 + " void g(int);\n" + "}\n" + "void f(std::vector v) {\n" + " N::g(v[0]);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (performance) Function parameter 'v' should be passed by const reference.\n", errout.str()); + Settings settings1 = settingsBuilder().platform(Platform::Type::Win64).build(); check("using ui64 = unsigned __int64;\n" "ui64 Test(ui64 one, ui64 two) { return one + two; }\n",