Author: Nikolas Klauser
Date: 2026-08-16T13:38:58+02:00
New Revision: e65f3c155d9a957939ef63c1a824aa254a4cc20c

URL: 
https://github.com/llvm/llvm-project/commit/e65f3c155d9a957939ef63c1a824aa254a4cc20c
DIFF: 
https://github.com/llvm/llvm-project/commit/e65f3c155d9a957939ef63c1a824aa254a4cc20c.diff

LOG: [Clang] Accept auto casts pre-C++23 as an extension (#200675)

GCC already supports this as an extension pre-C++23. It is also useful
for libc++ to replace `_LIBCPP_AUTO_CAST`.

Fixes #115609

Added: 
    

Modified: 
    clang/docs/LanguageExtensions.md
    clang/docs/ReleaseNotes.md
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/lib/Parse/ParseTentative.cpp
    clang/lib/Sema/SemaExprCXX.cpp
    clang/lib/Sema/SemaType.cpp
    clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
    clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.auto.deduct/p2.cpp
    clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp
    clang/test/Lexer/cxx-features.cpp
    clang/test/Parser/cxx1z-decomposition.cpp
    clang/test/Parser/cxx2b-auto-x.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.md 
b/clang/docs/LanguageExtensions.md
index 85586174e9190..3fbdbd9a511f3 100644
--- a/clang/docs/LanguageExtensions.md
+++ b/clang/docs/LanguageExtensions.md
@@ -1786,6 +1786,7 @@ More information can be found 
[here](https://clang.llvm.org/docs/Modules.html).
 | `= delete ("should have a reason");`          | \_\_cpp_deleted_function     
      | C++26         | C++03         |
 | Variadic Friends                              | \_\_cpp_variadic_friend      
      | C++26         | C++03         |
 | Trivial Relocatability                        | 
\_\_cpp_trivial_relocatability     | C++26         | C++03         |
+|``auto()`` cast                                | \_\_cpp_auto_cast            
      | C++26         | C++03         |
 | Designated initializers (N494)                |                              
      | C99           | C89           |
 | `_Complex` (N693)                             |                              
      | C99           | C89, C++      |
 | `_Bool` (N815)                                |                              
      | C99           | C89           |

diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 70ea2e35090c6..aa741bbf961e2 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -124,6 +124,8 @@ features cannot lower the translation-unit ABI level;
 
 ### C++ Language Changes
 
+- ``auto()`` casts are accepted as an extension pre-C++23.
+
 #### C++2d Feature Support
 
 - Clang now supports [P3658R1](https://wg21.link/p3658r1) (Adjust identifier

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b314c17ad27bd..4abf4b4598257 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -72,6 +72,8 @@ defm constexpr_static_var : CXX23Compat<
   "in a constexpr %select{function|constructor}0 "
   "is">;
 
+defm auto_expr : CXX23Compat<"'auto' as a functional-style cast is">;
+
 // C++26 compatibility with C++23 and earlier.
 defm decomp_decl_cond : CXX26Compat<"structured binding declaration in a 
condition is">;
 
@@ -2728,9 +2730,6 @@ def err_auto_new_ctor_multiple_expressions : Error<
 def err_auto_expr_init_paren_braces : Error<
   "cannot deduce actual type for %1 from "
   "%select{parenthesized|nested}0 initializer list">;
-def warn_cxx20_compat_auto_expr : Warning<
-  "'auto' as a functional-style cast is incompatible with C++ standards "
-  "before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def err_auto_missing_trailing_return : Error<
   "'auto' return without trailing return type; deduced return types are a "
   "C++14 extension">;

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp 
b/clang/lib/Frontend/InitPreprocessor.cpp
index 7f32f70fe52a3..7cc481b595f36 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -749,7 +749,6 @@ static void InitializeCPlusPlusFeatureTestMacros(const 
LangOptions &LangOpts,
     Builder.defineMacro("__cpp_size_t_suffix", "202011L");
     Builder.defineMacro("__cpp_if_consteval", "202106L");
     Builder.defineMacro("__cpp_multidimensional_subscript", "202211L");
-    Builder.defineMacro("__cpp_auto_cast", "202110L");
     Builder.defineMacro("__cpp_explicit_this_parameter", "202110L");
   }
 
@@ -757,6 +756,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const 
LangOptions &LangOpts,
   // we also define their feature test macros.
   if (LangOpts.CPlusPlus11)
     Builder.defineMacro("__cpp_static_call_operator", "202207L");
+  Builder.defineMacro("__cpp_auto_cast", "202110L");
   Builder.defineMacro("__cpp_named_character_escapes", "202606L");
   Builder.defineMacro("__cpp_placeholder_variables", "202306L");
 

diff  --git a/clang/lib/Parse/ParseTentative.cpp 
b/clang/lib/Parse/ParseTentative.cpp
index ab64b9d65d8e4..4010438c49d1f 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1144,8 +1144,6 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext 
AllowImplicitTypename,
                                      BracedCastResult, InvalidAsDeclSpec);
 
   case tok::kw_auto: {
-    if (!getLangOpts().CPlusPlus23)
-      return TPResult::True;
     if (NextToken().is(tok::l_brace))
       return TPResult::False;
     if (NextToken().is(tok::l_paren))

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 5709957b14439..cc9f85e2bb0cb 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1567,6 +1567,9 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
       Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits());
     }
 
+    if (Ty->getAs<AutoType>())
+      DiagCompat(TyBeginLoc, diag_compat::auto_expr) << FullRange;
+
     if (Inits.empty())
       return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_init_no_expression)
                        << Ty << FullRange);
