* cp-tree.def (UNBOUND_CLASS_TEMPLATE): New tree node.
* cp-tree.h (make_unbound_class_template): Prototype new function.
* decl.c (make_unbound_class_template): New function.
* decl2.c (arg_assoc_template_arg): Handle UNBOUND_CLASS_TEMPLATE.
* error.c (dump_type): Likewise.
* mangle.c (write_type): Likewise.
* parse.y (template_parm): Likewise.
(template_argument): Use make_unbound_class_template.
* pt.c (convert_template_argument): Handle UNBOUND_CLASS_TEMPLATE.
(tsubst): Likewise.
(tsubst_copy): Likewise.
(unify): Likewise.
* tree.c (walk_tree): Likewise.
* typeck.c (comptypes): Likewise.
From-SVN: r46430
+2001-10-24 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ * cp-tree.def (UNBOUND_CLASS_TEMPLATE): New tree node.
+ * cp-tree.h (make_unbound_class_template): Prototype new function.
+ * decl.c (make_unbound_class_template): New function.
+ * decl2.c (arg_assoc_template_arg): Handle UNBOUND_CLASS_TEMPLATE.
+ * error.c (dump_type): Likewise.
+ * mangle.c (write_type): Likewise.
+ * parse.y (template_parm): Likewise.
+ (template_argument): Use make_unbound_class_template.
+ * pt.c (convert_template_argument): Handle UNBOUND_CLASS_TEMPLATE.
+ (tsubst): Likewise.
+ (tsubst_copy): Likewise.
+ (unify): Likewise.
+ * tree.c (walk_tree): Likewise.
+ * typeck.c (comptypes): Likewise.
+
2001-10-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* xref.c (GNU_xref_member): Use safe-ctype macros and/or fold
of `T'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
+/* For template template argument of the form `T::template C'.
+ TYPE_CONTEXT is `T', the template parameter dependent object.
+ TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template. */
+DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", 't', 0)
+
/* A type designated by `__typeof (expr)'. TYPE_FIELDS is the
expression in question. */
DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
extern tree lookup_namespace_name PARAMS ((tree, tree));
extern tree build_typename_type PARAMS ((tree, tree, tree, tree));
extern tree make_typename_type PARAMS ((tree, tree, int));
+extern tree make_unbound_class_template PARAMS ((tree, tree, int));
extern tree lookup_name_nonclass PARAMS ((tree));
extern tree lookup_function_nonclass PARAMS ((tree, tree));
extern tree lookup_name PARAMS ((tree, int));
return build_typename_type (context, name, fullname, NULL_TREE);
}
+/* Resolve `CONTEXT::template NAME'. Returns an appropriate type,
+ unless an error occurs, in which case error_mark_node is returned.
+ If COMPLAIN zero, don't complain about any errors that occur. */
+
+tree
+make_unbound_class_template (context, name, complain)
+ tree context, name;
+ int complain;
+{
+ tree t;
+ tree d;
+
+ if (TYPE_P (name))
+ name = TYPE_IDENTIFIER (name);
+ else if (DECL_P (name))
+ name = DECL_NAME (name);
+ if (TREE_CODE (name) != IDENTIFIER_NODE)
+ my_friendly_abort (20010902);
+
+ if (!uses_template_parms (context)
+ || currently_open_class (context))
+ {
+ tree tmpl = NULL_TREE;
+
+ if (IS_AGGR_TYPE (context))
+ tmpl = lookup_field (context, name, 0, 0);
+
+ if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+ {
+ if (complain)
+ cp_error ("no class template named `%#T' in `%#T'", name, context);
+ return error_mark_node;
+ }
+
+ if (!enforce_access (context, tmpl))
+ return error_mark_node;
+
+ return tmpl;
+ }
+
+ /* Build the UNBOUND_CLASS_TEMPLATE. */
+ t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
+ TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+ TREE_TYPE (t) = NULL_TREE;
+
+ /* Build the corresponding TEMPLATE_DECL. */
+ d = build_decl (TEMPLATE_DECL, name, t);
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = FROB_CONTEXT (context);
+ DECL_ARTIFICIAL (d) = 1;
+
+ return t;
+}
+
/* Select the right _DECL from multiple choices. */
static tree
contribute to the set of associated namespaces. ] */
/* Consider first template template arguments. */
- if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
return 0;
else if (TREE_CODE (arg) == TEMPLATE_DECL)
{
dump_typename (t, flags);
break;
+ case UNBOUND_CLASS_TEMPLATE:
+ dump_type (TYPE_CONTEXT (t), flags);
+ print_scope_operator (scratch_buffer);
+ print_identifier (scratch_buffer, "template ");
+ dump_type (DECL_NAME (TYPE_NAME (t)), flags);
+ break;
+
case TYPEOF_TYPE:
output_add_string (scratch_buffer, "__typeof (");
dump_expr (TYPE_FIELDS (t), flags & ~TFF_EXPR_IN_PARENS);
break;
case TYPENAME_TYPE:
- /* We handle TYPENAME_TYPEs like ordinary nested names. */
+ case UNBOUND_CLASS_TEMPLATE:
+ /* We handle TYPENAME_TYPEs and UNBOUND_CLASS_TEMPLATEs like
+ ordinary nested names. */
write_nested_name (TYPE_STUB_DECL (type));
break;
{
if (TREE_CODE ($3) != TEMPLATE_DECL
&& TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
- && TREE_CODE ($3) != TYPE_DECL)
+ && TREE_CODE ($3) != TYPE_DECL
+ && TREE_CODE ($3) != UNBOUND_CLASS_TEMPLATE)
{
error ("invalid default template argument");
$3 = error_mark_node;
$$ = TREE_TYPE ($$);
}
| expr_no_comma_rangle
+ | nested_name_specifier TEMPLATE identifier
+ {
+ if (!processing_template_decl)
+ {
+ cp_error ("use of template qualifier outside template");
+ $$ = error_mark_node;
+ }
+ else
+ $$ = make_unbound_class_template ($1, $3, 1);
+ }
;
unop:
= ((TREE_CODE (arg) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE
|| (TREE_CODE (arg) == RECORD_TYPE
&& CLASSTYPE_TEMPLATE_INFO (arg)
&& TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
&& DECL_ARTIFICIAL (TYPE_NAME (arg))
&& requires_tmpl_type
&& is_base_of_enclosing_class (arg, current_class_type)));
- if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ if (is_tmpl_type
+ && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+ || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
arg = TYPE_STUB_DECL (arg);
else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
arg = CLASSTYPE_TI_TEMPLATE (arg);
{
if (requires_tmpl_type)
{
- tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
- tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
- if (coerce_template_template_parms (parmparm, argparm, complain,
- in_decl, inner_args))
- {
- val = arg;
-
- /* TEMPLATE_TEMPLATE_PARM node is preferred over
- TEMPLATE_DECL. */
- if (val != error_mark_node
- && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
- val = TREE_TYPE (val);
- }
+ if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
+ /* The number of argument required is not known yet.
+ Just accept it for now. */
+ val = TREE_TYPE (arg);
else
{
- if (in_decl && complain)
+ tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
+ tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
+
+ if (coerce_template_template_parms (parmparm, argparm,
+ complain, in_decl,
+ inner_args))
{
- cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
- i + 1, in_decl);
- cp_error (" expected a template of type `%D', got `%D'", parm, arg);
+ val = arg;
+
+ /* TEMPLATE_TEMPLATE_PARM node is preferred over
+ TEMPLATE_DECL. */
+ if (val != error_mark_node
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (val))
+ val = TREE_TYPE (val);
}
+ else
+ {
+ if (in_decl && complain)
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i + 1, in_decl);
+ cp_error (" expected a template of type `%D', got `%D'", parm, arg);
+ }
- val = error_mark_node;
+ val = error_mark_node;
+ }
}
}
else
complain);
}
+ case UNBOUND_CLASS_TEMPLATE:
+ {
+ tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, complain,
+ in_decl, /*entering_scope=*/1);
+ tree name = TYPE_IDENTIFIER (t);
+
+ if (ctx == error_mark_node || name == error_mark_node)
+ return error_mark_node;
+
+ return make_unbound_class_template (ctx, name, complain);
+ }
+
case INDIRECT_REF:
{
tree e = tsubst (TREE_OPERAND (t, 0), args, complain,
case METHOD_TYPE:
case ARRAY_TYPE:
case TYPENAME_TYPE:
+ case UNBOUND_CLASS_TEMPLATE:
case TYPE_DECL:
return tsubst (t, args, complain, in_decl);
switch (TREE_CODE (parm))
{
case TYPENAME_TYPE:
+ case UNBOUND_CLASS_TEMPLATE:
/* In a type which contains a nested-name-specifier, template
argument values cannot be deduced for template parameters used
within the nested-name-specifier. */
case DEFAULT_ARG:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
+ case UNBOUND_CLASS_TEMPLATE:
case TEMPLATE_PARM_INDEX:
case TEMPLATE_TYPE_PARM:
case TYPENAME_TYPE:
return 0;
return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
+ case UNBOUND_CLASS_TEMPLATE:
+ if (cp_tree_equal (TYPE_IDENTIFIER (t1),
+ TYPE_IDENTIFIER (t2)) < 1)
+ return 0;
+ return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
+
case COMPLEX_TYPE:
return same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <class T> struct X
+{
+};
+
+template <class T> struct C
+{
+ X<T::template B> x; // { dg-error "type" }
+};
+
+int main()
+{
+ C<A> c;
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+ template <class U> class B {};
+ C<D<T>::template B> c;
+};
+
+D<int> d;
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do link }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+ TT<int> y;
+};
+
+template <class T> struct C
+{
+ X<T::template B> x;
+};
+
+int main()
+{
+ C<A> c;
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do link }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <template <class> class TT> void f()
+{
+ TT<int> y;
+}
+
+template <class T> struct C
+{
+ void g() { f<T::template B>(); }
+};
+
+int main()
+{
+ C<A> c;
+ c.g();
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+template <class U> struct A
+{
+ template <class V> struct AA {
+ template <class T> struct B {
+ int i;
+ B() : i(1) {}
+ };
+ };
+};
+
+template <template <class> class TT> struct X
+{
+ TT<int> y;
+};
+
+template <class T, class U> struct C
+{
+ X<T::template AA<U>::template B> x;
+};
+
+int main()
+{
+ C<A<char>, int> c;
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do link }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <template <class> class TT, class T> struct X
+{
+ TT<int> y;
+ T z;
+};
+
+template <class T> struct X<T::template B, T>
+{
+ typename T::template B<int> y;
+ T z;
+};
+
+template <class T> struct C
+{
+ X<T::template B, A> x;
+};
+
+int main()
+{
+ C<A> c;
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+ TT<int> y;
+};
+
+template <class T> struct X<T::template B>
+{ // { dg-error "previous" }
+ T z;
+};
+
+template <class T> struct X<T::template B>
+{ // { dg-error "redefinition" }
+ T z;
+};
+
+template <class T> struct C
+{
+ X<T::template B> x;
+};
+
+int main()
+{
+ C<A> c;
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do run }
+
+extern "C" void abort();
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <template <class> class TT, class T> struct X
+{
+ TT<int> y;
+ T z;
+ int f() { return 0; }
+};
+
+template <class T> struct X<T::template B, T>
+{
+ typename T::template B<int> y;
+ T z;
+ int f() { return 1; }
+};
+
+template <class T> struct C
+{
+ X<T::template B, A> x;
+};
+
+int main()
+{
+ C<A> c;
+ X<A::B, A> x1;
+ X<A::B, int> x2;
+ if (x1.f() != 1)
+ abort();
+ if (x2.f() != 0)
+ abort();
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+// { dg-options "-fno-inline" }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+};
+
+template <class T> void f(X<T::template B>)
+{
+}
+
+int main()
+{
+ X<A::B> x;
+ f<A>(x);
+}
+
+// { dg-final { scan-assembler "\n_?_Z1fI1AEv1XIN1T1BEE\[: \t\n\]" } }
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+ TT<int> y;
+};
+
+struct C
+{
+ X<A::template B> x; // { dg-error "template|forbid" }
+};
+
+int main()
+{
+ C c;
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+ template <class T> class B {};
+};
+
+template <int i> struct X
+{
+};
+
+template <class T> struct C
+{
+ X<T::template B> x; // { dg-error "type" }
+};
+
+int main()
+{
+ C<A> c;
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+ template <class T, class U> class B {};
+};
+
+template <template <class> class TT> struct X
+{
+ TT<int> y;
+};
+
+template <class T> struct C
+{
+ X<T::template B> x; // { dg-error "type" "" }
+};
+
+int main()
+{
+ C<A> c; // { dg-error "instantiated" }
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+struct A
+{
+ template <class T> struct B {};
+};
+
+template <template <class, class> class TT> // { dg-error "provided" }
+struct X
+{
+ TT<int> y; // { dg-error "number|type" }
+};
+
+template <class T> struct C
+{
+ X<T::template B> x; // { dg-error "type" }
+};
+
+int main()
+{
+ C<A> c; // { dg-error "instantiated" }
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <class U> struct A
+{
+ template <class T> class B {}; // { dg-error "candidates" }
+};
+
+template <template <class> class TT> void f()
+{
+ TT<int> y;
+ y = 0; // { dg-error "no match" }
+}
+
+template <class T> struct C
+{
+ void g() { f<A<T>::template B>(); } // { dg-error "instantiated" }
+};
+
+int main()
+{
+ C<int> c;
+ c.g(); // { dg-error "instantiated" }
+}
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+ C<T::template B> c; // { dg-error "no class template" }
+};
+
+struct E {
+};
+
+D<E> d; // { dg-error "instantiated" }
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+ C<T::template B> c; // { dg-error "no class template" }
+};
+
+D<int> d; // { dg-error "instantiated" }
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D {
+ C<T::template B> c; // { dg-error "context" }
+};
+
+struct E {
+ private:
+ template <class T> class B {}; // { dg-error "private" }
+};
+
+D<E> d; // { dg-error "instantiated" }
--- /dev/null
+// Copyright (C) 2001 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+template <template <class> class TT> class C {
+};
+
+template <class T> struct D : T {
+ C<T::template B> c;
+};
+
+struct E {
+ protected:
+ template <class T> class B {};
+};
+
+D<E> d;