/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
FIELD, /* Declaration inside struct or union */
TYPENAME}; /* Typename (inside cast or sizeof) */
+/* States indicating how grokdeclarator() should handle declspecs marked
+ with __attribute__((deprecated)). An object declared as
+ __attribute__((deprecated)) suppresses warnings of uses of other
+ deprecated items. */
+
+enum deprecated_states {
+ DEPRECATED_NORMAL,
+ DEPRECATED_SUPPRESS
+};
+
\f
/* Nonzero if we have seen an invalid cross reference
to a struct, union, or enum, but not yet printed the message. */
/* True means we've initialized exception handling. */
bool c_eh_initialized_p;
-/* While defining an enum type, this is 1 plus the last enumerator
- constant value. Note that will do not have to save this or `enum_overflow'
- around nested function definition since such a definition could only
- occur in an enum value expression and we don't use these variables in
- that case. */
-
-static tree enum_next_value;
-
-/* Nonzero means that there was overflow computing enum_next_value. */
-
-static int enum_overflow;
-
/* The file and line that the prototype came from if this is an
old-style definition; used for diagnostics in
store_parm_decls_oldstyle. */
static int warn_about_return_type;
-/* Nonzero when starting a function declared `extern inline'. */
-
-static int current_extern_inline;
-
/* Nonzero when the current toplevel function contains a declaration
of a nested function which is never defined. */
union lang_tree_node
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
- chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *) TREE_CHAIN (&%h.generic)")))
+ chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) GENERIC_NEXT (&%h.generic))")))
{
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
declarations. */
BOOL_BITFIELD parm_flag : 1;
+ /* True if we saw [*] in this scope. Used to give an error messages
+ if these appears in a function definition. */
+ BOOL_BITFIELD had_vla_unspec : 1;
+
/* True if we already complained about forward parameter decls
in this scope. This prevents double warnings on
foo (int a; int b; ...) */
static bool next_is_function_body;
-/* Functions called automatically at the beginning and end of execution. */
-
-static GTY(()) tree static_ctors;
-static GTY(()) tree static_dtors;
-
/* Forward declarations. */
static tree lookup_name_in_scope (tree, struct c_scope *);
static tree c_make_fname_decl (tree, int);
static tree grokdeclarator (const struct c_declarator *,
struct c_declspecs *,
- enum decl_context, bool, tree *);
+ enum decl_context, bool, tree *,
+ enum deprecated_states);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
\f
{
enum tree_code code = TREE_CODE (t);
- if (EXPR_P (t) && code != LABEL_EXPR)
+ if (CAN_HAVE_LOCATION_P (t) && code != LABEL_EXPR)
{
if (!EXPR_HAS_LOCATION (t))
SET_EXPR_LOCATION (t, input_location);
return t;
}
\f
-/* States indicating how grokdeclarator() should handle declspecs marked
- with __attribute__((deprecated)). An object declared as
- __attribute__((deprecated)) suppresses warnings of uses of other
- deprecated items. */
-
-enum deprecated_states {
- DEPRECATED_NORMAL,
- DEPRECATED_SUPPRESS
-};
-
-static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
void
c_print_identifier (FILE *file, tree node, int indent)
error ("label %q+D used but not defined", p);
DECL_INITIAL (p) = error_mark_node;
}
- else if (!TREE_USED (p) && warn_unused_label)
- {
- if (DECL_INITIAL (p))
- warning (0, "label %q+D defined but not used", p);
- else
- warning (0, "label %q+D declared but not defined", p);
- }
+ else
+ warn_for_unused_label (p);
+
/* Labels go in BLOCK_VARS. */
TREE_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
gcc_assert (I_LABEL_BINDING (b->id) == b);
- I_LABEL_BINDING (b->id) = b->shadowed;
- break;
+ I_LABEL_BINDING (b->id) = b->shadowed;
+ break;
case ENUMERAL_TYPE:
case UNION_TYPE:
gcc_assert (I_TAG_BINDING (b->id) == b);
I_TAG_BINDING (b->id) = b->shadowed;
}
- break;
+ break;
case FUNCTION_DECL:
/* Propagate TREE_ADDRESSABLE from nested functions to their
&& DECL_ABSTRACT_ORIGIN (p) != p)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
if (!DECL_EXTERNAL (p)
- && DECL_INITIAL (p) == 0)
+ && !DECL_INITIAL (p)
+ && scope != file_scope
+ && scope != external_scope)
{
error ("nested function %q+D declared but never defined", p);
undef_nested_function = true;
}
+ /* C99 6.7.4p6: "a function with external linkage... declared
+ with an inline function specifier ... shall also be defined in the
+ same translation unit." */
+ else if (DECL_DECLARED_INLINE_P (p)
+ && TREE_PUBLIC (p)
+ && !DECL_INITIAL (p)
+ && !flag_gnu89_inline)
+ pedwarn ("inline function %q+D declared but never defined", p);
+
goto common_symbol;
case VAR_DECL:
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p)
&& scope != file_scope
- && scope != external_scope)
+ && scope != external_scope)
warning (OPT_Wunused_variable, "unused variable %q+D", p);
if (b->inner_comp)
for (;;)
{
- tree oldargtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs));
- tree newargtype = TYPE_MAIN_VARIANT (TREE_VALUE (newargs));
+ tree oldargtype = TREE_VALUE (oldargs);
+ tree newargtype = TREE_VALUE (newargs);
+
+ if (oldargtype == error_mark_node || newargtype == error_mark_node)
+ return false;
+
+ oldargtype = TYPE_MAIN_VARIANT (oldargtype);
+ newargtype = TYPE_MAIN_VARIANT (newargtype);
if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
break;
/* Function declarations can either be 'static' or 'extern' (no
qualifier is equivalent to 'extern' - C99 6.2.2p5) and therefore
- can never conflict with each other on account of linkage (6.2.2p4).
- Multiple definitions are not allowed (6.9p3,5) but GCC permits
- two definitions if one is 'extern inline' and one is not. The non-
- extern-inline definition supersedes the extern-inline definition. */
+ can never conflict with each other on account of linkage
+ (6.2.2p4). Multiple definitions are not allowed (6.9p3,5) but
+ gnu89 mode permits two definitions if one is 'extern inline' and
+ one is not. The non- extern-inline definition supersedes the
+ extern-inline definition. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
{
/* If both decls are in the same TU and the new declaration
isn't overriding an extern inline reject the new decl.
- When we handle c99 style inline rules we'll want to reject
- the following:
-
- DECL_EXTERN_INLINE (olddecl)
- && !DECL_EXTERN_INLINE (newdecl)
-
- if they're in the same translation unit. Until we implement
- the full semantics we accept the construct. */
- if (!(DECL_EXTERN_INLINE (olddecl)
- && !DECL_EXTERN_INLINE (newdecl))
+ In c99, no overriding is allowed in the same translation
+ unit. */
+ if ((!DECL_EXTERN_INLINE (olddecl)
+ || DECL_EXTERN_INLINE (newdecl)
+ || (!flag_gnu89_inline
+ && (!DECL_DECLARED_INLINE_P (olddecl)
+ || !lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (olddecl)))
+ && (!DECL_DECLARED_INLINE_P (newdecl)
+ || !lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (newdecl))))
+ )
&& same_translation_unit_p (newdecl, olddecl))
{
error ("redefinition of %q+D", newdecl);
warned = true;
}
}
+
+ /* Make sure gnu_inline attribute is either not present, or
+ present on all inline decls. */
+ if (DECL_DECLARED_INLINE_P (olddecl)
+ && DECL_DECLARED_INLINE_P (newdecl))
+ {
+ bool newa = lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (newdecl)) != NULL;
+ bool olda = lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (olddecl)) != NULL;
+ if (newa != olda)
+ {
+ error ("%<gnu_inline%> attribute present on %q+D",
+ newa ? newdecl : olddecl);
+ error ("%Jbut not here", newa ? olddecl : newdecl);
+ }
+ }
}
else if (TREE_CODE (newdecl) == VAR_DECL)
{
/* warnings */
/* All decls must agree on a visibility. */
- if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS)
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (newdecl), TS_DECL_WITH_VIS)
&& DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
??? Should we still warn about this now we have unit-at-a-time
mode and can get it right?
Definitely don't complain if the decls are in different translation
- units. */
+ units.
+ C99 permits this, so don't warn in that case. (The function
+ may not be inlined everywhere in function-at-a-time mode, but
+ we still shouldn't warn.) */
if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
- && same_translation_unit_p (olddecl, newdecl))
+ && same_translation_unit_p (olddecl, newdecl)
+ && flag_gnu89_inline)
{
if (TREE_USED (olddecl))
{
static void
merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
{
- int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
- && DECL_INITIAL (newdecl) != 0);
- int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
- && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
- int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
- && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
+ bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_INITIAL (newdecl) != 0);
+ bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
+ bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
+ bool extern_changed = false;
/* For real parm decl following a forward decl, rechain the old decl
in its new location and clear TREE_ASM_WRITTEN (it's not a
TREE_READONLY (olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
- {
- TREE_THIS_VOLATILE (olddecl) = 1;
- if (TREE_CODE (newdecl) == VAR_DECL)
- make_var_volatile (newdecl);
- }
+ TREE_THIS_VOLATILE (olddecl) = 1;
/* Merge deprecatedness. */
if (TREE_DEPRECATED (newdecl))
C_DECL_THREADPRIVATE_P (newdecl) = 1;
}
- if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
- {
- /* Merge the unused-warning information. */
- if (DECL_IN_SYSTEM_HEADER (olddecl))
- DECL_IN_SYSTEM_HEADER (newdecl) = 1;
- else if (DECL_IN_SYSTEM_HEADER (newdecl))
- DECL_IN_SYSTEM_HEADER (olddecl) = 1;
-
- /* Merge the section attribute.
- We want to issue an error if the sections conflict but that must be
- done later in decl_attributes since we are called before attributes
- are assigned. */
- if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
- DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
-
- /* Copy the assembler name.
- Currently, it can only be defined in the prototype. */
- COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
-
- /* Use visibility of whichever declaration had it specified */
- if (DECL_VISIBILITY_SPECIFIED (olddecl))
- {
- DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
- DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
- }
-
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
- DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
- DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
- DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
- |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
- TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
- TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
- DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
- DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
- DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
- }
-
- /* Merge the storage class information. */
- merge_weak (newdecl, olddecl);
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS))
+ {
+ /* Merge the unused-warning information. */
+ if (DECL_IN_SYSTEM_HEADER (olddecl))
+ DECL_IN_SYSTEM_HEADER (newdecl) = 1;
+ else if (DECL_IN_SYSTEM_HEADER (newdecl))
+ DECL_IN_SYSTEM_HEADER (olddecl) = 1;
- /* For functions, static overrides non-static. */
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
- /* This is since we don't automatically
- copy the attributes of NEWDECL into OLDDECL. */
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- /* If this clears `static', clear it in the identifier too. */
- if (!TREE_PUBLIC (olddecl))
- TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
- }
- }
-
- if (DECL_EXTERNAL (newdecl))
- {
- TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
- DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
-
- /* An extern decl does not override previous storage class. */
- TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
- if (!DECL_EXTERNAL (newdecl))
- {
- DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
- DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
- }
- }
- else
- {
- TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
- TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
- }
-
- if (TREE_CODE (newdecl) == FUNCTION_DECL)
- {
- /* If we're redefining a function previously defined as extern
- 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))
- {
- if (TREE_USED (olddecl)
- /* In unit-at-a-time mode we never inline re-defined extern
- inline functions. */
- && !flag_unit_at_a_time
- && cgraph_function_possibly_inlined_p (olddecl))
- (*debug_hooks->outlining_inline_function) (olddecl);
-
- /* The new defn must not be inline. */
- DECL_INLINE (newdecl) = 0;
- DECL_UNINLINABLE (newdecl) = 1;
- }
- else
- {
- /* If either decl says `inline', this fn is inline,
- unless its definition was passed already. */
- if (DECL_DECLARED_INLINE_P (newdecl)
- || DECL_DECLARED_INLINE_P (olddecl))
- DECL_DECLARED_INLINE_P (newdecl) = 1;
-
- DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
- = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
- }
+ /* Merge the section attribute.
+ We want to issue an error if the sections conflict but that
+ must be done later in decl_attributes since we are called
+ before attributes are assigned. */
+ if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+ DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
- if (DECL_BUILT_IN (olddecl))
- {
- /* If redeclaring a builtin function, it stays built in.
- But it gets tagged as having been declared. */
- DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
- DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
- C_DECL_DECLARED_BUILTIN (newdecl) = 1;
- if (new_is_prototype)
- C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
- else
- C_DECL_BUILTIN_PROTOTYPE (newdecl)
- = C_DECL_BUILTIN_PROTOTYPE (olddecl);
- }
+ /* Copy the assembler name.
+ Currently, it can only be defined in the prototype. */
+ COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
- /* Also preserve various other info from the definition. */
- if (!new_is_definition)
- {
- DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
- DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
- DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
- DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-
- /* Set DECL_INLINE on the declaration if we've got a body
- from which to instantiate. */
- if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
- {
- DECL_INLINE (newdecl) = 1;
- DECL_ABSTRACT_ORIGIN (newdecl)
- = DECL_ABSTRACT_ORIGIN (olddecl);
- }
- }
- else
- {
- /* If a previous declaration said inline, mark the
- definition as inlinable. */
- if (DECL_DECLARED_INLINE_P (newdecl)
- && !DECL_UNINLINABLE (newdecl))
- DECL_INLINE (newdecl) = 1;
- }
- }
-
- /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
+ /* Use visibility of whichever declaration had it specified */
+ if (DECL_VISIBILITY_SPECIFIED (olddecl))
+ {
+ DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+ DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+ }
+
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ {
+ DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
+ DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+ DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
+ DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
+ |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+ TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+ TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+ DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+ DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+ DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
+ }
+
+ /* Merge the storage class information. */
+ merge_weak (newdecl, olddecl);
+
+ /* For functions, static overrides non-static. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ {
+ TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
+ /* This is since we don't automatically
+ copy the attributes of NEWDECL into OLDDECL. */
+ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+ /* If this clears `static', clear it in the identifier too. */
+ if (!TREE_PUBLIC (olddecl))
+ TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
+ }
+ }
+
+ /* In c99, 'extern' declaration before (or after) 'inline' means this
+ function is not DECL_EXTERNAL, unless 'gnu_inline' attribute
+ is present. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && !flag_gnu89_inline
+ && (DECL_DECLARED_INLINE_P (newdecl)
+ || DECL_DECLARED_INLINE_P (olddecl))
+ && (!DECL_DECLARED_INLINE_P (newdecl)
+ || !DECL_DECLARED_INLINE_P (olddecl)
+ || !DECL_EXTERNAL (olddecl))
+ && DECL_EXTERNAL (newdecl)
+ && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl)))
+ DECL_EXTERNAL (newdecl) = 0;
+
+ if (DECL_EXTERNAL (newdecl))
+ {
+ TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
+ DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
+
+ /* An extern decl does not override previous storage class. */
+ TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
+ if (!DECL_EXTERNAL (newdecl))
+ {
+ DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
+ DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
+ }
+ }
+ else
+ {
+ TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
+ TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
+ }
+
+ if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ {
+ /* If we're redefining a function previously defined as extern
+ 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))
+ {
+ if (TREE_USED (olddecl)
+ /* In unit-at-a-time mode we never inline re-defined extern
+ inline functions. */
+ && !flag_unit_at_a_time
+ && cgraph_function_possibly_inlined_p (olddecl))
+ (*debug_hooks->outlining_inline_function) (olddecl);
+
+ /* The new defn must not be inline. */
+ DECL_INLINE (newdecl) = 0;
+ DECL_UNINLINABLE (newdecl) = 1;
+ }
+ else
+ {
+ /* If either decl says `inline', this fn is inline, unless
+ its definition was passed already. */
+ if (DECL_DECLARED_INLINE_P (newdecl)
+ || DECL_DECLARED_INLINE_P (olddecl))
+ DECL_DECLARED_INLINE_P (newdecl) = 1;
+
+ DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+ = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+ }
+
+ if (DECL_BUILT_IN (olddecl))
+ {
+ /* If redeclaring a builtin function, it stays built in.
+ But it gets tagged as having been declared. */
+ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
+ DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+ C_DECL_DECLARED_BUILTIN (newdecl) = 1;
+ if (new_is_prototype)
+ C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+ else
+ C_DECL_BUILTIN_PROTOTYPE (newdecl)
+ = C_DECL_BUILTIN_PROTOTYPE (olddecl);
+ }
+
+ /* Also preserve various other info from the definition. */
+ if (!new_is_definition)
+ {
+ DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
+ DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+ DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
+ DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+ DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
+
+ /* Set DECL_INLINE on the declaration if we've got a body
+ from which to instantiate. */
+ if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
+ {
+ DECL_INLINE (newdecl) = 1;
+ DECL_ABSTRACT_ORIGIN (newdecl)
+ = DECL_ABSTRACT_ORIGIN (olddecl);
+ }
+ }
+ else
+ {
+ /* If a previous declaration said inline, mark the
+ definition as inlinable. */
+ if (DECL_DECLARED_INLINE_P (newdecl)
+ && !DECL_UNINLINABLE (newdecl))
+ DECL_INLINE (newdecl) = 1;
+ }
+ }
+
+ extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
+
+ /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */
{
unsigned olddecl_uid = DECL_UID (olddecl);
tree olddecl_context = DECL_CONTEXT (olddecl);
-
+
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
break;
default:
-
+
memcpy ((char *) olddecl + sizeof (struct tree_decl_common),
(char *) newdecl + sizeof (struct tree_decl_common),
sizeof (struct tree_decl_non_common) - sizeof (struct tree_decl_common));
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl);
+
+ /* If we changed a function from DECL_EXTERNAL to !DECL_EXTERNAL,
+ and the definition is coming from the old version, cgraph needs
+ to be called again. */
+ if (extern_changed && !new_is_definition
+ && TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl))
+ cgraph_finalize_function (olddecl, false);
}
/* Handle when a new declaration NEWDECL has the same name as an old
translation and get back the corresponding typedef name. For
example, given:
- typedef struct S MY_TYPE;
+ typedef struct S MY_TYPE;
MY_TYPE object;
Later parts of the compiler might only know that `object' was of
static void
implicit_decl_warning (tree id, tree olddecl)
{
- void (*diag) (const char *, ...) ATTRIBUTE_GCC_CDIAG(1,2);
- switch (mesg_implicit_function_declaration)
+ if (warn_implicit_function_declaration)
{
- case 0: return;
- case 1: diag = warning0; break;
- case 2: diag = error; break;
- default: gcc_unreachable ();
+ if (flag_isoc99)
+ pedwarn (G_("implicit declaration of function %qE"), id);
+ else
+ warning (OPT_Wimplicit_function_declaration,
+ G_("implicit declaration of function %qE"), id);
+ if (olddecl)
+ locate_old_decl (olddecl, inform);
}
-
- diag (G_("implicit declaration of function %qE"), id);
- if (olddecl)
- locate_old_decl (olddecl, diag);
}
/* Generate an implicit declaration for identifier FUNCTIONID as a
}
/* If we are parsing old-style parameter decls, current_function_decl
- will be nonnull but current_function_scope will be null. */
+ will be nonnull but current_function_scope will be null. */
scope = current_function_scope ? current_function_scope : current_scope;
}
bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false);
if (!in_system_header && lookup_name (name))
warning (OPT_Wtraditional, "%Htraditional C lacks a separate namespace "
- "for labels, identifier %qE conflicts", &location, name);
+ "for labels, identifier %qE conflicts", &location, name);
nlist_se = XOBNEW (&parser_obstack, struct c_label_list);
nlist_se->next = label_context_stack_se->labels_def;
{
if (pending_invalid_xref != 0)
error ("%H%qE defined as wrong kind of tag",
- &pending_invalid_xref_location, pending_invalid_xref);
+ &pending_invalid_xref_location, pending_invalid_xref);
pending_invalid_xref = 0;
}
TREE_USED (decl) = 1;
- if (current_function_decl)
+ if (current_function_decl
+ /* For invalid programs like this:
+
+ void foo()
+ const char* p = __FUNCTION__;
+
+ the __FUNCTION__ is believed to appear in K&R style function
+ parameter declarator. In that case we still don't have
+ function_scope. */
+ && (!errorcount || current_function_scope))
{
DECL_CONTEXT (decl) = current_function_decl;
bind (id, decl, current_function_scope,
return decl;
}
-/* Return a definition for a builtin function named NAME and whose data type
- is TYPE. TYPE should be a function type with argument types.
- FUNCTION_CODE tells later passes how to compile calls to this function.
- See tree.h for its possible values.
-
- If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. If
- ATTRS is nonzero, use that for the function's attribute list. */
-
tree
-builtin_function (const char *name, tree type, int function_code,
- enum built_in_class cl, const char *library_name,
- tree attrs)
+c_builtin_function (tree decl)
{
- tree id = get_identifier (name);
- tree decl = build_decl (FUNCTION_DECL, id, type);
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = 1;
+ tree type = TREE_TYPE (decl);
+ tree id = DECL_NAME (decl);
+
+ const char *name = IDENTIFIER_POINTER (id);
DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
- DECL_BUILT_IN_CLASS (decl) = cl;
- DECL_FUNCTION_CODE (decl) = function_code;
C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
- if (library_name)
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
/* Should never be called on a symbol with a preexisting meaning. */
gcc_assert (!I_SYMBOL_BINDING (id));
visible_builtins = decl;
}
- /* Possibly apply some default attributes to this built-in function. */
- if (attrs)
- decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
- else
- decl_attributes (&decl, NULL_TREE, 0);
-
return decl;
}
\f
return quals;
}
-/* Construct an array declarator. EXPR is the expression inside [], or
- NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied
- to the pointer to which a parameter array is converted). STATIC_P is
- true if "static" is inside the [], false otherwise. VLA_UNSPEC_P
- is true if the array is [*], a VLA of unspecified length which is
- nevertheless a complete type (not currently implemented by GCC),
- false otherwise. The field for the contained declarator is left to be
- filled in by set_array_declarator_inner. */
+/* Construct an array declarator. EXPR is the expression inside [],
+ or NULL_TREE. QUALS are the type qualifiers inside the [] (to be
+ applied to the pointer to which a parameter array is converted).
+ STATIC_P is true if "static" is inside the [], false otherwise.
+ VLA_UNSPEC_P is true if the array is [*], a VLA of unspecified
+ length which is nevertheless a complete type, false otherwise. The
+ field for the contained declarator is left to be filled in by
+ set_array_declarator_inner. */
struct c_declarator *
build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
pedwarn ("ISO C90 does not support %<[*]%> array declarators");
}
if (vla_unspec_p)
- warning (0, "GCC does not yet properly implement %<[*]%> array declarators");
+ {
+ if (!current_scope->parm_flag)
+ {
+ /* C99 6.7.5.2p4 */
+ error ("%<[*]%> not allowed in other than function prototype scope");
+ declarator->u.array.vla_unspec_p = false;
+ return NULL;
+ }
+ current_scope->had_vla_unspec = true;
+ }
return declarator;
}
type_name->specs->attrs = NULL_TREE;
type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
- false, NULL);
+ false, NULL, DEPRECATED_NORMAL);
/* Apply attributes. */
decl_attributes (&type, attrs, 0);
{
tree decl;
tree tem;
+ enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
/* An object declared as __attribute__((deprecated)) suppresses
warnings of uses of other deprecated items. */
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
- NORMAL, initialized, NULL);
+ NORMAL, initialized, NULL,
+ deprecated_state);
if (!decl)
return 0;
- deprecated_state = DEPRECATED_NORMAL;
-
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& MAIN_NAME_P (DECL_NAME (decl)))
warning (OPT_Wmain, "%q+D is usually a function", decl);
/* Set attributes here so if duplicate decl, will have proper attributes. */
decl_attributes (&decl, attributes, 0);
+ /* Handle gnu_inline attribute. */
+ if (declspecs->inline_p
+ && !flag_gnu89_inline
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl)))
+ {
+ if (declspecs->storage_class == csc_auto && current_scope != file_scope)
+ ;
+ else if (declspecs->storage_class != csc_static)
+ DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl);
+ }
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (decl)))
{
warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
decl);
+ /* C99 6.7.4p3: An inline definition of a function with external
+ linkage shall not contain a definition of a modifiable object
+ with static storage duration... */
+ if (TREE_CODE (decl) == VAR_DECL
+ && current_scope != file_scope
+ && TREE_STATIC (decl)
+ && DECL_DECLARED_INLINE_P (current_function_decl)
+ && DECL_EXTERNAL (current_function_decl))
+ pedwarn ("%q+D is static but declared in inline function %qD "
+ "which is not static", decl, current_function_decl);
+
/* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
return tem;
}
+/* Initialize EH if not initialized yet and exceptions are enabled. */
+
+void
+c_maybe_initialize_eh (void)
+{
+ if (!flag_exceptions || c_eh_initialized_p)
+ return;
+
+ c_eh_initialized_p = true;
+ eh_personality_libfunc
+ = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+ ? "__gcc_personality_sj0"
+ : "__gcc_personality_v0");
+ default_init_unwind_resume_libfunc ();
+ using_eh_for_cleanups ();
+}
+
/* Finish processing of a declaration;
install its initial value.
If the length of an array type is not known before,
void
finish_decl (tree decl, tree init, tree asmspec_tree)
{
- tree type = TREE_TYPE (decl);
+ tree type;
int was_incomplete = (DECL_SIZE (decl) == 0);
const char *asmspec = 0;
|| TREE_CODE (decl) == FIELD_DECL))
objc_check_decl (decl);
+ type = TREE_TYPE (decl);
+
/* Deduce size of array from initialization, if not already known. */
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == 0
/* If #pragma weak was used, mark the decl weak now. */
maybe_apply_pragma_weak (decl);
- /* If this is a variable definition, determine its ELF visibility. */
- if (TREE_CODE (decl) == VAR_DECL
- && TREE_STATIC (decl)
- && !DECL_EXTERNAL (decl))
- c_determine_visibility (decl);
-
/* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union.
If not, it will get done when the type is completed. */
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
+ /* Determine the ELF visibility. */
+ if (TREE_PUBLIC (decl))
+ c_determine_visibility (decl);
+
/* This is a no-op in c-lang.c or something real in objc-act.c. */
if (c_dialect_objc ())
objc_check_decl (decl);
- if (asmspec)
+ if (asmspec)
{
/* If this is not a static variable, issue a warning.
It doesn't make any sense to give an ASMSPEC for an
else
set_user_assembler_name (decl, asmspec);
}
-
+
if (DECL_FILE_SCOPE_P (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE
add_stmt (build_stmt (DECL_EXPR, decl));
}
}
-
+
if (!DECL_FILE_SCOPE_P (decl))
{
}
/* If this was marked 'used', be sure it will be output. */
- if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+ if (!flag_unit_at_a_time && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
mark_decl_referenced (decl);
if (TREE_CODE (decl) == TYPE_DECL)
TREE_USED (cleanup_decl) = 1;
/* Initialize EH, if we've been told to do so. */
- if (flag_exceptions && !c_eh_initialized_p)
- {
- c_eh_initialized_p = true;
- eh_personality_libfunc
- = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- ? "__gcc_personality_sj0"
- : "__gcc_personality_v0");
- default_init_unwind_resume_libfunc ();
- using_eh_for_cleanups ();
- }
+ c_maybe_initialize_eh ();
push_cleanup (decl, cleanup, false);
}
grokparm (const struct c_parm *parm)
{
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
- NULL);
+ NULL, DEPRECATED_NORMAL);
decl_attributes (&decl, parm->attrs, 0);
{
tree decl;
- decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
+ decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
+ DEPRECATED_NORMAL);
decl_attributes (&decl, parm->attrs, 0);
decl = pushdecl (decl);
{
struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
if (!lt
- || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+ || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
|| w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
warning (0, "%qs is narrower than values of its type", name);
}
}
-/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
-static tree
-c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
+\f
+
+/* Print warning about variable length array if necessary. */
+
+static void
+warn_variable_length_array (const char *name, tree size)
{
- /* Extended integer types of the same width as a standard type have
- lesser rank, so those of the same width as int promote to int or
- unsigned int and are valid for printf formats expecting int or
- unsigned int. To avoid such special cases, avoid creating
- extended integer types for bit-fields if a standard integer type
- is available. */
- if (width == TYPE_PRECISION (integer_type_node))
- return unsignedp ? unsigned_type_node : integer_type_node;
- if (width == TYPE_PRECISION (signed_char_type_node))
- return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (width == TYPE_PRECISION (short_integer_type_node))
- return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (width == TYPE_PRECISION (long_integer_type_node))
- return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (width == TYPE_PRECISION (long_long_integer_type_node))
- return (unsignedp ? long_long_unsigned_type_node
- : long_long_integer_type_node);
- return build_nonstandard_integer_type (width, unsignedp);
+ int ped = !flag_isoc99 && pedantic && warn_vla != 0;
+ int const_size = TREE_CONSTANT (size);
+
+ if (ped)
+ {
+ if (const_size)
+ {
+ if (name)
+ pedwarn ("ISO C90 forbids array %qs whose size "
+ "can%'t be evaluated",
+ name);
+ else
+ pedwarn ("ISO C90 forbids array whose size "
+ "can%'t be evaluated");
+ }
+ else
+ {
+ if (name)
+ pedwarn ("ISO C90 forbids variable length array %qs",
+ name);
+ else
+ pedwarn ("ISO C90 forbids variable length array");
+ }
+ }
+ else if (warn_vla > 0)
+ {
+ if (const_size)
+ {
+ if (name)
+ warning (OPT_Wvla,
+ "the size of array %qs can"
+ "%'t be evaluated", name);
+ else
+ warning (OPT_Wvla,
+ "the size of array can %'t be evaluated");
+ }
+ else
+ {
+ if (name)
+ warning (OPT_Wvla,
+ "variable length array %qs is used",
+ name);
+ else
+ warning (OPT_Wvla,
+ "variable length array is used");
+ }
+ }
}
-\f
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
INITIALIZED is true if the decl has an initializer.
WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
representing the width of the bit-field.
+ DEPRECATED_STATE is a deprecated_states value indicating whether
+ deprecation warnings should be suppressed.
In the TYPENAME case, DECLARATOR is really an absolute declarator.
It may also be so in the PARM case, for a prototype where the
static tree
grokdeclarator (const struct c_declarator *declarator,
struct c_declspecs *declspecs,
- enum decl_context decl_context, bool initialized, tree *width)
+ enum decl_context decl_context, bool initialized, tree *width,
+ enum deprecated_states deprecated_state)
{
tree type = declspecs->type;
bool threadp = declspecs->thread_p;
int type_quals = TYPE_UNQUALIFIED;
const char *name, *orig_name;
tree typedef_type = 0;
- int funcdef_flag = 0;
+ bool funcdef_flag = false;
bool funcdef_syntax = false;
int size_varies = 0;
tree decl_attr = declspecs->decl_attr;
int array_ptr_quals = TYPE_UNQUALIFIED;
tree array_ptr_attrs = NULL_TREE;
int array_parm_static = 0;
+ bool array_parm_vla_unspec_p = false;
tree returned_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
if (decl_context == FUNCDEF)
- funcdef_flag = 1, decl_context = NORMAL;
+ funcdef_flag = true, decl_context = NORMAL;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
warn_deprecated_use (declspecs->type);
+ if ((decl_context == NORMAL || decl_context == FIELD)
+ && current_scope == file_scope
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ error ("variably modified %qs at file scope", name);
+ type = integer_type_node;
+ }
+
typedef_type = type;
size_varies = C_TYPE_VARIABLE_SIZE (type);
array_ptr_quals = declarator->u.array.quals;
array_ptr_attrs = declarator->u.array.attrs;
array_parm_static = declarator->u.array.static_p;
-
+ array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p;
+
declarator = declarator->declarator;
/* Check for some types that there cannot be arrays of. */
-
+
if (VOID_TYPE_P (type))
{
error ("declaration of %qs as array of voids", name);
type = error_mark_node;
}
-
+
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("declaration of %qs as array of functions", name);
type = error_mark_node;
}
-
+
if (pedantic && !in_system_header && flexible_array_type_p (type))
pedwarn ("invalid use of structure with flexible array member");
-
+
if (size == error_mark_node)
type = error_mark_node;
-
+
if (type == error_mark_node)
continue;
/* Strip NON_LVALUE_EXPRs since we aren't using as an
lvalue. */
STRIP_TYPE_NOPS (size);
-
+
if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
{
error ("size of array %qs has non-integer type", name);
size = integer_one_node;
}
-
+
if (pedantic && integer_zerop (size))
pedwarn ("ISO C forbids zero-size array %qs", name);
-
+
if (TREE_CODE (size) == INTEGER_CST)
{
constant_expression_warning (size);
size = integer_one_node;
}
}
+ else if ((decl_context == NORMAL || decl_context == FIELD)
+ && current_scope == file_scope)
+ {
+ error ("variably modified %qs at file scope", name);
+ size = integer_one_node;
+ }
else
{
/* Make sure the array size remains visibly
nonconstant even if it is (eg) a const variable
with known value. */
size_varies = 1;
-
- if (!flag_isoc99 && pedantic)
- {
- if (TREE_CONSTANT (size))
- pedwarn ("ISO C90 forbids array %qs whose size "
- "can%'t be evaluated",
- name);
- else
- pedwarn ("ISO C90 forbids variable-size array %qs",
- name);
- }
+ warn_variable_length_array (orig_name, size);
}
if (integer_zerop (size))
{
- /* A zero-length array cannot be represented with
- an unsigned index type, which is what we'll
- get with build_index_type. Create an
- open-ended range instead. */
+ /* A zero-length array cannot be represented with
+ an unsigned index type, which is what we'll
+ get with build_index_type. Create an
+ open-ended range instead. */
itype = build_range_type (sizetype, size, NULL_TREE);
}
else
convert (index_type,
size_one_node));
- /* If that overflowed, the array is too big. ???
+ /* If that overflowed, the array is too big. ???
While a size of INT_MAX+1 technically shouldn't
cause an overflow (because we subtract 1), the
overflow is recorded during the conversion to
type = error_mark_node;
continue;
}
-
+
itype = build_index_type (itype);
}
}
identical to GCC's zero-length array extension. */
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
}
+ else if (decl_context == PARM)
+ {
+ if (array_parm_vla_unspec_p)
+ {
+ if (! orig_name)
+ {
+ /* C99 6.7.5.2p4 */
+ error ("%<[*]%> not allowed in other than a declaration");
+ }
+
+ itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ size_varies = 1;
+ }
+ }
+ else if (decl_context == TYPENAME)
+ {
+ if (array_parm_vla_unspec_p)
+ {
+ /* The error is printed elsewhere. We use this to
+ avoid messing up with incomplete array types of
+ the same type, that would otherwise be modified
+ below. */
+ itype = build_range_type (sizetype, size_zero_node,
+ NULL_TREE);
+ }
+ }
/* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
{
error ("array type has incomplete element type");
- type = error_mark_node;
+ type = error_mark_node;
}
else
+ /* When itype is NULL, a shared incomplete array type is
+ returned for all array of a given type. Elsewhere we
+ make sure we don't complete that type before copying
+ it, but here we want to make sure we don't ever
+ modify the shared type, so we gcc_assert (itype)
+ below. */
type = build_array_type (type, itype);
if (type != error_mark_node)
{
if (size_varies)
- C_TYPE_VARIABLE_SIZE (type) = 1;
+ {
+ /* It is ok to modify type here even if itype is
+ NULL: if size_varies, we're in a
+ multi-dimensional array and the inner type has
+ variable size, so the enclosing shared array type
+ must too. */
+ if (size && TREE_CODE (size) == INTEGER_CST)
+ type
+ = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ C_TYPE_VARIABLE_SIZE (type) = 1;
+ }
/* The GCC extension for zero-length arrays differs from
ISO flexible array members in that sizeof yields
zero. */
if (size && integer_zerop (size))
{
+ gcc_assert (itype);
+ TYPE_SIZE (type) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (type) = size_zero_node;
+ }
+ if (array_parm_vla_unspec_p)
+ {
+ gcc_assert (itype);
+ /* The type is complete. C99 6.7.5.2p4 */
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
type for the function to return. */
if (type == error_mark_node)
continue;
-
+
size_varies = 0;
/* Warn about some types functions can't return. */
inner layer of declarator. */
arg_info = declarator->u.arg_info;
arg_types = grokparms (arg_info, really_funcdef);
+ if (really_funcdef)
+ put_pending_sizes (arg_info->pending_sizes);
/* Type qualifiers before the return type of the function
qualify the return type, not the function type. */
if (type_quals)
{
- /* Type qualifiers on a function return type are
+ /* Type qualifiers on a function return type are
normally permitted by the standard but have no
effect, so give a warning at -Wreturn-type.
Qualifiers on a void return type are banned on
else
warning (OPT_Wreturn_type,
"type qualifiers ignored on function return type");
-
+
type = c_build_qualified_type (type, type_quals);
}
type_quals = TYPE_UNQUALIFIED;
-
+
type = build_function_type (type, arg_types);
declarator = declarator->declarator;
-
+
/* Set the TYPE_CONTEXTs for each tagged type which is local to
the formal parameter list of this FUNCTION_TYPE to point to
the FUNCTION_TYPE node itself. */
{
tree link;
-
+
for (link = arg_info->tags;
link;
link = TREE_CHAIN (link))
type = c_build_qualified_type (type, type_quals);
size_varies = 0;
+ /* When the pointed-to type involves components of variable size,
+ care must be taken to ensure that the size evaluation code is
+ emitted early enough to dominate all the possible later uses
+ and late enough for the variables on which it depends to have
+ been assigned.
+
+ This is expected to happen automatically when the pointed-to
+ type has a name/declaration of it's own, but special attention
+ is required if the type is anonymous.
+
+ We handle the NORMAL and FIELD contexts here by attaching an
+ artificial TYPE_DECL to such pointed-to type. This forces the
+ sizes evaluation at a safe point and ensures it is not deferred
+ until e.g. within a deeper conditional context.
+
+ We expect nothing to be needed here for PARM or TYPENAME.
+ Pushing a TYPE_DECL at this point for TYPENAME would actually
+ be incorrect, as we might be in the middle of an expression
+ with side effects on the pointed-to type size "arguments" prior
+ to the pointer declaration point and the fake TYPE_DECL in the
+ enclosing context would force the size evaluation prior to the
+ side effects. */
+
+ if (!TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ tree decl = build_decl (TYPE_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (decl) = 1;
+ pushdecl (decl);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
+ TYPE_NAME (type) = decl;
+ }
+
type = build_pointer_type (type);
-
+
/* Process type qualifiers (such as const or volatile)
that were given inside the `*'. */
type_quals = declarator->u.pointer_quals;
return decl;
}
- /* Detect the case of an array type of unspecified size
- which came, as such, direct from a typedef name.
- We must copy the type, so that each identifier gets
- a distinct type, so that each identifier's size can be
- controlled separately by its own initializer. */
-
- if (type != 0 && typedef_type != 0
- && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
- {
- type = build_array_type (TREE_TYPE (type), 0);
- if (size_varies)
- C_TYPE_VARIABLE_SIZE (type) = 1;
- }
-
/* If this is a type name (such as, in a cast or sizeof),
compute the type and return it now. */
return type;
}
+ if (pedantic && decl_context == FIELD
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ /* C99 6.7.2.1p8 */
+ pedwarn ("a member of a structure or union cannot have a variably modified type");
+ }
+
/* Aside from typedefs and type names (handle above),
`void' at top level (not within pointer)
is allowed only in public variables.
type = build_pointer_type (type);
}
else if (TREE_CODE (type) != ERROR_MARK
- && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
+ && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
{
error ("field %qs has incomplete type", name);
type = error_mark_node;
type = c_build_qualified_type (type, type_quals);
decl = build_decl (FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
+ if (bitfield && !declarator->u.id)
+ TREE_NO_WARNING (decl) = 1;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
}
else if (storage_class == csc_static)
{
- error ("invalid storage class for function %qs", name);
- if (funcdef_flag)
+ error ("invalid storage class for function %qs", name);
+ if (funcdef_flag)
storage_class = declspecs->storage_class = csc_none;
else
return 0;
GCC to signify a forward declaration of a nested function. */
if (storage_class == csc_auto && current_scope != file_scope)
DECL_EXTERNAL (decl) = 0;
+ /* In C99, a function which is declared 'inline' with 'extern'
+ is not an external reference (which is confusing). It
+ means that the later definition of the function must be output
+ in this file, C99 6.7.4p6. In GNU C89, a function declared
+ 'extern inline' is an external reference. */
+ else if (declspecs->inline_p && storage_class != csc_static)
+ DECL_EXTERNAL (decl) = ((storage_class == csc_extern)
+ == flag_gnu89_inline);
else
- DECL_EXTERNAL (decl) = 1;
+ DECL_EXTERNAL (decl) = !initialized;
/* Record absence of global scope for `static' or `auto'. */
TREE_PUBLIC (decl)
the abstract origin pointing between the declarations,
which will confuse dwarf2out. */
if (initialized)
- {
- DECL_INLINE (decl) = 1;
- if (storage_class == csc_extern)
- current_extern_inline = 1;
- }
+ DECL_INLINE (decl) = 1;
}
/* If -finline-functions, assume it can be inlined. This does
two things: let the function be deferred until it is actually
}
if (threadp)
- {
- if (targetm.have_tls)
- DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
- else
- /* A mere warning is sure to result in improper semantics
- at runtime. Don't bother to allow this to compile. */
- error ("thread-local storage not supported for this target");
- }
+ DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
+ }
+
+ if (storage_class == csc_extern
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ /* C99 6.7.5.2p2 */
+ error ("object with variably modified type must have no linkage");
}
/* Record `register' declaration for warnings on &
}
\f
/* Decode the parameter-list info for a function type or function definition.
- The argument is the value returned by `get_parm_info' (or made in parse.y
+ The argument is the value returned by `get_parm_info' (or made in c-parse.c
if there is an identifier list instead of a parameter decl list).
These two functions are separate because when a function returns
or receives functions then each is called multiple times but the order
{
tree arg_types = arg_info->types;
+ if (funcdef_flag && arg_info->had_vla_unspec)
+ {
+ /* A function definition isn't function prototype scope C99 6.2.1p4. */
+ /* C99 6.7.5.2p4 */
+ error ("%<[*]%> not allowed in other than function prototype scope");
+ }
+
if (arg_types == 0 && !funcdef_flag && !in_system_header)
warning (OPT_Wstrict_prototypes,
"function declaration isn%'t a prototype");
arg_info->tags = 0;
arg_info->types = 0;
arg_info->others = 0;
+ arg_info->pending_sizes = 0;
+ arg_info->had_vla_unspec = current_scope->had_vla_unspec;
/* The bindings in this scope must not get put into a block.
We will take care of deleting the binding nodes. */
(by 'const' or 'volatile'), or has a storage class specifier
('register'), then the behavior is undefined; issue an error.
Typedefs for 'void' are OK (see DR#157). */
- if (b->prev == 0 /* one binding */
+ if (b->prev == 0 /* one binding */
&& TREE_CODE (b->decl) == PARM_DECL /* which is a parameter */
&& !DECL_NAME (b->decl) /* anonymous */
&& VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
arg_info->tags = tags;
arg_info->types = types;
arg_info->others = others;
+ arg_info->pending_sizes = get_pending_sizes ();
return arg_info;
}
\f
if (ref && TREE_CODE (ref) == code)
{
if (TYPE_SIZE (ref))
- {
+ {
if (code == UNION_TYPE)
error ("redefinition of %<union %E%>", name);
- else
+ else
error ("redefinition of %<struct %E%>", name);
}
else if (C_TYPE_BEING_DEFINED (ref))
{
if (code == UNION_TYPE)
error ("nested redefinition of %<union %E%>", name);
- else
+ else
error ("nested redefinition of %<struct %E%>", name);
+ /* Don't create structures that contain themselves. */
+ ref = NULL_TREE;
}
}
- 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. */
+
+ if (ref == NULL_TREE || TREE_CODE (ref) != code)
+ {
ref = make_node (code);
pushtag (name, ref);
}
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
- width ? &width : NULL);
+ width ? &width : NULL, DEPRECATED_NORMAL);
finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
saw_named_field = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
+ if (TREE_TYPE (x) == error_mark_node)
+ continue;
+
DECL_CONTEXT (x) = t;
if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
- if (len > 15 || DECL_NAME (x) == NULL)
- break;
- len += 1;
+ if (len > 15 || DECL_NAME (x) == NULL)
+ break;
+ len += 1;
}
if (len > 15)
{
- tree *field_array;
- struct lang_type *space;
- struct sorted_fields_type *space2;
+ tree *field_array;
+ struct lang_type *space;
+ struct sorted_fields_type *space2;
- len += list_length (x);
+ len += list_length (x);
- /* Use the same allocation policy here that make_node uses, to
- ensure that this lives as long as the rest of the struct decl.
- All decls in an inline function need to be saved. */
+ /* Use the same allocation policy here that make_node uses, to
+ ensure that this lives as long as the rest of the struct decl.
+ All decls in an inline function need to be saved. */
- space = GGC_CNEW (struct lang_type);
- space2 = GGC_NEWVAR (struct sorted_fields_type,
+ space = GGC_CNEW (struct lang_type);
+ space2 = GGC_NEWVAR (struct sorted_fields_type,
sizeof (struct sorted_fields_type) + len * sizeof (tree));
- len = 0;
+ len = 0;
space->s = space2;
field_array = &space2->elts[0];
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- {
- field_array[len++] = x;
-
- /* If there is anonymous struct or union, break out of the loop. */
- if (DECL_NAME (x) == NULL)
- break;
- }
- /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */
- if (x == NULL)
- {
- TYPE_LANG_SPECIFIC (t) = space;
- TYPE_LANG_SPECIFIC (t)->s->len = len;
- field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
- qsort (field_array, len, sizeof (tree), field_decl_cmp);
- }
+ for (x = fieldlist; x; x = TREE_CHAIN (x))
+ {
+ field_array[len++] = x;
+
+ /* If there is anonymous struct or union, break out of the loop. */
+ if (DECL_NAME (x) == NULL)
+ break;
+ }
+ /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */
+ if (x == NULL)
+ {
+ TYPE_LANG_SPECIFIC (t) = space;
+ TYPE_LANG_SPECIFIC (t)->s->len = len;
+ field_array = TYPE_LANG_SPECIFIC (t)->s->elts;
+ qsort (field_array, len, sizeof (tree), field_decl_cmp);
+ }
}
}
{
TYPE_FIELDS (x) = TYPE_FIELDS (t);
TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
- TYPE_ALIGN (x) = TYPE_ALIGN (t);
- TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
C_TYPE_FIELDS_READONLY (x) = C_TYPE_FIELDS_READONLY (t);
C_TYPE_FIELDS_VOLATILE (x) = C_TYPE_FIELDS_VOLATILE (t);
C_TYPE_VARIABLE_SIZE (x) = C_TYPE_VARIABLE_SIZE (t);
/* If we're inside a function proper, i.e. not file-scope and not still
parsing parameters, then arrange for the size of a variable sized type
to be bound now. */
- if (cur_stmt_list && variably_modified_type_p (t, NULL))
+ if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE))
add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t)));
return t;
may be used to declare the individual values as they are read. */
tree
-start_enum (tree name)
+start_enum (struct c_enum_contents *the_enum, tree name)
{
tree enumtype = 0;
TYPE_VALUES (enumtype) = 0;
}
- enum_next_value = integer_zero_node;
- enum_overflow = 0;
+ the_enum->enum_next_value = integer_zero_node;
+ the_enum->enum_overflow = 0;
if (flag_short_enums)
TYPE_PACKED (enumtype) = 1;
Assignment of sequential values by default is handled here. */
tree
-build_enumerator (tree name, tree value)
+build_enumerator (struct c_enum_contents *the_enum, tree name, tree value)
{
tree decl, type;
in the default. */
if (value == 0)
{
- value = enum_next_value;
- if (enum_overflow)
+ value = the_enum->enum_next_value;
+ if (the_enum->enum_overflow)
error ("overflow in enumeration values");
}
}
/* Set basis for default for next value. */
- enum_next_value = build_binary_op (PLUS_EXPR, value, integer_one_node, 0);
- enum_overflow = tree_int_cst_lt (enum_next_value, value);
+ the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value,
+ integer_one_node, 0);
+ the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
/* Now create a declaration for the enum value name. */
current_function_returns_null = 0;
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
- current_extern_inline = 0;
c_switch_stack = NULL;
nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se);
error message in c_finish_bc_stmt. */
c_break_label = c_cont_label = size_zero_node;
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL);
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
+ DEPRECATED_NORMAL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
decl1);
+ /* Handle gnu_inline attribute. */
+ if (declspecs->inline_p
+ && !flag_gnu89_inline
+ && TREE_CODE (decl1) == FUNCTION_DECL
+ && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)))
+ {
+ if (declspecs->storage_class != csc_static)
+ DECL_EXTERNAL (decl1) = !DECL_EXTERNAL (decl1);
+ }
+
announce_function (decl1);
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
/* If this definition isn't a prototype and we had a prototype declaration
before, copy the arg type info from that prototype. */
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
+ if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL)
+ old_decl = 0;
current_function_prototype_locus = UNKNOWN_LOCATION;
current_function_prototype_built_in = false;
current_function_prototype_arg_types = NULL_TREE;
warning (OPT_Wmissing_declarations,
"%q+D was used with no declaration before its definition", decl1);
- /* This is a definition, not a reference.
- So normally clear DECL_EXTERNAL.
- However, `extern inline' acts like a declaration
- except for defining how to inline. So set DECL_EXTERNAL in that case. */
- DECL_EXTERNAL (decl1) = current_extern_inline;
-
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1)))
{
- tree args;
- int argct = 0;
-
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
pedwarn ("return type of %q+D is not %<int%>", decl1);
- for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
- args = TREE_CHAIN (args))
- {
- tree type = args ? TREE_VALUE (args) : 0;
-
- if (type == void_type_node)
- break;
-
- ++argct;
- switch (argct)
- {
- case 1:
- if (TYPE_MAIN_VARIANT (type) != integer_type_node)
- pedwarn ("first argument of %q+D should be %<int%>", decl1);
- break;
-
- case 2:
- if (TREE_CODE (type) != POINTER_TYPE
- || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
- || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
- != char_type_node))
- pedwarn ("second argument of %q+D should be %<char **%>",
- decl1);
- break;
-
- case 3:
- if (TREE_CODE (type) != POINTER_TYPE
- || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
- || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
- != char_type_node))
- pedwarn ("third argument of %q+D should probably be "
- "%<char **%>", decl1);
- break;
- }
- }
-
- /* It is intentional that this message does not mention the third
- argument because it's only mentioned in an appendix of the
- standard. */
- if (argct > 0 && (argct < 2 || argct > 3))
- pedwarn ("%q+D takes only zero or two arguments", decl1);
+ check_main_parameter_types(decl1);
if (!TREE_PUBLIC (decl1))
pedwarn ("%q+D is normally a non-static function", decl1);
declare_parm_level ();
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
- /* Promote the value to int before returning it. */
- if (c_promoting_integer_type_p (restype))
- {
- /* It retains unsignedness if not really getting wider. */
- if (TYPE_UNSIGNED (restype)
- && (TYPE_PRECISION (restype)
- == TYPE_PRECISION (integer_type_node)))
- restype = unsigned_type_node;
- else
- restype = integer_type_node;
- }
-
resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
if (flag_isoc99)
pedwarn ("type of %q+D defaults to %<int%>", decl);
- else if (extra_warnings)
- warning (OPT_Wextra, "type of %q+D defaults to %<int%>", decl);
+ else
+ warning (OPT_Wmissing_parameter_type, "type of %q+D defaults to %<int%>", decl);
}
TREE_PURPOSE (parm) = decl;
tree type;
for (parm = DECL_ARGUMENTS (fndecl),
type = current_function_prototype_arg_types;
- parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
- != void_type_node));
+ parm || (type && TREE_VALUE (type) != error_mark_node
+ && (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node));
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
{
if (parm == 0 || type == 0
{
tree args = DECL_ARGUMENTS (fndecl);
for (; args; args = TREE_CHAIN (args))
- {
- tree type = TREE_TYPE (args);
- if (INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (args) = integer_type_node;
- }
+ {
+ tree type = TREE_TYPE (args);
+ if (INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ DECL_ARG_TYPE (args) = integer_type_node;
+ }
}
if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
TREE_NO_WARNING (fndecl) = 1;
}
- /* With just -Wextra, complain only if function returns both with
- and without a value. */
- if (extra_warnings
- && current_function_returns_value
- && current_function_returns_null)
- warning (OPT_Wextra, "this function may return with or without a value");
-
/* Store the end of the function, so that we get good line number
info for the epilogue. */
cfun->function_end_locus = input_location;
- /* If we don't have ctors/dtors sections, and this is a static
- constructor or destructor, it must be recorded now. */
- if (DECL_STATIC_CONSTRUCTOR (fndecl)
- && !targetm.have_ctors_dtors)
- static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
- if (DECL_STATIC_DESTRUCTOR (fndecl)
- && !targetm.have_ctors_dtors)
- static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
-
/* Finalize the ELF visibility for the function. */
c_determine_visibility (fndecl);
&& !undef_nested_function)
{
if (!decl_function_context (fndecl))
- {
- c_genericize (fndecl);
- c_gimple_diagnostics_recursively (fndecl);
+ {
+ c_genericize (fndecl);
+ c_gimple_diagnostics_recursively (fndecl);
/* ??? Objc emits functions after finalizing the compilation unit.
This should be cleaned up later and this conditional removed. */
}
cgraph_finalize_function (fndecl, false);
- }
+ }
else
- {
- /* Register this function with cgraph just far enough to get it
- added to our parent's nested function list. Handy, since the
- C front end doesn't have such a list. */
- (void) cgraph_node (fndecl);
- }
+ {
+ /* Register this function with cgraph just far enough to get it
+ added to our parent's nested function list. Handy, since the
+ C front end doesn't have such a list. */
+ (void) cgraph_node (fndecl);
+ }
}
if (!decl_function_context (fndecl))
cfun = NULL;
current_function_decl = NULL;
}
-
-/* Generate the RTL for the body of FNDECL. */
-
-void
-c_expand_body (tree fndecl)
-{
-
- if (!DECL_INITIAL (fndecl)
- || DECL_INITIAL (fndecl) == error_mark_node)
- return;
-
- tree_rest_of_compilation (fndecl);
-
- if (DECL_STATIC_CONSTRUCTOR (fndecl)
- && targetm.have_ctors_dtors)
- targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
- if (DECL_STATIC_DESTRUCTOR (fndecl)
- && targetm.have_ctors_dtors)
- targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
-}
\f
/* Check the declarations given in a for-loop for satisfying the C99
constraints. If exactly one such decl is found, return it. */
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type;
- p->extern_inline = current_extern_inline;
}
/* Restore the variables used during compilation of a C function. */
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type;
- current_extern_inline = p->extern_inline;
f->language = NULL;
}
gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
&& C_IS_RESERVED_WORD (scspec));
i = C_RID_CODE (scspec);
- if (extra_warnings && specs->non_sc_seen_p)
- warning (OPT_Wextra, "%qE is not at beginning of declaration", scspec);
+ if (specs->non_sc_seen_p)
+ warning (OPT_Wold_style_declaration,
+ "%qE is not at beginning of declaration", scspec);
switch (i)
{
case RID_INLINE:
return specs;
}
-/* Synthesize a function which calls all the global ctors or global
- dtors in this file. This is only used for targets which do not
- support .ctors/.dtors sections. FIXME: Migrate into cgraph. */
-static void
-build_cdtor (int method_type, tree cdtors)
-{
- tree body = 0;
-
- if (!cdtors)
- return;
-
- for (; cdtors; cdtors = TREE_CHAIN (cdtors))
- append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0),
- &body);
-
- cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
-}
-
/* A subroutine of c_write_global_declarations. Perform final processing
on one file scope's declarations (or the external scope's declarations),
GLOBALS. */
int flags;
FILE * stream = dump_begin (TDI_tu, &flags);
if (stream && tmp)
- {
- dump_node (tmp, flags & ~TDF_SLIM, stream);
- dump_end (TDI_tu, stream);
- }
+ {
+ dump_node (tmp, flags & ~TDF_SLIM, stream);
+ dump_end (TDI_tu, stream);
+ }
}
/* Process all file scopes in this compilation, and the external_scope,
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block));
- /* Generate functions to call static constructors and destructors
- for targets that do not support .ctors/.dtors sections. These
- functions have magic names which are detected by collect2. */
- build_cdtor ('I', static_ctors); static_ctors = 0;
- build_cdtor ('D', static_dtors); static_dtors = 0;
-
/* We're done parsing; proceed to optimize and emit assembly.
FIXME: shouldn't be the front end's responsibility to call this. */
cgraph_optimize ();