diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 9ac25874f..de51282e9 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -150,8 +150,9 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) const return isPointerDeRef(tok, unknown, mSettings); } -static bool isUnevaluated(const Token* tok) { - return tok && Token::Match(tok->previous(), "sizeof|decltype ("); +static bool isUnevaluatedOperator(const Token* tok) +{ + return Token::Match(tok, "sizeof|decltype|typeid|typeof|alignof|_Alignof|_alignof|__alignof|__alignof__ ("); } bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Settings *settings) @@ -190,7 +191,8 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Set return false; // Dereferencing pointer.. - if (parent->isUnaryOp("*") && !isUnevaluated(parent->astParent())) { + const Token* grandParent = parent->astParent(); + if (parent->isUnaryOp("*") && !(grandParent && isUnevaluatedOperator(grandParent->previous()))) { // declaration of function pointer if (tok->variable() && tok->variable()->nameToken() == tok) return false; @@ -288,7 +290,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec() const bool printInconclusive = (mSettings->certainty.isEnabled(Certainty::inconclusive)); for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { - if (Token::Match(tok, "sizeof|decltype|typeid|typeof (")) { + if (isUnevaluatedOperator(tok)) { tok = tok->next()->link(); continue; } @@ -347,7 +349,7 @@ void CheckNullPointer::nullConstantDereference() tok = scope->function->token; // Check initialization list for (; tok != scope->bodyEnd; tok = tok->next()) { - if (Token::Match(tok, "sizeof|decltype|typeid|typeof (")) + if (isUnevaluatedOperator(tok)) tok = tok->next()->link(); else if (Token::simpleMatch(tok, "* 0")) { diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index e86cebd83..81c7f1e64 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -153,6 +153,7 @@ private: TEST_CASE(scanf_with_invalid_va_argument); TEST_CASE(nullpointer_in_return); TEST_CASE(nullpointer_in_typeid); + TEST_CASE(nullpointer_in_alignof); // #11401 TEST_CASE(nullpointer_in_for_loop); TEST_CASE(nullpointerDelete); TEST_CASE(nullpointerSubFunction); @@ -3413,7 +3414,48 @@ private: " return typeid(*c) == typeid(*c);\n" "}", true); ASSERT_EQUALS("", errout.str()); + } + void nullpointer_in_alignof() // #11401 + { + check("size_t foo() {\n" + " char* c = 0;\n" + " return alignof(*c);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("size_t foo() {\n" + " return alignof(*0);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("void foo(int *p) {\n" + " f(alignof(*p));\n" + " if (p) {}\n" + " return;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("size_t foo() {\n" + " char* c = 0;\n" + " return _Alignof(*c);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("size_t foo() {\n" + " return _alignof(*0);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("size_t foo() {\n" + " return __alignof(*0);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("size_t foo() {\n" + " return __alignof__(*0);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); } void nullpointer_in_for_loop() { @@ -4350,6 +4392,15 @@ private: " f(NULL);\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + ctu("size_t f(int* p) {\n" + " size_t len = alignof(*p);\n" + " return len;\n" + "}\n" + "void g() {\n" + " f(NULL);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } };