https://github.com/philnik777 updated 
https://github.com/llvm/llvm-project/pull/200670

>From 9891738fa1ad6d78932484c81e65d62245adf154 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <[email protected]>
Date: Sun, 31 May 2026 17:52:02 +0200
Subject: [PATCH 1/3] [Clang] Accept auto parameters in all language modes as
 an extension

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 ++
 clang/lib/Sema/SemaType.cpp                   | 13 +++--
 .../dcl.spec/dcl.type/dcl.spec.auto/p5.cpp    |  6 +--
 clang/test/CXX/dcl/dcl.fct/p17.cpp            | 42 ++++++++-------
 clang/test/CXX/drs/cwg6xx.cpp                 |  3 +-
 clang/test/Parser/cxx1z-decomposition.cpp     |  2 +-
 clang/test/SemaCXX/crash-GH173943.cpp         |  4 +-
 .../SemaCXX/deduced-return-type-cxx14.cpp     | 51 +++++++++----------
 8 files changed, 67 insertions(+), 57 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 077aace321264..6d566d40d3b41 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2667,6 +2667,9 @@ def err_auto_not_allowed : Error<
   "|in declaration of conversion function template"
   "|in lambda parameter before C++14}1">;
 
+def ext_auto_arg : ExtWarn<
+  "'auto' parameters are a C++20 extension">, InGroup<CXX20>;
+
 def err_dependent_deduced_tst : Error<
   "typename specifier refers to "
   "%select{class template|function template|variable template|alias template|"
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 44ac4f6630690..5ec96aa1bfba4 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3262,6 +3262,10 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
         (Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
     bool IsDeducedReturnType = false;
 
+    SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
+    if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
+      AutoRange = D.getName().getSourceRange();
+
     switch (D.getContext()) {
     case DeclaratorContext::LambdaExpr:
       // Declared return type of a lambda-declarator is implicit and is always
@@ -3279,7 +3283,7 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
       InventedTemplateParameterInfo *Info = nullptr;
       if (D.getContext() == DeclaratorContext::Prototype) {
         // With concepts we allow 'auto' in function parameters.
-        if (!SemaRef.getLangOpts().CPlusPlus20 || !Auto ||
+        if (!SemaRef.getLangOpts().CPlusPlus || !Auto ||
             Auto->getKeyword() != AutoTypeKeyword::Auto) {
           Error = 0;
           break;
@@ -3288,6 +3292,9 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
           break;
         }
 
+        if (!SemaRef.getLangOpts().CPlusPlus20)
+          SemaRef.Diag(AutoRange.getBegin(), diag::ext_auto_arg);
+
         Info = &SemaRef.InventedParameterInfos.back();
       } else {
         // In C++14, generic lambdas allow 'auto' in their parameters.
@@ -3419,10 +3426,6 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
         (!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType))
       Error = 13;
 
-    SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
-    if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
-      AutoRange = D.getName().getSourceRange();
-
     if (Error != -1) {
       unsigned Kind;
       if (Auto) {
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 9571d6670e70d..3c5490605e19f 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
@@ -19,17 +19,17 @@ typedef auto *AutoPtr; // expected-error{{'auto' not 
allowed in typedef}}
 typedef auto (*PFun)(int a); // expected-error{{'auto' not allowed in typedef}}
 typedef auto Fun(int a) -> decltype(a + a);
 
-void g(auto a) { // expected-error{{'auto' not allowed in function prototype}}
+void g(auto a) { // expected-warning{{'auto' parameters are a C++20 extension}}
   try { }
   catch (auto &a) { } // expected-error{{'auto' not allowed in exception 
declaration}}
   catch (const auto a) { } // expected-error{{'auto' not allowed in exception 
declaration}}
   try { } catch (auto a) { } // expected-error{{'auto' not allowed in 
exception declaration}}
 }
 
-void h(auto a[10]) { // expected-error{{'auto' not allowed in function 
prototype}}
+void h(auto a[10]) { // expected-warning{{'auto' parameters are a C++20 
extension}}
 }
 
