+2018-04-05 Alexandre Oliva <aoliva@redhat.com>
+
+ PR c++/84979
+ * pt.c (check_auto_in_tmpl_args): New.
+ (tsubst_qualified_id): Use it to reject template args
+ referencing auto for non-type templates.
+ * parser.c (cp_parser_template_id): Likewise.
+ * cp-tree.h (check_auto_in_tmpl_args): Declare.
+ * typeck2.c (build_functional_cast): Report correct location
+ for invalid use of auto.
+
2018-04-04 Jason Merrill <jason@redhat.com>
PR c++/85215 - ICE with copy-init from conversion.
/* in pt.c */
extern bool check_template_shadow (tree);
+extern bool check_auto_in_tmpl_args (tree, tree);
extern tree get_innermost_template_args (tree, int);
extern void maybe_begin_member_template_processing (tree);
extern void maybe_end_member_template_processing (void);
location_t combined_loc
= make_location (token->location, token->location, finish_loc);
+ /* Check for concepts autos where they don't belong. We could
+ identify types in some cases of idnetifier TEMPL, looking ahead
+ for a CPP_SCOPE, but that would buy us nothing: we accept auto in
+ types. We reject them in functions, but if what we have is an
+ identifier, even with none_type we can't conclude it's NOT a
+ type, we have to wait for template substitution. */
+ if (flag_concepts && check_auto_in_tmpl_args (templ, arguments))
+ template_id = error_mark_node;
/* Build a representation of the specialization. */
- if (identifier_p (templ))
+ else if (identifier_p (templ))
template_id = build_min_nt_loc (combined_loc,
TEMPLATE_ID_EXPR,
templ, arguments);
if (is_template)
{
+ /* We may be repeating a check already done during parsing, but
+ if it was well-formed and passed then, it will pass again
+ now, and if it didn't, we wouldn't have got here. The case
+ we want to catch is when we couldn't tell then, and can now,
+ namely when templ prior to substitution was an
+ identifier. */
+ if (flag_concepts && check_auto_in_tmpl_args (expr, template_args))
+ return error_mark_node;
+
if (variable_template_p (expr))
expr = lookup_and_finish_template_variable (expr, template_args,
complain);
return find_type_usage (type, is_auto);
}
+/* Report ill-formed occurrences of auto types in ARGUMENTS. If
+ concepts are enabled, auto is acceptable in template arguments, but
+ only when TEMPL identifies a template class. Return TRUE if any
+ such errors were reported. */
+
+bool
+check_auto_in_tmpl_args (tree tmpl, tree args)
+{
+ /* If there were previous errors, nevermind. */
+ if (!args || TREE_CODE (args) != TREE_VEC)
+ return false;
+
+ /* If TMPL is an identifier, we're parsing and we can't tell yet
+ whether TMPL is supposed to be a type, a function or a variable.
+ We'll only be able to tell during template substitution, so we
+ expect to be called again then. If concepts are enabled and we
+ know we have a type, we're ok. */
+ if (flag_concepts
+ && (identifier_p (tmpl)
+ || (DECL_P (tmpl)
+ && (DECL_TYPE_TEMPLATE_P (tmpl)
+ || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))))
+ return false;
+
+ /* Quickly search for any occurrences of auto; usually there won't
+ be any, and then we'll avoid allocating the vector. */
+ if (!type_uses_auto (args))
+ return false;
+
+ bool errors = false;
+
+ tree vec = extract_autos (args);
+ for (int i = 0; i < TREE_VEC_LENGTH (vec); i++)
+ {
+ tree xauto = TREE_VALUE (TREE_VEC_ELT (vec, i));
+ error_at (DECL_SOURCE_LOCATION (xauto),
+ "invalid use of %qT in template argument", xauto);
+ errors = true;
+ }
+
+ return errors;
+}
+
/* For a given template T, return the vector of typedefs referenced
in T for which access check is needed at T instantiation time.
T is either a FUNCTION_DECL or a RECORD_TYPE.
if (!CLASS_PLACEHOLDER_TEMPLATE (anode))
{
if (complain & tf_error)
- error ("invalid use of %qT", anode);
+ error_at (DECL_SOURCE_LOCATION (TEMPLATE_TYPE_DECL (anode)),
+ "invalid use of %qT", anode);
return error_mark_node;
}
else if (!parms)
+2018-04-05 Alexandre Oliva <aoliva@redhat.com>
+
+ PR c++/84979
+ * g++.dg/concepts/pr84979.C: New.
+ * g++.dg/concepts/pr84979-2.C: New.
+ * g++.dg/concepts/pr84979-3.C: New.
+
2018-04-04 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/80026
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "-fconcepts" }
+
+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" }
+}
+
+struct T1 {
+ template <typename T> struct C {
+ C(T1&);
+ static void f(T1&, C&);
+ };
+ template <typename T> struct D {
+ D(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" }
+}
+
+struct T2 {
+ template <typename T> struct C {
+ C(T2&);
+ static void f(T2&, C&);
+ };
+ template <typename T> static void D(T2&);
+};
+
+void f(T1& t1, T2& t2) {
+ foo1 (t1);
+ foo2 (t2);
+}
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "-fconcepts" }
+
+// This is like pr84979-2.C, except that we swap the types passed to
+// the template functions foo1 and foo2, so that the expectations WRT
+// D's typeness are not met.
+
+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" }
+}
+
+struct T1 {
+ template <typename T> struct C {
+ C(T1&);
+ static void f(T1&, C&);
+ };
+ template <typename T> struct D {
+ D(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" }
+}
+
+struct T2 {
+ template <typename T> struct C {
+ C(T2&);
+ static void f(T2&, C&);
+ };
+ template <typename T> static void D(T2&);
+};
+
+void f(T1& t1, T2& t2) {
+ foo1 (t2);
+ foo2 (t1);
+}
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "-fconcepts" }
+
+template<typename> void foo() {}
+
+void bar()
+{
+ foo<auto>(); // { dg-error "invalid" }
+}