#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "intl.h"
#include "tree.h"
#include "tree-inline.h"
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
+#include "cgraph.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, int));
-static void c_expand_body PARAMS ((tree, int, int));
+static void c_expand_body_1 PARAMS ((tree, int));
static void warn_if_shadowing PARAMS ((tree, tree));
static bool flexible_array_type_p PARAMS ((tree));
\f
}
}
error_with_decl (olddecl, "previous declaration of `%s'");
+
+ /* This is safer because the initializer might contain references
+ to variables that were declared between olddecl and newdecl. This
+ will make the initializer invalid for olddecl in case it gets
+ assigned to olddecl below. */
+ if (TREE_CODE (newdecl) == VAR_DECL)
+ DECL_INITIAL (newdecl) = 0;
}
/* TLS cannot follow non-TLS declaration. */
else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
inline, make sure we emit debug info for the inline before we
throw it away, in case it was inlined into a function that hasn't
been written out yet. */
- if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
+ if (new_is_definition && DECL_INITIAL (olddecl))
{
- (*debug_hooks->outlining_inline_function) (olddecl);
+ if (TREE_USED (olddecl))
+ (*debug_hooks->outlining_inline_function) (olddecl);
/* The new defn must not be inline. */
DECL_INLINE (newdecl) = 0;
}
/* If we are processing a typedef statement, generate a whole new
- ..._TYPE node (which will be just an variant of the existing
+ ..._TYPE node (which will be just a variant of the existing
..._TYPE node with identical properties) and then install the
TYPE_DECL node generated to represent the typedef name as the
TYPE_NAME of this brand new (duplicate) ..._TYPE node.
DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
+
+ if (current_function_decl)
+ {
+ /* Add the decls to the outermost block. */
+ struct binding_level *b = current_binding_level;
+ struct binding_level *old = b;
+ while (b->level_chain->parm_flag == 0)
+ b = b->level_chain;
+ current_binding_level = b;
+ pushdecl (decl);
+ current_binding_level = old;
+ }
finish_decl (decl, init, NULL_TREE);
Thread-local variables are never common, since there's no entrenched
body of code to break, and it allows more efficient variable references
- in the presense of dynamic linking. */
+ in the presence of dynamic linking. */
if (TREE_CODE (decl) == VAR_DECL
&& !initialized
current_binding_level->parm_order = NULL_TREE;
}
\f
+static GTY(()) int compound_literal_number;
+
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR that initializes the compound
/* This decl needs a name for the assembler output. We also need
a unique suffix to be added to the name. */
char *name;
- extern int var_labelno;
- ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal", var_labelno);
- var_labelno++;
+ ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+ compound_literal_number);
+ compound_literal_number++;
DECL_NAME (decl) = get_identifier (name);
DECL_DEFER_OUTPUT (decl) = 1;
DECL_COMDAT (decl) = 1;
{
/* Type qualifiers on a function return type are normally
permitted by the standard but have no effect, so give a
- warning at -W. Qualifiers on a void return type have
+ warning at -Wextra. Qualifiers on a void return type have
meaning as a GNU extension, and are banned on function
definitions in ISO C. FIXME: strictly we shouldn't
pedwarn for qualified void return types except on function
needed, and let dwarf2 know that the function is inlinable. */
else if (flag_inline_trees == 2 && initialized)
{
+ if (!DECL_INLINE (decl))
+ DID_INLINE_FUNC (decl) = 1;
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
}
ref = lookup_tag (code, name, current_binding_level, 1);
if (ref && TREE_CODE (ref) == code)
{
- C_TYPE_BEING_DEFINED (ref) = 1;
- TYPE_PACKED (ref) = flag_pack_struct;
if (TYPE_FIELDS (ref))
{
if (code == UNION_TYPE)
- error ("redefinition of `union %s'",
- IDENTIFIER_POINTER (name));
+ error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
else
- error ("redefinition of `struct %s'",
- IDENTIFIER_POINTER (name));
+ error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
}
-
- return ref;
}
+ else
+ {
+ /* Otherwise create a forward-reference just so the tag is in scope. */
- /* Otherwise create a forward-reference just so the tag is in scope. */
-
- ref = make_node (code);
- pushtag (name, ref);
+ ref = make_node (code);
+ pushtag (name, ref);
+ }
+
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
return ref;
again this is an anonymous struct.
Otherwise this is an error.
- Oh what a horrid tangled web we weave. I wonder if MS consiously
+ Oh what a horrid tangled web we weave. I wonder if MS consciously
took this from Plan 9 or if it was an accident of implementation
that took root before someone noticed the bug... */
free_after_compilation (cfun);
cfun = NULL;
+ if (flag_unit_at_a_time && can_defer_p)
+ {
+ cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
+ current_function_decl = NULL;
+ return;
+ }
+
if (! nested)
{
- /* Generate RTL for the body of this function. */
- c_expand_body (fndecl, nested, can_defer_p);
+ /* Function is parsed.
+ Generate RTL for the body of this function or defer
+ it for later expansion. */
+ int uninlinable = 1;
+
+ /* There's no reason to do any of the work here if we're only doing
+ semantic analysis; this code just generates RTL. */
+ if (flag_syntax_only)
+ {
+ current_function_decl = NULL;
+ DECL_SAVED_TREE (fndecl) = NULL_TREE;
+ return;
+ }
+
+ if (flag_inline_trees)
+ {
+ /* First, cache whether the current function is inlinable. Some
+ predicates depend on cfun and current_function_decl to
+ function completely. */
+ timevar_push (TV_INTEGRATION);
+ uninlinable = ! tree_inlinable_function_p (fndecl, 0);
+
+ if (! uninlinable && can_defer_p
+ /* Save function tree for inlining. Should return 0 if the
+ language does not support function deferring or the
+ function could not be deferred. */
+ && defer_fn (fndecl))
+ {
+ /* Let the back-end know that this function exists. */
+ (*debug_hooks->deferred_inline_function) (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ current_function_decl = NULL;
+ return;
+ }
+
+ /* Then, inline any functions called in it. */
+ optimize_inline_calls (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ }
+
+ c_expand_body (fndecl);
+
+ if (uninlinable)
+ {
+ /* Allow the body of the function to be garbage collected. */
+ DECL_SAVED_TREE (fndecl) = NULL_TREE;
+ }
/* Let the error reporting routines know that we're outside a
function. For a nested function, this value is used in
function was deferred, e.g. in duplicate_decls. */
if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
{
- c_expand_body (fndecl, 0, 0);
+ if (flag_inline_trees)
+ {
+ timevar_push (TV_INTEGRATION);
+ optimize_inline_calls (fndecl);
+ timevar_pop (TV_INTEGRATION);
+ }
+ c_expand_body (fndecl);
current_function_decl = NULL;
}
}
generation of RTL. */
static void
-c_expand_body (fndecl, nested_p, can_defer_p)
+c_expand_body_1 (fndecl, nested_p)
tree fndecl;
- int nested_p, can_defer_p;
+ int nested_p;
{
- int uninlinable = 1;
-
- /* There's no reason to do any of the work here if we're only doing
- semantic analysis; this code just generates RTL. */
- if (flag_syntax_only)
- return;
-
- if (flag_inline_trees)
- {
- /* First, cache whether the current function is inlinable. Some
- predicates depend on cfun and current_function_decl to
- function completely. */
- timevar_push (TV_INTEGRATION);
- uninlinable = ! tree_inlinable_function_p (fndecl);
-
- if (! uninlinable && can_defer_p
- /* Save function tree for inlining. Should return 0 if the
- language does not support function deferring or the
- function could not be deferred. */
- && defer_fn (fndecl))
- {
- /* Let the back-end know that this function exists. */
- (*debug_hooks->deferred_inline_function) (fndecl);
- timevar_pop (TV_INTEGRATION);
- return;
- }
-
- /* Then, inline any functions called in it. */
- optimize_inline_calls (fndecl);
- timevar_pop (TV_INTEGRATION);
- }
-
timevar_push (TV_EXPAND);
if (nested_p)
current_function_decl = fndecl;
input_filename = DECL_SOURCE_FILE (fndecl);
init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
+ lineno = DECL_SOURCE_LINE (fndecl);
/* This function is being processed in whole-function mode. */
cfun->x_whole_function_mode_p = 1;
/* Generate the RTL for this function. */
expand_stmt (DECL_SAVED_TREE (fndecl));
- if (uninlinable)
- {
- /* 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
if (nested_p)
ggc_pop_context ();
- /* With just -W, complain only if function returns both with
+ /* With just -Wextra, complain only if function returns both with
and without a value. */
if (extra_warnings
&& current_function_returns_value
pop_function_context ();
timevar_pop (TV_EXPAND);
}
+
+/* Like c_expand_body_1 but only for unnested functions. */
+
+void
+c_expand_body (fndecl)
+ tree fndecl;
+{
+ c_expand_body_1 (fndecl, 0);
+}
\f
/* Check the declarations given in a for-loop for satisfying the C99
constraints. */
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_CONTEXT (decl) == current_function_decl
&& DECL_SAVED_TREE (decl))
- c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
+ c_expand_body_1 (decl, 1);
}
/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since