findLambdaEndToken handle explicit type (#1458)

* findLambdaEndToken: Add tests

* Add handling of explicit return in findLambdaEndToken()

* Use AST in findLambdaEndToken()

* Fix ast when lambda is mutable
This commit is contained in:
rikardfalkeborn 2018-10-31 12:36:08 +01:00 committed by Daniel Marjamäki
parent fafd0742d4
commit 88008fedb1
5 changed files with 43 additions and 13 deletions

View File

@ -939,18 +939,12 @@ const Token *findLambdaEndToken(const Token *first)
{
if (!first || first->str() != "[")
return nullptr;
const Token* tok = first->link();
if (Token::simpleMatch(tok, "] {"))
return tok->linkAt(1);
if (!Token::simpleMatch(tok, "] ("))
return nullptr;
tok = tok->linkAt(1)->next();
if (tok && tok->str() == "constexpr")
tok = tok->next();
if (tok && tok->str() == "mutable")
tok = tok->next();
if (tok && tok->str() == "{")
return tok->link();
const Token * tok = first;
if (tok->astOperand1() && tok->astOperand1()->str() == "(")
tok = tok->astOperand1();
if (tok->astOperand1() && tok->astOperand1()->str() == "{")
return tok->astOperand1()->link();
return nullptr;
}

View File

@ -126,7 +126,6 @@ std::vector<const Token *> getArguments(const Token *ftok);
/**
* find lambda function end token
* \todo handle explicit return type
* \param first The [ token
* \return nullptr or the }
*/

View File

@ -680,6 +680,8 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
if (Token::simpleMatch(squareBracket->link(), "] (")) {
Token* const roundBracket = squareBracket->link()->next();
Token* curlyBracket = roundBracket->link()->next();
if (curlyBracket && curlyBracket->str() == "mutable")
curlyBracket = curlyBracket->next();
if (curlyBracket && curlyBracket->originalName() == "->") {
while (Token::Match(curlyBracket, "%name%|.|::|&|*"))
curlyBracket = curlyBracket->next();

View File

@ -33,11 +33,44 @@ public:
private:
void run() override {
TEST_CASE(findLambdaEndToken);
TEST_CASE(isReturnScope);
TEST_CASE(isVariableChanged);
TEST_CASE(isVariableChangedByFunctionCall);
}
bool findLambdaEndToken(const char code[]) {
Settings settings;
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
const Token * const tokEnd = ::findLambdaEndToken(tokenizer.tokens());
return tokEnd && tokEnd->next() == nullptr;
}
void findLambdaEndToken() {
ASSERT(nullptr == ::findLambdaEndToken(nullptr));
ASSERT_EQUALS(false, findLambdaEndToken("void f() { }"));
ASSERT_EQUALS(true, findLambdaEndToken("[]{ }"));
ASSERT_EQUALS(true, findLambdaEndToken("[]{ return 0 }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](){ }"));
ASSERT_EQUALS(true, findLambdaEndToken("[&](){ }"));
ASSERT_EQUALS(true, findLambdaEndToken("[&, i](){ }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](void) { return -1 }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) { return a + b }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) mutable { return a + b }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](int a, int b) constexpr { return a + b }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](void) -> int { return -1 }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](void) mutable -> int { return -1 }"));
ASSERT_EQUALS(false, findLambdaEndToken("[](void) foo -> int { return -1 }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> int { return -1 }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> int* { return x }"));
ASSERT_EQUALS(true, findLambdaEndToken("[](void) constexpr -> 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 * const* int { return x }"));
}
bool isReturnScope(const char code[], int offset) {
Settings settings;
Tokenizer tokenizer(&settings, this);

View File

@ -8551,6 +8551,8 @@ private:
ASSERT_EQUALS("{([cd,(return 0return", testAst("return [](int a, int b) -> int { return 0; }(c, d);"));
ASSERT_EQUALS("x{([=", testAst("x = [&]()->std::string const & {};"));
ASSERT_EQUALS("f{([=", testAst("f = []() -> foo* {};"));
ASSERT_EQUALS("f{([=", testAst("f = [](void) mutable -> foo* {};"));
ASSERT_EQUALS("f{([=", testAst("f = []() mutable {};"));
ASSERT_EQUALS("x{([= 0return", testAst("x = [](){return 0; };"));