From 3913fd8398d9fcec8a6e8ea65ab3823e894a9bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 18 Dec 2012 19:02:30 +0100 Subject: [PATCH] Fixed #4320 (False positives 'unassignedVariable' and 'uninitvar') --- lib/checkuninitvar.cpp | 14 ++++++++++---- lib/checkunusedvar.cpp | 4 ++++ test/testuninitvar.cpp | 15 +++++++++++++++ test/testunusedvar.cpp | 7 +++++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 2b609ecf1..ff5fb54dd 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -574,7 +574,8 @@ private: return tok.tokAt(3); } - else if ((!isC && Token::Match(tok.previous(), "<<|>>")) || Token::simpleMatch(tok.next(), "=")) { + else if ((!isC && (Token::Match(tok.previous(), "<<|>>") || Token::Match(tok.previous(), "[;{}] %var% <<"))) || + Token::simpleMatch(tok.next(), "=")) { // TODO: Don't bail out for "<<" and ">>" if these are // just computations ExecutionPath::bailOutVar(checks, tok.varId()); @@ -1328,12 +1329,17 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer) const } if (_tokenizer->isCPP() && Token::Match(vartok->next(), "<<|>>")) { + // Is this calculation done in rhs? + const Token *tok = vartok; + while (tok && Token::Match(tok, "%var%|.|::")) + tok = tok->previous(); + if (Token::Match(tok, "[;{}]")) + return false; + // Is variable a known POD type then this is a variable usage, // otherwise we assume it's not. const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(vartok->varId()); - if (var && var->typeStartToken()->isStandardType()) - return true; - return false; + return (var && var->typeStartToken()->isStandardType()); } if (Token::Match(vartok->next(), "++|--|%op%")) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index a9b91c365..15b631719 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -954,6 +954,10 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const } } + else if (_tokenizer->isCPP() && Token::Match(tok, "[;{}] %var% <<")) { + variables.erase(tok->next()->varId()); + } + else if (Token::Match(tok, "& %var%")) { if (tok->previous()->isName() || tok->previous()->isNumber()) { // bitop variables.read(tok->next()->varId(), tok); diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index fb2ba7d81..42361ae80 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -377,6 +377,14 @@ private: "}\n", "test.c"); ASSERT_EQUALS("[test.c:3]: (error) Uninitialized variable: ret\n", errout.str()); + + // #4320 + checkUninitVar("void f() {\n" + " int a;\n" + " a << 1;\n" + " return a;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } checkUninitVar("void a() {\n" // asm @@ -2341,6 +2349,13 @@ private: " char a = c << 2;\n" "}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: c\n", errout.str()); + + // #4320 + checkUninitVar2("void f() {\n" + " int a;\n" + " a << 1;\n" // there might be a operator<< + "}\n"); + ASSERT_EQUALS("", errout.str()); } // Handling of unknown types. Assume they are POD in C. diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index dda000258..975820940 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -3005,6 +3005,13 @@ private: " ints << 1;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + functionVariableUsage("int foo() {\n" // #4320 + " int x;\n" + " x << 1;\n" + " return x;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void localvarCast() {