Fix 11992: FN (regression): uninitvar (#5465)

This commit is contained in:
Paul Fultz II 2023-09-19 23:43:58 -05:00 committed by GitHub
parent 3089fc393b
commit 58a7519cbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 52 deletions

View File

@ -2809,6 +2809,11 @@ bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp,
return false;
if (Token::Match(start, "; %varid% =", var->declarationId()))
start = start->tokAt(2);
if (Token::simpleMatch(start, "=")) {
const Token* next = nextAfterAstRightmostLeafGeneric(start);
if (next)
start = next;
}
return isExpressionChanged(var->nameToken(), start->next(), var->scope()->bodyEnd, settings, cpp, depth);
}

View File

@ -231,9 +231,12 @@ private:
" if (b) { (int)((INTOF(8))result >> b); }\n"
"}", "if", "}");
// #9235
ASSERT_EQUALS(true, isVariableChanged("void f() {\n"
" int &a = a;\n"
"}\n", "= a", "}"));
ASSERT_EQUALS(false,
isVariableChanged("void f() {\n"
" int &a = a;\n"
"}\n",
"= a",
"}"));
ASSERT_EQUALS(false, isVariableChanged("void f(const A& a) { a.f(); }", "{", "}"));
ASSERT_EQUALS(true,

View File

@ -2653,9 +2653,9 @@ private:
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const T& z = x;\n" //Make sure we find all assignments
" T& y = x\n"
" y.mutate();\n" //to avoid warnings that y can be const
" const T& z = x;\n" // Make sure we find all assignments
" T& y = x;\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
@ -2667,29 +2667,29 @@ private:
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = x\n"
" y.mutate();\n" //to avoid warnings that y can be const
" U& y = x;\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" my<fancy>::type& y = x\n" //we don't know if y is const or not
" y.mutate();\n" //to avoid warnings that y can be const
" my<fancy>::type& y = x;\n" // we don't know if y is const or not
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U& y = static_cast<const U&>(x)\n"
" y.mutate();\n" //to avoid warnings that y can be const
" const U& y = static_cast<const U&>(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = static_cast<U&>(x)\n"
" y.mutate();\n" //to avoid warnings that y can be const
" U& y = static_cast<U&>(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
@ -2698,129 +2698,127 @@ private:
" const U& y = dynamic_cast<const U&>(x)\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check(
"struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U& y = dynamic_cast<U const &>(x)\n"
"}"
);
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U& y = dynamic_cast<U & const>(x)\n"
" const U& y = dynamic_cast<U const &>(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = dynamic_cast<U&>(x)\n"
" y.mutate();\n" //to avoid warnings that y can be const
" const U& y = dynamic_cast<U & const>(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = dynamic_cast<U&>(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U& y = dynamic_cast<typename const U&>(x)\n"
" const U& y = dynamic_cast<typename const U&>(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = dynamic_cast<typename U&>(x)\n"
" y.mutate();\n" //to avoid warnings that y can be const
" U& y = dynamic_cast<typename U&>(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U* y = dynamic_cast<U*>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" U* y = dynamic_cast<U*>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U * y = dynamic_cast<const U *>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" const U * y = dynamic_cast<const U *>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U const * y = dynamic_cast<U const *>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" U const * y = dynamic_cast<U const *>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U * const y = dynamic_cast<U * const>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" U * const y = dynamic_cast<U * const>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U const * const * const * const y = dynamic_cast<const U const * const * const * const>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" const U const * const * const * const y = dynamic_cast<const U const * const * const * const>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U const * const * * const y = dynamic_cast<const U const * const * * const>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" const U const * const * * const y = dynamic_cast<const U const * const * * const>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" my::fancy<typename type const *> const * * const y = dynamic_cast<my::fancy<typename type const *> const * * const>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" my::fancy<typename type const *> const * * const y = dynamic_cast<my::fancy<typename type const *> const * * const>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" my::fancy<typename type const *> const * const * const y = dynamic_cast<my::fancy<typename type const *> const * const * const>(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" my::fancy<typename type const *> const * const * const y = dynamic_cast<my::fancy<typename type const *> const * const * const>(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U& y = (const U&)(x)\n"
" const U& y = (const U&)(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = (U&)(x)\n"
" y.mutate();\n" //to avoid warnings that y can be const
" U& y = (U&)(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" const U& y = (typename const U&)(x)\n"
" const U& y = (typename const U&)(x);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U& y = (typename U&)(x)\n"
" y.mutate();\n" //to avoid warnings that y can be const
" U& y = (typename U&)(x);\n"
" y.mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("", errout.str());
check("struct T : public U { void dostuff() const {}};\n"
"void a(T& x) {\n"
" x.dostuff();\n"
" U* y = (U*)(&x)\n"
" y->mutate();\n" //to avoid warnings that y can be const
" U* y = (U*)(&x);\n"
" y->mutate();\n" // to avoid warnings that y can be const
"}");
ASSERT_EQUALS("[test.cpp:4]: (style) C-style pointer casting\n", errout.str());

View File

@ -6224,6 +6224,19 @@ private:
" int* a[] = { &x };\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// #11992
valueFlowUninit("void foo(const int &x) {\n"
" if(x==42) {;}\n"
"}\n"
"void test(void) {\n"
" int t;\n"
" int &p = t;\n"
" int &s = p;\n"
" int &q = s;\n"
" foo(q);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: q\n", errout.str());
}
void valueFlowUninitBreak() { // Do not show duplicate warnings about the same uninitialized value