aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mmitchell@usa.net>1998-03-27 13:23:03 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-03-27 13:23:03 +0000
commit7fe6899fb7d5a9651177de41dd92032a6b5f7f63 (patch)
tree6496943e636a190747309a2835840c217fba8d41 /gcc
parent7daa142bd6b311e464766a803c8ff08deb7b7816 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/pt.c60
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/defarg3.C16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/redecl1.C22
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