From ad352daa086abe4e688749f1a664b7e047a0736f Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Mon, 16 Dec 2019 05:17:01 -0600 Subject: [PATCH] Fix issue 9535: Syntax Error: AST broken, 'if' doesn't have two operands. (#2450) --- lib/tokenlist.cpp | 14 ++++++++------ test/testtokenize.cpp | 8 ++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 34a6b8640..401b2c0ce 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -516,9 +516,9 @@ static bool iscast(const Token *tok) return false; } -static const Token* findTypeEnd(const Token* tok) +static Token* findTypeEnd(Token* tok) { - while (Token::Match(tok, "%name%|.|::|<|(|template|decltype|sizeof")) { + while (Token::Match(tok, "%name%|.|::|*|&|<|(|template|decltype|sizeof")) { if (Token::Match(tok, "(|<")) tok = tok->link(); if (!tok) @@ -528,6 +528,11 @@ static const Token* findTypeEnd(const Token* tok) return tok; } +static const Token* findTypeEnd(const Token* tok) +{ + return findTypeEnd(const_cast(tok)); +} + static const Token * findLambdaEndScope(const Token *tok) { if (!Token::simpleMatch(tok, "[")) @@ -867,10 +872,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state) if (Token::Match(curlyBracket, "mutable|const")) curlyBracket = curlyBracket->next(); if (curlyBracket && curlyBracket->originalName() == "->") { - while (Token::Match(curlyBracket, "%name%|.|::|&|*")) - curlyBracket = curlyBracket->next(); - if (curlyBracket && curlyBracket->str() == "<" && curlyBracket->link()) - curlyBracket = curlyBracket->link()->next(); + curlyBracket = findTypeEnd(curlyBracket->next()); } if (curlyBracket && curlyBracket->str() == "{") { squareBracket->astOperand1(roundBracket); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 1ab8923a3..6e4489241 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -7811,6 +7811,7 @@ private: ASSERT_EQUALS("{([(return 0return", testAst("return []() -> int { return 0; }();")); ASSERT_EQUALS("{([(return 0return", testAst("return [something]() -> int { return 0; }();")); ASSERT_EQUALS("{([cd,(return 0return", testAst("return [](int a, int b) -> int { return 0; }(c, d);")); + ASSERT_EQUALS("{([return", testAst("return []() -> decltype(0) {};")); ASSERT_EQUALS("x{([=", testAst("x = [&]()->std::string const & {};")); ASSERT_EQUALS("f{([=", testAst("f = []() -> foo* {};")); ASSERT_EQUALS("f{([=", testAst("f = [](void) mutable -> foo* {};")); @@ -8159,6 +8160,13 @@ private: " return 0;\n" " }};\n" "}\n")) + // #0535 + ASSERT_NO_THROW(tokenizeAndStringify("template struct a;\n" + "template void c() {\n" + " ([]() -> decltype(0) {\n" + " if (a::d) {}\n" + " });\n" + "}\n")) } void checkIfCppCast() { ASSERT_NO_THROW(tokenizeAndStringify("struct a {\n"