aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r--gcc/c-decl.c331
1 files changed, 200 insertions, 131 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index bc1857c..b8421a7 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -125,6 +125,19 @@ static tree current_function_parm_tags;
static const char *current_function_prototype_file;
static int current_function_prototype_line;
+/* The current statement tree. */
+
+static struct stmt_tree_s c_stmt_tree;
+
+/* The current scope statement stack. */
+
+static tree c_scope_stmt_stack;
+
+/* Nonzero if __FUNCTION__ and its ilk have been declared in this
+ function. */
+
+static int c_function_name_declared_p;
+
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
that have names. Here so we can clear out their names' definitions
at the end of the function. */
@@ -296,6 +309,7 @@ static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, const char *, int));
+static void c_expand_body PARAMS ((tree, int));
/* C-specific option variables. */
@@ -471,10 +485,6 @@ int warn_float_equal = 0;
int warn_multichar = 1;
-/* Wrapper since C and C++ expand_expr_stmt are different. */
-
-expand_expr_stmt_fn lang_expand_expr_stmt = c_expand_expr_stmt;
-
/* The variant of the C language being processed. */
c_language_kind c_language = clk_c;
@@ -1088,12 +1098,6 @@ poplevel (keep, reverse, functionbody)
if (DECL_ABSTRACT_ORIGIN (decl) != 0
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else if (DECL_SAVED_INSNS (decl) != 0)
- {
- push_function_context ();
- output_inline_function (decl);
- pop_function_context ();
- }
}
/* If there were any declarations or structure tags in that level,
@@ -1235,6 +1239,7 @@ poplevel (keep, reverse, functionbody)
if (block)
TREE_USED (block) = 1;
+
return block;
}
@@ -2063,8 +2068,8 @@ pushdecl (x)
/* A local extern declaration for a function doesn't constitute nesting.
A local auto declaration does, since it's a forward decl
for a nested function coming later. */
- if (TREE_CODE (x) == FUNCTION_DECL && DECL_INITIAL (x) == 0
- && DECL_EXTERNAL (x))
+ if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+ && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
DECL_CONTEXT (x) = 0;
if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
@@ -2618,7 +2623,7 @@ redeclaration_error_message (newdecl, olddecl)
return 1;
return 0;
}
- else if (current_binding_level == global_binding_level)
+ else if (DECL_CONTEXT (newdecl) == NULL_TREE)
{
/* Objects declared at top level: */
/* If at least one is a reference, it's ok. */
@@ -2678,9 +2683,6 @@ lookup_label (id)
decl = build_decl (LABEL_DECL, id, void_type_node);
- /* Make sure every label has an rtx. */
- label_rtx (decl);
-
/* A label not explicitly declared must be local to where it's ref'd. */
DECL_CONTEXT (decl) = current_function_decl;
@@ -3217,6 +3219,8 @@ init_decl_processing ()
/* Record our roots. */
ggc_add_tree_root (c_global_trees, CTI_MAX);
+ ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
+ ggc_add_tree_root (&c_scope_stmt_stack, 1);
ggc_add_tree_root (&named_labels, 1);
ggc_add_tree_root (&shadowed_labels, 1);
ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
@@ -3553,7 +3557,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
/* But not if this is a duplicate decl
and we preserved the rtl from the previous one
(which may or may not happen). */
- && DECL_RTL (tem) == 0)
+ && DECL_RTL (tem) == 0
+ && !DECL_CONTEXT (tem))
{
if (COMPLETE_TYPE_P (TREE_TYPE (tem)))
expand_decl (tem);
@@ -3703,9 +3708,17 @@ finish_decl (decl, init, asmspec_tree)
{
/* This is a no-op in c-lang.c or something real in objc-actions.c. */
maybe_objc_check_decl (decl);
- rest_of_decl_compilation (decl, asmspec,
- (DECL_CONTEXT (decl) == 0
- || TREE_ASM_WRITTEN (decl)), 0);
+
+ if (!DECL_CONTEXT (decl))
+ rest_of_decl_compilation (decl, asmspec,
+ (DECL_CONTEXT (decl) == 0
+ || TREE_ASM_WRITTEN (decl)), 0);
+ else
+ {
+ if (asmspec)
+ DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+ add_decl_stmt (decl);
+ }
if (DECL_CONTEXT (decl) != 0)
{
@@ -3719,11 +3732,7 @@ finish_decl (decl, init, asmspec_tree)
/* If it's still incomplete now, no init will save it. */
if (DECL_SIZE (decl) == 0)
DECL_INITIAL (decl) = 0;
- expand_decl (decl);
}
- /* Compute and store the initial value. */
- if (TREE_CODE (decl) != FUNCTION_DECL)
- expand_decl_init (decl);
}
}
@@ -5784,6 +5793,7 @@ build_enumerator (name, value)
return tree_cons (decl, value, NULL_TREE);
}
+
/* Create the FUNCTION_DECL for a function definition.
DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
@@ -6432,25 +6442,20 @@ store_parm_decls ()
init_function_start (fndecl, input_filename, lineno);
- /* If this is a varargs function, inform function.c. */
-
- if (c_function_varargs)
- mark_varargs ();
+ /* 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));
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
-
- declare_function_name ();
+ /* This function is being processed in whole-function mode. */
+ cfun->x_whole_function_mode_p = 1;
- /* Set up parameters and prepare for return, for the function. */
-
- expand_function_start (fndecl, 0);
-
- /* If this function is `main', emit a call to `__main'
- to run global initializers, etc. */
- if (DECL_NAME (fndecl)
- && MAIN_NAME_P (DECL_NAME (fndecl))
- && DECL_CONTEXT (fndecl) == NULL_TREE)
- expand_main_function ();
+ /* Even though we're inside a function body, we still don't want to
+ call expand_expr to calculate the size of a variable-sized array.
+ We haven't necessarily assigned RTL to all variables yet, so it's
+ not safe to try to expand expressions involving them. */
+ immediate_size_expand = 0;
+ cfun->x_dont_save_pending_sizes_p = 1;
}
/* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
@@ -6650,6 +6655,82 @@ finish_function (nested)
}
}
+ /* Tie off the statement tree for this function. */
+ finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ /* Clear out memory we no longer need. */
+ free_after_parsing (cfun);
+ /* Since we never call rest_of_compilation, we never clear
+ CFUN. Do so explicitly. */
+ free_after_compilation (cfun);
+ cfun = NULL;
+
+ if (! nested)
+ {
+ /* Generate RTL for the body of this function. */
+ c_expand_body (fndecl, nested);
+ /* Let the error reporting routines know that we're outside a
+ function. For a nested function, this value is used in
+ pop_c_function_context and then reset via pop_function_context. */
+ current_function_decl = NULL;
+ }
+}
+
+/* Generate the RTL for the body of FNDECL. If NESTED_P is non-zero,
+ then we are already in the process of generating RTL for another
+ function. */
+
+static void
+c_expand_body (fndecl, nested_p)
+ tree fndecl;
+ int nested_p;
+{
+ /* Squirrel away our current state. */
+ if (nested_p)
+ push_function_context ();
+
+ /* Initialize the RTL code for the function. */
+ current_function_decl = fndecl;
+ init_function_start (fndecl, input_filename, lineno);
+
+ /* This function is being processed in whole-function mode. */
+ cfun->x_whole_function_mode_p = 1;
+
+ /* Even though we're inside a function body, we still don't want to
+ call expand_expr to calculate the size of a variable-sized array.
+ We haven't necessarily assigned RTL to all variables yet, so it's
+ not safe to try to expand expressions involving them. */
+ immediate_size_expand = 0;
+ cfun->x_dont_save_pending_sizes_p = 1;
+
+ /* Set up parameters and prepare for return, for the function. */
+ expand_function_start (fndecl, 0);
+
+ /* If this function is `main', emit a call to `__main'
+ to run global initializers, etc. */
+ if (DECL_NAME (fndecl)
+ && MAIN_NAME_P (DECL_NAME (fndecl))
+ && DECL_CONTEXT (fndecl) == NULL_TREE)
+ expand_main_function ();
+
+ /* If this is a varargs function, inform function.c. */
+ if (c_function_varargs)
+ mark_varargs ();
+
+ /* Generate the RTL for this function. */
+ expand_stmt (DECL_SAVED_TREE (fndecl));
+ /* 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. */
+ immediate_size_expand = 1;
+
+ /* Allow language dialects to perform special processing. */
+ if (lang_expand_function_end)
+ (*lang_expand_function_end) ();
+
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 0);
@@ -6658,14 +6739,14 @@ finish_function (nested)
/* If this is a nested function, protect the local variables in the stack
above us from being collected while we're compiling this function. */
- if (nested)
+ if (nested_p)
ggc_push_context ();
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
/* Undo the GC context switch. */
- if (nested)
+ if (nested_p)
ggc_pop_context ();
current_function_returns_null |= can_reach_end;
@@ -6715,7 +6796,7 @@ finish_function (nested)
}
}
- if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
+ if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p)
{
/* Stop pointing to the local nodes about to be freed.
But DECL_INITIAL must remain nonzero so we know this
@@ -6748,13 +6829,20 @@ finish_function (nested)
assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
}
- if (! nested)
+ if (nested_p)
{
- /* Let the error reporting routines know that we're outside a
- function. For a nested function, this value is used in
- pop_c_function_context and then reset via pop_function_context. */
- current_function_decl = NULL;
+ /* Return to the enclosing function. */
+ pop_function_context ();
+ /* If the nested function was inline, write it out if that is
+ necessary. */
+ if (!TREE_ASM_WRITTEN (fndecl) && TREE_ADDRESSABLE (fndecl))
+ {
+ push_function_context ();
+ output_inline_function (fndecl);
+ pop_function_context ();
+ }
}
+
}
/* Save and restore the variables in this file and elsewhere
@@ -6785,6 +6873,9 @@ push_c_function_context (f)
xmalloc (sizeof (struct c_language_function)));
f->language = (struct language_function *) p;
+ p->base.x_stmt_tree = c_stmt_tree;
+ p->base.x_scope_stmt_stack = c_scope_stmt_stack;
+ p->base.x_function_name_declared_p = c_function_name_declared_p;
p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
@@ -6810,7 +6901,8 @@ pop_c_function_context (f)
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
= TREE_VALUE (link);
- if (DECL_SAVED_INSNS (current_function_decl) == 0)
+ if (DECL_SAVED_INSNS (current_function_decl) == 0
+ && DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
{
/* Stop pointing to the local nodes about to be freed. */
/* But DECL_INITIAL must remain nonzero so we know this
@@ -6819,6 +6911,9 @@ pop_c_function_context (f)
DECL_ARGUMENTS (current_function_decl) = 0;
}
+ c_stmt_tree = p->base.x_stmt_tree;
+ c_scope_stmt_stack = p->base.x_scope_stmt_stack;
+ c_function_name_declared_p = p->base.x_function_name_declared_p;
named_labels = p->named_labels;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
@@ -6843,18 +6938,27 @@ mark_c_function_context (f)
if (p == 0)
return;
+ mark_c_language_function (&p->base);
ggc_mark_tree (p->shadowed_labels);
ggc_mark_tree (p->named_labels);
mark_binding_level (&p->binding_level);
}
-/* integrate_decl_tree calls this function, but since we don't use the
- DECL_LANG_SPECIFIC field, this is a no-op. */
+/* Copy the DECL_LANG_SEPECIFIC data associated with NODE. */
void
-copy_lang_decl (node)
- tree node ATTRIBUTE_UNUSED;
+copy_lang_decl (decl)
+ tree decl;
{
+ struct lang_decl *ld;
+
+ if (!DECL_LANG_SPECIFIC (decl))
+ return;
+
+ ld = (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl));
+ bcopy ((char *)DECL_LANG_SPECIFIC (decl), (char *)ld,
+ sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (decl) = ld;
}
/* Mark ARG for GC. */
@@ -6886,6 +6990,11 @@ lang_mark_tree (t)
}
else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
ggc_mark (TYPE_LANG_SPECIFIC (t));
+ else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
+ {
+ ggc_mark (DECL_LANG_SPECIFIC (t));
+ c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+ }
}
/* The functions below are required for functionality of doing
@@ -6910,7 +7019,15 @@ stmts_are_full_exprs_p ()
stmt_tree
current_stmt_tree ()
{
- return cfun ? &cfun->language->x_stmt_tree : NULL;
+ return &c_stmt_tree;
+}
+
+/* Returns the stack of SCOPE_STMTs for the current function. */
+
+tree *
+current_scope_stmt_stack ()
+{
+ return &c_scope_stmt_stack;
}
/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
@@ -6923,94 +7040,46 @@ anon_aggr_type_p (node)
return 0;
}
-/* One if we have already declared __FUNCTION__ (and related
- variables) in the current function. Two if we are in the process
- of doing so. */
+/* Dummy function in place of callback used by C++. */
-int
-current_function_name_declared ()
+void
+extract_interface_info ()
{
- abort ();
- return 0;
}
-/* Code to generate the RTL for a case label in C. */
+/* Return a new COMPOUND_STMT, after adding it to the current
+ statement tree. */
-void
-do_case (low_value, high_value)
- tree low_value;
- tree high_value;
+tree
+c_begin_compound_stmt ()
{
- tree value1 = NULL_TREE, value2 = NULL_TREE, label;
-
- if (low_value != NULL_TREE)
- value1 = check_case_value (low_value);
- if (high_value != NULL_TREE)
- value2 = check_case_value (high_value);
-
- label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ tree stmt;
- if (pedantic && (high_value != NULL_TREE))
- pedwarn ("ISO C forbids case ranges");
-
- if (value1 != error_mark_node && value2 != error_mark_node)
+ /* Create the COMPOUND_STMT. */
+ stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
+ /* If we haven't already declared __FUNCTION__ and its ilk then this
+ is the opening curly brace of the function. Declare them now. */
+ if (!c_function_name_declared_p)
{
- tree duplicate;
- int success;
-
- if (high_value == NULL_TREE && value1 != NULL_TREE &&
- pedantic && ! INTEGRAL_TYPE_P (TREE_TYPE (value1)))
- pedwarn ("label must have integral type in ISO C");
-
- if (low_value == NULL_TREE)
- success = pushcase (NULL_TREE, 0, label, &duplicate);
- else if (high_value == NULL_TREE)
- success = pushcase (value1, convert_and_check, label, &duplicate);
- else
- success = pushcase_range (value1, value2, convert_and_check,
- label, &duplicate);
-
- if (success == 1)
- {
- if (low_value == NULL_TREE)
- error ("default label not within a switch statement");
- else
- error ("case label not within a switch statement");
- }
- else if (success == 2)
- {
- if (low_value == NULL_TREE)
- {
- error ("multiple default labels in one switch");
- error_with_decl (duplicate, "this is the first default label");
- }
- else
- error ("duplicate case value");
- if (high_value != NULL_TREE)
- error_with_decl (duplicate,
- "this is the first entry for that value");
- }
- else if (low_value != NULL_TREE)
- {
- if (success == 3)
- warning ("case value out of range");
- else if (success == 5)
- error ("case label within scope of cleanup or variable array");
- }
+ c_function_name_declared_p = 1;
+ declare_function_name ();
}
+
+ return stmt;
}
-/* Accessor to set the 'current_function_name_declared' flag. */
+/* Expand T (a DECL_STMT) if it declares an entity not handled by the
+ common code. */
void
-set_current_function_name_declared (i)
- int i ATTRIBUTE_UNUSED;
-{
- abort ();
-}
-
-/* Dummy function in place of callback used by C++. */
-void
-extract_interface_info ()
+c_expand_decl_stmt (t)
+ tree t;
{
+ tree decl = DECL_STMT_DECL (t);
+
+ /* Expand nested functions. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_CONTEXT (decl) == current_function_decl
+ && DECL_SAVED_TREE (decl))
+ c_expand_body (decl, /*nested_p=*/1);
}