@@ -1576,10 +1579,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
                             diag::err_auto_expr_init_multiple_expressions)
                        << Ty << FullRange);
     }
-    if (getLangOpts().CPlusPlus23) {
-      if (Ty->getAs<AutoType>())
-        Diag(TyBeginLoc, diag::warn_cxx20_compat_auto_expr) << FullRange;
-    }
     Expr *Deduce = Inits[0];
     if (isa<InitListExpr>(Deduce))
       return ExprError(

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index f9033ecb48581..42ef93b98aa0a 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3379,8 +3379,7 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
     case DeclaratorContext::FunctionalCast:
       if (isa<DeducedTemplateSpecializationType>(Deduced))
         break;
-      if (SemaRef.getLangOpts().CPlusPlus23 && IsCXXAutoType &&
-          !Auto->isDecltypeAuto())
+      if (IsCXXAutoType && !Auto->isDecltypeAuto())
         break; // auto(x)
       [[fallthrough]];
     case DeclaratorContext::TypeName:

diff  --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp 
b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
index 3c5490605e19f..e90d7c41f9da6 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
@@ -56,8 +56,8 @@ void j() {
   (void)reinterpret_cast<auto>(n);    // expected-error{{'auto' not allowed 
here}}
   (void)const_cast<auto>(n);          // expected-error{{'auto' not allowed 
here}}
   (void)(auto)(n);                    // expected-error{{'auto' not allowed 
here}}
-  (void)auto(n);                      // expected-error{{'auto' not allowed 
here}}
-  (void)auto{n};                      // expected-error{{'auto' not allowed 
here}}
+  (void)auto(n);                      // expected-warning{{'auto' as a 
functional-style cast is a C++23 extension}}
+  (void)auto{n};                      // expected-warning{{'auto' as a 
functional-style cast is a C++23 extension}}
 }
 
 template <auto a = 10> class C { }; // expected-error{{'auto' not allowed in 
template parameter}}

diff  --git 
a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.auto.deduct/p2.cpp 
b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.auto.deduct/p2.cpp
index 1655685f44808..1c6c66882c570 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.auto.deduct/p2.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.auto.deduct/p2.cpp
@@ -1,37 +1,38 @@
+// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20 %s
 // RUN: %clang_cc1 -std=c++23 -verify %s
 
 // p2.3 allows only T = auto in T(x).
 
 void test_decay() {
   int v[3];
-  static_assert(__is_same(decltype(auto(v)), int *));
-  static_assert(__is_same(decltype(auto{v}), int *));
-  static_assert(__is_same(decltype(auto("lit")), char const *));
-  static_assert(__is_same(decltype(auto{"lit"}), char const *));
+  static_assert(__is_same(decltype(auto(v)), int *)); // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto{v}), int *)); // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto("lit")), char const *)); // 
cxx20-warning {{'auto' as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto{"lit"}), char const *)); // 
cxx20-warning {{'auto' as a functional-style cast is a C++23 extension}}
 
   constexpr long i = 1;
   static_assert(__is_same(decltype(i), long const));
-  static_assert(__is_same(decltype(auto(1L)), long));
-  static_assert(__is_same(decltype(auto{1L}), long));
-  static_assert(__is_same(decltype(auto(i)), long));
-  static_assert(__is_same(decltype(auto{i}), long));
+  static_assert(__is_same(decltype(auto(1L)), long)); // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto{1L}), long)); // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto(i)), long));  // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto{i}), long));  // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
 
   class A {
   } a;
   A const ac;
 
