From 190506db409c656a344d76c7c2decbbd90aec7bf Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sun, 13 Mar 2022 06:27:17 +0100 Subject: [PATCH] Fix #10737 Regression: unusedStructMember (#3894) * Fix #10737 Regression: unusedStructMember * Add test for #9161 * simpleMatch --- lib/symboldatabase.cpp | 15 +++++++-------- test/teststl.cpp | 8 ++++++++ test/testunusedvar.cpp | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3b9124f1e..9d280b4a3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -106,16 +106,15 @@ static bool isExecutableScope(const Token* tok) const Token * tok2 = tok->link()->previous(); if (Token::simpleMatch(tok2, "; }")) return true; - if (Token::Match(tok2, "{|} }")) { - const Token* startTok = tok2->str() == "{" ? tok2 : tok2->link(); + if (tok2 == tok) + return false; + if (Token::simpleMatch(tok2, "} }")) { // inner scope + const Token* startTok = tok2->link(); if (Token::Match(startTok->previous(), "do|try|else {")) return true; - if (Token::simpleMatch(startTok->previous(), ") {")) + if (Token::Match(startTok->previous(), ")|] {")) return !findLambdaStartToken(tok2); - if (tok->str() == "{") - return false; - else - return isExecutableScope(startTok); + return isExecutableScope(startTok); } return false; } @@ -128,7 +127,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() // pointer to current scope Scope *scope = &scopeList.back(); - // Store the edning of init lists + // Store the ending of init lists std::stack> endInitList; auto inInitList = [&] { if (endInitList.empty()) diff --git a/test/teststl.cpp b/test/teststl.cpp index 4f8d6c053..5596ad0a9 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -3904,6 +3904,14 @@ private: " f(p.c_str());\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("struct S {\n" //#9161 + " const char* f() const noexcept {\n" + " return (\"\" + m).c_str();\n" + " }\n" + " std::string m;\n" + "};\n", /*inconclusive*/ true); + ASSERT_EQUALS("[test.cpp:3]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call.\n", errout.str()); } void uselessCalls() { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 5727dd0a5..5c8910e79 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -67,6 +67,7 @@ private: TEST_CASE(structmember17); // #10591 TEST_CASE(structmember18); // #10684 TEST_CASE(structmember19); // #10826, #10848, #10852 + TEST_CASE(structmember20); // #10737 TEST_CASE(localvar1); TEST_CASE(localvar2); @@ -1743,6 +1744,21 @@ private: settings.enforcedLang = Settings::None; } + void structmember20() { // #10737 + checkStructMemberUsage("void f() {\n" + " {\n" + " }\n" + " {\n" + " struct S { int a; };\n" + " S s{};\n" + " {\n" + " if (s.a) {}\n" + " }\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void functionVariableUsage_(const char* file, int line, const char code[], const char filename[] = "test.cpp") { // Clear the error buffer.. errout.str("");