Message ID | 20211104202643.94785-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: Implement C++23 P0849R8 - auto(x) [PR103049] | expand |
On 11/4/21 16:26, Marek Polacek wrote: > 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. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? OK. > 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/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. > --- > gcc/cp/semantics.c | 14 +++++ > gcc/cp/typeck2.c | 26 +++++--- > gcc/testsuite/g++.dg/cpp0x/auto25.C | 4 +- > 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 +++++ > .../g++.dg/cpp2a/concepts-pr84979-2.C | 3 +- > .../g++.dg/cpp2a/concepts-pr84979-3.C | 3 +- > 11 files changed, 214 insertions(+), 12 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast1.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast2.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast3.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast4.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast5.C > create mode 100644 gcc/testsuite/g++.dg/cpp23/auto-fncast6.C > > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c > index 2443d032749..21b48d6abad 100644 > --- a/gcc/cp/semantics.c > +++ b/gcc/cp/semantics.c > @@ -3143,6 +3143,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 c01f2f8ced4..f2c980ad7a9 100644 > --- a/gcc/cp/typeck2.c > +++ b/gcc/cp/typeck2.c > @@ -2192,19 +2192,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/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 { > > base-commit: 1b4a63593bc6b9770789816b205039fdf3cfd3fc >
On Thu, Nov 18, 2021 at 05:36:45PM -0500, Jason Merrill wrote: > On 11/4/21 16:26, Marek Polacek wrote: > > 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. > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > OK. Running dg.exp again, I noticed FAIL: g++.dg/cpp0x/auto9.C -std=c++23 (test for errors, line 48) which I'd missed before, but that was an obvious fix, so I fixed it and pushed the patch, thanks! Marek
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2443d032749..21b48d6abad 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3143,6 +3143,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 c01f2f8ced4..f2c980ad7a9 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -2192,19 +2192,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/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 {