From: Mark Mitchell Date: Fri, 27 Mar 1998 13:23:03 +0000 (+0000) Subject: pt.c (redeclare_class_template): New function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7fe6899fb7d5a9651177de41dd92032a6b5f7f63;p=gcc.git pt.c (redeclare_class_template): New function. * pt.c (redeclare_class_template): New function. * cp_tree.h (redeclare_class_template): Declare it. * decl.c (xref_tag): Use it. From-SVN: r18855 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 15d07097552..0b0971f3c46 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +Fri Mar 27 13:22:18 1998 Mark Mitchell + + * pt.c (redeclare_class_template): New function. + * cp_tree.h (redeclare_class_template): Declare it. + * decl.c (xref_tag): Use it. + Thu Mar 26 11:16:30 1998 Jason Merrill * call.c (build_over_call): Check IS_AGGR_TYPE, not diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9d76c9c5552..4a65a4875fa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2457,6 +2457,7 @@ extern tree end_template_parm_list PROTO((tree)); extern void end_template_decl PROTO((void)); extern tree current_template_args PROTO((void)); extern tree push_template_decl PROTO((tree)); +extern void redeclare_class_template PROTO((tree)); extern tree lookup_template_class PROTO((tree, tree, tree, tree)); extern tree lookup_template_function PROTO((tree, tree)); extern int uses_template_parms PROTO((tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 15fa6fb20c5..b3f065b24ec 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10889,6 +10889,9 @@ xref_tag (code_type_node, name, binfo, globalize) if (BINDING_VALUE (binding) == NULL_TREE) BINDING_VALUE (binding) = TYPE_NAME (ref); } + + if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref)) + redeclare_class_template (ref); } if (binfo) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3c72a449b5f..a529f236e24 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1792,6 +1792,66 @@ push_template_decl (decl) return DECL_TEMPLATE_RESULT (tmpl); } +/* Called when a class template TYPE is redeclared, e.g.: + + template struct S; + template struct S {}; */ + +void +redeclare_class_template (type) + tree type; +{ + tree tmpl = CLASSTYPE_TI_TEMPLATE (type); + tree tmpl_parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); + tree parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); + int i; + + if (!PRIMARY_TEMPLATE_P (tmpl)) + /* The type is nested in some template class. Nothing to worry + about here; there are no new template parameters for the nested + type. */ + return; + + if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms)) + { + cp_error_at ("previous declaration `%D'", tmpl); + cp_error ("used %d template parameter%s instead of %d", + TREE_VEC_LENGTH (tmpl_parms), + TREE_VEC_LENGTH (tmpl_parms) == 1 ? "" : "s", + TREE_VEC_LENGTH (parms)); + return; + } + + for (i = 0; i < TREE_VEC_LENGTH (tmpl_parms); ++i) + { + tree tmpl_parm = TREE_VALUE (TREE_VEC_ELT (tmpl_parms, i)); + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + tree tmpl_default = TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)); + tree parm_default = TREE_PURPOSE (TREE_VEC_ELT (parms, i)); + + if (TREE_CODE (tmpl_parm) != TREE_CODE (parm)) + { + cp_error_at ("template parameter `%#D'", tmpl_parm); + cp_error ("redeclared here as `%#D'", parm); + return; + } + + if (tmpl_default != NULL_TREE && parm_default != NULL_TREE) + { + /* We have in [temp.param]: + + A template-parameter may not be given default arguments + by two different declarations in the same scope. */ + cp_error ("redefinition of default argument for `%#D'", parm); + return; + } + + if (parm_default != NULL_TREE) + /* Update the previous template parameters (which are the ones + that will really count) with the new default value. */ + TREE_PURPOSE (TREE_VEC_ELT (tmpl_parms, i)) = parm_default; + } +} /* Attempt to convert the non-type template parameter EXPR to the indicated TYPE. If the conversion is successful, return the diff --git a/gcc/testsuite/g++.old-deja/g++.pt/defarg3.C b/gcc/testsuite/g++.old-deja/g++.pt/defarg3.C new file mode 100644 index 00000000000..9a7e0460497 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/defarg3.C @@ -0,0 +1,16 @@ +// Build don't link: + +template +struct S; + +template +struct S {}; + +template +struct S; + +void f() +{ + S<> s; +} + diff --git a/gcc/testsuite/g++.old-deja/g++.pt/redecl1.C b/gcc/testsuite/g++.old-deja/g++.pt/redecl1.C new file mode 100644 index 00000000000..7bc3eaae26b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/redecl1.C @@ -0,0 +1,22 @@ +// Build don't link: + +template +struct S1; // ERROR - previous declaration + +template +struct S1 {}; // ERROR - used 1 template parameter + +template +struct S2; + +template +struct S2; // ERROR - redefinition of default + +template // ERROR - template parameter +struct S3; + +template +struct S3; // ERROR - redeclared here + +template