From 88008fedb1d394a459d2f6f68958da0edd8964e1 Mon Sep 17 00:00:00 2001 From: rikardfalkeborn Date: Wed, 31 Oct 2018 12:36:08 +0100 Subject: [PATCH] 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 --- lib/astutils.cpp | 18 ++++++------------ lib/astutils.h | 1 - lib/tokenlist.cpp | 2 ++ test/testastutils.cpp | 33 +++++++++++++++++++++++++++++++++ test/testtokenize.cpp | 2 ++ 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 192cdc5db..9be3419b3 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -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; } diff --git a/lib/astutils.h b/lib/astutils.h index 80ef0d23c..9bc2b9c01 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -126,7 +126,6 @@ std::vector getArguments(const Token *ftok); /** * find lambda function end token - * \todo handle explicit return type * \param first The [ token * \return nullptr or the } */ diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 55b259d3f..9057cf732 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -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(); diff --git a/test/testastutils.cpp b/test/testastutils.cpp index 78a927cb6..6ff882fbd 100644 --- a/test/testastutils.cpp +++ b/test/testastutils.cpp @@ -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); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 79e18c281..dfc37643c 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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; };"));