-void i(const auto a) { // expected-error{{'auto' not allowed in function 
prototype}}
+void i(const auto a) { // expected-warning{{'auto' parameters are a C++20 
extension}}
 }
 
 namespace std {
diff --git a/clang/test/CXX/dcl/dcl.fct/p17.cpp 
b/clang/test/CXX/dcl/dcl.fct/p17.cpp
index 431a8fbdf38a0..703a058d9d905 100644
--- a/clang/test/CXX/dcl/dcl.fct/p17.cpp
+++ b/clang/test/CXX/dcl/dcl.fct/p17.cpp
@@ -1,4 +1,6 @@
-// RUN:  %clang_cc1 -std=c++2a -verify %s
+// RUN:  %clang_cc1 -std=c++17 -verify=expected,ext %s
+// RUN:  %clang_cc1 -std=c++20 -verify %s
+
 template<typename T, typename U> constexpr bool is_same_v = false;
 template<typename T> constexpr bool is_same_v<T, T> = true;
 
@@ -6,27 +8,27 @@ template<typename... T>
 struct type_list;
 
 namespace unconstrained {
-  decltype(auto) f1(auto x) { return x; }
+  decltype(auto) f1(auto x) { return x; } // ext-warning {{'auto' parameters 
are a C++20 extension}}
   static_assert(is_same_v<decltype(f1(1)), int>);
   static_assert(is_same_v<decltype(f1('c')), char>);
 
-  decltype(auto) f2(auto &x) { return x; }
+  decltype(auto) f2(auto &x) { return x; } // ext-warning {{'auto' parameters 
are a C++20 extension}}
   // expected-note@-1{{candidate function [with x:auto = int] not viable: 
expects an lvalue for 1st argument}}
   // expected-note@-2{{candidate function [with x:auto = char] not viable: 
expects an lvalue for 1st argument}}
   static_assert(is_same_v<decltype(f2(1)), int &>); // expected-error{{no 
matching}}
   static_assert(is_same_v<decltype(f2('c')), char &>); // expected-error{{no 
matching}}
 
-  decltype(auto) f3(const auto &x) { return x; }
+  decltype(auto) f3(const auto &x) { return x; } // ext-warning {{'auto' 
parameters are a C++20 extension}}
   static_assert(is_same_v<decltype(f3(1)), const int &>);
   static_assert(is_same_v<decltype(f3('c')), const char &>);
 
-  decltype(auto) f4(auto (*x)(auto y)) { return x; } // expected-error{{'auto' 
not allowed in function prototype}}
+  decltype(auto) f4(auto (*x)(auto y)) { return x; } // expected-error{{'auto' 
not allowed in function prototype}} ext-warning {{'auto' parameters are a C++20 
extension}}
 
   decltype(auto) f5(void (*x)(decltype(auto) y)) { return x; } // 
expected-error{{'decltype(auto)' not allowed in function prototype}}
 
   int return_int(); void return_void(); int foo(int);
 
-  decltype(auto) f6(auto (*x)()) { return x; }
+  decltype(auto) f6(auto (*x)()) { return x; } // ext-warning {{'auto' 
parameters are a C++20 extension}}
   // expected-note@-1{{candidate template ignored: failed template argument 
deduction}}
   static_assert(is_same_v<decltype(f6(return_int)), int (*)()>);
   static_assert(is_same_v<decltype(f6(return_void)), void (*)()>);
@@ -40,42 +42,43 @@ namespace unconstrained {
   using f7c2 = decltype(f7(foo)); // expected-error{{no matching}}
   static_assert(is_same_v<decltype(&f7), int (*(*)(int (*x)()))()>);
 
-  decltype(auto) f8(auto... x) { return (x + ...); }
+  decltype(auto) f8(auto... x) { return (x + ...); } // ext-warning {{'auto' 
parameters are a C++20 extension}}
   static_assert(is_same_v<decltype(f8(1, 2, 3)), int>);
   static_assert(is_same_v<decltype(f8('c', 'd')), int>);
   static_assert(is_same_v<decltype(f8('c', 1)), int>);
 
