/* 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.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Process declarations and symbol lookup for C front end.
Also constructs types; the standard scalar types at initialization,
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)")))
struct c_scope *s_ = (scope); \
tree d_ = (decl); \
if (s_->list##_last) \
- TREE_CHAIN (s_->list##_last) = d_; \
+ BLOCK_CHAIN (s_->list##_last) = d_; \
else \
s_->list = d_; \
s_->list##_last = d_; \
struct c_scope *t_ = (tscope); \
struct c_scope *f_ = (fscope); \
if (t_->to##_last) \
- TREE_CHAIN (t_->to##_last) = f_->from; \
+ BLOCK_CHAIN (t_->to##_last) = f_->from; \
else \
t_->to = f_->from; \
t_->to##_last = f_->from##_last; \
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 *, 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)
TREE_USED (block) = 1;
/* In each subblock, record that this is its superior. */
- for (p = scope->blocks; p; p = TREE_CHAIN (p))
+ for (p = scope->blocks; p; p = BLOCK_CHAIN (p))
BLOCK_SUPERCONTEXT (p) = block;
BLOCK_VARS (block) = 0;
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;
&& 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:
/* 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)
{
??? 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
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
DECL_MODE (newdecl) = DECL_MODE (olddecl);
- if (TREE_CODE (olddecl) != FUNCTION_DECL)
- if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
- {
- DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
- DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
- }
+ if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
+ {
+ DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+ DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
+ }
}
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))
}
}
+ /* 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_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+
+ DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ = DECL_DISREGARD_INLINE_LIMITS (olddecl)
+ = (DECL_DISREGARD_INLINE_LIMITS (newdecl)
+ || DECL_DISREGARD_INLINE_LIMITS (olddecl));
}
if (DECL_BUILT_IN (olddecl))
}
}
+ 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. */
{
|| (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
if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
{
- /* Avoid `unused variable' and other warnings warnings for OLDDECL. */
+ /* Avoid `unused variable' and other warnings for OLDDECL. */
TREE_NO_WARNING (olddecl) = 1;
return false;
}
Obviously, we don't want to generate a duplicate ..._TYPE node if
the TYPE_DECL node that we are now processing really represents a
- standard built-in type.
-
- Since all standard types are effectively declared at line zero
- in the source file, we can easily check to see if we are working
- on a standard type by checking the current value of lineno. */
+ standard built-in type. */
static void
clone_underlying_type (tree x)
struct c_binding *b;
bool nested = false;
- /* Functions need the lang_decl data. */
- if (TREE_CODE (x) == FUNCTION_DECL && !DECL_LANG_SPECIFIC (x))
- DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
-
/* Must set DECL_CONTEXT for everything not at file scope or
DECL_FILE_SCOPE_P won't work. Local externs don't count
unless they have initializers (which generate code). */
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
DECL_ARTIFICIAL (decl) = 1;
init = build_string (length + 1, name);
- free ((char *) name);
+ free (CONST_CAST (char *, name));
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
- DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
/* Should never be called on a symbol with a preexisting meaning. */
/* Set the contained declarator of an array declarator. DECL is the
declarator, as constructed by build_array_declarator; INNER is what
- appears on the left of the []. ABSTRACT_P is true if it is an
- abstract declarator, false otherwise; this is used to reject static
- and type qualifiers in abstract declarators, where they are not in
- the C99 grammar (subject to possible change in DR#289). */
+ appears on the left of the []. */
struct c_declarator *
set_array_declarator_inner (struct c_declarator *decl,
- struct c_declarator *inner, bool abstract_p)
+ struct c_declarator *inner)
{
decl->declarator = inner;
- if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED
- || decl->u.array.attrs != NULL_TREE
- || decl->u.array.static_p))
- error ("static or type qualifiers in abstract declarator");
return decl;
}
type_name->specs->attrs = NULL_TREE;
type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
- false, NULL);
+ false, NULL, &attrs, 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, &attributes,
+ 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
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);
}
tree
grokparm (const struct c_parm *parm)
{
+ tree attrs = parm->attrs;
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
- NULL);
+ NULL, &attrs, DEPRECATED_NORMAL);
- decl_attributes (&decl, parm->attrs, 0);
+ decl_attributes (&decl, attrs, 0);
return decl;
}
void
push_parm_decl (const struct c_parm *parm)
{
+ tree attrs = parm->attrs;
tree decl;
- decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
- decl_attributes (&decl, parm->attrs, 0);
+ decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
+ &attrs, DEPRECATED_NORMAL);
+ decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
&& type_mv != boolean_type_node)
pedwarn ("type of bit-field %qs is a GCC extension", name);
- if (type_mv == boolean_type_node)
- max_width = CHAR_TYPE_SIZE;
- else
- max_width = TYPE_PRECISION (*type);
+ max_width = TYPE_PRECISION (*type);
if (0 < compare_tree_int (*width, max_width))
{
}
\f
+
+/* Print warning about variable length array if necessary. */
+
+static void
+warn_variable_length_array (const char *name, tree size)
+{
+ 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");
+ }
+ }
+}
+
/* 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.
+ DECL_ATTRS points to the list of attributes that should be added to this
+ decl. Any nested attributes that belong on the decl itself will be
+ added to this list.
+ 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,
+ tree *decl_attrs, enum deprecated_states deprecated_state)
{
tree type = declspecs->type;
bool threadp = declspecs->thread_p;
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))
gcc_unreachable ();
}
}
+ *decl_attrs = chainon (returned_attrs, *decl_attrs);
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl = build_decl (TYPE_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
- decl_attributes (&decl, returned_attrs, 0);
if (declspecs->inline_p)
pedwarn ("typedef %q+D declared %<inline%>", decl);
return decl;
pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl_attributes (&type, returned_attrs, 0);
return type;
}
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = array_ptr_quals;
+ if (type_quals)
+ type = c_build_qualified_type (type, type_quals);
/* We don't yet implement attributes in this context. */
if (array_ptr_attrs != NULL_TREE)
type_as_written = type;
decl = build_decl (PARM_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
}
type = c_build_qualified_type (type, type_quals);
decl = build_decl (FIELD_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
DECL_NONADDRESSABLE_P (decl) = bitfield;
+ if (bitfield && !declarator->u.id)
+ TREE_NO_WARNING (decl) = 1;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
}
decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
decl = build_decl_attribute_variant (decl, decl_attr);
- DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
-
if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
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
name of a variable. Thus, if it's known before this, die horribly. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
- decl_attributes (&decl, returned_attrs, 0);
-
return decl;
}
}
error ("nested redefinition of %<union %E%>", name);
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);
}
/* Process the specs, declarator and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
+ DECL_ATTRS is as for grokdeclarator.
This is done during the parsing of the struct declaration.
The FIELD_DECL nodes are chained together and the lot of them
tree
grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
- tree width)
+ tree width, tree *decl_attrs)
{
tree value;
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
- width ? &width : NULL);
+ width ? &width : NULL, decl_attrs,
+ DEPRECATED_NORMAL);
finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
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,
+ &attributes, 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))))
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;
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
gen_aux_info_record (fndecl, 1, 0, proto);
/* Initialize the RTL code for the function. */
- allocate_struct_function (fndecl);
+ allocate_struct_function (fndecl, false);
/* Begin the statement tree for this function. */
DECL_SAVED_TREE (fndecl) = push_stmt_list ();
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);
+ /* For GNU C extern inline functions disregard inline limits. */
+ if (DECL_EXTERNAL (fndecl)
+ && DECL_DECLARED_INLINE_P (fndecl))
+ DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
+
/* Genericize before inlining. Delay genericizing nested functions
until their parent function is genericized. Since finalizing
requires GENERIC, delay that as well. */
This should be cleaned up later and this conditional removed. */
if (cgraph_global_info_ready)
{
- c_expand_body (fndecl);
+ cgraph_add_new_function (fndecl, false);
return;
}
/* We're leaving the context of this function, so zap cfun.
It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
tree_rest_of_compilation. */
- cfun = NULL;
+ set_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;
}
C. */
int
-anon_aggr_type_p (tree ARG_UNUSED (node))
+anon_aggr_type_p (const_tree ARG_UNUSED (node))
{
return 0;
}
ret->const_p = false;
ret->volatile_p = false;
ret->restrict_p = false;
+ ret->saturating_p = false;
return ret;
}
}
if ((int) i <= (int) RID_LAST_MODIFIER)
{
- /* "long", "short", "signed", "unsigned" or "_Complex". */
+ /* "long", "short", "signed", "unsigned", "_Complex" or "_Sat". */
bool dupe = false;
switch (i)
{
else if (specs->typespec_word == cts_dfloat128)
error ("both %<complex%> and %<_Decimal128%> in "
"declaration specifiers");
+ else if (specs->typespec_word == cts_fract)
+ error ("both %<complex%> and %<_Fract%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_accum)
+ error ("both %<complex%> and %<_Accum%> in "
+ "declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<complex%> and %<_Sat%> in "
+ "declaration specifiers");
else
specs->complex_p = true;
break;
+ case RID_SAT:
+ dupe = specs->saturating_p;
+ if (pedantic)
+ pedwarn ("ISO C does not support saturating types");
+ if (specs->typespec_word == cts_void)
+ error ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_int)
+ error ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat32)
+ error ("both %<_Sat%> and %<_Decimal32%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat64)
+ error ("both %<_Sat%> and %<_Decimal64%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_dfloat128)
+ error ("both %<_Sat%> and %<_Decimal128%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<_Sat%> and %<complex%> in "
+ "declaration specifiers");
+ else
+ specs->saturating_p = true;
+ break;
default:
gcc_unreachable ();
}
}
else
{
- /* "void", "_Bool", "char", "int", "float" or "double". */
+ /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
+ "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
if (specs->typespec_word != cts_none)
{
error ("two or more data types in declaration specifiers");
else if (specs->complex_p)
error ("both %<complex%> and %<void%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_void;
return specs;
else if (specs->complex_p)
error ("both %<complex%> and %<_Bool%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_bool;
return specs;
else if (specs->short_p)
error ("both %<short%> and %<char%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_char;
return specs;
case RID_INT:
- specs->typespec_word = cts_int;
+ if (specs->saturating_p)
+ error ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_int;
return specs;
case RID_FLOAT:
if (specs->long_p)
else if (specs->unsigned_p)
error ("both %<unsigned%> and %<float%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_float;
return specs;
else if (specs->unsigned_p)
error ("both %<unsigned%> and %<double%> in "
"declaration specifiers");
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers");
else
specs->typespec_word = cts_double;
return specs;
else if (specs->complex_p)
error ("both %<complex%> and %<%s%> in "
"declaration specifiers", str);
+ else if (specs->saturating_p)
+ error ("both %<_Sat%> and %<%s%> in "
+ "declaration specifiers", str);
else if (i == RID_DFLOAT32)
specs->typespec_word = cts_dfloat32;
else if (i == RID_DFLOAT64)
if (pedantic)
pedwarn ("ISO C does not support decimal floating point");
return specs;
+ case RID_FRACT:
+ case RID_ACCUM:
+ {
+ const char *str;
+ if (i == RID_FRACT)
+ str = "_Fract";
+ else
+ str = "_Accum";
+ if (specs->complex_p)
+ error ("both %<complex%> and %<%s%> in "
+ "declaration specifiers", str);
+ else if (i == RID_FRACT)
+ specs->typespec_word = cts_fract;
+ else
+ specs->typespec_word = cts_accum;
+ }
+ if (!targetm.fixed_point_supported_p ())
+ error ("fixed-point types not supported for this target");
+ if (pedantic)
+ pedwarn ("ISO C does not support fixed-point types");
+ return specs;
default:
/* ObjC reserved word "id", handled below. */
break;
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:
"_Complex short" is equivalent to "_Complex short int". */
if (specs->typespec_word == cts_none)
{
- if (specs->long_p || specs->short_p
- || specs->signed_p || specs->unsigned_p)
+ if (specs->saturating_p)
+ {
+ error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+ specs->typespec_word = cts_fract;
+ }
+ else if (specs->long_p || specs->short_p
+ || specs->signed_p || specs->unsigned_p)
{
specs->typespec_word = cts_int;
}
else
specs->type = dfloat128_type_node;
break;
+ case cts_fract:
+ gcc_assert (!specs->complex_p);
+ if (specs->saturating_p)
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_long_fract_type_node
+ : sat_long_long_fract_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_fract_type_node
+ : sat_long_fract_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_short_fract_type_node
+ : sat_short_fract_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_fract_type_node
+ : sat_fract_type_node;
+ }
+ else
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_long_fract_type_node
+ : long_long_fract_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_fract_type_node
+ : long_fract_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_short_fract_type_node
+ : short_fract_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? unsigned_fract_type_node
+ : fract_type_node;
+ }
+ break;
+ case cts_accum:
+ gcc_assert (!specs->complex_p);
+ if (specs->saturating_p)
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_long_accum_type_node
+ : sat_long_long_accum_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_long_accum_type_node
+ : sat_long_accum_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_short_accum_type_node
+ : sat_short_accum_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? sat_unsigned_accum_type_node
+ : sat_accum_type_node;
+ }
+ else
+ {
+ if (specs->long_long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_long_accum_type_node
+ : long_long_accum_type_node;
+ else if (specs->long_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_long_accum_type_node
+ : long_accum_type_node;
+ else if (specs->short_p)
+ specs->type = specs->unsigned_p
+ ? unsigned_short_accum_type_node
+ : short_accum_type_node;
+ else
+ specs->type = specs->unsigned_p
+ ? unsigned_accum_type_node
+ : accum_type_node;
+ }
+ break;
default:
gcc_unreachable ();
}
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. */
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 ();