From 47384a179915ce47f8ddde72a78e16a27df589d3 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:09:06 +0200 Subject: [PATCH 1/5] Update astutils.cpp --- lib/astutils.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 486eb730e4a..03d97464cd4 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3295,15 +3295,32 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings const Token* ftok = getTokenArgumentFunction(tok, argnr); if (!ftok) return ExprUsage::None; - if (ftok->function()) { + const Function* func = ftok->function(); + if (!func && ftok->variable() && ftok == ftok->variable()->nameToken()) { // variable init/constructor call + if (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container)) // STL types or containers don't initialize external variables + return ExprUsage::Used; + // TODO: resolve between different constructors + if (ftok->variable()->type() && ftok->variable()->type()->classScope) { + const int nCtor = ftok->variable()->type()->classScope->numConstructors; + if (nCtor == 0) + return ExprUsage::Used; + if (nCtor == 1) { + const Scope* scope = ftok->variable()->type()->classScope; + auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [](const Function& f) { return f.isConstructor(); }); + if (it != scope->functionList.end()) + func = &*it; + } + } + } + if (func) { std::vector args = getArgumentVars(ftok, argnr); for (const Variable* arg : args) { if (!arg) continue; if (arg->isReference() || (arg->isPointer() && indirect == 1)) { - if (!ftok->function()->hasBody()) + if (!func->hasBody()) return ExprUsage::PassedByReference; - for (const Token* bodytok = ftok->function()->functionScope->bodyStart; bodytok != ftok->function()->functionScope->bodyEnd; bodytok = bodytok->next()) { + for (const Token* bodytok = func->functionScope->bodyStart; bodytok != func->functionScope->bodyEnd; bodytok = bodytok->next()) { if (bodytok->variable() == arg) { if (arg->isReference()) return ExprUsage::PassedByReference; @@ -3321,11 +3338,6 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings return ExprUsage::Used; } else if (ftok->str() == "{") { return indirect == 0 ? ExprUsage::Used : ExprUsage::Inconclusive; - } else if (ftok->variable() && ftok == ftok->variable()->nameToken()) { // variable init/constructor call - if (ftok->variable()->type() && ftok->variable()->type()->classScope && ftok->variable()->type()->classScope->numConstructors == 0) - return ExprUsage::Used; - if (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container)) // STL types or containers don't initialize external variables - return ExprUsage::Used; } else { const bool isnullbad = settings.library.isnullargbad(ftok, argnr + 1); if (indirect == 0 && astIsPointer(tok) && !addressOf && isnullbad) From 9eff3377232482cc2425f43b85cb6ec195ec4143 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:13:50 +0200 Subject: [PATCH 2/5] Update testuninitvar.cpp --- test/testuninitvar.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 98359185b0d..13debb94b1c 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -7438,7 +7438,7 @@ class TestUninitVar : public TestFixture { "[test.cpp:27]: (error) Uninitialized variable: s.t.j\n", errout_str()); - valueFlowUninit("struct S { int x; };\n" + valueFlowUninit("struct S { int x; };\n" // #6933 "void f() {\n" " int i;\n" " S s(i);\n" @@ -7525,6 +7525,16 @@ class TestUninitVar : public TestFixture { " return s2;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + valueFlowUninit("struct S {\n" // #12685 + " explicit S(double v);\n" + " double m;\n" + "};\n" + "void f() {\n" + " double d;\n" + " S s(d);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: d\n", errout_str()); } void uninitvar_memberfunction() { From f065a87d808b3d9db829f320e3383b92a35044f8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:15:52 +0200 Subject: [PATCH 3/5] Update astutils.cpp --- lib/astutils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 03d97464cd4..65045f982bd 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3296,8 +3296,10 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings if (!ftok) return ExprUsage::None; const Function* func = ftok->function(); - if (!func && ftok->variable() && ftok == ftok->variable()->nameToken()) { // variable init/constructor call - if (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container)) // STL types or containers don't initialize external variables + // variable init/constructor call? + if (!func && ftok->variable() && ftok == ftok->variable()->nameToken()) { + // STL types or containers don't initialize external variables + if (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container)) return ExprUsage::Used; // TODO: resolve between different constructors if (ftok->variable()->type() && ftok->variable()->type()->classScope) { From 81fb5a042bc38ebc29814aa3fb83a2d10e9c397a Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 30 Apr 2024 19:15:08 +0200 Subject: [PATCH 4/5] Update testuninitvar.cpp --- test/testuninitvar.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 13debb94b1c..08335e8cbeb 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -7535,6 +7535,16 @@ class TestUninitVar : public TestFixture { " S s(d);\n" "}\n"); ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: d\n", errout_str()); + + valueFlowUninit("struct S {\n" + " explicit S(double v) : m(v) {}\n" + " double m;\n" + "};\n" + "void f() {\n" + " double d;\n" + " S s{ d };\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: d\n", errout_str()); } void uninitvar_memberfunction() { From 490071a6a959de848edbbd32f3be0099c558ca26 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 30 Apr 2024 19:19:36 +0200 Subject: [PATCH 5/5] Update astutils.cpp --- lib/astutils.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 65045f982bd..afc5ef81ac1 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3296,23 +3296,25 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings if (!ftok) return ExprUsage::None; const Function* func = ftok->function(); - // variable init/constructor call? + // variable init/constructor call? if (!func && ftok->variable() && ftok == ftok->variable()->nameToken()) { - // STL types or containers don't initialize external variables - if (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container)) - return ExprUsage::Used; - // TODO: resolve between different constructors - if (ftok->variable()->type() && ftok->variable()->type()->classScope) { - const int nCtor = ftok->variable()->type()->classScope->numConstructors; - if (nCtor == 0) - return ExprUsage::Used; - if (nCtor == 1) { - const Scope* scope = ftok->variable()->type()->classScope; - auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [](const Function& f) { return f.isConstructor(); }); - if (it != scope->functionList.end()) - func = &*it; - } - } + // STL types or containers don't initialize external variables + if (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container)) + return ExprUsage::Used; + // TODO: resolve multiple constructors + if (ftok->variable()->type() && ftok->variable()->type()->classScope) { + const int nCtor = ftok->variable()->type()->classScope->numConstructors; + if (nCtor == 0) + return ExprUsage::Used; + if (nCtor == 1) { + const Scope* scope = ftok->variable()->type()->classScope; + auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [](const Function& f) { + return f.isConstructor(); + }); + if (it != scope->functionList.end()) + func = &*it; + } + } } if (func) { std::vector args = getArgumentVars(ftok, argnr);