-  decltype(auto) f9(auto &... x) { return (x, ...); }
+  decltype(auto) f9(auto &... x) { return (x, ...); } // ext-warning {{'auto' 
parameters are a C++20 extension}}
   // expected-note@-1{{candidate function [with x:auto = <int (), int>] not 
viable: expects an lvalue for 2nd argument}}
   using f9c1 = decltype(f9(return_int, 1)); // expected-error{{no matching}}
 
   decltype(auto) f11(decltype(auto) x) { return x; } // 
expected-error{{'decltype(auto)' not allowed in function prototype}}
 
   template<typename T>
-  auto f12(auto x, T y) -> type_list<T, decltype(x)>;
+  auto f12(auto x, T y) -> type_list<T, decltype(x)>; // ext-warning {{'auto' 
parameters are a C++20 extension}}
   static_assert(is_same_v<decltype(f12(1, 'c')), type_list<char, int>>);
   static_assert(is_same_v<decltype(f12<char>(1, 'c')), type_list<char, int>>);
 
   template<typename T>
-  auto f13(T x, auto y) -> type_list<T, decltype(y)>;
+  auto f13(T x, auto y) -> type_list<T, decltype(y)>; // ext-warning {{'auto' 
parameters are a C++20 extension}}
   static_assert(is_same_v<decltype(f13(1, 'c')), type_list<int, char>>);
   static_assert(is_same_v<decltype(f13<char>(1, 'c')), type_list<char, char>>);
 
   template<typename T>
-  auto f14(auto y) -> type_list<T, decltype(y)>;
+  auto f14(auto y) -> type_list<T, decltype(y)>; // ext-warning {{'auto' 
parameters are a C++20 extension}}
   static_assert(is_same_v<decltype(f14<int>('c')), type_list<int, char>>);
   static_assert(is_same_v<decltype(f14<int, char>('c')), type_list<int, 
char>>);
 
   template<typename T, typename U>
-  auto f15(auto y, U u) -> type_list<T, U, decltype(y)>;
+  auto f15(auto y, U u) -> type_list<T, U, decltype(y)>; // ext-warning 
{{'auto' parameters are a C++20 extension}}
   static_assert(is_same_v<decltype(f15<int>('c', nullptr)), type_list<int, 
decltype(nullptr), char>>);
   static_assert(is_same_v<decltype(f15<int, decltype(nullptr)>('c', nullptr)), 
type_list<int, decltype(nullptr), char>>);
 
-  auto f16(auto x, auto y) -> type_list<decltype(x), decltype(y)>;
+  auto f16(auto x, auto y) -> type_list<decltype(x), decltype(y)>; // 
ext-warning {{'auto' parameters are a C++20 extension}} ext-warning {{'auto' 
parameters are a C++20 extension}}
   static_assert(is_same_v<decltype(f16('c', 1)), type_list<char, int>>);
   static_assert(is_same_v<decltype(f16<int>('c', 1)), type_list<int, int>>);
   static_assert(is_same_v<decltype(f16<int, char>('c', 1)), type_list<int, 
char>>);
 
+#if __cplusplus >= 202002L
   void f17(auto x, auto y) requires (sizeof(x) > 1);
   // expected-note@-1{{candidate template ignored: constraints not satisfied 
[with x:auto = char, y:auto = int]}}
   // expected-note@-2{{because 'sizeof (x) > 1' (1 > 1) evaluated to false}}
@@ -94,27 +97,28 @@ namespace unconstrained {
   static_assert(is_same_v<decltype(f18('c', 1)), void>);
   static_assert(is_same_v<decltype(f18('c', 1, 2)), void>);
   // expected-error@-1{{no matching}}
+#endif
 
   template<typename T>
   struct S { // #defined-here
-    constexpr auto f1(auto x, T t) -> decltype(x + t);
+    constexpr auto f1(auto x, T t) -> decltype(x + t); // ext-warning {{'auto' 
parameters are a C++20 extension}}
 
     template<typename U>
-    constexpr auto f2(U u, auto x, T t) -> decltype(x + u + t);
+    constexpr auto f2(U u, auto x, T t) -> decltype(x + u + t); // ext-warning 
{{'auto' parameters are a C++20 extension}}
   };
 
   template<typename T>
