Fix spurious lambda detection (#5101)
This commit is contained in:
parent
a91222fad8
commit
0b44429a7c
|
@ -2948,8 +2948,25 @@ const Token *findLambdaStartToken(const Token *last)
|
||||||
template<class T>
|
template<class T>
|
||||||
T* findLambdaEndTokenGeneric(T* first)
|
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() != "[")
|
if (!first || first->str() != "[")
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
if (!maybeLambda(first->previous()))
|
||||||
|
return nullptr;
|
||||||
if (!Token::Match(first->link(), "] (|{"))
|
if (!Token::Match(first->link(), "] (|{"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (first->astOperand1() != first->link()->next())
|
if (first->astOperand1() != first->link()->next())
|
||||||
|
|
|
@ -48,14 +48,15 @@ private:
|
||||||
TEST_CASE(isUsedAsBool);
|
TEST_CASE(isUsedAsBool);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define findLambdaEndToken(code) findLambdaEndToken_(code, __FILE__, __LINE__)
|
#define findLambdaEndToken(...) findLambdaEndToken_(__FILE__, __LINE__, __VA_ARGS__)
|
||||||
bool findLambdaEndToken_(const char code[], const char* file, int line) {
|
bool findLambdaEndToken_(const char* file, int line, const char code[], const char pattern[] = nullptr, bool checkNext = true) {
|
||||||
const Settings settings;
|
const Settings settings;
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
|
ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line);
|
||||||
const Token * const tokEnd = (::findLambdaEndToken)(tokenizer.tokens());
|
const Token* const tokStart = pattern ? Token::findsimplematch(tokenizer.tokens(), pattern, strlen(pattern)) : tokenizer.tokens();
|
||||||
return tokEnd && tokEnd->next() == nullptr;
|
const Token * const tokEnd = (::findLambdaEndToken)(tokStart);
|
||||||
|
return tokEnd && (!checkNext || tokEnd->next() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void findLambdaEndTokenTest() {
|
void findLambdaEndTokenTest() {
|
||||||
|
@ -80,6 +81,10 @@ private:
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) mutable -> const * int { return x; }"));
|
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 ** int { return x; }"));
|
||||||
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> const * 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<Type *[]> sp{ new Type *[2] {new Type, new Type}, Deleter<Type>{ 2 } };", "[ 2"));
|
||||||
|
ASSERT_EQUALS(true, findLambdaEndToken("int i = 5 * []{ return 7; }();", "[", /*checkNext*/ false));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define findLambdaStartToken(code) findLambdaStartToken_(code, __FILE__, __LINE__)
|
#define findLambdaStartToken(code) findLambdaStartToken_(code, __FILE__, __LINE__)
|
||||||
|
|
Loading…
Reference in New Issue