meissner@DG-RTP.DG.COM (Michael Meissner) (10/17/89)
GCC 1.36 modified the 'build_int' function to cache the integers 0 to 32, presumably to save space in the obstack for each simple variable getting a unique node that holds the size. This is a very good optimization, however the cache code had a bug in it. The bug is that 'build_int' calls 'build_int2', which in turn calls 'make_node'. The 'make_node' function uses the current value of 'expression_obstack' as the obstack to allocate from. The variable 'expression_obstack' in turn points to either 'permanent_obstack', or one of the temporary obstacks ('temporary_obstack', etc.). Of the different obstacks, 'permanent_obstack' is the only obstack that has a lifetime past the current function or statement. The following program should demonstrate the problem. When build_int is called with the value 16 for the structure within cmp_T108, expression_obstack points to maybepermanent_obstack. When build_int is called with the value 16 for the structure within cmp_utype, it is returned the cache'd value for 16. The memory the cached pointer points to has since been reclaimed, and has a zero for the type_code field (which is ERROR_MARK). Later on in layout_field, it is assumed that the size is non-constant, and it core dumps because all of the fields are not set up. ---------------------------------------- extern int global_decl; int cmp_T08() { return 0; } int test08() { int use = global_decl; struct { char a; double type; }; } int test09() { struct { char a; struct { char a; } type; }; } int cmp_utype() { return call(); } int test10() { struct { char a; union { char a; short b; double f; } type; }; } ---------------------------------------- Here is my fix, which just stores the appropriate value into expression_obstack, and then restores it. *** stor-layout.c.orig Tue Sep 12 18:48:57 1989 --- stor-layout.c Mon Oct 16 19:18:15 1989 *************** *** 22,27 **** --- 22,28 ---- #include <stdio.h> #include "tree.h" + #include "obstack.h" #include "rtl.h" /* For GET_MODE_SIZE */ #define MAX(x,y) ((x) > (y) ? (x) : (y)) *************** *** 28,33 **** --- 29,37 ---- #define MIN(x,y) ((x) < (y) ? (x) : (y)) #define CEIL(x,y) (((x) + (y) - 1) / (y)) + extern struct obstack permanent_obstack; + extern struct obstack *expression_obstack; + /* Data type for the expressions representing sizes of data types. It is the first integer type laid out. In C, this is int. */ *************** *** 206,222 **** build_int (v) int v; { - register tree t; /* Type-size nodes already made for small sizes. */ static tree size_table[33]; ! if (v < 33 && size_table[v] != 0) ! return size_table[v]; ! t = build_int_2 (v, 0); ! TREE_TYPE (t) = sizetype; ! if (v < 33) ! size_table[v] = t; ! return t; } /* Combine operands OP1 and OP2 with arithmetic operation OPC. --- 210,234 ---- build_int (v) int v; { /* Type-size nodes already made for small sizes. */ static tree size_table[33]; ! if (v < 33 && v >= 0) ! { ! if (size_table[v] == 0) ! { ! /* We must go to the permanent_obstack, if we are going ! to cache small numbers, otherwise it won't be valid ! in the next module. */ ! register struct obstack *cur = expression_obstack; ! expression_obstack = &permanent_obstack; ! size_table[v] = build_int_2 (v, 0); ! expression_obstack = cur; ! } ! return size_table[v]; ! } ! else ! return build_int_2 (v, 0); } /* Combine operands OP1 and OP2 with arithmetic operation OPC.