-  static_assert(__is_same(decltype(auto(a)), A));
-  static_assert(__is_same(decltype(auto(ac)), A));
+  static_assert(__is_same(decltype(auto(a)), A));  // cxx20-warning {{'auto' 
as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto(ac)), A)); // cxx20-warning {{'auto' 
as a functional-style cast is a C++23 extension}}
 
   A &lr = a;
   A const &lrc = a;
   A &&rr = static_cast<A &&>(a);
   A const &&rrc = static_cast<A &&>(a);
 
-  static_assert(__is_same(decltype(auto(lr)), A));
-  static_assert(__is_same(decltype(auto(lrc)), A));
-  static_assert(__is_same(decltype(auto(rr)), A));
-  static_assert(__is_same(decltype(auto(rrc)), A));
+  static_assert(__is_same(decltype(auto(lr)), A));  // cxx20-warning {{'auto' 
as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto(lrc)), A)); // cxx20-warning {{'auto' 
as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto(rr)), A));  // cxx20-warning {{'auto' 
as a functional-style cast is a C++23 extension}}
+  static_assert(__is_same(decltype(auto(rrc)), A)); // cxx20-warning {{'auto' 
as a functional-style cast is a C++23 extension}}
 }
 
 class cmdline_parser {
@@ -42,7 +43,7 @@ class cmdline_parser {
 
 void test_rvalue_fluent_interface() {
   auto cmdline = cmdline_parser("driver");
-  auto internal = auto{cmdline}.add_option("--dump-full", "do not minimize 
dump");
+  auto internal = auto{cmdline}.add_option("--dump-full", "do not minimize 
dump"); // cxx20-warning {{'auto' as a functional-style cast is a C++23 
extension}}
 }
 
 template <class T> constexpr auto decay_copy(T &&v) { return static_cast<T 
&&>(v); } // expected-error {{calling a protected constructor}}
@@ -55,17 +56,17 @@ class A {
   A();
 
   auto test_access() {
-    static_assert(__is_same(decltype(auto(*this)), A));
-    static_assert(__is_same(decltype(auto(this)), A *));
+    static_assert(__is_same(decltype(auto(*this)), A));  // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
+    static_assert(__is_same(decltype(auto(this)), A *)); // cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
 
     f(A(*this));          // ok
-    f(auto(*this));       // ok in P0849
+    f(auto(*this));       // ok in P0849 cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
     f(decay_copy(*this)); // expected-note {{in instantiation of function 
template specialization}}
   }
 
   auto test_access() const {
-    static_assert(__is_same(decltype(auto(*this)), A)); // ditto
-    static_assert(__is_same(decltype(auto(this)), A const *));
+    static_assert(__is_same(decltype(auto(*this)), A)); // ditto cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
+    static_assert(__is_same(decltype(auto(this)), A const *)); // 
cxx20-warning {{'auto' as a functional-style cast is a C++23 extension}}
   }
 
 protected:
@@ -77,5 +78,5 @@ namespace auto_x {
 constexpr struct Uncopyable {
   constexpr explicit Uncopyable(int) {}
   constexpr Uncopyable(Uncopyable &&) = delete;
-} u = auto(Uncopyable(auto(Uncopyable(42))));
+} u = auto(Uncopyable(auto(Uncopyable(42)))); // cxx20-warning 2 {{'auto' as a 
functional-style cast is a C++23 extension}}
 } // namespace auto_x

diff  --git a/clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp 
b/clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp
index bbfce5e698d15..08560ea19c9c7 100644
--- a/clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp
+++ b/clang/test/CXX/expr/expr.post/expr.type.conv/p1-2b.cpp
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20 %s
 // RUN: %clang_cc1 -std=c++23 -verify %s
 
 template <class T>
@@ -12,28 +13,28 @@ struct A {
 // C++23 [dcl.type.auto.deduct]p2.3
 // For an explicit type conversion, T is the specified type, which shall be 
auto.
 void diagnostics() {
-  foo(auto());   // expected-error {{initializer for functional-style cast to 
'auto' is empty}}
-  foo(auto{});   // expected-error {{initializer for functional-style cast to 
'auto' is empty}}
-  foo(auto({})); // expected-error {{cannot deduce actual type for 'auto' from 
parenthesized initializer list}}
-  foo(auto{{}}); // expected-error {{cannot deduce actual type for 'auto' from 
nested initializer list}}
+  foo(auto());   // expected-error {{initializer for functional-style cast to 
'auto' is empty}} cxx20-warning {{'auto' as a functional-style cast is a C++23 
extension}}
+  foo(auto{});   // expected-error {{initializer for functional-style cast to 
'auto' is empty}} cxx20-warning {{'auto' as a functional-style cast is a C++23 
extension}}
+  foo(auto({})); // expected-error {{cannot deduce actual type for 'auto' from 
parenthesized initializer list}} cxx20-warning {{'auto' as a functional-style 
cast is a C++23 extension}}
+  foo(auto{{}}); // expected-error {{cannot deduce actual type for 'auto' from 
nested initializer list}} cxx20-warning {{'auto' as a functional-style cast is 
a C++23 extension}}
 
   // - If the initializer is a parenthesized expression-list, the 
