public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Marek Polacek <mpolacek@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-5386] c++: Implement C++23 P0849R8 - auto(x) [PR103049] Date: Thu, 18 Nov 2021 23:01:29 +0000 (GMT) [thread overview] Message-ID: <20211118230129.CF6CA385800F@sourceware.org> (raw) https://gcc.gnu.org/g:93810fd673654db9ff16170624a6d36449eab241 commit r12-5386-g93810fd673654db9ff16170624a6d36449eab241 Author: Marek Polacek <polacek@redhat.com> Date: Wed Nov 3 11:04:22 2021 -0400 c++: Implement C++23 P0849R8 - auto(x) [PR103049] This patch implements P0849R8 which allows auto in a functional cast, the result of which is a prvalue. [expr.type.conv]/1 says that the type is determined by placeholder type deduction. We only accept 'auto', not 'decltype(auto)' -- that the type shall be auto comes from [dcl.type.auto.deduct]. Therefore the rules are like for [temp.deduct.call], deducing template arguments from a function call, so the result type will never be a reference, and we decay arrays/functions. PR c++/103049 gcc/cp/ChangeLog: * semantics.c (finish_compound_literal): Accept C++23 auto{x}. * typeck2.c (build_functional_cast_1): Accept C++23 auto(x). gcc/testsuite/ChangeLog: * g++.dg/cpp0x/auto25.C: Adjust dg-error. * g++.dg/cpp0x/auto9.C: Likewise. * g++.dg/cpp2a/concepts-pr84979-2.C: Likewise. * g++.dg/cpp2a/concepts-pr84979-3.C: Likewise. * g++.dg/cpp23/auto-fncast1.C: New test. * g++.dg/cpp23/auto-fncast2.C: New test. * g++.dg/cpp23/auto-fncast3.C: New test. * g++.dg/cpp23/auto-fncast4.C: New test. * g++.dg/cpp23/auto-fncast5.C: New test. * g++.dg/cpp23/auto-fncast6.C: New test. Diff: --- gcc/cp/semantics.c | 14 ++++++ gcc/cp/typeck2.c | 26 +++++++---- gcc/testsuite/g++.dg/cpp0x/auto25.C | 4 +- gcc/testsuite/g++.dg/cpp0x/auto9.C | 2 +- gcc/testsuite/g++.dg/cpp23/auto-fncast1.C | 14 ++++++ gcc/testsuite/g++.dg/cpp23/auto-fncast2.C | 62 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp23/auto-fncast3.C | 21 +++++++++ gcc/testsuite/g++.dg/cpp23/auto-fncast4.C | 26 +++++++++++ gcc/testsuite/g++.dg/cpp23/auto-fncast5.C | 39 ++++++++++++++++ gcc/testsuite/g++.dg/cpp23/auto-fncast6.C | 14 ++++++ gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C | 3 +- gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C | 3 +- 12 files changed, 215 insertions(+), 13 deletions(-) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8f79f047c01..d962b290211 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3134,6 +3134,20 @@ finish_compound_literal (tree type, tree compound_literal, if (type == error_mark_node) return error_mark_node; } + /* C++23 auto{x}. */ + else if (is_auto (type) + && !AUTO_IS_DECLTYPE (type) + && CONSTRUCTOR_NELTS (compound_literal) == 1) + { + if (cxx_dialect < cxx23) + pedwarn (input_location, OPT_Wc__23_extensions, + "%<auto{x}%> only available with " + "%<-std=c++2b%> or %<-std=gnu++2b%>"); + type = do_auto_deduction (type, compound_literal, type, complain, + adc_variable_type); + if (type == error_mark_node) + return error_mark_node; + } /* Used to hold a copy of the compound literal in a template. */ tree orig_cl = NULL_TREE; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index e98fbf7f5fa..3fb651a02ba 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -2201,19 +2201,29 @@ build_functional_cast_1 (location_t loc, tree exp, tree parms, if (tree anode = type_uses_auto (type)) { - if (!CLASS_PLACEHOLDER_TEMPLATE (anode)) + tree init; + if (CLASS_PLACEHOLDER_TEMPLATE (anode)) + init = parms; + /* C++23 auto(x). */ + else if (!AUTO_IS_DECLTYPE (anode) + && list_length (parms) == 1) { - if (complain & tf_error) - error_at (loc, "invalid use of %qT", anode); - return error_mark_node; + init = TREE_VALUE (parms); + if (cxx_dialect < cxx23) + pedwarn (loc, OPT_Wc__23_extensions, + "%<auto(x)%> only available with " + "%<-std=c++2b%> or %<-std=gnu++2b%>"); } else { - type = do_auto_deduction (type, parms, anode, complain, - adc_variable_type); - if (type == error_mark_node) - return error_mark_node; + if (complain & tf_error) + error_at (loc, "invalid use of %qT", anode); + return error_mark_node; } + type = do_auto_deduction (type, init, anode, complain, + adc_variable_type); + if (type == error_mark_node) + return error_mark_node; } if (processing_template_decl) diff --git a/gcc/testsuite/g++.dg/cpp0x/auto25.C b/gcc/testsuite/g++.dg/cpp0x/auto25.C index 19d51bc8590..3af089958fb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto25.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto25.C @@ -3,10 +3,10 @@ template<int> struct A { - int a[auto(1)]; // { dg-error "9:invalid use of" } + int a[auto(1)]; // { dg-error "9:only available" "" { target c++20_down } } }; template<int> void foo() { - int a[auto(1)]; // { dg-error "9:invalid use of" } + int a[auto(1)]; // { dg-error "9:only available" "" { target c++20_down } } } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C index 0e80c30ef74..a3a6caf0a66 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto9.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C @@ -45,7 +45,7 @@ foo () C<int> c; dynamic_cast<auto> (c); // { dg-error "auto" } reinterpret_cast<auto> (c); // { dg-error "auto" } - int i = auto (0); // { dg-error "auto" } + int i = auto (0); // { dg-error "auto" "" { target c++20_down } } auto p1 = new (auto); // { dg-error "auto" } auto p2 = new (auto) (42); // { dg-error "invalid use of|deduce" } offsetof (auto, fld); // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast1.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast1.C new file mode 100644 index 00000000000..25e53c4d61e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast1.C @@ -0,0 +1,14 @@ +// PR c++/103049 +// P0849R8 - auto(x) +// { dg-do compile { target c++23 } } +// Testcase from P0849R8. + +struct A {}; +void f(A&) = delete; // #1 +void f(A&&); // #2 +A& g(); +void h() { +// f(g()); // calls #1 + f(A(g())); // calls #2 with a temporary object + f(auto(g())); // calls #2 with a temporary object +} diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast2.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast2.C new file mode 100644 index 00000000000..327a4480030 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast2.C @@ -0,0 +1,62 @@ +// PR c++/103049 +// P0849R8 - auto(x) +// { dg-do compile { target c++23 } } + +struct X { }; +X& fn (); +X&& fnr (); + +void h() +{ + double v[] = { 1.2, 3.4 }; + +auto(v); + +auto{v}; + static_assert (__is_same_as (decltype (auto(v)), double *)); + static_assert (__is_same_as (decltype (auto{v}), double *)); + auto a1 = fn (); + static_assert (__is_same_as (decltype (auto(fn())), decltype (a1))); + static_assert (__is_same_as (decltype (auto{fn()}), decltype (a1))); + auto a2 = fnr (); + static_assert (__is_same_as (decltype (auto(fnr())), decltype (a2))); + static_assert (__is_same_as (decltype (auto{fnr()}), decltype (a2))); + +auto(1); + new auto(1); + +auto{1}; + new auto{1}; +} + +template<typename T> +void baz (T t, const T &tr, T &&trr) +{ + +auto(t); + +auto{t}; + +auto(tr); + +auto{tr}; + +auto(trr); + +auto{trr}; + static_assert (__is_same_as (decltype (auto(t)), T)); + static_assert (__is_same_as (decltype (auto{t}), T)); + static_assert (__is_same_as (decltype (auto(tr)), T)); + static_assert (__is_same_as (decltype (auto{tr}), T)); + static_assert (__is_same_as (decltype (auto(trr)), T)); + static_assert (__is_same_as (decltype (auto{trr}), T)); +} + +template<typename = decltype(auto(1))> +void foo () +{ +} + +template<int = auto(1)> +void bar () +{ +} + +void +g() +{ + foo<>(); + bar<>(); + int i = 42; + baz (1, i, 42); +} diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast3.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast3.C new file mode 100644 index 00000000000..1204458c931 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast3.C @@ -0,0 +1,21 @@ +// PR c++/103049 +// P0849R8 - auto(x) +// { dg-do compile { target c++23 } } +// Test invalid use. + +void +f () +{ + char x[] = "foo"; + +decltype(auto){x}; // { dg-error "invalid use of .decltype\\(auto\\)." } + +decltype(auto)(x); // { dg-error "invalid use of .decltype\\(auto\\)." } + + +auto(); // { dg-error "invalid use of .auto." } + new auto(); // { dg-error "requires exactly one element" } + +auto{}; // { dg-error "invalid use of .auto." } + new auto{}; // { dg-error "requires exactly one element" } + +auto(1, 2); // { dg-error "invalid use of .auto." } + new auto(1, 2); // { dg-error "requires exactly one element" } + +auto{1, 2}; // { dg-error "too many initializers" } + new auto{1, 2}; // { dg-error "requires exactly one element" } +} diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast4.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast4.C new file mode 100644 index 00000000000..0e26bf2bc66 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast4.C @@ -0,0 +1,26 @@ +// PR c++/103049 +// P0849R8 - auto(x) +// { dg-do compile { target c++23 } } + +class cmdline_parser +{ + public: + cmdline_parser(char const*); + + auto add_option(char const*, char const*) & -> cmdline_parser &; + auto add_option(char const*, char const*) && -> cmdline_parser &&; + + void parse(int, char**); +}; + +int main(int argc, char *argv[]) +{ + auto cmdline = cmdline_parser("driver"); + + cmdline.add_option("-h", "show help messages") + .add_option("-v", "show version"); + + auto internal = auto(cmdline).add_option("--logging-level", "set logging level to 1-3") + .add_option("--dump-full", "do not minimize dump"); + internal.parse(argc, argv); +} diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast5.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast5.C new file mode 100644 index 00000000000..b29901ffea4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast5.C @@ -0,0 +1,39 @@ +// PR c++/103049 +// P0849R8 - auto(x) +// { dg-do compile { target c++23 } } + +struct X { + X() = default; + X(const X&) = delete; +}; + +void +g () +{ + X x; + +X(x); // { dg-error "use of deleted function" } + +auto(x); // { dg-error "use of deleted function" } +} + +class A; +void f(A); + +class A { + int x; + +public: + A(); + + auto run() { + f(A(*this)); + f(auto(*this)); + } + +protected: + A(const A&); +}; + +void z () { + A a; + a.run (); +} diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast6.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast6.C new file mode 100644 index 00000000000..6b7858d9de5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast6.C @@ -0,0 +1,14 @@ +// PR c++/103049 +// P0849R8 - auto(x) +// { dg-do compile { target c++20 } } + +void f (int); + +void +g () +{ + auto a1 = auto(f); // { dg-error "only available with" "" { target c++20_only } } + auto a2 = auto{f}; // { dg-error "only available with" "" { target c++20_only } } + static_assert (__is_same_as (decltype (a1), void(*)(int))); + static_assert (__is_same_as (decltype (a2), void(*)(int))); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C index 290aaf83819..025bbf3bb93 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C @@ -6,7 +6,8 @@ void foo1(T& t) { typename T::template C<void> tcv = t; typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } } T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" } - (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted" } + (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted|unable" } +// { dg-warning "only available" "" { target c++17_down } .-1 } } struct T1 { diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C index d612327b9ae..80a388462eb 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C @@ -10,7 +10,8 @@ void foo1(T& t) { typename T::template C<void> tcv = t; typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } } T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" } - (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted" } + (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted|no class" } +// { dg-warning "only available" "" { target c++17_down } .-1 } } struct T1 {
reply other threads:[~2021-11-18 23:01 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20211118230129.CF6CA385800F@sourceware.org \ --to=mpolacek@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).