-  constexpr auto S<T>::f1(auto x, T t) -> decltype(x + t) { return x + t; }
+  constexpr auto S<T>::f1(auto x, T t) -> decltype(x + t) { return x + t; } // 
ext-warning {{'auto' parameters are a C++20 extension}}
 
   template<typename T>
   template<typename U>
-  constexpr auto S<T>::f2(auto x, U u, T t) -> decltype(x + u + t) { return x 
+ u + t; }
+  constexpr auto S<T>::f2(auto x, U u, T t) -> decltype(x + u + t) { return x 
+ u + t; } // ext-warning {{'auto' parameters are a C++20 extension}}
   // expected-error@-1 {{out-of-line definition of 'f2' does not match any 
declaration in 'unconstrained::S<T>'}}
   // expected-note@#defined-here {{S defined here}}
 
   template<typename T>
   template<typename U>
-  constexpr auto S<T>::f2(U u, auto x, T t) -> decltype(x + u + t) { return x 
+ u + t; }
+  constexpr auto S<T>::f2(U u, auto x, T t) -> decltype(x + u + t) { return x 
+ u + t; } // ext-warning {{'auto' parameters are a C++20 extension}}
 
   template<>
   template<>
@@ -126,6 +130,7 @@ namespace unconstrained {
   static_assert(S<int>{}.f2<double>(1, '2', '\x00') == 42);
 }
 
+#if __cplusplus >= 202002L
 namespace constrained {
   template<typename T>
   concept C = is_same_v<T, int>;
@@ -259,3 +264,4 @@ namespace constrained {
   // expected-error@-1{{no matching}}
   static_assert(is_same_v<decltype(S2('a')), S2>);
 }
+#endif // __cplusplus >= 202002L
diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp
index b7b2ebf700375..4df56ccb41079 100644
--- a/clang/test/CXX/drs/cwg6xx.cpp
+++ b/clang/test/CXX/drs/cwg6xx.cpp
@@ -269,8 +269,7 @@ namespace cwg625 { // cwg625: 2.9
   void f(int);
   void (*p)(auto) = f;
   // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}}
-  // cxx98-17-error@-2 {{'auto' not allowed in function prototype}}
-  // since-cxx20-error@-3 {{'auto' not allowed in function prototype that is 
not a function declaration}}
+  // expected-error@-2 {{'auto' not allowed in function prototype that is not 
a function declaration}}
 } // namespace cwg625
 
 namespace cwg626 { // cwg626: 2.7
diff --git a/clang/test/Parser/cxx1z-decomposition.cpp 
b/clang/test/Parser/cxx1z-decomposition.cpp
index 21c9419e8f413..10f0c07766ccf 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -32,7 +32,7 @@ namespace ForRangeDecl {
 namespace OtherDecl {
   // A parameter-declaration is not a simple-declaration.
   // This parses as an array declaration.
-  void f(auto [a, b, c]); // cxx17-error {{'auto' not allowed in function 
prototype}} expected-error 1+{{'a'}}
+  void f(auto [a, b, c]); // cxx17-warning {{'auto' parameters are a C++20 
extension}} expected-error 1+{{'a'}}
 
   void g() {
     // A condition is allowed as a Clang extension.
diff --git a/clang/test/SemaCXX/crash-GH173943.cpp 
b/clang/test/SemaCXX/crash-GH173943.cpp
index e00a0f2fb12c9..f4033d80457eb 100644
--- a/clang/test/SemaCXX/crash-GH173943.cpp
+++ b/clang/test/SemaCXX/crash-GH173943.cpp
@@ -3,9 +3,9 @@
 
 // https://github.com/llvm/llvm-project/issues/173943
 
-constexpr void f(this auto& self) // expected-note {{candidate function}}
+constexpr void f(this auto& self)
     // expected-error@-1 {{unknown type name 'constexpr'}}
-    // expected-error@-2 {{'auto' not allowed in function prototype}}
+    // expected-warning@-2 {{'auto' parameters are a C++20 extension}}
     // expected-error@-3 {{explicit object parameters are incompatible with 
C++ standards before C++2b}}
     // expected-error@-4 {{expected ';' after top level declarator}}
     // expected-error@-5 {{an explicit object parameter cannot appear in a 
