llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: cor3ntin (cor3ntin) <details> <summary>Changes</summary> When tentatively parsing cast expressions, we were assuming `[` was the start of a lambda expression. However, the expression might instead by a subscripted parenthesized postfix expression. Therefore, we need to check if the expression is in fact a lambda. We do that by looking for an open brace, bailing early when possible. Fixes #<!-- -->20723 --- Patch is 24.73 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/140053.diff 8 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+1) - (modified) clang/include/clang/Parse/Parser.h (+4) - (modified) clang/lib/Parse/ParseExpr.cpp (+4-2) - (modified) clang/lib/Parse/ParseExprCXX.cpp (+62) - (modified) clang/test/Parser/cxx0x-lambda-expressions.cpp (+82) - (modified) clang/test/Parser/cxx1z-constexpr-lambdas.cpp (+24-14) - (modified) clang/test/Parser/cxx2a-template-lambdas.cpp (+25-19) - (modified) clang/test/Parser/cxx2b-lambdas.cpp (+76-55) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 31c517338c21f..a7c8b2514b226 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -710,6 +710,7 @@ Bug Fixes to C++ Support - Clang now correctly parses arbitrary order of ``[[]]``, ``__attribute__`` and ``alignas`` attributes for declarations (#GH133107) - Fixed a crash when forming an invalid function type in a dependent context. (#GH138657) (#GH115725) (#GH68852) - Clang no longer segfaults when there is a configuration mismatch between modules and their users (http://crbug.com/400353616). +- Fix parsing of expressions of the form ``((T))[expr]``. (#GH20723) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index e6492b81dfff8..016708de2bf4c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -4639,6 +4639,10 @@ class Parser : public CodeCompletionHandler { ParseLambdaIntroducer(LambdaIntroducer &Intro, LambdaIntroducerTentativeParse *Tentative = nullptr); + /// Tries to determine if an expression of the form (S())[...]... + /// is a type-cast followed by a lambda, or a subscript expression + bool IsLambdaAfterTypeCast(); + /// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda /// expression. ExprResult ParseLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 11cfbbe790418..09dabaad4e231 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1585,8 +1585,10 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, } break; } - Res = ParseLambdaExpression(); - break; + if (isTypeCast != TypeCastState::IsTypeCast || IsLambdaAfterTypeCast()) { + Res = ParseLambdaExpression(); + break; + } } if (getLangOpts().ObjC) { Res = ParseObjCMessageExpression(); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index d95260829e4a0..996833b3cc293 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -692,6 +692,68 @@ ExprResult Parser::ParseLambdaExpression() { return ParseLambdaExpressionAfterIntroducer(Intro); } +bool Parser::IsLambdaAfterTypeCast() { + assert(getLangOpts().CPlusPlus && Tok.is(tok::l_square) && + "Not at the start of a possible lambda expression."); + RevertingTentativeParsingAction TPA(*this); + ConsumeBracket(); + // skip the introducer + if (Tok.is(tok::equal) || + (Tok.is(tok::amp) && NextToken().isOneOf(tok::comma, tok::r_square))) + SkipUntil(tok::r_square); + + auto IsLambdaKWOrAttribute = [&]() { + // These keyworks that either can appear somewhere in a lambda declarator, + // or cannot appear in a cast expression and we recover in favor of lambdas + if (Tok.isOneOf(tok::kw___declspec, tok::kw___noinline__, tok::kw_noexcept, + tok::kw_throw, tok::kw_mutable, tok::kw___attribute, + tok::kw_constexpr, tok::kw_consteval, tok::kw_static, + tok::kw_inline, tok::kw_extern, tok::kw___private, + tok::kw___global, tok::kw___local, tok::kw___constant, + tok::kw___generic, tok::kw_groupshared, tok::kw_requires, + tok::kw_noexcept)) + return true; + return Tok.isRegularKeywordAttribute() || + isCXX11AttributeSpecifier() != + CXX11AttributeKind::NotAttributeSpecifier; + }; + + if (Tok.is(tok::l_brace) || IsLambdaKWOrAttribute()) + return true; + + // This is a generic lambda, + if (Tok.is(tok::less)) { + ConsumeToken(); + // Common cases. We consider <> as an invalid lambda. + if (Tok.isOneOf(tok::greater, tok::kw_typename, tok::kw_auto, + tok::kw_template)) + return true; + if (isStartOfTemplateTypeParameter() != TPResult::False) + return true; + return isCXXDeclarationSpecifier(ImplicitTypenameContext::Yes) != + TPResult::False; + } + // skip the parameter list + if (Tok.is(tok::l_paren)) { + ConsumeParen(); + SkipUntil(tok::r_paren); + } + + if (IsLambdaKWOrAttribute()) + return true; + + if (Tok.is(tok::arrow)) { + ConsumeToken(); + // These cases are always id-expressions + if (Tok.isOneOf(tok::kw_template, tok::kw_operator, tok::tilde)) + return false; + if (!Tok.is(tok::identifier)) + return true; + return isCXXTypeId(TentativeCXXTypeIdContext::InTrailingReturnType); + } + return Tok.is(tok::l_brace); +} + ExprResult Parser::TryParseLambdaExpression() { assert(getLangOpts().CPlusPlus && Tok.is(tok::l_square) && "Not at the start of a possible lambda expression."); diff --git a/clang/test/Parser/cxx0x-lambda-expressions.cpp b/clang/test/Parser/cxx0x-lambda-expressions.cpp index a786a964163e4..d5466d44d8fff 100644 --- a/clang/test/Parser/cxx0x-lambda-expressions.cpp +++ b/clang/test/Parser/cxx0x-lambda-expressions.cpp @@ -40,6 +40,33 @@ class C { return 1; } + int type_cast() { + int foo, bar; + + (void)[]; // expected-error {{expected expression}} + (void)[+] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + (void)[foo+] {}; // expected-error {{expected ',' or ']' in lambda capture list}} + (void)[foo,&this] {}; // expected-error {{'this' cannot be captured by reference}} + (void)[&this] {}; // expected-error {{'this' cannot be captured by reference}} + (void)[&,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + (void)[=,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + (void)[] {}; + (void)[=] (int i) {}; + (void)[&] (int) mutable -> void {}; + (void)[foo,bar] () { return 3; }; + (void)[=,&foo] () {}; + (void)[&,foo] () {}; + (void)[this] () {}; + (void)[] () -> class C { return C(); }; + (void)[] () -> enum E { return e; }; + + (void)[] -> int { return 0; }; // cxx23ext-warning {{lambda without a parameter clause is a C++23 extension}} + (void)[] mutable -> int { return 0; }; // cxx23ext-warning {{is a C++23 extension}} + + (void)[](int) -> {}; // PR13652 expected-error {{expected a type}} + return 1; + } + void designator_or_lambda() { typedef int T; const int b = 0; @@ -125,10 +152,46 @@ class C { [][[]]{}; // cxx23ext-warning {{an attribute specifier sequence in this position is a C++23 extension}} } + void attributes_type_cast() { + (void)[] __attribute__((noreturn)){}; // cxx23ext-warning {{lambda without a parameter clause is a C++23 extension}} + + (void)[]() [[]] + mutable {}; // expected-error {{expected body of lambda expression}} + + (void)[]() [[]] {}; + (void)[]() [[]] -> void {}; + (void)[]() mutable [[]] -> void {}; +#if __cplusplus >= 201103L + (void)[]() mutable noexcept [[]] -> void {}; +#endif + + // Testing GNU-style attributes on lambdas -- the attribute is specified + // before the mutable specifier instead of after (unlike C++11). + (void)[]() __attribute__((noreturn)) mutable { while(1); }; + (void)[]() mutable + __attribute__((noreturn)) { while(1); }; // expected-error {{expected body of lambda expression}} + + // Testing support for P2173 on adding attributes to the declaration + // rather than the type. + (void)[][[]](){}; // cxx23ext-warning {{an attribute specifier sequence in this position is a C++23 extension}} + + (void)[]<typename>[[]](){}; // cxx20ext-warning {{explicit template parameter list for lambdas is a C++20 extension}} + // cxx23ext-warning@-1 {{an attribute specifier sequence in this position is a C++23 extension}} + + (void)[][[]]{}; // cxx23ext-warning {{an attribute specifier sequence in this position is a C++23 extension}} + } + void missing_parens() { [] mutable {}; // cxx23ext-warning {{is a C++23 extension}} #if __cplusplus >= 201103L [] noexcept {}; // cxx23ext-warning {{is a C++23 extension}} +#endif + } + + void missing_parens_type_cast() { + (void)[] mutable {}; // cxx23ext-warning {{is a C++23 extension}} +#if __cplusplus >= 201103L + (void)[] noexcept {}; // cxx23ext-warning {{is a C++23 extension}} #endif } }; @@ -150,6 +213,25 @@ struct S { }; } +#if __cplusplus >= 201103L +namespace GH20723 { +struct S { + S operator[](int); + S operator()(); + S operator<(int); + S* operator->(); + long a; +}; +int n; +void f() { + static_assert(__is_same_as(decltype((S())[n]()), S), ""); + static_assert(__is_same_as(decltype((S())[n] < 0), S), ""); + static_assert(__is_same_as(decltype((S())[n]->a), long), ""); +} +} +#endif + + struct S { template <typename T> void m (T x =[0); // expected-error{{expected variable name or 'this' in lambda capture list}} diff --git a/clang/test/Parser/cxx1z-constexpr-lambdas.cpp b/clang/test/Parser/cxx1z-constexpr-lambdas.cpp index 87584ee5ca91b..bba63b4925298 100644 --- a/clang/test/Parser/cxx1z-constexpr-lambdas.cpp +++ b/clang/test/Parser/cxx1z-constexpr-lambdas.cpp @@ -1,26 +1,34 @@ -// RUN: %clang_cc1 -std=c++23 %s -verify -// RUN: %clang_cc1 -std=c++20 %s -verify -// RUN: %clang_cc1 -std=c++17 %s -verify -// RUN: %clang_cc1 -std=c++14 %s -verify -// RUN: %clang_cc1 -std=c++11 %s -verify +// RUN: %clang_cc1 -std=c++23 %s -verify -Wno-unused "-DTYPE_CAST=" +// RUN: %clang_cc1 -std=c++20 %s -verify -Wno-unused "-DTYPE_CAST=" +// RUN: %clang_cc1 -std=c++17 %s -verify -Wno-unused "-DTYPE_CAST=" +// RUN: %clang_cc1 -std=c++14 %s -verify -Wno-unused "-DTYPE_CAST=" +// RUN: %clang_cc1 -std=c++11 %s -verify -Wno-unused "-DTYPE_CAST=" -auto XL0 = [] constexpr { return true; }; +// RUN: %clang_cc1 -std=c++23 %s -verify "-DTYPE_CAST=(void)" +// RUN: %clang_cc1 -std=c++20 %s -verify "-DTYPE_CAST=(void)" +// RUN: %clang_cc1 -std=c++17 %s -verify "-DTYPE_CAST=(void)" +// RUN: %clang_cc1 -std=c++14 %s -verify "-DTYPE_CAST=(void)" +// RUN: %clang_cc1 -std=c++11 %s -verify "-DTYPE_CAST=(void)" + +void test() { + +TYPE_CAST [] constexpr { return true; }; #if __cplusplus <= 201402L // expected-warning@-2 {{is a C++17 extension}} #endif #if __cplusplus <= 202002L // expected-warning@-5 {{lambda without a parameter clause is a C++23 extension}} #endif -auto XL1 = []() mutable // +TYPE_CAST []() mutable // mutable // expected-error{{cannot appear multiple times}} mutable {}; // expected-error{{cannot appear multiple times}} #if __cplusplus > 201402L -auto XL2 = [] () constexpr mutable constexpr { }; //expected-error{{cannot appear multiple times}} -auto L = []() mutable constexpr { }; -auto L2 = []() constexpr { }; -auto L4 = []() constexpr mutable { }; -auto XL16 = [] () constexpr +TYPE_CAST [] () constexpr mutable constexpr { }; //expected-error{{cannot appear multiple times}} +TYPE_CAST []() mutable constexpr { }; +TYPE_CAST []() constexpr { }; +TYPE_CAST []() constexpr mutable { }; +TYPE_CAST [] () constexpr mutable constexpr //expected-error{{cannot appear multiple times}} mutable //expected-error{{cannot appear multiple times}} @@ -31,8 +39,10 @@ auto XL16 = [] () constexpr #else auto L = []() mutable constexpr {return 0; }; //expected-warning{{is a C++17 extension}} -auto L2 = []() constexpr { return 0;};//expected-warning{{is a C++17 extension}} -auto L4 = []() constexpr mutable { return 0; }; //expected-warning{{is a C++17 extension}} +TYPE_CAST []() constexpr { return 0;};//expected-warning{{is a C++17 extension}} +TYPE_CAST []() constexpr mutable { return 0; }; //expected-warning{{is a C++17 extension}} #endif +} + diff --git a/clang/test/Parser/cxx2a-template-lambdas.cpp b/clang/test/Parser/cxx2a-template-lambdas.cpp index 98c74a247b535..bb43101045e9e 100644 --- a/clang/test/Parser/cxx2a-template-lambdas.cpp +++ b/clang/test/Parser/cxx2a-template-lambdas.cpp @@ -1,38 +1,44 @@ -// RUN: %clang_cc1 -std=c++23 %s -verify -// RUN: %clang_cc1 -std=c++20 %s -verify +// RUN: %clang_cc1 -std=c++23 %s -verify -Wno-unused "-DTYPE_CAST=" +// RUN: %clang_cc1 -std=c++20 %s -verify -Wno-unused "-DTYPE_CAST=" +// RUN: %clang_cc1 -std=c++23 %s -verify "-DTYPE_CAST=(void)" +// RUN: %clang_cc1 -std=c++20 %s -verify "-DTYPE_CAST=(void)" -auto L0 = []<> { }; //expected-error {{cannot be empty}} +void test() { -auto L1 = []<typename T1, typename T2> { }; -auto L2 = []<typename T1, typename T2>(T1 arg1, T2 arg2) -> T1 { }; -auto L3 = []<typename T>(auto arg) { T t; }; -auto L4 = []<int I>() { }; +TYPE_CAST []<> { }; //expected-error {{cannot be empty}} + +TYPE_CAST []<typename T1, typename T2> { }; +TYPE_CAST []<typename T1, typename T2>(T1 arg1, T2 arg2) -> T1 { }; +TYPE_CAST []<typename T>(auto arg) { T t; }; +TYPE_CAST []<int I>() { }; // http://llvm.org/PR49736 -auto L5 = []<auto>(){}; -auto L6 = []<auto>{}; -auto L7 = []<auto>() noexcept {}; -auto L8 = []<auto> noexcept {}; +TYPE_CAST []<auto>(){}; +TYPE_CAST []<auto>{}; +TYPE_CAST []<auto>() noexcept {}; +TYPE_CAST []<auto> noexcept {}; #if __cplusplus <= 202002L // expected-warning@-2 {{lambda without a parameter clause is a C++23 extension}} #endif -auto L9 = []<auto> requires true {}; -auto L10 = []<auto> requires true(){}; -auto L11 = []<auto> requires true() noexcept {}; -auto L12 = []<auto> requires true noexcept {}; +TYPE_CAST []<auto> requires true {}; +TYPE_CAST []<auto> requires true(){}; +TYPE_CAST []<auto> requires true() noexcept {}; +TYPE_CAST []<auto> requires true noexcept {}; #if __cplusplus <= 202002L // expected-warning@-2 {{is a C++23 extension}} #endif -auto L13 = []<auto>() noexcept requires true {}; -auto L14 = []<auto> requires true() noexcept requires true {}; +TYPE_CAST []<auto>() noexcept requires true {}; +TYPE_CAST []<auto> requires true() noexcept requires true {}; -auto XL0 = []<auto> noexcept requires true {}; // expected-error {{expected body of lambda expression}} -auto XL1 = []<auto> requires true noexcept requires true {}; // expected-error {{expected body}} +TYPE_CAST []<auto> noexcept requires true {}; // expected-error {{expected body of lambda expression}} +TYPE_CAST []<auto> requires true noexcept requires true {}; // expected-error {{expected body}} #if __cplusplus <= 202002L // expected-warning@-3 {{is a C++23 extension}} // expected-warning@-3 {{is a C++23 extension}} #endif +} + namespace GH64962 { void f() { [] <typename T>(T i) -> int[] // expected-error {{function cannot return array type 'int[]'}} diff --git a/clang/test/Parser/cxx2b-lambdas.cpp b/clang/test/Parser/cxx2b-lambdas.cpp index 758ec9a42f56d..a769fbda36276 100644 --- a/clang/test/Parser/cxx2b-lambdas.cpp +++ b/clang/test/Parser/cxx2b-lambdas.cpp @@ -1,88 +1,109 @@ -// RUN: %clang_cc1 -std=c++03 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions -Wno-c++11-extensions -// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11 -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions -// RUN: %clang_cc1 -std=c++14 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -// RUN: %clang_cc1 -std=c++17 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions -// RUN: %clang_cc1 -std=c++20 %s -verify -Wno-c++23-extensions -// RUN: %clang_cc1 -std=c++23 %s -verify - -auto LL0 = [] {}; -auto LL1 = []() {}; -auto LL2 = []() mutable {}; +// RUN: %clang_cc1 -std=c++03 %s "-DTYPE_CAST=" -verify -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions -Wno-c++11-extensions +// RUN: %clang_cc1 -std=c++11 %s "-DTYPE_CAST=" -verify=expected,cxx11 -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions +// RUN: %clang_cc1 -std=c++14 %s "-DTYPE_CAST=" -verify -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions +// RUN: %clang_cc1 -std=c++17 %s "-DTYPE_CAST=" -verify -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions +// RUN: %clang_cc1 -std=c++20 %s "-DTYPE_CAST=" -verify -Wno-unused -Wno-c++23-extensions +// RUN: %clang_cc1 -std=c++23 %s "-DTYPE_CAST=" -verify -Wno-unused + +// RUN: %clang_cc1 -std=c++03 %s "-DTYPE_CAST=(void)" -verify -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions -Wno-c++11-extensions +// RUN: %clang_cc1 -std=c++11 %s "-DTYPE_CAST=(void)" -verify=expected,cxx11 -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions +// RUN: %clang_cc1 -std=c++14 %s "-DTYPE_CAST=(void)" -verify -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions +// RUN: %clang_cc1 -std=c++17 %s "-DTYPE_CAST=(void)" -verify -Wno-unused -Wno-c++23-extensions -Wno-c++20-extensions +// RUN: %clang_cc1 -std=c++20 %s "-DTYPE_CAST=(void)" -verify -Wno-unused -Wno-c++23-extensions +// RUN: %clang_cc1 -std=c++23 %s "-DTYPE_CAST=(void)" -verify -Wno-unused + +void test() { + +TYPE_CAST [] {}; +TYPE_CAST []() {}; +TYPE_CAST []() mutable {}; #if __cplusplus >= 201103L -auto LL3 = []() constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} +TYPE_CAST []() constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} #endif #if __cplusplus >= 201103L -auto L0 = [] constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} +TYPE_CAST [] constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} #endif -auto L1 = [] mutable {}; +TYPE_CAST [] mutable {}; #if __cplusplus >= 201103L -auto L2 = [] noexcept {}; -auto L3 = [] constexpr mutable {}; // cxx11-error {{return type 'void' is not a literal type}} -auto L4 = [] mutable constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} -auto L5 = [] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}} +TYPE_CAST [] noexcept {}; +TYPE_CAST [] constexpr mutable {}; // cxx11-error {{return type 'void' is not a literal type}} +TYPE_CAST [] mutable constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} +TYPE_CAST [] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}} #endif -auto L6 = [s = 1] mutable {}; +TYPE_CAST [s = 1] mutable {}; #if __cplusplus >= 201103L -auto L7 = [s = 1] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}} +TYPE_CAST [s = 1] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}} #endif -auto L8 = [] -> bool { return true; }; -auto L9 = []<typename T> { return true; }; +TYPE_CAST [] -> bool { return true; }; +TYPE_CAST []<typename T> { return true; }; #if __cplusplus >= 201103L -auto L10 = []<typename T> noexcept { return true; }; +TYPE_CAST []<typename T> noexcept { return true; }; #endif -auto L11 = []<typename T> -> bool { return true; }; +TYPE_CAST []<typename T> -> bool { return true; }; #if __cplusplus >= 202002L -auto L12 = [] consteval {}; -auto L13 = []() requires true {}; // expected-error{{non-templated function cannot have a requires clause}} -auto L14 = []<auto> requires true() requires true {}; -auto L15 = []<auto> requires true noexcept {}; +TYPE_CAST [] consteval {}; +TYPE_CAST []() requires true {}; // expected-error{{non-templated function cannot have a requires clause}} +TYPE_CAST []<auto> requires true() requires true {}; +TYPE_CAST []<auto> requires true noexcept {}; #endif -auto L16 = [] [[maybe_unused]]{}; +TYPE_CAST [] [[maybe_unused]]{}; #if __cplusplus >= 201103L -auto XL0 = [] mutable constexpr mutable {}; // expected-error{{cannot appear multiple times}} cxx11-error {{return type 'void' is not a literal type}} -auto XL1 = [] constexpr mutable constexpr {}; // expected-error{{cannot appear multiple times}} cxx11-error {{return type 'void' is not a literal type}} -auto XL2 = []) constexpr mutable constexpr {}; // expected-error{{expected body of lambda expression}} -au... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/140053 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits