This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: template enum buglet?
- To: brendan at cygnus dot com
- Subject: Re: template enum buglet?
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Wed, 26 Aug 1998 14:00:12 -0700
- Cc: egcs-patches at cygnus dot com
- References: <13795.28077.902573.268378@lisa.cygnus.com>
- Reply-to: mark at markmitchell dot com
Brendan --
Attached is a patch for the problem you reported.
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-08-26 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (finish_enum): Change prototype.
* decl.c (finish_enum): Use TYPE_VALUES, rather than taking a
VALUES parameter. Don't try to compute mins/maxs if
processing_template_decl.
* parse.y (structsp): Use new calling sequence for finish_enum.
* pt.c (tsubst_enum): Likewise. Take the new type as input.
(lookup_template_class): Remove unused variables. Tweak.
Register enums on instantiation list before substituting
enumeration constants.
(tsubst_decl): Remove unused variables.
(regenerate_decl_from_template): Likewise.
Index: testsuite/g++.old-deja/g++.pt/enum8.C
===================================================================
RCS file: enum8.C
diff -N enum8.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- enum8.C Wed Aug 26 12:38:59 1998
***************
*** 0 ****
--- 1,18 ----
+ // Build don't link:
+
+ template <int I>
+ void f();
+
+ template <>
+ void f<4>() {}
+
+ template <class T>
+ struct S
+ {
+ enum E { a = 1, b = a + 3 };
+ };
+
+ int main()
+ {
+ f<S<int>::b>();
+ }
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.117
diff -c -p -r1.117 cp-tree.h
*** cp-tree.h 1998/08/25 11:34:20 1.117
--- cp-tree.h 1998/08/26 19:39:14
*************** extern tree xref_tag PROTO((tree, tre
*** 2562,2568 ****
extern tree xref_tag_from_type PROTO((tree, tree, int));
extern void xref_basetypes PROTO((tree, tree, tree, tree));
extern tree start_enum PROTO((tree));
! extern tree finish_enum PROTO((tree, tree));
extern tree build_enumerator PROTO((tree, tree));
extern tree grok_enum_decls PROTO((tree));
extern int start_function PROTO((tree, tree, tree, int));
--- 2562,2568 ----
extern tree xref_tag_from_type PROTO((tree, tree, int));
extern void xref_basetypes PROTO((tree, tree, tree, tree));
extern tree start_enum PROTO((tree));
! extern tree finish_enum PROTO((tree));
extern tree build_enumerator PROTO((tree, tree));
extern tree grok_enum_decls PROTO((tree));
extern int start_function PROTO((tree, tree, tree, int));
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.192
diff -c -p -r1.192 decl.c
*** decl.c 1998/08/25 01:59:48 1.192
--- decl.c 1998/08/26 19:40:01
*************** start_enum (name)
*** 11861,11872 ****
Returns ENUMTYPE. */
tree
! finish_enum (enumtype, values)
! register tree enumtype, values;
{
register tree minnode = NULL_TREE, maxnode = NULL_TREE;
/* Calculate the maximum value of any enumerator in this type. */
if (values)
{
tree pair;
--- 11862,11874 ----
Returns ENUMTYPE. */
tree
! finish_enum (enumtype)
! tree enumtype;
{
register tree minnode = NULL_TREE, maxnode = NULL_TREE;
/* Calculate the maximum value of any enumerator in this type. */
+ tree values = TYPE_VALUES (enumtype);
if (values)
{
tree pair;
*************** finish_enum (enumtype, values)
*** 11899,11910 ****
= build1 (NOP_EXPR, enumtype, value);
TREE_TYPE (value) = enumtype;
! if (!minnode)
! minnode = maxnode = value;
! else if (tree_int_cst_lt (maxnode, value))
! maxnode = value;
! else if (tree_int_cst_lt (value, minnode))
! minnode = value;
}
/* In the list we're building up, we want the enumeration
--- 11901,11915 ----
= build1 (NOP_EXPR, enumtype, value);
TREE_TYPE (value) = enumtype;
! if (!processing_template_decl)
! {
! if (!minnode)
! minnode = maxnode = value;
! else if (tree_int_cst_lt (maxnode, value))
! maxnode = value;
! else if (tree_int_cst_lt (value, minnode))
! minnode = value;
! }
}
/* In the list we're building up, we want the enumeration
Index: cp/parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.82
diff -c -p -r1.82 parse.y
*** parse.y 1998/08/24 11:27:27 1.82
--- parse.y 1998/08/26 19:40:45
*************** structsp:
*** 2060,2083 ****
{ $<itype>3 = suspend_momentary ();
$<ttype>$ = start_enum ($2); }
enumlist maybecomma_warn '}'
! { $$.t = finish_enum ($<ttype>4, $5);
$$.new_type_flag = 1;
resume_momentary ((int) $<itype>3);
check_for_missing_semicolon ($<ttype>4); }
| ENUM identifier '{' '}'
! { $$.t = finish_enum (start_enum ($2), NULL_TREE);
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM '{'
{ $<itype>2 = suspend_momentary ();
$<ttype>$ = start_enum (make_anon_name ()); }
enumlist maybecomma_warn '}'
! { $$.t = finish_enum ($<ttype>3, $4);
resume_momentary ((int) $<itype>1);
check_for_missing_semicolon ($<ttype>3);
$$.new_type_flag = 1; }
| ENUM '{' '}'
! { $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE);
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
--- 2060,2085 ----
{ $<itype>3 = suspend_momentary ();
$<ttype>$ = start_enum ($2); }
enumlist maybecomma_warn '}'
! { TYPE_VALUES ($<ttype>4) = $5;
! $$.t = finish_enum ($<ttype>4);
$$.new_type_flag = 1;
resume_momentary ((int) $<itype>3);
check_for_missing_semicolon ($<ttype>4); }
| ENUM identifier '{' '}'
! { $$.t = finish_enum (start_enum ($2));
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM '{'
{ $<itype>2 = suspend_momentary ();
$<ttype>$ = start_enum (make_anon_name ()); }
enumlist maybecomma_warn '}'
! { TYPE_VALUES ($<ttype>3) = $4;
! $$.t = finish_enum ($<ttype>3);
resume_momentary ((int) $<itype>1);
check_for_missing_semicolon ($<ttype>3);
$$.new_type_flag = 1; }
| ENUM '{' '}'
! { $$.t = finish_enum (start_enum (make_anon_name()));
$$.new_type_flag = 1;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.187
diff -c -p -r1.187 pt.c
*** pt.c 1998/08/25 18:52:45 1.187
--- pt.c 1998/08/26 20:51:02
*************** static tree tsubst_expr_values PROTO((tr
*** 85,91 ****
static int list_eq PROTO((tree, tree));
static tree get_class_bindings PROTO((tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
! static tree tsubst_enum PROTO((tree, tree));
static tree add_to_template_args PROTO((tree, tree));
static tree add_outermost_template_args PROTO((tree, tree));
static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
--- 85,91 ----
static int list_eq PROTO((tree, tree));
static tree get_class_bindings PROTO((tree, tree, tree));
static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
! static void tsubst_enum PROTO((tree, tree, tree));
static tree add_to_template_args PROTO((tree, tree));
static tree add_outermost_template_args PROTO((tree, tree));
static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
*************** lookup_template_class (d1, arglist, in_d
*** 3152,3159 ****
int entering_scope;
{
tree template = NULL_TREE, parmlist;
! char *mangled_name;
! tree id, t;
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
--- 3152,3158 ----
int entering_scope;
{
tree template = NULL_TREE, parmlist;
! tree t;
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
*************** lookup_template_class (d1, arglist, in_d
*** 3242,3252 ****
--- 3241,3254 ----
}
else
{
+ extern tree current_local_enum;
tree template_type = TREE_TYPE (template);
tree type_decl;
tree found = NULL_TREE;
int arg_depth;
int parm_depth;
+ int is_partial_instantiation;
+ tree prev_local_enum;
template = most_general_template (template);
parmlist = DECL_TEMPLATE_PARMS (template);
*************** lookup_template_class (d1, arglist, in_d
*** 3398,3410 ****
DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
push_obstacks (&permanent_obstack, &permanent_obstack);
/* Create the type. */
if (TREE_CODE (template_type) == ENUMERAL_TYPE)
{
! if (!uses_template_parms (arglist))
! t = tsubst_enum (template_type, arglist);
else
! /* We don't want to call tsubst_enum for this type, since
the values for the enumeration constants may involve
template parameters. And, no one should be interested
in the enumeration constants for such a type. */
--- 3400,3419 ----
DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
push_obstacks (&permanent_obstack, &permanent_obstack);
+ /* This type is a "partial instantiation" if any of the template
+ arguments still inolve template parameters. */
+ is_partial_instantiation = uses_template_parms (arglist);
+
/* Create the type. */
if (TREE_CODE (template_type) == ENUMERAL_TYPE)
{
! if (!is_partial_instantiation)
! {
! prev_local_enum = current_local_enum;
! t = start_enum (TYPE_IDENTIFIER (template_type));
! }
else
! /* We don't want to call start_enum for this type, since
the values for the enumeration constants may involve
template parameters. And, no one should be interested
in the enumeration constants for such a type. */
*************** lookup_template_class (d1, arglist, in_d
*** 3439,3460 ****
else
type_decl = TYPE_NAME (t);
- /* We're done with the permanent obstack, now. */
- pop_obstacks ();
-
/* Set up the template information. */
arglist = copy_to_permanent (arglist);
SET_TYPE_TEMPLATE_INFO (t,
! perm_tree_cons (template, arglist, NULL_TREE));
! DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
! (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
/* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
is set up. */
if (TREE_CODE (t) != ENUMERAL_TYPE)
DECL_NAME (type_decl) = classtype_mangled_name (t);
DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
! if (! uses_template_parms (arglist))
{
DECL_ASSEMBLER_NAME (type_decl)
= get_identifier (build_overload_name (t, 1, 1));
--- 3448,3484 ----
else
type_decl = TYPE_NAME (t);
/* Set up the template information. */
arglist = copy_to_permanent (arglist);
SET_TYPE_TEMPLATE_INFO (t,
! tree_cons (template, arglist, NULL_TREE));
! DECL_TEMPLATE_INSTANTIATIONS (template)
! = tree_cons (arglist, t,
! DECL_TEMPLATE_INSTANTIATIONS (template));
!
! if (TREE_CODE (t) == ENUMERAL_TYPE
! && !is_partial_instantiation)
! {
! /* Now that the type has been registered on the
! instantiations list, we set up the enumerators. Because
! the enumeration constants may involve the enumeration
! type itself, we make sure to register the type first, and
! then create the constants. That way, doing tsubst_expr
! for the enumeration constants won't result in recursive
! calls here; we'll find the instantiation and exit above. */
! tsubst_enum (template_type, t, arglist);
! current_local_enum = prev_local_enum;
! }
!
! /* We're done with the permanent obstack, now. */
! pop_obstacks ();
/* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
is set up. */
if (TREE_CODE (t) != ENUMERAL_TYPE)
DECL_NAME (type_decl) = classtype_mangled_name (t);
DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
! if (!is_partial_instantiation)
{
DECL_ASSEMBLER_NAME (type_decl)
= get_identifier (build_overload_name (t, 1, 1));
*************** tsubst_decl (t, args, type, in_decl)
*** 4708,4715 ****
/* We can get here when processing a member template function
of a template class. */
tree decl = DECL_TEMPLATE_RESULT (t);
- tree parms;
- tree* new_parms;
tree spec;
int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
--- 4732,4737 ----
*************** regenerate_decl_from_template (decl, tmp
*** 7781,7787 ****
tree tmpl;
{
tree args;
- tree save_ti;
tree code_pattern;
tree new_decl;
tree gen_tmpl;
--- 7803,7808 ----
*************** add_maybe_template (d, fns)
*** 8172,8189 ****
DECL_MAYBE_TEMPLATE (d) = 1;
}
! /* Instantiate an enumerated type. */
! static tree
! tsubst_enum (tag, args)
! tree tag, args;
{
! extern tree current_local_enum;
! tree prev_local_enum = current_local_enum;
- tree newtag = start_enum (TYPE_IDENTIFIER (tag));
- tree e, values = NULL_TREE;
-
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
tree value;
--- 8193,8210 ----
DECL_MAYBE_TEMPLATE (d) = 1;
}
! /* Instantiate an enumerated type. TAG is the template type, NEWTAG
! is the instantiation (which should have been created with
! start_enum) and ARGS are the template arguments to use. */
! static void
! tsubst_enum (tag, newtag, args)
! tree tag;
! tree newtag;
! tree args;
{
! tree e;
for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
{
tree value;
*************** tsubst_enum (tag, args)
*** 8194,8214 ****
{
if (TREE_CODE (value) == NOP_EXPR)
/* This is the special case where the value is really a
! TEMPLATE_PARM_INDEX. See finish_enum. */
value = TREE_OPERAND (value, 0);
value = tsubst_expr (value, args, NULL_TREE);
}
elt = build_enumerator (TREE_PURPOSE (e), value);
- TREE_CHAIN (elt) = values;
- values = elt;
- }
! finish_enum (newtag, values);
!
! current_local_enum = prev_local_enum;
! return newtag;
}
/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
--- 8215,8236 ----
{
if (TREE_CODE (value) == NOP_EXPR)
/* This is the special case where the value is really a
! TEMPLATE_PARM_INDEX. See finish_enum. */
value = TREE_OPERAND (value, 0);
value = tsubst_expr (value, args, NULL_TREE);
}
elt = build_enumerator (TREE_PURPOSE (e), value);
! /* We save the enumerators we have built so far in the
! TYPE_VALUES so that if the enumeration constants for
! subsequent enumerators involve those for previous ones,
! tsubst_copy will be able to find them. */
! TREE_CHAIN (elt) = TYPE_VALUES (newtag);
! TYPE_VALUES (newtag) = elt;
! }
! finish_enum (newtag);
}
/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that