From 47d727d45439286a71f99b79fc0b6be4d529a9e8 Mon Sep 17 00:00:00 2001 From: lerdsuwa Date: Tue, 23 Oct 2001 09:14:15 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46430 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 17 ++++++++ gcc/cp/cp-tree.def | 5 +++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 55 ++++++++++++++++++++++++++ gcc/cp/decl2.c | 3 +- gcc/cp/error.c | 7 ++++ gcc/cp/mangle.c | 4 +- gcc/cp/parse.y | 13 ++++++- gcc/cp/pt.c | 65 +++++++++++++++++++++---------- gcc/cp/tree.c | 1 + gcc/cp/typeck.c | 6 +++ gcc/testsuite/g++.dg/template/qualttp1.C | 22 +++++++++++ gcc/testsuite/g++.dg/template/qualttp10.C | 13 +++++++ gcc/testsuite/g++.dg/template/qualttp11.C | 23 +++++++++++ gcc/testsuite/g++.dg/template/qualttp12.C | 24 ++++++++++++ gcc/testsuite/g++.dg/template/qualttp13.C | 27 +++++++++++++ gcc/testsuite/g++.dg/template/qualttp14.C | 30 ++++++++++++++ gcc/testsuite/g++.dg/template/qualttp15.C | 33 ++++++++++++++++ gcc/testsuite/g++.dg/template/qualttp16.C | 40 +++++++++++++++++++ gcc/testsuite/g++.dg/template/qualttp17.C | 25 ++++++++++++ gcc/testsuite/g++.dg/template/qualttp18.C | 23 +++++++++++ gcc/testsuite/g++.dg/template/qualttp2.C | 22 +++++++++++ gcc/testsuite/g++.dg/template/qualttp3.C | 23 +++++++++++ gcc/testsuite/g++.dg/template/qualttp4.C | 24 ++++++++++++ gcc/testsuite/g++.dg/template/qualttp5.C | 25 ++++++++++++ gcc/testsuite/g++.dg/template/qualttp6.C | 15 +++++++ gcc/testsuite/g++.dg/template/qualttp7.C | 12 ++++++ gcc/testsuite/g++.dg/template/qualttp8.C | 17 ++++++++ gcc/testsuite/g++.dg/template/qualttp9.C | 17 ++++++++ 29 files changed, 569 insertions(+), 23 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/qualttp1.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp10.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp11.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp12.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp13.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp14.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp15.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp16.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp17.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp18.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp2.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp3.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp4.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp5.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp6.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp7.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp8.C create mode 100644 gcc/testsuite/g++.dg/template/qualttp9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a8bff6cd..34abbc4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2001-10-24 Kriang Lerdsuwanakij + + * 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 * xref.c (GNU_xref_member): Use safe-ctype macros and/or fold diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index e7ef2b9..1395301 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 290f8ed..f58e2154 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bd64bc4..1b3fc9e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 8c5dba1..f384f0a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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) { diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 2e71184..5cd3ee7 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 6ad9ffa..0f6500e 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -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; diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index f3e85ff..937e1c8 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -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: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5a5cf4d..a99b80d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); @@ -3360,30 +3363,38 @@ convert_template_argument (parm, arg, args, complain, i, in_decl) { 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 @@ -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. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2c4c744..6ae0a35 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 850ce8b..dda76fe 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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)); diff --git a/gcc/testsuite/g++.dg/template/qualttp1.C b/gcc/testsuite/g++.dg/template/qualttp1.C new file mode 100644 index 0000000..b97ef42 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/qualttp1.C @@ -0,0 +1,22 @@ +// Copyright (C) 2001 Free Software Foundation +// Contributed by Kriang Lerdsuwanakij +// { dg-do compile } + +struct A +{ + template class B {}; +}; + +template struct X +{ +}; + +template struct C +{ + X x; // { dg-error "type" } +}; + +int main() +{ + C c; +} diff --git a/gcc/testsuite/g++.dg/template/qualttp10.C b/gcc/testsuite/g++.dg/template/qualttp10.C new file mode 100644 index 0000000..8734ddc --- /dev/null +++ b/gcc/testsuite/g++.dg/template/qualttp10.C @@ -0,0 +1,13 @@ +// Copyright (C) 2001 Free Software Foundation +// Contributed by Kriang Lerdsuwanakij +// { dg-do compile } + +template