From 346532d312d1c76166269eea09ff234b27fd00e5 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Wed, 21 Jan 2015 13:10:38 +0100 Subject: [PATCH] Fixed false positives in CheckUninitVar::checkStruct() --- lib/checkuninitvar.cpp | 38 ++++++++++++++++++----------------- test/testuninitvar.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index bda40a806..2f685b97a 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1126,29 +1126,31 @@ void CheckUninitVar::checkStruct(const Scope* scope, const Token *tok, const Var if (scope2->className == structname && scope2->numConstructors == 0U) { for (std::list::const_iterator it = scope2->varlist.begin(); it != scope2->varlist.end(); ++it) { const Variable &var = *it; - if (!var.hasDefault() && !var.isArray()) { - // is the variable declared in a inner union? - bool innerunion = false; - for (std::list::const_iterator it2 = symbolDatabase->scopeList.begin(); it2 != symbolDatabase->scopeList.end(); ++it2) { - const Scope &innerScope = *it2; - if (innerScope.type == Scope::eUnion && innerScope.nestedIn == scope2) { - if (var.typeStartToken()->linenr() >= innerScope.classStart->linenr() && - var.typeStartToken()->linenr() <= innerScope.classEnd->linenr()) { - innerunion = true; - break; - } + if (var.hasDefault() || var.isArray() || (!_tokenizer->isC() && var.isClass() && (!var.type() || var.type()->needInitialization != Type::True))) + continue; + + // is the variable declared in a inner union? + bool innerunion = false; + for (std::list::const_iterator it2 = symbolDatabase->scopeList.begin(); it2 != symbolDatabase->scopeList.end(); ++it2) { + const Scope &innerScope = *it2; + if (innerScope.type == Scope::eUnion && innerScope.nestedIn == scope2) { + if (var.typeStartToken()->linenr() >= innerScope.classStart->linenr() && + var.typeStartToken()->linenr() <= innerScope.classEnd->linenr()) { + innerunion = true; + break; } - } - if (!innerunion) { - bool alloc = false; - const Token *tok2 = tok; - if (tok->str() == "}") - tok2 = tok2->next(); - checkScopeForVariable(scope, tok2, structvar, nullptr, nullptr, &alloc, var.name()); } } + + if (!innerunion) { + bool alloc = false; + const Token *tok2 = tok; + if (tok->str() == "}") + tok2 = tok2->next(); + checkScopeForVariable(scope, tok2, structvar, nullptr, nullptr, &alloc, var.name()); + } } } } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 61cb96b50..c06a8a044 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -3301,6 +3301,51 @@ private: " int b = ab.b;\n" "}"); ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized struct member: ab.b\n", errout.str()); + + // STL class member + checkUninitVar2("struct A {\n" + " std::map m;\n" + " int i;\n" + "};\n" + "void foo() {\n" + " A a;\n" + " x = a.m;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + // Unknown type (C++) + checkUninitVar2("struct A {\n" + " C m;\n" + " int i;\n" + "};\n" + "void foo() {\n" + " A a;\n" + " x = a.m;\n" + "}", "test.cpp"); + ASSERT_EQUALS("", errout.str()); + + // Unknown type (C) + checkUninitVar2("struct A {\n" + " C m;\n" + " int i;\n" + "};\n" + "void foo() {\n" + " A a;\n" + " x = a.m;\n" + "}", "test.c"); + ASSERT_EQUALS("[test.c:7]: (error) Uninitialized struct member: a.m\n", errout.str()); + + // Type with constructor + checkUninitVar2("class C { C(); }\n" + "struct A {\n" + " C m;\n" + " int i;\n" + "};\n" + "void foo() {\n" + " A a;\n" + " x = a.m;\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void uninitvar2_while() {