This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
(C++) patch for obstack pain
- To: egcs-patches at cygnus dot com
- Subject: (C++) patch for obstack pain
- From: Jason Merrill <jason at cygnus dot com>
- Date: Wed, 31 Mar 1999 18:59:23 -0800
My last checkin revealed a latent bug in declspec handling wrt obstacks;
code like
static const union { int foo () { } } u;
breaks because the declspecs are thrown away when we finish compiling foo.
We didn't notice this because we handled the case of a single spec
specially, and never tested multiple specs. This patch uses hash_tree_cons
to avoid the problem.
1999-03-31 Jason Merrill <jason@yorick.cygnus.com>
* semantics.c (begin_inline_definitions,
finish_inline_definitions): Rename from finish_default_args and
begin_inline_definitions, respectively, to something that isn't a
total lie. :)
* parse.y (structsp): Adjust.
* tree.c (hash_tree_cons): Remove obsolete via_* parms.
(list_hash_lookup): Likewise.
(hash_tree_chain): Adjust.
* pt.c (tsubst): Adjust.
(tsubst_arg_types): Use plain hash_tree_cons.
* cp-tree.h (hash_tree_cons_simple): Lose.
* parse.y (declmods, nonempty_cv_qualifiers): Use hash_tree_cons.
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.211
diff -c -p -r1.211 cp-tree.h
*** cp-tree.h 1999/03/30 23:30:05 1.211
--- cp-tree.h 1999/04/01 02:55:21
*************** extern tree begin_class_definition
*** 3252,3257 ****
--- 3252,3258 ----
extern tree finish_class_definition PROTO((tree, tree, int));
extern void finish_default_args PROTO((void));
extern void begin_inline_definitions PROTO((void));
+ extern void finish_inline_definitions PROTO((void));
extern tree finish_member_class_template PROTO((tree));
extern void finish_template_decl PROTO((tree));
extern tree finish_template_type PROTO((tree, tree, int));
*************** extern tree build_cplus_array_type PROT
*** 3295,3301 ****
extern int layout_basetypes PROTO((tree, int));
extern tree build_vbase_pointer_fields PROTO((tree));
extern tree build_base_fields PROTO((tree));
! extern tree hash_tree_cons PROTO((int, int, int, tree, tree, tree));
extern tree hash_tree_chain PROTO((tree, tree));
extern tree hash_chainon PROTO((tree, tree));
extern tree make_binfo PROTO((tree, tree, tree, tree));
--- 3296,3302 ----
extern int layout_basetypes PROTO((tree, int));
extern tree build_vbase_pointer_fields PROTO((tree));
extern tree build_base_fields PROTO((tree));
! extern tree hash_tree_cons PROTO((tree, tree, tree));
extern tree hash_tree_chain PROTO((tree, tree));
extern tree hash_chainon PROTO((tree, tree));
extern tree make_binfo PROTO((tree, tree, tree, tree));
*************** extern tree build_dummy_object PROTO((
*** 3347,3359 ****
extern tree maybe_dummy_object PROTO((tree, tree *));
extern int is_dummy_object PROTO((tree));
extern tree search_tree PROTO((tree, tree (*)(tree)));
#define scratchalloc expralloc
#define scratch_tree_cons expr_tree_cons
#define build_scratch_list build_expr_list
#define make_scratch_vec make_temp_vec
#define push_scratch_obstack push_expression_obstack
- #define hash_tree_cons_simple(PURPOSE, VALUE, CHAIN) \
- hash_tree_cons (0, 0, 0, (PURPOSE), (VALUE), (CHAIN))
/* in typeck.c */
extern int string_conv_p PROTO((tree, tree, int));
--- 3348,3359 ----
extern tree maybe_dummy_object PROTO((tree, tree *));
extern int is_dummy_object PROTO((tree));
extern tree search_tree PROTO((tree, tree (*)(tree)));
+
#define scratchalloc expralloc
#define scratch_tree_cons expr_tree_cons
#define build_scratch_list build_expr_list
#define make_scratch_vec make_temp_vec
#define push_scratch_obstack push_expression_obstack
/* in typeck.c */
extern int string_conv_p PROTO((tree, tree, int));
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.112
diff -c -p -r1.112 parse.y
*** parse.y 1999/03/30 23:30:26 1.112
--- parse.y 1999/04/01 02:55:22
*************** reserved_declspecs:
*** 1753,1776 ****
to redeclare a typedef-name.
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
declmods:
nonempty_cv_qualifiers %prec EMPTY
{ $$ = $1.t; TREE_STATIC ($$) = 1; }
| SCSPEC
! { $$ = build_decl_list (NULL_TREE, $$); }
| declmods CV_QUALIFIER
! { $$ = decl_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = 1; }
| declmods SCSPEC
{ if (extra_warnings && TREE_STATIC ($$))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
! $$ = decl_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = TREE_STATIC ($1); }
| declmods attributes
! { $$ = decl_tree_cons ($2, NULL_TREE, $1); }
| attributes
! { $$ = decl_tree_cons ($1, NULL_TREE, NULL_TREE); }
;
/* Used instead of declspecs where storage classes are not allowed
--- 1753,1785 ----
to redeclare a typedef-name.
In the result, declspecs have a non-NULL TREE_VALUE, attributes do not. */
+ /* We use hash_tree_cons for lists of typeless declspecs so that they end
+ up on a persistent obstack. Otherwise, they could appear at the
+ beginning of something like
+
+ static const struct { int foo () { } } b;
+
+ and would be discarded after we finish compiling foo. We don't need to
+ worry once we see a type. */
+
declmods:
nonempty_cv_qualifiers %prec EMPTY
{ $$ = $1.t; TREE_STATIC ($$) = 1; }
| SCSPEC
! { $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
| declmods CV_QUALIFIER
! { $$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = 1; }
| declmods SCSPEC
{ if (extra_warnings && TREE_STATIC ($$))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
! $$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = TREE_STATIC ($1); }
| declmods attributes
! { $$ = hash_tree_cons ($2, NULL_TREE, $1); }
| attributes
! { $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
;
/* Used instead of declspecs where storage classes are not allowed
*************** structsp:
*** 2141,2151 ****
$<ttype>$ = finish_class_definition ($1, $5, semi);
}
pending_defargs
! { finish_default_args (); }
pending_inlines
! { $$.t = $<ttype>6;
$$.new_type_flag = 1;
! begin_inline_definitions (); }
| class_head %prec EMPTY
{
$$.new_type_flag = 0;
--- 2150,2164 ----
$<ttype>$ = finish_class_definition ($1, $5, semi);
}
pending_defargs
! {
! begin_inline_definitions ();
! }
pending_inlines
! {
! finish_inline_definitions ();
! $$.t = $<ttype>6;
$$.new_type_flag = 1;
! }
| class_head %prec EMPTY
{
$$.new_type_flag = 0;
*************** cv_qualifiers:
*** 2689,2698 ****
nonempty_cv_qualifiers:
CV_QUALIFIER
! { $$.t = build_decl_list (NULL_TREE, $1);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers CV_QUALIFIER
! { $$.t = decl_tree_cons (NULL_TREE, $2, $1.t);
$$.new_type_flag = $1.new_type_flag; }
;
--- 2702,2711 ----
nonempty_cv_qualifiers:
CV_QUALIFIER
! { $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers CV_QUALIFIER
! { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
$$.new_type_flag = $1.new_type_flag; }
;
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.277
diff -c -p -r1.277 pt.c
*** pt.c 1999/03/29 01:09:28 1.277
--- pt.c 1999/04/01 02:55:23
*************** tsubst_arg_types (arg_types, args, compl
*** 5834,5841 ****
/* Note that we do not substitute into default arguments here. The
standard mandates that they be instantiated only when needed,
which is done in build_over_call. */
! return hash_tree_cons_simple (TREE_PURPOSE (arg_types), type,
! remaining_arg_types);
}
--- 5834,5841 ----
/* Note that we do not substitute into default arguments here. The
standard mandates that they be instantiated only when needed,
which is done in build_over_call. */
! return hash_tree_cons (TREE_PURPOSE (arg_types), type,
! remaining_arg_types);
}
*************** tsubst (t, args, complain, in_decl)
*** 6195,6209 ****
case TREE_LIST:
{
tree purpose, value, chain, result;
- int via_public, via_virtual, via_protected;
if (t == void_list_node)
return t;
- via_public = TREE_VIA_PUBLIC (t);
- via_protected = TREE_VIA_PROTECTED (t);
- via_virtual = TREE_VIA_VIRTUAL (t);
-
purpose = TREE_PURPOSE (t);
if (purpose)
{
--- 6195,6204 ----
*************** tsubst (t, args, complain, in_decl)
*** 6229,6236 ****
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
! result = hash_tree_cons (via_public, via_virtual, via_protected,
! purpose, value, chain);
TREE_PARMLIST (result) = TREE_PARMLIST (t);
return result;
}
--- 6224,6230 ----
&& value == TREE_VALUE (t)
&& chain == TREE_CHAIN (t))
return t;
! result = hash_tree_cons (purpose, value, chain);
TREE_PARMLIST (result) = TREE_PARMLIST (t);
return result;
}
Index: semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.44
diff -c -p -r1.44 semantics.c
*** semantics.c 1999/03/30 23:30:31 1.44
--- semantics.c 1999/04/01 02:55:23
*************** finish_class_definition (t, attributes,
*** 1465,1471 ****
the processing of a class definition. */
void
! finish_default_args ()
{
if (pending_inlines
&& current_scope () == current_function_decl)
--- 1465,1471 ----
the processing of a class definition. */
void
! begin_inline_definitions ()
{
if (pending_inlines
&& current_scope () == current_function_decl)
*************** finish_default_args ()
*** 1476,1482 ****
processing of a class definition. */
void
! begin_inline_definitions ()
{
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
--- 1476,1482 ----
processing of a class definition. */
void
! finish_inline_definitions ()
{
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.102
diff -c -p -r1.102 tree.c
*** tree.c 1999/03/30 23:30:32 1.102
--- tree.c 1999/04/01 02:55:23
*************** static tree perm_manip PROTO((tree));
*** 33,40 ****
static tree build_cplus_array_type_1 PROTO((tree, tree));
static void list_hash_add PROTO((int, tree));
static int list_hash PROTO((tree, tree, tree));
! static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
! tree));
static void propagate_binfo_offsets PROTO((tree, tree));
static int avoid_overlap PROTO((tree, tree));
static int lvalue_p_1 PROTO((tree, int));
--- 33,39 ----
static tree build_cplus_array_type_1 PROTO((tree, tree));
static void list_hash_add PROTO((int, tree));
static int list_hash PROTO((tree, tree, tree));
! static tree list_hash_lookup PROTO((int, tree, tree, tree));
static void propagate_binfo_offsets PROTO((tree, tree));
static int avoid_overlap PROTO((tree, tree));
static int lvalue_p_1 PROTO((tree, int));
*************** list_hash (purpose, value, chain)
*** 978,995 ****
If one is found, return it. Otherwise return 0. */
static tree
! list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
! purpose, value, chain)
! int hashcode, via_public, via_virtual, via_protected;
tree purpose, value, chain;
{
register struct list_hash *h;
for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == via_virtual
- && TREE_VIA_PUBLIC (h->list) == via_public
- && TREE_VIA_PROTECTED (h->list) == via_protected
&& TREE_PURPOSE (h->list) == purpose
&& TREE_VALUE (h->list) == value
&& TREE_CHAIN (h->list) == chain)
--- 977,990 ----
If one is found, return it. Otherwise return 0. */
static tree
! list_hash_lookup (hashcode, purpose, value, chain)
! int hashcode;
tree purpose, value, chain;
{
register struct list_hash *h;
for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode
&& TREE_PURPOSE (h->list) == purpose
&& TREE_VALUE (h->list) == value
&& TREE_CHAIN (h->list) == chain)
*************** list_hash_add (hashcode, list)
*** 1014,1037 ****
list_hash_table[hashcode % TYPE_HASH_SIZE] = h;
}
! /* Given TYPE, and HASHCODE its hash code, return the canonical
! object for an identical list if one already exists.
! Otherwise, return TYPE, and record it as the canonical object
! if it is a permanent object.
!
! To use this function, first create a list of the sort you want.
! Then compute its hash code from the fields of the list that
! make it different from other similar lists.
! Then call this function and use the value.
! This function frees the list you pass in if it is a duplicate. */
/* Set to 1 to debug without canonicalization. Never set by program. */
static int debug_no_list_hash = 0;
tree
! hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
! int via_public, via_virtual, via_protected;
tree purpose, value, chain;
{
struct obstack *ambient_obstack = current_obstack;
--- 1009,1024 ----
list_hash_table[hashcode % TYPE_HASH_SIZE] = h;
}
! /* Given list components PURPOSE, VALUE, AND CHAIN, return the canonical
! object for an identical list if one already exists. Otherwise, build a
! new one, and record it as the canonical object. */
/* Set to 1 to debug without canonicalization. Never set by program. */
static int debug_no_list_hash = 0;
tree
! hash_tree_cons (purpose, value, chain)
tree purpose, value, chain;
{
struct obstack *ambient_obstack = current_obstack;
*************** hash_tree_cons (via_public, via_virtual,
*** 1041,1048 ****
if (! debug_no_list_hash)
{
hashcode = list_hash (purpose, value, chain);
! t = list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
! purpose, value, chain);
if (t)
return t;
}
--- 1028,1034 ----
if (! debug_no_list_hash)
{
hashcode = list_hash (purpose, value, chain);
! t = list_hash_lookup (hashcode, purpose, value, chain);
if (t)
return t;
}
*************** hash_tree_cons (via_public, via_virtual,
*** 1050,1058 ****
current_obstack = &class_obstack;
t = tree_cons (purpose, value, chain);
- TREE_VIA_PUBLIC (t) = via_public;
- TREE_VIA_PROTECTED (t) = via_protected;
- TREE_VIA_VIRTUAL (t) = via_virtual;
/* If this is a new list, record it for later reuse. */
if (! debug_no_list_hash)
--- 1036,1041 ----
*************** tree
*** 1068,1074 ****
hash_tree_chain (value, chain)
tree value, chain;
{
! return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */
--- 1051,1057 ----
hash_tree_chain (value, chain)
tree value, chain;
{
! return hash_tree_cons (NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */