Fixed #9729 (AST broken: lambda with noexcept keyword) (#3243)

The previous fix for the issue (43b58dbc9e) didn't seem to actually fix
it because it added a check for noexcept without a condition, but when
AST is created noexcept always has a condition due to simplification
from "noexcept" to "noexcept(true)" in Tokenizer::simplifyKeyword().
The issue from the ticket couldn't be reproduced neither on 43b58dbc9e
nor on the previous commit, so it is hard to tell whether the fix was
effective or not.

The issue appeared again after a refactoring of AST code in ac67049661.
Test added with the original fix was unable to catch that because it
used testAst() helper function which skips most simplification steps.

To fix the issue we now check for noexcept with a condition and add a
proper regression test that:
1. Uses tokenizeAndStringify() to ensure that all simplifications are
   performed before AST is created.
2. Parses the code snippet from the ticket, as having "if (cond)" is
   crucial to reproducing the original issue (internalAstError).

Also fix AST creation for lambdas that have both constexpr and mutable
keywords.
This commit is contained in:
dummyunit 2021-05-02 22:34:28 +03:00 committed by GitHub
parent f7d0bf7a59
commit ac505afe69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 3 deletions

View File

@ -951,8 +951,10 @@ 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 (Token::Match(curlyBracket, "mutable|const|noexcept")) while (Token::Match(curlyBracket, "mutable|const"))
curlyBracket = curlyBracket->next(); curlyBracket = curlyBracket->next();
if (Token::simpleMatch(curlyBracket, "noexcept ("))
curlyBracket = curlyBracket->linkAt(1)->next();
if (curlyBracket && curlyBracket->originalName() == "->") if (curlyBracket && curlyBracket->originalName() == "->")
curlyBracket = findTypeEnd(curlyBracket->next()); curlyBracket = findTypeEnd(curlyBracket->next());
if (curlyBracket && curlyBracket->str() == "{") { if (curlyBracket && curlyBracket->str() == "{") {

View File

@ -5932,8 +5932,16 @@ private:
ASSERT_EQUALS("x{(a&[( ai=", testAst("x([&a](int i){a=i;});")); ASSERT_EQUALS("x{(a&[( ai=", testAst("x([&a](int i){a=i;});"));
ASSERT_EQUALS("{([(return 0return", testAst("return [](){ return 0; }();")); ASSERT_EQUALS("{([(return 0return", testAst("return [](){ return 0; }();"));
// noexcept // noexcept (which if simplified to always have a condition by the time AST is created)
ASSERT_EQUALS("x{([( ai=", testAst("x([](int i)noexcept{a=i;});")); ASSERT_EQUALS("x{([( ai=", testAst("x([](int i) noexcept(true) { a=i; });"));
ASSERT_EQUALS("x{([( ai=", testAst("x([](int i) mutable noexcept(true) { a=i; });"));
ASSERT_EQUALS("x{([( ai=", testAst("x([](int i) const noexcept(true) { a=i; });"));
// both mutable and constexpr (which is simplified to 'const' by the time AST is created)
ASSERT_EQUALS("x{([( ai=", testAst("x([](int i) const mutable { a=i; });"));
ASSERT_EQUALS("x{([( ai=", testAst("x([](int i) mutable const { a=i; });"));
ASSERT_EQUALS("x{([( ai=", testAst("x([](int i) const mutable noexcept(true) { a=i; });"));
ASSERT_EQUALS("x{([( ai=", testAst("x([](int i) mutable const noexcept(true) { a=i; });"));
// -> // ->
ASSERT_EQUALS("{([(return 0return", testAst("return []() -> int { return 0; }();")); ASSERT_EQUALS("{([(return 0return", testAst("return []() -> int { return 0; }();"));
@ -5989,6 +5997,9 @@ private:
// Lambda capture expression (C++14) // Lambda capture expression (C++14)
ASSERT_EQUALS("a{b1=[= c2=", testAst("a = [b=1]{c=2;};")); ASSERT_EQUALS("a{b1=[= c2=", testAst("a = [b=1]{c=2;};"));
// #9729
ASSERT_NO_THROW(tokenizeAndStringify("void foo() { bar([]() noexcept { if (0) {} }); }"));
} }
void astcase() { void astcase() {