expression-list shall be a single assignmentexpression and E is the 
assignment-expression.
-  foo(auto(a));
+  foo(auto(a)); // cxx20-warning {{'auto' as a functional-style cast is a 
C++23 extension}}
   // - If the initializer is a braced-init-list, it shall consist of a single 
brace-enclosed assignment-expression and E is the assignment-expression.
-  foo(auto{a});
-  foo(auto({a})); // expected-error {{cannot deduce actual type for 'auto' 
from parenthesized initializer list}}
-  foo(auto{{a}}); // expected-error {{cannot deduce actual type for 'auto' 
from nested initializer list}}
+  foo(auto{a});   // cxx20-warning {{'auto' as a functional-style cast is a 
C++23 extension}}
+  foo(auto({a})); // expected-error {{cannot deduce actual type for 'auto' 
from parenthesized initializer list}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto{{a}}); // expected-error {{cannot deduce actual type for 'auto' 
from nested initializer list}} cxx20-warning {{'auto' as a functional-style 
cast is a C++23 extension}}
 
-  foo(auto(&A::g)); // expected-error {{functional-style cast to 'auto' has 
incompatible initializer of type '<overloaded function type>'}}
+  foo(auto(&A::g)); // expected-error {{functional-style cast to 'auto' has 
incompatible initializer of type '<overloaded function type>'}} cxx20-warning 
{{'auto' as a functional-style cast is a C++23 extension}}
 
-  foo(auto(a, 3.14));     // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}}
-  foo(auto{a, 3.14});     // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}}
-  foo(auto({a, 3.14}));   // expected-error {{cannot deduce actual type for 
'auto' from parenthesized initializer list}}
-  foo(auto{{a, 3.14}});   // expected-error {{cannot deduce actual type for 
'auto' from nested initializer list}}
-  foo(auto({a}, {3.14})); // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}}
-  foo(auto{{a}, {3.14}}); // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}}
+  foo(auto(a, 3.14));     // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto{a, 3.14});     // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto({a, 3.14}));   // expected-error {{cannot deduce actual type for 
'auto' from parenthesized initializer list}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto{{a, 3.14}});   // expected-error {{cannot deduce actual type for 
'auto' from nested initializer list}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto({a}, {3.14})); // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto{{a}, {3.14}}); // expected-error {{initializer for functional-style 
cast to 'auto' contains multiple expressions}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
 
-  foo(auto{1, 2});   // expected-error {{initializer for functional-style cast 
to 'auto' contains multiple expressions}}
-  foo(auto({1, 2})); // expected-error {{cannot deduce actual type for 'auto' 
from parenthesized initializer list}}
-  foo(auto{{1, 2}}); // expected-error {{cannot deduce actual type for 'auto' 
from nested initializer list}}
+  foo(auto{1, 2});   // expected-error {{initializer for functional-style cast 
to 'auto' contains multiple expressions}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto({1, 2})); // expected-error {{cannot deduce actual type for 'auto' 
from parenthesized initializer list}} cxx20-warning {{'auto' as a 
functional-style cast is a C++23 extension}}
+  foo(auto{{1, 2}}); // expected-error {{cannot deduce actual type for 'auto' 
from nested initializer list}} cxx20-warning {{'auto' as a functional-style 
cast is a C++23 extension}}s
 }

diff  --git a/clang/test/Lexer/cxx-features.cpp 
b/clang/test/Lexer/cxx-features.cpp
index f4749342d148b..b505f18dff14f 100644
--- a/clang/test/Lexer/cxx-features.cpp
+++ b/clang/test/Lexer/cxx-features.cpp
@@ -60,7 +60,7 @@
 
 // --- C++23 features ---
 
-#if check(auto_cast, 0, 0, 0, 0, 0, 202110, 202110)
+#if check(auto_cast, 202110, 202110, 202110, 202110, 202110, 202110, 202110)
 #error "wrong value for __cpp_auto_cast"
 #endif
 

