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() != "[") if (!first || first->str() != "[")
return nullptr; return nullptr;
const Token* tok = first->link(); const Token * tok = first;
if (Token::simpleMatch(tok, "] {"))
return tok->linkAt(1); if (tok->astOperand1() && tok->astOperand1()->str() == "(")
if (!Token::simpleMatch(tok, "] (")) tok = tok->astOperand1();
return nullptr; if (tok->astOperand1() && tok->astOperand1()->str() == "{")
tok = tok->linkAt(1)->next(); return tok->astOperand1()->link();
if (tok && tok->str() == "constexpr")
tok = tok->next();
if (tok && tok->str() == "mutable")
tok = tok->next();
if (tok && tok->str() == "{")
return tok->link();
return nullptr; return nullptr;
} }

View File

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

View File

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

View File

@ -33,11 +33,44 @@ public:
private: private:
void run() override { void run() override {
TEST_CASE(findLambdaEndToken);
TEST_CASE(isReturnScope); TEST_CASE(isReturnScope);
TEST_CASE(isVariableChanged); TEST_CASE(isVariableChanged);
TEST_CASE(isVariableChangedByFunctionCall); 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) { bool isReturnScope(const char code[], int offset) {
Settings settings; Settings settings;
Tokenizer tokenizer(&settings, this); 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("{([cd,(return 0return", testAst("return [](int a, int b) -> int { return 0; }(c, d);"));
ASSERT_EQUALS("x{([=", testAst("x = [&]()->std::string const & {};")); ASSERT_EQUALS("x{([=", testAst("x = [&]()->std::string const & {};"));
ASSERT_EQUALS("f{([=", testAst("f = []() -> foo* {};")); 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; };")); ASSERT_EQUALS("x{([= 0return", testAst("x = [](){return 0; };"));