/* 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)")))
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;
&& 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);
}
}
+ 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
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 (name));
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
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
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
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);
}
\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.
+ 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;
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))
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)
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;
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
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);
}
}
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;
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))))
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_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);
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. */
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 ();