This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
PATCH for redeclaration of template classes
- To: Jason Merrill <jason at cygnus dot com>
- Subject: PATCH for redeclaration of template classes
- From: Mark Mitchell <mmitchell at usa dot net>
- Date: Thu, 26 Mar 1998 16:49:15 -0800
- Cc: egcs-bugs at cygnus dot com
- Reply-to: mmitchell at usa dot net
Here's a patch that improves both the error-checking and the
default argument processing of template class redeclarations. Is it
OK?
--
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available
Thu Mar 26 16:43:49 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.
* error.c (dump_decl): Be a bit more explicit with template
type arguments, when verbose.
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.106
diff -c -p -r1.106 pt.c
*** pt.c 1998/03/26 10:32:03 1.106
--- pt.c 1998/03/27 00:29:35
*************** push_template_decl (decl)
*** 1792,1798 ****
--- 1792,1857 ----
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;
+ }
+
+ /* 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
converted value. If the conversion is unsuccesful, return
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.30
diff -c -p -r1.30 error.c
*** error.c 1998/03/24 10:25:41 1.30
--- error.c 1998/03/27 00:29:38
*************** dump_decl (t, v)
*** 655,660 ****
--- 655,664 ----
/* Don't say 'typedef class A' */
if (DECL_ARTIFICIAL (t))
{
+ if (v > 0 && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
+ /* Say `class T' not just `T'. */
+ OB_PUTS ("class ");
+
dump_type (TREE_TYPE (t), v);
break;
}
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.46
diff -c -p -r1.46 cp-tree.h
*** cp-tree.h 1998/03/25 16:14:45 1.46
--- cp-tree.h 1998/03/27 00:29:49
*************** extern tree end_template_parm_list PROT
*** 2457,2462 ****
--- 2457,2463 ----
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: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.84
diff -c -p -r1.84 decl.c
*** decl.c 1998/03/26 11:16:45 1.84
--- decl.c 1998/03/27 00:30:27
*************** xref_tag (code_type_node, name, binfo, g
*** 10889,10894 ****
--- 10889,10897 ----
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: redecl1.C
===================================================================
RCS file: redecl1.C
diff -N redecl1.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- redecl1.C Thu Mar 26 16:30:43 1998
***************
*** 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
Index: defarg3.C
===================================================================
RCS file: defarg3.C
diff -N defarg3.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- defarg3.C Thu Mar 26 16:31:28 1998
***************
*** 0 ****
--- 1,10 ----
+ // Build don't link:
+
+ template <class T = int>
+ struct S {};
+
+ void f()
+ {
+ S<> s;
+ }
+