From 0c51977f86c6fbaae9c12e7fe4acb7f79700070b Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 16 Sep 2023 13:03:14 +0200 Subject: [PATCH] Fix valueFlowBailoutIncompleteVar for cast and template args (refs #10045) (#5452) --- lib/symboldatabase.cpp | 16 ++++++++++----- test/testsymboldatabase.cpp | 40 ++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 9066592a9..b20e8bfc9 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1478,6 +1478,14 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars() continue; if (tok->varId() != 0) continue; + if (tok->isCast() && !isCPPCast(tok) && tok->link() && tok->str() == "(") { + tok = tok->link(); + continue; + } + if (Token::Match(tok, "catch|typeid (")) { + tok = tok->linkAt(1); + continue; + } if (!tok->isNameOnly()) continue; if (tok->type()) @@ -1486,16 +1494,14 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars() continue; if (Token::Match(tok->next(), "&|&&|* )|,|%var%")) continue; - if (Token::simpleMatch(tok->next(), ")") && Token::simpleMatch(tok->next()->link()->previous(), "catch (")) - continue; // Very likely a typelist if (Token::Match(tok->tokAt(-2), "%type% ,") || Token::Match(tok->next(), ", %type%")) continue; // Inside template brackets - if (Token::Match(tok->next(), "<|>") && tok->next()->link()) - continue; - if (Token::simpleMatch(tok->previous(), "<") && tok->previous()->link()) + if (Token::simpleMatch(tok->next(), "<") && tok->linkAt(1)) { + tok = tok->linkAt(1); continue; + } // Skip goto labels if (Token::simpleMatch(tok->previous(), "goto")) continue; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 87570be03..cc3cbb978 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -5432,15 +5432,37 @@ private: void createSymbolDatabaseIncompleteVars() { - GET_SYMBOL_DB("void f() {\n" - " auto s1 = std::string{ \"abc\" };\n" - " auto s2 = std::string(\"def\");\n" - "}\n"); - ASSERT(db && errout.str().empty()); - const Token* s1 = Token::findsimplematch(tokenizer.tokens(), "string {"); - ASSERT(s1 && !s1->isIncompleteVar()); - const Token* s2 = Token::findsimplematch(s1, "string ("); - ASSERT(s2 && !s2->isIncompleteVar()); + { + GET_SYMBOL_DB("void f() {\n" + " auto s1 = std::string{ \"abc\" };\n" + " auto s2 = std::string(\"def\");\n" + "}\n"); + ASSERT(db && errout.str().empty()); + const Token* s1 = Token::findsimplematch(tokenizer.tokens(), "string {"); + ASSERT(s1 && !s1->isIncompleteVar()); + const Token* s2 = Token::findsimplematch(s1, "string ("); + ASSERT(s2 && !s2->isIncompleteVar()); + } + { + GET_SYMBOL_DB("std::string f(int n, std::type_info t) {\n" + " std::vector v(n);\n" + " g();\n" + " if (static_cast(x)) {}\n" + " if (t == typeid(std::string)) {}\n" + " return (std::string) \"abc\";\n" + "}\n"); + ASSERT(db && errout.str().empty()); + const Token* s1 = Token::findsimplematch(tokenizer.tokens(), "string *"); + ASSERT(s1 && !s1->isIncompleteVar()); + const Token* s2 = Token::findsimplematch(s1, "string &"); + ASSERT(s2 && !s2->isIncompleteVar()); + const Token* x = Token::findsimplematch(s2, "x"); + ASSERT(x && x->isIncompleteVar()); + const Token* s3 = Token::findsimplematch(x, "string )"); + ASSERT(s3 && !s3->isIncompleteVar()); + const Token* s4 = Token::findsimplematch(s3->next(), "string )"); + ASSERT(s4 && !s4->isIncompleteVar()); + } } void enum1() {