diff  --git a/clang/test/Parser/cxx1z-decomposition.cpp 
b/clang/test/Parser/cxx1z-decomposition.cpp
index 607a628506e8a..916d4f74b0075 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -106,9 +106,10 @@ namespace BadSpecifiers {
     // defining-type-specifiers other than cv-qualifiers and 'auto'
     S [a] = s; // expected-error {{cannot be declared with type 'S'}}
     decltype(auto) [b] = s; // expected-error {{cannot be declared with type 
'decltype(auto)'}}
-    auto ([c2]) = s; // cxx17-error {{structured binding declaration cannot be 
declared with parenthese}} \
-                     // post2b-error {{use of undeclared identifier 'c2'}} \
-                     // post2b-error {{expected body of lambda expression}} \
+
+    // FIXME: This diagnostic could be improved.
+    auto ([c2]) = s; // expected-error {{use of undeclared identifier 'c2'}} \
+                     // expected-error {{expected body of lambda expression}}
 
     // FIXME: This error is not very good.
     auto [d]() = s; // expected-error {{expected ';'}} expected-error 
{{expected expression}}

diff  --git a/clang/test/Parser/cxx2b-auto-x.cpp 
b/clang/test/Parser/cxx2b-auto-x.cpp
index 9e0277eee76a9..fed80ace7db85 100644
--- a/clang/test/Parser/cxx2b-auto-x.cpp
+++ b/clang/test/Parser/cxx2b-auto-x.cpp
@@ -2,14 +2,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
 
 void looks_like_decltype_auto() {
-  decltype(auto(42)) b = 42; // cxx20-error {{'auto' not allowed here}} \
+  decltype(auto(42)) b = 42; // cxx20-warning {{'auto' as a functional-style 
cast is a C++23 extension}} \
                                 cxx23-warning {{'auto' as a functional-style 
cast is incompatible with C++ standards before C++23}}
   decltype(long *) a = 42;   // expected-error {{expected '(' for 
function-style cast or type construction}} \
                                 expected-error {{expected expression}}
   decltype(auto *) a = 42;   // expected-error {{expected '(' for 
function-style cast or type construction}} \
                                 expected-error {{expected expression}}
-  decltype(auto()) c = 42;   // cxx23-error {{initializer for functional-style 
cast to 'auto' is empty}} \
-                                cxx20-error {{'auto' not allowed here}}
+  decltype(auto()) c = 42;   // expected-error {{initializer for 
functional-style cast to 'auto' is empty}} \
+                                cxx20-warning {{'auto' as a functional-style 
cast is a C++23 extension}} \
+                                cxx23-warning {{'auto' as a functional-style 
cast is incompatible with C++ standards before C++23}}
 }
 
 struct looks_like_declaration {
@@ -19,11 +20,9 @@ struct looks_like_declaration {
 using T = looks_like_declaration *;
 void f() { T(&a)->n = 1; }
 void g() { auto(&a)->n = 0; } // cxx23-warning {{before C++23}} \
-                              // cxx20-error {{declaration of variable 'a' 
with deduced type 'auto (&)' requires an initializer}} \
-                              // cxx20-error {{expected ';' at end of 
declaration}}
+                              // cxx20-warning {{'auto' as a functional-style 
cast is a C++23 extension}}
 void h() { auto{&a}->n = 0; } // cxx23-warning {{before C++23}} \
-                              // cxx20-error {{expected unqualified-id}} \
-                              // cxx20-error {{expected expression}}
+                              // cxx20-warning {{'auto' as a functional-style 
cast is a C++23 extension}}
 
 void e(auto (*p)(int y) -> decltype(y)) {}
 
@@ -36,19 +35,15 @@ struct S{
 } s; // expected-note {{here}}
 
 void test() {
-    auto(s)()->N; // cxx23-warning {{expression result unused}} \
+    auto(s)()->N; // expected-warning {{expression result unused}} \
                   // cxx23-warning {{before C++23}} \
-                  // cxx20-error {{unknown type name 'N'}}
+                  // cxx20-warning {{'auto' as a functional-style cast is a 
C++23 extension}}
     auto(s)()->M; // expected-error {{redefinition of 's' as 
diff erent kind of symbol}}
 }
 
 void test_paren() {
     int a = (auto(0)); // cxx23-warning {{before C++23}} \
-                       // cxx20-error {{expected expression}} \
-                       // cxx20-error {{expected ')'}} \
-                       // cxx20-note  {{to match this '('}}
+                       // cxx20-warning {{'auto' as a functional-style cast is 
a C++23 extension}}
     int b = (auto{0}); // cxx23-warning {{before C++23}} \
-                       // cxx20-error {{expected expression}} \
-                       // cxx20-error {{expected ')'}} \
-                       // cxx20-note  {{to match this '('}}
+                       // cxx20-warning {{'auto' as a functional-style cast is 
a C++23 extension}}
 }


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to