cp-tree.def (UNBOUND_CLASS_TEMPLATE): New tree node.

* 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
This commit is contained in:
Kriang Lerdsuwanakij 2001-10-23 09:14:15 +00:00 committed by Kriang Lerdsuwanakij
parent 69f75f9daa
commit b8c6534b88
29 changed files with 570 additions and 24 deletions

View File

@ -1,3 +1,20 @@
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

View File

@ -163,6 +163,11 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm", 't',
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)

View File

@ -3617,6 +3617,7 @@ extern void set_namespace_binding PARAMS ((tree, tree, tree));
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));

View File

@ -5696,6 +5696,61 @@ make_typename_type (context, name, complain)
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

View File

@ -4559,7 +4559,8 @@ arg_assoc_template_arg (k, arg)
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)
{

View File

@ -458,6 +458,13 @@ dump_type (t, flags)
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);

View File

@ -1393,7 +1393,9 @@ write_type (type)
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;

View File

@ -669,7 +669,8 @@ template_parm:
{
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;
@ -1100,6 +1101,16 @@ template_arg:
$$ = 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:

View File

@ -3301,13 +3301,16 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
= ((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);
@ -3359,12 +3362,19 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
if (is_type)
{
if (requires_tmpl_type)
{
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
{
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))
if (coerce_template_template_parms (parmparm, argparm,
complain, in_decl,
inner_args))
{
val = arg;
@ -3386,6 +3396,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
val = error_mark_node;
}
}
}
else
{
val = groktypename (arg);
@ -6750,6 +6761,18 @@ tsubst (t, args, complain, in_decl)
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,
@ -7150,6 +7173,7 @@ tsubst_copy (t, args, complain, in_decl)
case METHOD_TYPE:
case ARRAY_TYPE:
case TYPENAME_TYPE:
case UNBOUND_CLASS_TEMPLATE:
case TYPE_DECL:
return tsubst (t, args, complain, in_decl);
@ -8542,6 +8566,7 @@ unify (tparms, targs, parm, arg, strict)
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. */

View File

@ -2079,6 +2079,7 @@ cp_walk_subtrees (tp, walk_subtrees_p, func, data, htab)
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:

View File

@ -1097,6 +1097,12 @@ comptypes (t1, t2, strict)
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));

View File

@ -0,0 +1,22 @@
// 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;
}

View File

@ -0,0 +1,13 @@
// 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;

View File

@ -0,0 +1,23 @@
// 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;
}

View File

@ -0,0 +1,24 @@
// 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();
}

View File

@ -0,0 +1,27 @@
// 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;
}

View File

@ -0,0 +1,30 @@
// 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;
}

View File

@ -0,0 +1,33 @@
// 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;
}

View File

@ -0,0 +1,40 @@
// 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();
}

View File

@ -0,0 +1,25 @@
// 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\]" } }

View File

@ -0,0 +1,23 @@
// 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;
}

View File

@ -0,0 +1,22 @@
// 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;
}

View File

@ -0,0 +1,23 @@
// 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" }
}

View File

@ -0,0 +1,24 @@
// 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" }
}

View File

@ -0,0 +1,25 @@
// 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" }
}

View File

@ -0,0 +1,15 @@
// 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" }

View File

@ -0,0 +1,12 @@
// 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" }

View File

@ -0,0 +1,17 @@
// 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" }

View File

@ -0,0 +1,17 @@
// 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;