[clang] e63f9be - [Clang] Accept auto parameters pre-C++20 as an extension (#200670)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 10 03:54:58 PDT 2026
Author: Nikolas Klauser
Date: 2026-06-10T12:54:53+02:00
New Revision: e63f9bec814bde36f0aa13cd01c1a9abb8527c83
URL: https://github.com/llvm/llvm-project/commit/e63f9bec814bde36f0aa13cd01c1a9abb8527c83
DIFF: https://github.com/llvm/llvm-project/commit/e63f9bec814bde36f0aa13cd01c1a9abb8527c83.diff
LOG: [Clang] Accept auto parameters pre-C++20 as an extension (#200670)
GCC already accepts auto parameters as an extenion.
Added:
Modified:
clang/docs/LanguageExtensions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaType.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
clang/test/CXX/dcl/dcl.fct/p17.cpp
clang/test/CXX/drs/cwg6xx.cpp
clang/test/Parser/cxx1z-decomposition.cpp
clang/test/SemaCXX/crash-GH173943.cpp
clang/test/SemaCXX/deduced-return-type-cxx14.cpp
Removed:
################################################################################
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 9fa39c09b1f6c..f378a73c20de0 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1967,6 +1967,7 @@ Familiar template syntax for generic lambdas __cpp_generic_lambdas C
Designated initializers __cpp_designated_initializers C++20 C++03
Conditional ``explicit`` __cpp_conditional_explicit C++20 C++03
``using enum`` __cpp_using_enum C++20 C++03
+``auto`` parameters C++20 C++03
``if consteval`` __cpp_if_consteval C++23 C++20
``static operator()`` __cpp_static_call_operator C++23 C++03
Attributes on Lambda-Expressions C++23 C++11
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 869c480167926..b7e5e2372fd68 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -191,6 +191,7 @@ C++ Language Changes
--------------------
- ``__is_trivially_equality_comparable`` no longer returns false for all enum types. (#GH132672)
+- ``auto`` parameters are now available in all C++ language modes as an extension.
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9ab2b282e2d2f..a3b575b7ee63a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -53,6 +53,8 @@ defm ctad_for_alias_templates
defm implicit_typename
: CXX20Compat<"missing 'typename' prior to dependent type name %0 is">;
+defm auto_param : CXX20Compat<"'auto' parameters are">;
+
// C++23 compatibility with C++20 and earlier.
defm constexpr_static_var : CXX23Compat<
"definition of a %select{static|thread_local}1 variable "
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 6283fe4f41f36..ea4a6fb208dc3 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,11 +3283,16 @@ 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;
- } else if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) {
+ }
+
+ if (!SemaRef.getLangOpts().CPlusPlus20)
+ SemaRef.DiagCompat(AutoRange.getBegin(), diag_compat::auto_param);
+
+ if (!SemaRef.getCurScope()->isFunctionDeclarationScope()) {
Error = 21;
break;
}
@@ -3419,10 +3428,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/p3-generic-lambda-1y.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
index ca8d50fe22728..a590f8eb77005 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
@@ -49,24 +49,24 @@ int main()
static double dfi(int i) { return i + 3.14; }
static Local localfi(int) { return Local{}; }
};
- auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from returned value of type 'Local' to function return type 'int'}}
+ auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from returned value of type 'Local' to function return type 'int'}}
l4(&Local::ifi);
l4(&Local::cfi);
l4(&Local::dfi);
- l4(&Local::localfi); //expected-note{{in instantiation of function template specialization}}
+ l4(&Local::localfi); //expected-note{{in instantiation of function template specialization}}
}
{
auto unnamed_parameter = [](auto, auto) -> void { };
unnamed_parameter(3, '4');
}
{
- auto l = [](auto
- (*)(auto)) { }; //expected-error{{'auto' not allowed}}
+ auto l = [](auto (*)(auto)) { }; //expected-error{{'auto' not allowed}} expected-warning {{'auto' parameters are a C++20 extension}}
//FIXME: These diagnostics might need some work.
auto l2 = [](char auto::*pm) { }; // expected-error {{cannot combine with previous 'char' declaration specifier}} \
expected-error{{'pm' does not point into a class}}
auto l3 = [](char (auto::*pmf)()) { }; // expected-error{{'auto' not allowed}}\
expected-error{{'pmf' does not point into a class}}\
- expected-error{{function cannot return function type 'char ()'}}
+ expected-error{{function cannot return function type 'char ()'}} \
+ expected-warning {{'auto' parameters are a C++20 extension}}
}
}
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..d837d0900d5b9 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 at -1{{candidate function [with x:auto = int] not viable: expects an lvalue for 1st argument}}
// expected-note at -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 2 {{'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 at -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 at -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 at -1{{candidate template ignored: constraints not satisfied [with x:auto = char, y:auto = int]}}
// expected-note at -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 at -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 at -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,15 @@ namespace unconstrained {
static_assert(S<int>{}.f2<double>(1, '2', '\x00') == 42);
}
+namespace not_a_concept {
+void undefined(Foo auto); // expected-error {{unknown type name 'Foo'}}
+
+struct AStruct {};
+
+void a_struct(AStruct auto); // expected-error {{cannot combine with previous 'type-name' declaration specifier}}
+}
+
+#if __cplusplus >= 202002L
namespace constrained {
template<typename T>
concept C = is_same_v<T, int>;
@@ -259,3 +272,4 @@ namespace constrained {
// expected-error at -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..3ba2b372cb715 100644
--- a/clang/test/CXX/drs/cwg6xx.cpp
+++ b/clang/test/CXX/drs/cwg6xx.cpp
@@ -269,8 +269,8 @@ namespace cwg625 { // cwg625: 2.9
void f(int);
void (*p)(auto) = f;
// cxx98-error at -1 {{'auto' type specifier is a C++11 extension}}
- // cxx98-17-error at -2 {{'auto' not allowed in function prototype}}
- // since-cxx20-error at -3 {{'auto' not allowed in function prototype that is not a function declaration}}
+ // cxx98-17-error at -2 {{'auto' parameters are a C++20 extension}}
+ // expected-error at -3 {{'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 at -1 {{unknown type name 'constexpr'}}
- // expected-error at -2 {{'auto' not allowed in function prototype}}
+ // expected-warning at -2 {{'auto' parameters are a C++20 extension}}
// expected-error at -3 {{explicit object parameters are incompatible with C++ standards before C++2b}}
// expected-error at -4 {{expected ';' after top level declarator}}
// expected-error at -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 89d59b08ce3c9..1be3c6b06a5a8 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 {{
diff er 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 at -1 {{'auto' not allowed in declaration of conversion function template}}
+ // expected-error at -1 {{'auto' not allowed in declaration of conversion function template}}
template <typename T>
operator const auto() const { return int(); }
- // since-cxx14-error at -1 {{'auto' not allowed in declaration of conversion function template}}
+ // expected-error at -1 {{'auto' not allowed in declaration of conversion function template}}
template <typename T>
operator const auto&() const { return char(); }
- // since-cxx14-error at -1 {{'auto' not allowed in declaration of conversion function template}}
+ // expected-error at -1 {{'auto' not allowed in declaration of conversion function template}}
template <typename T>
operator decltype(auto)() const { return unsigned(); }
- // since-cxx14-error at -1 {{'decltype(auto)' not allowed in declaration of conversion function template}}
+ // expected-error at -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 at -1 {{'auto' not allowed in declaration of conversion function template}}
+ // expected-error at -1 {{'auto' not allowed in declaration of conversion function template}}
template <typename T>
operator C decltype(auto)() const { return double(); }
- // since-cxx20-error at -1 {{'decltype(auto)' not allowed in declaration of conversion function template}}
+ // expected-error at -1 {{'decltype(auto)' not allowed in declaration of conversion function template}}
#endif
};
More information about the cfe-commits
mailing list