non-member function}}
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp 
b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index aa62c4a57a636..bef460c6c7d6c 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -std=c++23 -fsyntax-only 
-verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23    %s
-// RUN: %clang_cc1 -std=c++23 -fsyntax-only 
-verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23    %s 
-fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23    
%s
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23    
%s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s 
-fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-verify=expected,cxx20,cxx14_20,cxx20_23 %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only 
-verify=expected,cxx20,cxx14_20,cxx20_23 %s -fdelayed-template-parsing 
-DDELAYED_TEMPLATE_PARSING
 
-// RUN: %clang_cc1 -std=c++14 -fsyntax-only 
-verify=expected,since-cxx14,cxx14_20,cxx14    %s
-// RUN: %clang_cc1 -std=c++14 -fsyntax-only 
-verify=expected,since-cxx14,cxx14_20,cxx14    %s -fdelayed-template-parsing 
-DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14    
%s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14    
%s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
 auto f(); // expected-note {{previous}}
 int f(); // expected-error {{differ only in their return type}}
@@ -672,8 +672,7 @@ struct Node {
 bool parse(const char*);
 Node* parsePrimaryExpr();
 
-auto parseMulExpr(auto node) { // cxx14-error {{'auto' not allowed in function 
prototype}} \
-                               // cxx14-note {{not viable}}
+auto parseMulExpr(auto node) { // cxx14-warning {{'auto' parameters are a 
C++20 extension}}
   if (node == nullptr) node = parsePrimaryExpr();
   if (!parse("*")) return node;
   return parseMulExpr(new Node{.left = node, .right = parsePrimaryExpr()});
@@ -693,12 +692,12 @@ auto parseMulExpr3(T node) { // expected-note {{declared 
here}}
 }
 
 void foo() {
-  parseMulExpr(new Node{}); // cxx14-error {{no matching function}}
+  parseMulExpr(new Node{});
   parseMulExpr2(new Node{});
   parseMulExpr3(new Node{}); // expected-note {{in instantiation}}
 }
 
-auto f(auto x) { // cxx14-error {{'auto' not allowed in function prototype}}
+auto f(auto x) { // cxx14-warning {{'auto' parameters are a C++20 extension}}
   if (x == 0) return 0;
   return f(1) + 1;
 }
@@ -706,15 +705,15 @@ auto f(auto x) { // cxx14-error {{'auto' not allowed in 
function prototype}}
 namespace GH122892 {
   struct NonTemplate {
     void caller() {
-        c1(int{}); // since-cxx20-error {{cannot be used before it is defined}}
-        c2(int{}); // since-cxx14-error {{cannot be used before it is defined}}
+        c1(int{}); // expected-error {{cannot be used before it is defined}}
+        c2(int{}); // expected-error {{cannot be used before it is defined}}
     }
 
-    static auto c1(auto x) { // since-cxx20-note {{declared here}} // 
cxx14-error {{'auto' not allowed in function prototype}}
+    static auto c1(auto x) { // expected-note {{declared here}} cxx14-warning 
{{'auto' parameters are a C++20 extension}}
     }
 
     template <typename T>
-    static auto c2(T x) { // since-cxx14-note {{declared here}}
+    static auto c2(T x) { // expected-note {{declared here}}
         return x;
     }
   };
@@ -725,23 +724,23 @@ namespace GH122892 {
 
     template <>
     void specialized<int>() {
-      c1(int{}); // since-cxx20-error {{cannot be used before it is defined}}
-      c2(int{}); // since-cxx14-error {{cannot be used before it is defined}}
+      c1(int{}); // expected-error {{cannot be used before it is defined}}
+      c2(int{}); // expected-error {{cannot be used before it is defined}}
     }
 
-    static auto c1(auto x) { // since-cxx20-note {{declared here}} // 
cxx14-error {{'auto' not allowed in function prototype}}
+    static auto c1(auto x) { // expected-note {{declared here}} cxx14-warning 
{{'auto' parameters are a C++20 extension}}
     }
 
     template <typename T>
-    static auto c2(T x) { // since-cxx14-note {{declared here}}
+    static auto c2(T x) { // expected-note {{declared here}}
         return x;
     }
   };
 
   struct MemberInit {
-    int x1 = c1(int{}); // since-cxx20-error {{cannot be used before it is 
defined}}
+    int x1 = c1(int{}); // expected-error {{cannot be used before it is 
defined}}
 
-    static auto c1(auto x) { return x; } // since-cxx20-note {{declared here}} 
// cxx14-error {{'auto' not allowed in function prototype}}
+    static auto c1(auto x) { return x; } // expected-note {{declared here}} 
cxx14-warning {{'auto' parameters are a C++20 extension}}
   };
 
 }
