diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index fbb9947f39d3e..1ecc8c01a5f8e 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1978,6 +1978,7 @@ Pack Indexing __cpp_pack_indexing C ``= 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++ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fc0a1d2d4c926..8056365fcc9a7 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()`` casts are accepted as an extension pre-C++23 C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ @@ -363,7 +364,7 @@ Modified Compiler Flags - The `-mno-outline` flag will now add the `nooutline` IR attribute, so that `-mno-outline` and `-moutline` objects can be mixed correctly during LTO. -- Slightly changed hash id generation to get the unique linkage symbols names +- Slightly changed hash id generation to get the unique linkage symbols names by ``-unique-internal-linkage-names`` option. Now it uses a path that normalized in favor of the target system (same as the preprocessor does for the file macros) and allows the reproducable IDs on any build system. @@ -414,7 +415,7 @@ Attribute Changes in Clang - The ``[[clang::unsafe_buffer_usage]]`` attribute is now supported in API notes. For example: - + .. code-block:: yaml Functions: @@ -866,10 +867,10 @@ clang-format ------------ - Add ``ObjCSpaceAfterMethodDeclarationPrefix`` option to control space between the '-'/'+' and the return type in Objective-C method declarations -- Deprecate the ``BinPackParameters`` and ``BinPackArguments`` options and replace - them with the ``PackParameters`` and ``PackArguments`` structs (respectively) to - unify packing behavior. Add the ``BreakAfter`` option to the structs, allowing - parameter and argument lists to be formatted with one parameter/argument on each +- Deprecate the ``BinPackParameters`` and ``BinPackArguments`` options and replace + them with the ``PackParameters`` and ``PackArguments`` structs (respectively) to + unify packing behavior. Add the ``BreakAfter`` option to the structs, allowing + parameter and argument lists to be formatted with one parameter/argument on each line if they exceed the specified count. - Add ``AfterComma`` value to ``BreakConstructorInitializers`` to allow breaking constructor initializers after commas, keeping the colon on the same line. diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 077aace321264..859eabe97b4c4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -59,6 +59,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">; @@ -2702,9 +2704,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, 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 3f0468a938149..448cb551cc930 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -735,7 +735,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"); } @@ -743,6 +742,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", "202207L"); Builder.defineMacro("__cpp_placeholder_variables", "202306L"); diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index f77b1001332fe..74180cf2ddeaf 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1143,8 +1143,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 00c873833c8a7..22b1d62cfaa06 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1560,6 +1560,9 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, Inits = MultiExprArg(ILE->getInits(), ILE->getNumInits()); } + if (Ty->getAs()) + DiagCompat(TyBeginLoc, diag_compat::auto_expr) << FullRange; + if (Inits.empty()) return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_init_no_expression) << Ty << FullRange); @@ -1569,10 +1572,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, diag::err_auto_expr_init_multiple_expressions) << Ty << FullRange); } - if (getLangOpts().CPlusPlus23) { - if (Ty->getAs()) - Diag(TyBeginLoc, diag::warn_cxx20_compat_auto_expr) << FullRange; - } Expr *Deduce = Inits[0]; if (isa(Deduce)) return ExprError( diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 44ac4f6630690..9e8abee1e2d44 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3251,6 +3251,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, DeducedIsTrailingReturnType = true; } + SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc(); + if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId) + AutoRange = D.getName().getSourceRange(); + // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. if (Deduced) { AutoType *Auto = dyn_cast(Deduced); @@ -3382,8 +3386,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case DeclaratorContext::FunctionalCast: if (isa(Deduced)) break; - if (SemaRef.getLangOpts().CPlusPlus23 && IsCXXAutoType && - !Auto->isDecltypeAuto()) + if (IsCXXAutoType && !Auto->isDecltypeAuto()) break; // auto(x) [[fallthrough]]; case DeclaratorContext::TypeName: @@ -3419,10 +3422,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..bdf3a587a7c52 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(n); // expected-error{{'auto' not allowed here}} (void)const_cast(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 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 const &&rrc = static_cast(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 constexpr auto decay_copy(T &&v) { return static_cast(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 @@ -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 ''}} + foo(auto(&A::g)); // expected-error {{functional-style cast to 'auto' has incompatible initializer of 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 171ef99cee5b7..9e67240ee8491 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 21c9419e8f413..7927748840b18 100644 --- a/clang/test/Parser/cxx1z-decomposition.cpp +++ b/clang/test/Parser/cxx1z-decomposition.cpp @@ -105,9 +105,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 different 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}} }