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;
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)
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 } }
}
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" }
--- /dev/null
+// 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
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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" }
+}
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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 ();
+}
--- /dev/null
+// 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)));
+}
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 {
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 {