@@ -765,23 +764,23 @@ struct DeducedTargetTypeOfConversionFunction {
 
   template <typename T>
   operator auto() const { return short(); }
-  // since-cxx14-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
+  // expected-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
   template <typename T>
   operator const auto() const { return int(); }
-  // since-cxx14-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
+  // expected-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
   template <typename T>
   operator const auto&() const { return char(); }
-  // since-cxx14-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
+  // expected-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
   template <typename T>
   operator decltype(auto)() const { return unsigned(); }
-  // since-cxx14-error@-1 {{'decltype(auto)' not allowed in declaration of 
conversion function template}}
+  // expected-error@-1 {{'decltype(auto)' not allowed in declaration of 
conversion function template}}
 #if __cplusplus >= 202002L
   template <typename T>
   operator C auto() const { return float(); }
-  // since-cxx20-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
+  // expected-error@-1 {{'auto' not allowed in declaration of conversion 
function template}}
   template <typename T>
   operator C decltype(auto)() const { return double(); }
-  // since-cxx20-error@-1 {{'decltype(auto)' not allowed in declaration of 
conversion function template}}
+  // expected-error@-1 {{'decltype(auto)' not allowed in declaration of 
conversion function template}}
 #endif
 };
 

>From 5619f57acc3c290007b17198df4d5dfc887e77fc Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <[email protected]>
Date: Mon, 1 Jun 2026 11:16:20 +0200
Subject: [PATCH 2/3] Address comments

---
 clang/lib/Sema/SemaType.cpp | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 5ec96aa1bfba4..d35663bc4decc 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3287,14 +3287,16 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
             Auto->getKeyword() != AutoTypeKeyword::Auto) {
           Error = 0;
           break;
-        } else if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) {
-          Error = 21;
-          break;
         }
 
         if (!SemaRef.getLangOpts().CPlusPlus20)
           SemaRef.Diag(AutoRange.getBegin(), diag::ext_auto_arg);
 
+        if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) {
+          Error = 21;
+          break;
+        }
+
         Info = &SemaRef.InventedParameterInfos.back();
       } else {
         // In C++14, generic lambdas allow 'auto' in their parameters.

>From 0e3c8448131dcb5155e056211a82b87058f4d470 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <[email protected]>
Date: Mon, 1 Jun 2026 11:25:00 +0200
Subject: [PATCH 3/3] Address comments

---
 clang/test/CXX/drs/cwg6xx.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp
index 4df56ccb41079..3ba2b372cb715 100644
--- a/clang/test/CXX/drs/cwg6xx.cpp
+++ b/clang/test/CXX/drs/cwg6xx.cpp
@@ -269,7 +269,8 @@ namespace cwg625 { // cwg625: 2.9
   void f(int);
   void (*p)(auto) = f;
   // cxx98-error@-1 {{'auto' type specifier is a C++11 extension}}
-  // expected-error@-2 {{'auto' not allowed in function prototype that is not 
a function declaration}}
+  // cxx98-17-error@-2 {{'auto' parameters are a C++20 extension}}
+  // expected-error@-3 {{'auto' not allowed in function prototype that is not 
a function declaration}}
 } // namespace cwg625
 
 namespace cwg626 { // cwg626: 2.7

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

Reply via email to