diff options
author | Mark Mitchell <mmitchell@usa.net> | 1998-03-27 13:23:03 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-03-27 13:23:03 +0000 |
commit | 7fe6899fb7d5a9651177de41dd92032a6b5f7f63 (patch) | |
tree | 6496943e636a190747309a2835840c217fba8d41 /gcc | |
parent | 7daa142bd6b311e464766a803c8ff08deb7b7816 (diff) | |
download | gcc-7fe6899fb7d5a9651177de41dd92032a6b5f7f63.zip gcc-7fe6899fb7d5a9651177de41dd92032a6b5f7f63.tar.gz gcc-7fe6899fb7d5a9651177de41dd92032a6b5f7f63.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/cp/pt.c | 60 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/defarg3.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/redecl1.C | 22 |
6 files changed, 108 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 15d0709..0b0971f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +Fri Mar 27 13:22:18 1998 Mark Mitchell <mmitchell@usa.net> + + * 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 <jason@yorick.cygnus.com> * 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 9d76c9c..4a65a48 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 15fa6fb..b3f065b 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 3c72a44..a529f23 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 <class T> struct S; + template <class T> 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 0000000..9a7e046 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/defarg3.C @@ -0,0 +1,16 @@ +// Build don't link: + +template <class T> +struct S; + +template <class T = int> +struct S {}; + +template <class T> +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 0000000..7bc3eaa --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/redecl1.C @@ -0,0 +1,22 @@ +// Build don't link: + +template <class T> +struct S1; // ERROR - previous declaration + +template <class T, class U> +struct S1 {}; // ERROR - used 1 template parameter + +template <class T = int> +struct S2; + +template <class T = int> +struct S2; // ERROR - redefinition of default + +template <class T> // ERROR - template parameter +struct S3; + +template <int I> +struct S3; // ERROR - redeclared here + +template <template <class T> class C> +struct S3; // ERROR - redeclared here |