From 92eb59981d79fd11bbaf077be36232e77c8e243f Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Sun, 29 Aug 2021 08:40:10 -0500 Subject: [PATCH] Fix 10435: False positive: containerOutOfBounds (#3426) --- lib/token.cpp | 48 +++++++++++++++++++++++++++++++++++++ lib/token.h | 5 ++++ lib/tokenize.cpp | 28 +++++++++++++++++++++- lib/tokenlist.cpp | 46 ----------------------------------- test/testsimplifytokens.cpp | 9 ++++++- 5 files changed, 88 insertions(+), 48 deletions(-) diff --git a/lib/token.cpp b/lib/token.cpp index efaef51e8..c04d8e2d4 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2533,3 +2533,51 @@ bool TokenImpl::getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, M *value = attr->value; return attr != nullptr; } + +Token* findTypeEnd(Token* tok) +{ + while (Token::Match(tok, "%name%|.|::|*|&|&&|<|(|template|decltype|sizeof")) { + if (Token::Match(tok, "(|<")) + tok = tok->link(); + if (!tok) + return nullptr; + tok = tok->next(); + } + return tok; +} + +const Token* findTypeEnd(const Token* tok) { + return findTypeEnd(const_cast(tok)); +} + +Token* findLambdaEndScope(Token* tok) +{ + if (!Token::simpleMatch(tok, "[")) + return nullptr; + tok = tok->link(); + if (!Token::Match(tok, "] (|{")) + return nullptr; + tok = tok->linkAt(1); + if (Token::simpleMatch(tok, "}")) + return tok; + if (Token::simpleMatch(tok, ") {")) + return tok->linkAt(1); + if (!Token::simpleMatch(tok, ")")) + return nullptr; + tok = tok->next(); + while (Token::Match(tok, "mutable|constexpr|constval|noexcept|.")) { + if (Token::simpleMatch(tok, "noexcept (")) + tok = tok->linkAt(1); + if (Token::simpleMatch(tok, ".")) { + tok = findTypeEnd(tok); + break; + } + tok = tok->next(); + } + if (Token::simpleMatch(tok, "{")) + return tok->link(); + return nullptr; +} +const Token* findLambdaEndScope(const Token* tok) { + return findLambdaEndScope(const_cast(tok)); +} diff --git a/lib/token.h b/lib/token.h index 687784f04..88de794fc 100644 --- a/lib/token.h +++ b/lib/token.h @@ -1395,6 +1395,11 @@ public: } }; +Token* findTypeEnd(Token* tok); +const Token* findTypeEnd(const Token* tok); +Token* findLambdaEndScope(Token* tok); +const Token* findLambdaEndScope(const Token* tok); + /// @} //--------------------------------------------------------------------------- #endif // tokenH diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index a19851748..0fc1dc14e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7239,8 +7239,34 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co // Split up variable declarations.. // "int a=4;" => "int a; a=4;" bool finishedwithkr = true; + bool scopeDecl = false; for (Token *tok = tokBegin; tok != tokEnd; tok = tok->next()) { - if (Token::simpleMatch(tok, "= {")) { + if (Token::Match(tok, "{|;")) + scopeDecl = false; + if (isCPP()) { + if (Token::Match(tok, "class|struct|namespace|union")) + scopeDecl = true; + if (Token::Match(tok, "decltype|noexcept (")) { + tok = tok->next()->link(); + // skip decltype(...){...} + if (tok && Token::simpleMatch(tok->previous(), ") {")) + tok = tok->link(); + } else if (Token::simpleMatch(tok, "= {") || + (!scopeDecl && Token::Match(tok, "%name%|> {") && + !Token::Match(tok, "else|try|do|const|constexpr|override|volatile|noexcept"))) { + if (!tok->next()->link()) + syntaxError(tokBegin); + // Check for lambdas before skipping + for (Token* tok2 = tok->next(); tok2 != tok->next()->link(); tok2 = tok2->next()) { + Token* lambdaEnd = findLambdaEndScope(tok2); + if (!lambdaEnd) + continue; + simplifyVarDecl(lambdaEnd->link()->next(), lambdaEnd, only_k_r_fpar); + } + tok = tok->next()->link(); + } + + } else if (Token::simpleMatch(tok, "= {")) { tok = tok->next()->link(); } if (!tok) { diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index ec5f40c0f..f10286bec 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -560,52 +560,6 @@ static bool iscast(const Token *tok, bool cpp) return false; } -static Token* findTypeEnd(Token* tok) -{ - while (Token::Match(tok, "%name%|.|::|*|&|&&|<|(|template|decltype|sizeof")) { - if (Token::Match(tok, "(|<")) - tok = tok->link(); - if (!tok) - return nullptr; - tok = tok->next(); - } - return tok; -} - -static const Token* findTypeEnd(const Token* tok) -{ - return findTypeEnd(const_cast(tok)); -} - -static const Token * findLambdaEndScope(const Token *tok) -{ - if (!Token::simpleMatch(tok, "[")) - return nullptr; - tok = tok->link(); - if (!Token::Match(tok, "] (|{")) - return nullptr; - tok = tok->linkAt(1); - if (Token::simpleMatch(tok, "}")) - return tok; - if (Token::simpleMatch(tok, ") {")) - return tok->linkAt(1); - if (!Token::simpleMatch(tok, ")")) - return nullptr; - tok = tok->next(); - while (Token::Match(tok, "mutable|constexpr|constval|noexcept|.")) { - if (Token::simpleMatch(tok, "noexcept (")) - tok = tok->linkAt(1); - if (Token::simpleMatch(tok, ".")) { - tok = findTypeEnd(tok); - break; - } - tok = tok->next(); - } - if (Token::simpleMatch(tok, "{")) - return tok->link(); - return nullptr; -} - // int(1), int*(2), .. static Token * findCppTypeInitPar(Token *tok) { diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 3c0047816..dede4b01f 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -367,7 +367,7 @@ private: TEST_CASE(simplify_constants4); TEST_CASE(simplify_constants5); TEST_CASE(simplify_constants6); // Ticket #5625: Ternary operator as template parameter - + TEST_CASE(simplifyVarDeclInitLists); } std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native) { @@ -7063,6 +7063,13 @@ private: ASSERT_EQUALS(exp, tok(code)); } } + + void simplifyVarDeclInitLists() + { + const char code[] = "std::vector v{a * b, 1};"; + const char exp[] = "std :: vector < int > v { a * b , 1 } ;"; + ASSERT_EQUALS(exp, tok(code)); + } }; REGISTER_TEST(TestSimplifyTokens)