OSDN Git Service

* pt.c (redeclare_class_template): New function.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Mar 1998 13:23:03 +0000 (13:23 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Mar 1998 13:23:03 +0000 (13:23 +0000)
* cp_tree.h (redeclare_class_template): Declare it.
* decl.c (xref_tag): Use it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@18855 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/g++.old-deja/g++.pt/defarg3.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/redecl1.C [new file with mode: 0644]

index 15d0709..0b0971f 100644 (file)
@@ -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 
index 9d76c9c..4a65a48 100644 (file)
@@ -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));
index 15fa6fb..b3f065b 100644 (file)
@@ -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)
index 3c72a44..a529f23 100644 (file)
@@ -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 (file)
index 0000000..9a7e046
--- /dev/null
@@ -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 (file)
index 0000000..7bc3eaa
--- /dev/null
@@ -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