if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL;
+ bool auto_typeid_ok = false;
+ /* The concepts TS allows 'auto' as a type-id. */
+ if (flag_concepts_ts)
+ auto_typeid_ok = !parser->in_type_id_in_expr_p;
+ /* DR 625 prohibits use of auto as a template-argument. We allow 'auto'
+ outside the template-argument-list context here only for the sake of
+ diagnostic: grokdeclarator then can emit a better error message for
+ e.g. using T = auto. */
+ else if (flag_concepts)
+ auto_typeid_ok = (!parser->in_type_id_in_expr_p
+ && !parser->in_template_argument_list_p);
+
if (type_specifier_seq.type
- /* The concepts TS allows 'auto' as a type-id. */
- && (!flag_concepts || parser->in_type_id_in_expr_p)
+ && !auto_typeid_ok
/* None of the valid uses of 'auto' in C++14 involve the type-id
nonterminal, but it is valid in a trailing-return-type. */
&& !(cxx_dialect >= cxx14 && is_trailing_return))
inform (DECL_SOURCE_LOCATION (tmpl), "%qD declared here",
tmpl);
}
+ else if (parser->in_template_argument_list_p)
+ error_at (loc, "%qT not permitted in template argument",
+ auto_node);
else
error_at (loc, "invalid use of %qT", auto_node);
return error_mark_node;
--- /dev/null
+// DR 625 - Use of auto as a template-argument
+// PR c++/97479
+// { dg-do compile { target c++14 } }
+
+template<typename>
+struct A { };
+
+void f(int);
+
+int main()
+{
+ A<decltype(auto)> x = A<void>(); // { dg-error "not permitted|invalid|cannot convert" }
+ A<auto> a = A<void>(); // { dg-error "not permitted|invalid|cannot convert" }
+ void (*p)(auto); // { dg-error "parameter" }
+}
A<int> A1;
// CWG issue 625
-A<auto> A2 = A1; // { dg-error "" "" { target { ! concepts } } }
+A<auto> A2 = A1; // { dg-error "" }
auto foo() { } // { dg-error "auto" "" { target { ! c++14 } } }
template <auto V = 4> struct G {}; // { dg-error "11:parameter" "" { target { ! c++17 } } }
template <typename T> struct H { H (); ~H (); };
-H<auto> h; // { dg-error "invalid|initializer" }
+H<auto> h; // { dg-error "invalid|initializer|not permitted in template argument" }
void qq (auto); // { dg-error "auto" "" { target { ! concepts } } }
void qr (auto*); // { dg-error "auto" "" { target { ! concepts } } }
template <typename T>
void foo1(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- (typename T::template D<auto> (t)); // { dg-error "invalid" }
+ 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" }
}
struct T1 {
template <typename T>
void foo2(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- T::template D<auto> (t); // { dg-error "invalid" }
+ 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" }
+ T::template D<auto> (t); // { dg-error "invalid|not permitted" }
}
struct T2 {
template <typename T>
void foo1(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- (typename T::template D<auto> (t)); // { dg-error "invalid" }
+ 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" }
}
struct T1 {
template <typename T>
void foo2(T& t) {
typename T::template C<void> tcv = t;
- typename T::template C<auto> u = tcv;
- T::template C<auto>::f (tcv, u); // { dg-error "incomplete" }
- T::template D<auto> (t); // { dg-error "yields a type" }
+ 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" }
+ T::template D<auto> (t); // { dg-error "yields a type|not permitted" }
}
struct T2 {
void bar()
{
- foo<auto>(); // { dg-error "invalid" }
+ foo<auto>(); // { dg-error "not permitted|invalid|no matching function" }
}