diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 1b04d4f84..fb84b502d 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -1404,6 +1404,22 @@ bool FwdAnalysis::possiblyAliased(const Token *expr, const Token *startToken) co if (tok->str() == "{" && tok->scope()->type == Scope::eFunction) break; + if (Token::Match(tok, "%name% (") && !Token::Match(tok, "if|while|for")) { + // Is argument passed by reference? + const std::vector args = getArguments(tok); + for (unsigned int argnr = 0; argnr < args.size(); ++argnr) { + if (!Token::Match(args[argnr], "%name%|.|::")) + continue; + if (tok->function() && tok->function()->getArgumentVar(argnr) && !tok->function()->getArgumentVar(argnr)->isReference() && !tok->function()->isConst()) + continue; + for (const Token *subexpr = expr; subexpr; subexpr = subexpr->astOperand1()) { + if (isSameExpression(mCpp, macro, subexpr, args[argnr], mLibrary, pure, followVar)) + return true; + } + } + continue; + } + const Token *addrOf = nullptr; if (Token::Match(tok, "& %name% =")) addrOf = tok->tokAt(2)->astOperand2(); diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 9598ea0eb..8cc6b79f1 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -822,7 +822,6 @@ void Preprocessor::getErrorMessages(ErrorLogger *errorLogger, const Settings *se { Settings settings2(*settings); Preprocessor preprocessor(settings2, errorLogger); - // cppcheck-suppress unreadVariable // FP settings2.checkConfiguration = true; preprocessor.missingInclude(emptyString, 1, emptyString, UserHeader); preprocessor.missingInclude(emptyString, 1, emptyString, SystemHeader); diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 33f3cc46f..e842aae72 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -2161,14 +2161,25 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'x' is assigned a value that is never used.\n", errout.str()); - functionVariableUsage("void fun() {\n" + functionVariableUsage("void dostuff(int x);\n" + "void fun() {\n" " int x = 1;\n" " while (c) {\n" " dostuff(x);\n" " if (y) { x=10; break; }\n" " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:5]: (style) Variable 'x' is assigned a value that is never used.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:6]: (style) Variable 'x' is assigned a value that is never used.\n", errout.str()); + + functionVariableUsage("void dostuff(int &x);\n" + "void fun() {\n" + " int x = 1;\n" + " while (c) {\n" + " dostuff(x);\n" + " if (y) { x=10; break; }\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); // TODO : in this special case we can ignore that x is aliased. x is local and there are no function calls after the assignment functionVariableUsage("void fun() {\n" " int x = 0;\n" @@ -3170,11 +3181,25 @@ private: } void localvaralias14() { // #5619 + functionVariableUsage("char * dostuff(char *p);\n" + "void f() {\n" + " char a[4], *p=a;\n" + " p = dostuff(p);\n" + "}"); + ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'p' is assigned a value that is never used.\n", errout.str()); + + functionVariableUsage("char * dostuff(char *&p);\n" + "void f() {\n" + " char a[4], *p=a;\n" + " p = dostuff(p);\n" + "}"); + ASSERT_EQUALS("", errout.str()); // TODO: we can warn in this special case; variable is local and there are no function calls after the assignment + functionVariableUsage("void f() {\n" " char a[4], *p=a;\n" " p = dostuff(p);\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'p' is assigned a value that is never used.\n", errout.str()); + ASSERT_EQUALS("", errout.str()); // TODO: we can warn in this special case; variable is local and there are no function calls after the assignment } void localvaralias15() { // #6315