diff --git a/lib/check.h b/lib/check.h index 186baa603..2cf53b402 100644 --- a/lib/check.h +++ b/lib/check.h @@ -104,6 +104,10 @@ public: std::cout << errmsg.toXML(true, 1) << std::endl; } + bool inconclusiveFlag() const { + return _settings && _settings->inconclusive; + } + protected: const std::string _name; const Tokenizer * const _tokenizer; diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index a260bf5be..9747210eb 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -184,8 +184,13 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) if (Token::Match(tok->tokAt(-3), "!!sizeof [;{}=+-/(,] * %var%") && Token::Match(tok->tokAt(-3), "!!decltype [;{}=+-/(,] * %var%")) return true; - if (!Token::simpleMatch(tok->tokAt(-2), "& (") && !Token::Match(tok->tokAt(-2), "sizeof|decltype (") && tok->strAt(-1) != "&" && tok->strAt(-1) != "&&" && Token::Match(tok->next(), ". %var%")) - return true; + // read/write member variable + if (!Token::simpleMatch(tok->tokAt(-2), "& (") && !Token::Match(tok->tokAt(-2), "sizeof|decltype (") && tok->strAt(-1) != "&" && tok->strAt(-1) != "&&" && Token::Match(tok->next(), ". %var%")) { + if (tok->strAt(3) != "(") + return true; + unknown = true; + return false; + } if (Token::Match(tok->previous(), "[;{}=+-/(,] %var% [")) return true; @@ -299,6 +304,11 @@ void CheckNullPointer::nullPointerAfterLoop() if (CheckNullPointer::isPointerDeRef(tok2, unknown)) { nullPointerError(tok2, varname, tok->linenr(), inconclusive); } + + else if (unknown && _settings->inconclusive) { + nullPointerError(tok2, varname, tok->linenr(), true); + } + break; } } @@ -1050,6 +1060,8 @@ private: setnull(checks, tok.varId()); else if (CheckNullPointer::isPointerDeRef(&tok, unknown)) dereference(checks, &tok); + else if (unknown && owner->inconclusiveFlag()) + dereference(checks, &tok); else // TODO: Report debug warning that it's unknown if a // pointer is dereferenced diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 16054882d..4cb0266ba 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -87,15 +87,22 @@ private: ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: tok - otherwise it is redundant to check if tok is null at line 3\n", errout.str()); // #2681 - check("void foo(const Token *tok)\n" - "{\n" - " while (tok && tok->str() == \"=\")\n" - " tok = tok->next();\n" - "\n" - " if (tok->str() != \";\")\n" - " ;\n" - "}\n"); - ASSERT_EQUALS("[test.cpp:6]: (error) Possible null pointer dereference: tok - otherwise it is redundant to check if tok is null at line 3\n", errout.str()); + { + const char code[] = "void foo(const Token *tok)\n" + "{\n" + " while (tok && tok->str() == \"=\")\n" + " tok = tok->next();\n" + "\n" + " if (tok->str() != \";\")\n" + " ;\n" + "}\n"; + + check(code, false); // inconclusive=false => no error + ASSERT_EQUALS("", errout.str()); + + check(code, true); // inconclusive=true => error + ASSERT_EQUALS("[test.cpp:6]: (error) Possible null pointer dereference: tok - otherwise it is redundant to check if tok is null at line 3\n", errout.str()); + } check("void foo()\n" "{\n" @@ -715,12 +722,21 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference\n", errout.str()); - check("static void foo(int x)\n" - "{\n" - " Foo *abc = 0;\n" - " abc->a();\n" - "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: abc\n", errout.str()); + { + const char code[] = "static void foo(int x)\n" + "{\n" + " Foo *abc = 0;\n" + " abc->a();\n" + "}\n"; + + // inconclusive=false => no error + check(code,false); + ASSERT_EQUALS("", errout.str()); + + // inconclusive=true => error + check(code, true); + ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: abc\n", errout.str()); + } check("static void foo()\n" "{\n" @@ -899,6 +915,13 @@ private: " int x = &fred->x;\n" "}"); ASSERT_EQUALS("", errout.str()); + + // ticket #3220: calling member function + check("void f() {\n" + " Fred *fred = NULL;\n" + " fred->do_something();\n" + "}"); + ASSERT_EQUALS("", errout.str()); } // Ticket #2350