diff --git a/lib/astutils.cpp b/lib/astutils.cpp index d247bd29f..cf5f228e1 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2948,8 +2948,25 @@ const Token *findLambdaStartToken(const Token *last) template T* findLambdaEndTokenGeneric(T* first) { + auto maybeLambda = [](T* tok) -> bool { + while (Token::Match(tok, "*|%name%|::|>")) { + if (tok->link()) + tok = tok->link()->previous(); + else { + if (tok->str() == ">") + return true; + if (tok->str() == "new") + return false; + tok = tok->previous(); + } + } + return true; + }; + if (!first || first->str() != "[") return nullptr; + if (!maybeLambda(first->previous())) + return nullptr; if (!Token::Match(first->link(), "] (|{")) return nullptr; if (first->astOperand1() != first->link()->next()) diff --git a/test/testastutils.cpp b/test/testastutils.cpp index d12b6e993..d14d35640 100644 --- a/test/testastutils.cpp +++ b/test/testastutils.cpp @@ -48,14 +48,15 @@ private: TEST_CASE(isUsedAsBool); } -#define findLambdaEndToken(code) findLambdaEndToken_(code, __FILE__, __LINE__) - bool findLambdaEndToken_(const char code[], const char* file, int line) { +#define findLambdaEndToken(...) findLambdaEndToken_(__FILE__, __LINE__, __VA_ARGS__) + bool findLambdaEndToken_(const char* file, int line, const char code[], const char pattern[] = nullptr, bool checkNext = true) { const Settings settings; Tokenizer tokenizer(&settings, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); - const Token * const tokEnd = (::findLambdaEndToken)(tokenizer.tokens()); - return tokEnd && tokEnd->next() == nullptr; + const Token* const tokStart = pattern ? Token::findsimplematch(tokenizer.tokens(), pattern, strlen(pattern)) : tokenizer.tokens(); + const Token * const tokEnd = (::findLambdaEndToken)(tokStart); + return tokEnd && (!checkNext || tokEnd->next() == nullptr); } void findLambdaEndTokenTest() { @@ -80,6 +81,10 @@ private: ASSERT_EQUALS(true, findLambdaEndToken("[](void) mutable -> const * int { return x; }")); ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const ** int { return x; }")); ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const * const* int { return x; }")); + ASSERT_EQUALS(false, findLambdaEndToken("int** a[] { new int*[2] { new int, new int} }", "[ ]")); + ASSERT_EQUALS(false, findLambdaEndToken("int** a[] { new int*[2] { new int, new int} }", "[ 2")); + ASSERT_EQUALS(false, findLambdaEndToken("shared_ptr sp{ new Type *[2] {new Type, new Type}, Deleter{ 2 } };", "[ 2")); + ASSERT_EQUALS(true, findLambdaEndToken("int i = 5 * []{ return 7; }();", "[", /*checkNext*/ false)); } #define findLambdaStartToken(code) findLambdaStartToken_(code, __FILE__, __LINE__)