* checknullpointer: Don't report dereference with alignof * Refactor unevaluating operator check in checknullpointer Unifying these ensures the different checks treat the operators the same. * Fix FP with _Alignof and null pointer Just like alignof, _Alignof does not evaluate its operand. * CheckNullPointer: Also support compiler specific alignof This fixes #11401 which is about __alignof__. For good measure, also add the microsoft extensions __alignof and _alignof.
This commit is contained in:
parent
8465d901c8
commit
52264b9c26
|
@ -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")) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue