PATCH: PR2924
Mark Mitchell
mark@codesourcery.com
Mon Jun 4 23:49:00 GMT 2001
This patch fixes PR2924, which is an evil conjunction of two of my
least favorite GNU C extensions: nested functions and variable-sized
types. Ugh.
Here's the fix, which is pretty ugly itself. This could be done in
better ways -- but not without some substantial reworking of the
front-end.
Bootstrapped and tested on i686-pc-linux-gnu, installed on the
mainline and on the branch.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2001-06-04 Mark Mitchell <mark@codesourcery.com>
* c-tree.h (lang_decl): Add pending_sizes fields.
* c-decl.c (store_parm_decls): Save pending_sizes away for nested
functions.
(c_expand_body): Expand them.
(lang_mark_tree): Mark lang_decl:pending_sizes.
* function.c (expand_pending_sizes): New function, broken out
from ...
(expand_function_start): ... here.
* tree.h (expand_pending_sizes): Declare it.
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.207.2.10
diff -c -p -r1.207.2.10 c-decl.c
*** c-decl.c 2001/05/21 18:08:50 1.207.2.10
--- c-decl.c 2001/06/05 06:33:21
*************** store_parm_decls ()
*** 6083,6088 ****
--- 6083,6091 ----
/* Nonzero if this definition is written with a prototype. */
int prototype = 0;
+ /* The function containing FNDECL, if any. */
+ tree context = decl_function_context (fndecl);
+
if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
{
/* This case is when the function was defined with an ANSI prototype.
*************** store_parm_decls ()
*** 6451,6464 ****
gen_aux_info_record (fndecl, 1, 0, prototype);
/* Initialize the RTL code for the function. */
-
init_function_start (fndecl, input_filename, lineno);
/* Begin the statement tree for this function. */
DECL_LANG_SPECIFIC (current_function_decl)
! =((struct lang_decl *) ggc_alloc (sizeof (struct lang_decl)));
begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
/* This function is being processed in whole-function mode. */
cfun->x_whole_function_mode_p = 1;
--- 6454,6481 ----
gen_aux_info_record (fndecl, 1, 0, prototype);
/* Initialize the RTL code for the function. */
init_function_start (fndecl, input_filename, lineno);
/* Begin the statement tree for this function. */
DECL_LANG_SPECIFIC (current_function_decl)
! =((struct lang_decl *) ggc_alloc_cleared (sizeof (struct lang_decl)));
begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
+ /* If this is a nested function, save away the sizes of any
+ variable-size types so that we can expand them when generating
+ RTL. */
+ if (context)
+ {
+ tree t;
+
+ DECL_LANG_SPECIFIC (fndecl)->pending_sizes
+ = nreverse (get_pending_sizes ());
+ for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
+ t;
+ t = TREE_CHAIN (t))
+ SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
+ }
+
/* This function is being processed in whole-function mode. */
cfun->x_whole_function_mode_p = 1;
*************** c_expand_body (fndecl, nested_p)
*** 6702,6710 ****
if (flag_syntax_only)
return;
- /* Squirrel away our current state. */
if (nested_p)
! push_function_context ();
/* Initialize the RTL code for the function. */
current_function_decl = fndecl;
--- 6719,6732 ----
if (flag_syntax_only)
return;
if (nested_p)
! {
! /* Make sure that we will evaluate variable-sized types involved
! in our function's type. */
! expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
! /* Squirrel away our current state. */
! push_function_context ();
! }
/* Initialize the RTL code for the function. */
current_function_decl = fndecl;
*************** c_expand_body (fndecl, nested_p)
*** 6739,6745 ****
/* Allow the body of the function to be garbage collected. */
DECL_SAVED_TREE (fndecl) = NULL_TREE;
! /* We hard-wired immediate_size_expand to zero in start_function.
expand_function_end will decrement this variable. So, we set the
variable to one here, so that after the decrement it will remain
zero. */
--- 6761,6767 ----
/* Allow the body of the function to be garbage collected. */
DECL_SAVED_TREE (fndecl) = NULL_TREE;
! /* We hard-wired immediate_size_expand to zero above.
expand_function_end will decrement this variable. So, we set the
variable to one here, so that after the decrement it will remain
zero. */
*************** lang_mark_tree (t)
*** 7034,7039 ****
--- 7056,7062 ----
{
ggc_mark (DECL_LANG_SPECIFIC (t));
c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+ ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
}
}
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.54
diff -c -p -r1.54 c-tree.h
*** c-tree.h 2000/12/20 18:18:24 1.54
--- c-tree.h 2001/06/05 06:33:21
*************** struct lang_identifier
*** 42,53 ****
enum rid rid_code;
};
! /* Wrapping c_lang_decl in another struct is an unfortunate
! necessity. */
struct lang_decl
{
struct c_lang_decl base;
};
/* Macros for access to language-specific slots in an identifier. */
--- 42,56 ----
enum rid rid_code;
};
! /* Language-specific declaration information. */
struct lang_decl
{
struct c_lang_decl base;
+ /* The return types and parameter types may have variable size.
+ This is a list of any SAVE_EXPRs that need to be evaluated to
+ compute those sizes. */
+ tree pending_sizes;
};
/* Macros for access to language-specific slots in an identifier. */
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.250.2.10
diff -c -p -r1.250.2.10 function.c
*** function.c 2001/05/18 07:26:05 1.250.2.10
--- function.c 2001/06/05 06:33:24
*************** expand_main_function ()
*** 6263,6268 ****
--- 6263,6291 ----
extern struct obstack permanent_obstack;
+ /* The PENDING_SIZES represent the sizes of variable-sized types.
+ Create RTL for the various sizes now (using temporary variables),
+ so that we can refer to the sizes from the RTL we are generating
+ for the current function. The PENDING_SIZES are a TREE_LIST. The
+ TREE_VALUE of each node is a SAVE_EXPR. */
+
+ void
+ expand_pending_sizes (pending_sizes)
+ tree pending_sizes;
+ {
+ tree tem;
+
+ /* Evaluate now the sizes of any types declared among the arguments. */
+ for (tem = pending_sizes; tem; tem = TREE_CHAIN (tem))
+ {
+ expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode,
+ EXPAND_MEMORY_USE_BAD);
+ /* Flush the queue in case this parameter declaration has
+ side-effects. */
+ emit_queue ();
+ }
+ }
+
/* Start the RTL for a new function, and set variables used for
emitting RTL.
SUBR is the FUNCTION_DECL node.
*************** expand_function_start (subr, parms_have_
*** 6497,6510 ****
tail_recursion_reentry = emit_note (NULL_PTR, NOTE_INSN_DELETED);
/* Evaluate now the sizes of any types declared among the arguments. */
! for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem))
! {
! expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode,
! EXPAND_MEMORY_USE_BAD);
! /* Flush the queue in case this parameter declaration has
! side-effects. */
! emit_queue ();
! }
/* Make sure there is a line number after the function entry setup code. */
force_next_line_note ();
--- 6520,6526 ----
tail_recursion_reentry = emit_note (NULL_PTR, NOTE_INSN_DELETED);
/* Evaluate now the sizes of any types declared among the arguments. */
! expand_pending_sizes (nreverse (get_pending_sizes ()));
/* Make sure there is a line number after the function entry setup code. */
force_next_line_note ();
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.223.2.10
diff -c -p -r1.223.2.10 tree.h
*** tree.h 2001/05/22 03:01:50 1.223.2.10
--- tree.h 2001/06/05 06:33:37
*************** extern void print_obstack_name PARAMS (
*** 2727,2732 ****
--- 2727,2733 ----
#endif
extern void expand_function_end PARAMS ((const char *, int, int));
extern void expand_function_start PARAMS ((tree, int));
+ extern void expand_pending_sizes PARAMS ((tree));
extern int real_onep PARAMS ((tree));
extern int real_twop PARAMS ((tree));
Index: testsuite/gcc.c-torture/compile/20010605-1.c
===================================================================
RCS file: 20010605-1.c
diff -N 20010605-1.c
*** /dev/null Tue May 5 13:32:27 1998
--- 20010605-1.c Mon Jun 4 23:33:39 2001
***************
*** 0 ****
--- 1,15 ----
+ int
+ main (int argc, char **argv)
+ {
+ int size = 10;
+
+ typedef struct {
+ char val[size];
+ } block;
+ block retframe_block()
+ {
+ return *(block*)0;
+ }
+
+ return 0;
+ }
More information about the Gcc-patches
mailing list