/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC.
#include "c-family/c-pragma.h"
#include "c-lang.h"
#include "langhooks.h"
-#include "tree-mudflap.h"
#include "tree-iterator.h"
#include "diagnostic-core.h"
#include "tree-dump.h"
static bool undef_nested_function;
-/* True means global_bindings_p should return false even if the scope stack
- says we are in file scope. */
-bool c_override_global_bindings_to_false;
+/* Mode used to build pointers (VOIDmode means ptr_mode). */
+
+enum machine_mode c_default_pointer_mode = VOIDmode;
\f
/* Each c_binding structure describes one binding of an identifier to
/* The resulting tree type. */
union 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))"))) lang_tree_node
+ chain_next ("(union lang_tree_node *) c_tree_chain_next (&%h.generic)"))) lang_tree_node
{
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
/* Add T to the statement-tree. Non-side-effect statements need to be
recorded during statement expressions. */
+ if (!building_stmt_list_p ())
+ push_stmt_list ();
append_to_statement_list_force (t, &cur_stmt_list);
return t;
}
+\f
+/* Build a pointer type using the default pointer mode. */
+
+static tree
+c_build_pointer_type (tree to_type)
+{
+ addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
+ : TYPE_ADDR_SPACE (to_type);
+ enum machine_mode pointer_mode;
+
+ if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode)
+ pointer_mode = targetm.addr_space.pointer_mode (as);
+ else
+ pointer_mode = c_default_pointer_mode;
+ return build_pointer_type_for_mode (to_type, pointer_mode, false);
+}
+
\f
/* Return true if we will want to say something if a goto statement
crosses DECL. */
static bool
decl_jump_unsafe (tree decl)
{
- if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+ if (error_operand_p (decl))
return false;
/* Always warn about crossing variably modified types. */
complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
- layout_decl (decl, 0);
+ relayout_decl (decl);
}
}
}
}
}
-/* Nonzero if we are currently in file scope. */
+/* Return true if we are in the global binding level. */
-int
+bool
global_bindings_p (void)
{
- return (current_scope == file_scope && !c_override_global_bindings_to_false
- ? -1
- : 0);
+ return current_scope == file_scope;
}
void
DECL_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
}
- else if (VAR_OR_FUNCTION_DECL_P (p))
+ else if (VAR_OR_FUNCTION_DECL_P (p) && scope != file_scope)
{
/* For block local externs add a special
DECL_EXTERNAL decl for debug info generation. */
/* Redeclaration of a type is a constraint violation (6.7.2.3p1),
but silently ignore the redeclaration if either is in a system
header. (Conflicting redeclarations were handled above.) This
- is allowed for C1X if the types are the same, not just
+ is allowed for C11 if the types are the same, not just
compatible. */
if (TREE_CODE (newdecl) == TYPE_DECL)
{
newdecl);
locate_old_decl (olddecl);
}
- else if (pedantic && !flag_isoc1x)
+ else if (pedantic && !flag_isoc11)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"redefinition of typedef %q+D", newdecl);
locate_old_decl (olddecl);
}
&& prototype_p (TREE_TYPE (newdecl)));
bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
&& prototype_p (TREE_TYPE (olddecl)));
- 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_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
C_DECL_DECLARED_BUILTIN (newdecl) = 1;
if (new_is_prototype)
- C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+ {
+ C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+ if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+ switch (fncode)
+ {
+ /* If a compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with the
+ expected semantics. */
+ case BUILT_IN_STPCPY:
+ if (builtin_decl_explicit_p (fncode))
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ break;
+ }
+ }
+ }
else
C_DECL_BUILTIN_PROTOTYPE (newdecl)
= C_DECL_BUILTIN_PROTOTYPE (olddecl);
}
}
- extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
-
/* Merge the USED information. */
if (TREE_USED (olddecl))
TREE_USED (newdecl) = 1;
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl_common) - sizeof (struct tree_common));
+ DECL_USER_ALIGN (olddecl) = DECL_USER_ALIGN (newdecl);
switch (TREE_CODE (olddecl))
{
case FUNCTION_DECL:
|| (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_mark_if_needed (olddecl);
}
/* Handle when a new declaration NEWDECL has the same name as an old
/* Is anything being shadowed? Invisible decls do not count. */
for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
- if (b->decl && b->decl != new_decl && !b->invisible)
+ if (b->decl && b->decl != new_decl && !b->invisible
+ && (b->decl == error_mark_node
+ || diagnostic_report_warnings_p (global_dc,
+ DECL_SOURCE_LOCATION (b->decl))))
{
tree old_decl = b->decl;
skip_external_and_shadow_checks:
if (TREE_CODE (x) == TYPE_DECL)
- set_underlying_type (x);
+ {
+ /* So this is a typedef, set its underlying type. */
+ set_underlying_type (x);
+
+ /* If X is a typedef defined in the current function, record it
+ for the purpose of implementing the -Wunused-local-typedefs
+ warning. */
+ record_locally_defined_typedef (x);
+ }
bind (name, x, scope, /*invisible=*/false, nested, locus);
{
struct c_binding *b = I_SYMBOL_BINDING (name);
if (b && !b->invisible)
- return b->decl;
+ {
+ maybe_record_typedef_use (b->decl);
+ return b->decl;
+ }
return 0;
}
using preprocessed headers. */
input_location = BUILTINS_LOCATION;
- build_common_tree_nodes (flag_signed_char);
-
c_common_nodes_and_builtins ();
/* In C, comparisons and TRUTH_* expressions have type int. */
warned = 1;
pending_xref_error ();
}
+ else if (declspecs->typespec_kind != ctsk_tagdef
+ && declspecs->typespec_kind != ctsk_tagfirstref
+ && declspecs->alignas_p)
+ {
+ if (warned != 1)
+ pedwarn (input_location, 0,
+ "empty declaration with %<_Alignas%> "
+ "does not redeclare tag");
+ warned = 1;
+ pending_xref_error ();
+ }
else
{
pending_invalid_xref = 0;
warned = 1;
}
+ if (declspecs->noreturn_p)
+ {
+ error ("%<_Noreturn%> in empty declaration");
+ warned = 1;
+ }
+
if (current_scope == file_scope && declspecs->storage_class == csc_auto)
{
error ("%<auto%> in file-scope empty declaration");
warned = 2;
}
+ if (!warned && !in_system_header && declspecs->alignas_p)
+ {
+ warning (0, "useless %<_Alignas%> in empty declaration");
+ warned = 2;
+ }
+
if (warned != 1)
{
if (!found_tag)
&& !specs->unsigned_p
&& !specs->complex_p
&& !specs->inline_p
+ && !specs->noreturn_p
&& !specs->thread_p);
return quals;
}
if (!flag_isoc99)
{
if (static_p || quals != NULL)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C90 does not support %<static%> or type "
"qualifiers in parameter array declarators");
if (vla_unspec_p)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C90 does not support %<[*]%> array declarators");
}
if (vla_unspec_p)
return 0;
if (expr)
- add_stmt (expr);
+ add_stmt (fold_convert (void_type_node, expr));
if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
warning (OPT_Wmain, "%q+D is usually a function", decl);
b_ext = b_ext->shadowed;
if (b_ext)
{
- if (b_ext->u.type)
+ if (b_ext->u.type && comptypes (b_ext->u.type, type))
b_ext->u.type = composite_type (b_ext->u.type, type);
else
b_ext->u.type = type;
if (DECL_INITIAL (decl))
TREE_TYPE (DECL_INITIAL (decl)) = type;
- layout_decl (decl, 0);
+ relayout_decl (decl);
}
if (TREE_CODE (decl) == VAR_DECL)
}
/* If this is a function and an assembler name is specified, reset DECL_RTL
- so we can give it its new name. Also, update built_in_decls if it
+ so we can give it its new name. Also, update builtin_decl if it
was a normal built-in. */
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
when a tentative file-scope definition is seen.
But at end of compilation, do output code for them. */
DECL_DEFER_OUTPUT (decl) = 1;
+ if (asmspec && C_DECL_REGISTER (decl))
+ DECL_HARD_REGISTER (decl) = 1;
rest_of_decl_compilation (decl, true, 0);
}
else
rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
}
- /* At the end of a declaration, throw away any variable type sizes
- of types defined inside that declaration. There is no use
- computing them in the following function definition. */
- if (current_scope == file_scope)
- get_pending_sizes ();
-
/* Install a cleanup (aka destructor) if one was given. */
if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
{
&& C_TYPE_FIELDS_READONLY (type))
diagnose_uninitialized_cst_member (decl, type);
}
+
+ invoke_plugin_callbacks (PLUGIN_FINISH_DECL, decl);
}
-/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
+/* Given a parsed parameter declaration, decode it into a PARM_DECL.
+ EXPR is NULL or a pointer to an expression that needs to be
+ evaluated for the side effects of array size expressions in the
+ parameters. */
tree
-grokparm (const struct c_parm *parm)
+grokparm (const struct c_parm *parm, tree *expr)
{
tree attrs = parm->attrs;
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
- NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL);
+ NULL, &attrs, expr, NULL, DEPRECATED_NORMAL);
decl_attributes (&decl, attrs, 0);
}
/* Given a parsed parameter declaration, decode it into a PARM_DECL
- and push that on the current scope. */
+ and push that on the current scope. EXPR is a pointer to an
+ expression that needs to be evaluated for the side effects of array
+ size expressions in the parameters. */
void
-push_parm_decl (const struct c_parm *parm)
+push_parm_decl (const struct c_parm *parm, tree *expr)
{
tree attrs = parm->attrs;
tree decl;
decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
- &attrs, NULL, NULL, DEPRECATED_NORMAL);
+ &attrs, expr, NULL, DEPRECATED_NORMAL);
decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
if (pedantic && !current_scope->warned_forward_parm_decls)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C forbids forward parameter declarations");
current_scope->warned_forward_parm_decls = true;
}
TREE_USED (decl) = 1;
DECL_READ_P (decl) = 1;
TREE_TYPE (decl) = type;
- TREE_READONLY (decl) = TYPE_READONLY (type);
+ TREE_READONLY (decl) = (TYPE_READONLY (type)
+ || (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_READONLY (TREE_TYPE (type))));
store_init_value (loc, decl, init, NULL_TREE);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
*width = c_fully_fold (*width, false, NULL);
if (TREE_CODE (*width) == INTEGER_CST)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"bit-field %qs width not an integer constant expression",
name);
}
&& type_mv != integer_type_node
&& type_mv != unsigned_type_node
&& type_mv != boolean_type_node)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"type of bit-field %qs is a GCC extension", name);
max_width = TYPE_PRECISION (*type);
{
error ("width of %qs exceeds its type", name);
w = max_width;
- *width = build_int_cst (NULL_TREE, w);
+ *width = build_int_cst (integer_type_node, w);
}
else
w = tree_low_cst (*width, 1);
}
}
-/* Given a size SIZE that may not be a constant, return a SAVE_EXPR to
- serve as the actual size-expression for a type or decl. This is
- like variable_size in stor-layout.c, but we make global_bindings_p
- return negative to avoid calls to that function from outside the
- front end resulting in errors at file scope, then call this version
- instead from front-end code. */
-
-static tree
-c_variable_size (tree size)
-{
- tree save;
-
- if (TREE_CONSTANT (size))
- return size;
-
- size = save_expr (size);
-
- save = skip_simple_arithmetic (size);
-
- if (cfun && cfun->dont_save_pending_sizes_p)
- return size;
-
- if (!global_bindings_p ())
- put_pending_size (save);
-
- return size;
-}
-
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
tree expr_dummy;
bool expr_const_operands_dummy;
enum c_declarator_kind first_non_attr_kind;
+ unsigned int alignas_align = 0;
if (TREE_CODE (type) == ERROR_MARK)
return error_mark_node;
if (pedantic && !flag_isoc99)
{
if (constp > 1)
- pedwarn (loc, OPT_pedantic, "duplicate %<const%>");
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<const%>");
if (restrictp > 1)
- pedwarn (loc, OPT_pedantic, "duplicate %<restrict%>");
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
if (volatilep > 1)
- pedwarn (loc, OPT_pedantic, "duplicate %<volatile%>");
+ pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
}
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
{
if (storage_class == csc_auto)
pedwarn (loc,
- (current_scope == file_scope) ? 0 : OPT_pedantic,
+ (current_scope == file_scope) ? 0 : OPT_Wpedantic,
"function definition declared %<auto%>");
if (storage_class == csc_register)
error_at (loc, "function definition declared %<register%>");
error_at (loc, "file-scope declaration of %qE specifies %<auto%>",
name);
if (pedantic && storage_class == csc_register)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"file-scope declaration of %qE specifies %<register%>", name);
}
else
}
if (pedantic && !in_system_header && flexible_array_type_p (type))
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"invalid use of structure with flexible array member");
if (size == error_mark_node)
if (pedantic && size_maybe_const && integer_zerop (size))
{
if (name)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C forbids zero-size array %qE", name);
else
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C forbids zero-size array");
}
MINUS_EXPR, which allows the -1 to get folded
with the +1 that happens when building TYPE_SIZE. */
if (size_varies)
- size = c_variable_size (size);
+ size = save_expr (size);
if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
integer_zero_node, size);
convert (index_type,
size_one_node));
- /* 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
- index_type, before the subtraction. Handling
- this case seems like an unnecessary
- complication. */
- if (TREE_CODE (itype) == INTEGER_CST
- && TREE_OVERFLOW (itype))
+ /* The above overflows when size does not fit
+ in index_type.
+ ??? While a size of INT_MAX+1 technically shouldn't
+ cause an overflow (because we subtract 1), handling
+ this case seems like an unnecessary complication. */
+ if (TREE_CODE (size) == INTEGER_CST
+ && !int_fits_type_p (size, index_type))
{
if (name)
error_at (loc, "size of array %qE is too large",
}
if (flexible_array_member
&& pedantic && !flag_isoc99 && !in_system_header)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C90 does not support flexible array members");
/* ISO C99 Flexible array members are effectively
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 (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
TYPE_NAME (type) = decl;
}
- type = build_pointer_type (type);
+ type = c_build_pointer_type (type);
/* Process type qualifiers (such as const or volatile)
that were given inside the `*'. */
if (bitfield)
check_bitfield_type_and_width (&type, width, name);
- /* Did array size calculations overflow? */
+ /* Reject invalid uses of _Alignas. */
+ if (declspecs->alignas_p)
+ {
+ if (storage_class == csc_typedef)
+ error_at (loc, "alignment specified for typedef %qE", name);
+ else if (storage_class == csc_register)
+ error_at (loc, "alignment specified for %<register%> object %qE",
+ name);
+ else if (decl_context == PARM)
+ {
+ if (name)
+ error_at (loc, "alignment specified for parameter %qE", name);
+ else
+ error_at (loc, "alignment specified for unnamed parameter");
+ }
+ else if (bitfield)
+ {
+ if (name)
+ error_at (loc, "alignment specified for bit-field %qE", name);
+ else
+ error_at (loc, "alignment specified for unnamed bit-field");
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ error_at (loc, "alignment specified for function %qE", name);
+ else if (declspecs->align_log != -1)
+ {
+ alignas_align = 1U << declspecs->align_log;
+ if (alignas_align < TYPE_ALIGN_UNIT (type))
+ {
+ if (name)
+ error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+ "alignment of %qE", name);
+ else
+ error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+ "alignment of unnamed field");
+ alignas_align = 0;
+ }
+ }
+ }
+ /* Did array size calculations overflow or does the array cover more
+ than half of the address-space? */
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
&& TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
- && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
+ && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
{
if (name)
error_at (loc, "size of array %qE is too large", name);
tree decl;
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (declspecs->inline_p)
pedwarn (loc, 0,"typedef %q+D declared %<inline%>", decl);
+ if (declspecs->noreturn_p)
+ pedwarn (loc, 0,"typedef %q+D declared %<_Noreturn%>", decl);
if (warn_cxx_compat && declarator->u.id != NULL_TREE)
{
/* Note that the grammar rejects storage classes in typenames
and fields. */
gcc_assert (storage_class == csc_none && !threadp
- && !declspecs->inline_p);
+ && !declspecs->inline_p && !declspecs->noreturn_p);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
&& variably_modified_type_p (type, NULL_TREE))
{
/* C99 6.7.2.1p8 */
- pedwarn (loc, OPT_pedantic, "a member of a structure or union cannot "
+ pedwarn (loc, OPT_Wpedantic, "a member of a structure or union cannot "
"have a variably modified type");
}
type = TREE_TYPE (type);
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- type = build_pointer_type (type);
+ type = c_build_pointer_type (type);
type_quals = array_ptr_quals;
if (type_quals)
type = c_build_qualified_type (type, type_quals);
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (type_quals)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- type = build_pointer_type (type);
+ type = c_build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
}
else if (type_quals)
DECL_ARG_TYPE (decl) = promoted_type;
if (declspecs->inline_p)
pedwarn (loc, 0, "parameter %q+D declared %<inline%>", decl);
+ if (declspecs->noreturn_p)
+ pedwarn (loc, 0, "parameter %q+D declared %<_Noreturn%>", decl);
}
else if (decl_context == FIELD)
{
/* Note that the grammar rejects storage classes in typenames
and fields. */
gcc_assert (storage_class == csc_none && !threadp
- && !declspecs->inline_p);
+ && !declspecs->inline_p && !declspecs->noreturn_p);
/* Structure field. It may not be a function. */
GCC allows 'auto', perhaps with 'inline', to support
nested functions. */
if (storage_class == csc_auto)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"invalid storage class for function %qE", name);
else if (storage_class == csc_static)
{
decl = build_decl_attribute_variant (decl, decl_attr);
if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C forbids qualified function types");
/* Every function declaration is an external reference
if (declspecs->default_int_p)
C_FUNCTION_IMPLICIT_INT (decl) = 1;
- /* Record presence of `inline', if it is reasonable. */
+ /* Record presence of `inline' and `_Noreturn', if it is
+ reasonable. */
if (flag_hosted && MAIN_NAME_P (declarator->u.id))
{
if (declspecs->inline_p)
pedwarn (loc, 0, "cannot inline function %<main%>");
+ if (declspecs->noreturn_p)
+ pedwarn (loc, 0, "%<main%> declared %<_Noreturn%>");
+ }
+ else
+ {
+ if (declspecs->inline_p)
+ /* Record that the function is declared `inline'. */
+ DECL_DECLARED_INLINE_P (decl) = 1;
+ if (declspecs->noreturn_p)
+ {
+ if (!flag_isoc11)
+ {
+ if (flag_isoc99)
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C99 does not support %<_Noreturn%>");
+ else
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C90 does not support %<_Noreturn%>");
+ }
+ TREE_THIS_VOLATILE (decl) = 1;
+ }
}
- else if (declspecs->inline_p)
- /* Record that the function is declared `inline'. */
- DECL_DECLARED_INLINE_P (decl) = 1;
}
else
{
if (declspecs->inline_p)
pedwarn (loc, 0, "variable %q+D declared %<inline%>", decl);
+ if (declspecs->noreturn_p)
+ pedwarn (loc, 0, "variable %q+D declared %<_Noreturn%>", decl);
/* At file scope, an initialized extern declaration may follow
a static declaration. In that case, DECL_EXTERNAL will be
/* Record constancy and volatility. */
c_apply_type_quals_to_decl (type_quals, decl);
+ /* Apply _Alignas specifiers. */
+ if (alignas_align)
+ {
+ DECL_ALIGN (decl) = alignas_align * BITS_PER_UNIT;
+ DECL_USER_ALIGN (decl) = 1;
+ }
+
/* If a type has volatile components, it should be stored in memory.
Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler.
This structure is later fed to 'grokparms' and 'store_parm_decls'.
ELLIPSIS being true means the argument list ended in '...' so don't
- append a sentinel (void_list_node) to the end of the type-list. */
+ append a sentinel (void_list_node) to the end of the type-list.
+
+ EXPR is NULL or an expression that needs to be evaluated for the
+ side effects of array size expressions in the parameters. */
struct c_arg_info *
-get_parm_info (bool ellipsis)
+get_parm_info (bool ellipsis, tree expr)
{
struct c_binding *b = current_scope->bindings;
struct c_arg_info *arg_info = build_arg_info ();
arg_info->tags = tags;
arg_info->types = types;
arg_info->others = others;
- arg_info->pending_sizes = get_pending_sizes ();
+ arg_info->pending_sizes = expr;
return arg_info;
}
\f
If this is something of the form "foo;" and foo is a TYPE_DECL, then
If foo names a structure or union without a tag, then this
- is an anonymous struct (this is permitted by C1X).
+ is an anonymous struct (this is permitted by C11).
If MS or Plan 9 extensions are enabled and foo names a
structure, then again this is an anonymous struct.
Otherwise this is an error.
pedwarn (loc, 0, "declaration does not declare anything");
return NULL_TREE;
}
- if (!flag_isoc1x)
+ if (!flag_isoc11)
{
if (flag_isoc99)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C99 doesn%'t support unnamed structs/unions");
else
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C90 doesn%'t support unnamed structs/unions");
}
}
int timeout = 10;
/* If the struct is the list of instance variables of an Objective-C
- class, then we need to add all the instance variables of
- superclasses before checking for duplicates (since you can't have
+ class, then we need to check all the instance variables of
+ superclasses when checking for duplicates (since you can't have
an instance variable in a subclass with the same name as an
- instance variable in a superclass). objc_get_interface_ivars()
- leaves fieldlist unchanged if we are not in this case, so in that
- case nothing changes compared to C.
- */
+ instance variable in a superclass). We pass on this job to the
+ Objective-C compiler. objc_detect_field_duplicates() will return
+ false if we are not checking the list of instance variables and
+ the C frontend should proceed with the standard field duplicate
+ checks. If we are checking the list of instance variables, the
+ ObjC frontend will do the check, emit the errors if needed, and
+ then return true. */
if (c_dialect_objc ())
- fieldlist = objc_get_interface_ivars (fieldlist);
+ if (objc_detect_field_duplicates (false))
+ return;
/* First, see if there are more than "a few" fields.
This is trivially true if there are zero or one fields. */
{
if (DECL_NAME (x) != 0)
break;
- if (flag_isoc1x
+ if (flag_isoc11
&& (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
break;
if (TREE_CODE (t) == UNION_TYPE)
{
if (fieldlist)
- pedwarn (loc, OPT_pedantic, "union has no named members");
+ pedwarn (loc, OPT_Wpedantic, "union has no named members");
else
- pedwarn (loc, OPT_pedantic, "union has no members");
+ pedwarn (loc, OPT_Wpedantic, "union has no members");
}
else
{
if (fieldlist)
- pedwarn (loc, OPT_pedantic, "struct has no named members");
+ pedwarn (loc, OPT_Wpedantic, "struct has no named members");
else
- pedwarn (loc, OPT_pedantic, "struct has no members");
+ pedwarn (loc, OPT_Wpedantic, "struct has no members");
}
}
}
if (pedantic && TREE_CODE (t) == RECORD_TYPE
&& flexible_array_type_p (TREE_TYPE (x)))
- pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic,
+ pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
"invalid use of structure with flexible array member");
if (DECL_NAME (x)
if (c_dialect_objc ())
objc_check_decl (decl);
rest_of_decl_compilation (decl, toplevel, 0);
- if (!toplevel)
- expand_decl (decl);
}
}
C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
/* 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_TREE))
+ if (building_stmt_list_p () && variably_modified_type_p (t, NULL_TREE))
add_stmt (build_stmt (loc,
DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
{
value = c_fully_fold (value, false, NULL);
if (TREE_CODE (value) == INTEGER_CST)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"enumerator value for %qE is not an integer "
"constant expression", name);
}
(6.4.4.3/2 in the C99 Standard). GCC allows any integer type as
an extension. */
else if (!int_fits_type_p (value, integer_type_node))
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C restricts enumerator values to range of %<int%>");
/* The ISO C Standard mandates enumerators to have type int, even
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
- if (decl1 == 0)
+ if (decl1 == 0
+ || TREE_CODE (decl1) != FUNCTION_DECL)
return 0;
loc = DECL_SOURCE_LOCATION (decl1);
old-style definition and discarded? */
if (current_function_prototype_built_in)
warning_at (DECL_SOURCE_LOCATION (parm),
- OPT_pedantic, "promoted argument %qD "
+ OPT_Wpedantic, "promoted argument %qD "
"doesn%'t match built-in prototype", parm);
else
{
pedwarn (DECL_SOURCE_LOCATION (parm),
- OPT_pedantic, "promoted argument %qD "
+ OPT_Wpedantic, "promoted argument %qD "
"doesn%'t match prototype", parm);
- pedwarn (current_function_prototype_locus, OPT_pedantic,
+ pedwarn (current_function_prototype_locus, OPT_Wpedantic,
"prototype declaration");
}
}
/* Initialize the RTL code for the function. */
allocate_struct_function (fndecl, false);
+ if (warn_unused_local_typedefs)
+ cfun->language = ggc_alloc_cleared_language_function ();
+
/* Begin the statement tree for this function. */
DECL_SAVED_TREE (fndecl) = push_stmt_list ();
because we throw away the array type in favor of a pointer type, and
thus won't naturally see the SAVE_EXPR containing the increment. All
other pending sizes would be handled by gimplify_parameters. */
- {
- VEC(tree,gc) *pending_sizes = get_pending_sizes ();
- tree t;
- int i;
-
- FOR_EACH_VEC_ELT (tree, pending_sizes, i, t)
- add_stmt (t);
- }
-
- /* Even though we're inside a function body, we still don't want to
- call expand_expr to calculate the size of a variable-sized array.
- We haven't necessarily assigned RTL to all variables yet, so it's
- not safe to try to expand expressions involving them. */
- cfun->dont_save_pending_sizes_p = 1;
+ if (arg_info->pending_sizes)
+ add_stmt (arg_info->pending_sizes);
}
\f
"parameter %qD set but not used", decl);
}
+ /* Complain about locally defined typedefs that are not used in this
+ function. */
+ maybe_warn_unused_local_typedefs ();
+
/* Store the end of the function, so that we get good line number
info for the epilogue. */
cfun->function_end_locus = input_location;
/* 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);
+ (void) cgraph_get_create_node (fndecl);
}
}
if (!decl_function_context (fndecl))
undef_nested_function = false;
+ if (cfun->language != NULL)
+ {
+ ggc_free (cfun->language);
+ cfun->language = NULL;
+ }
+
/* 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->language = p;
p->base.x_stmt_tree = c_stmt_tree;
+ c_stmt_tree.x_cur_stmt_list
+ = VEC_copy (tree, gc, c_stmt_tree.x_cur_stmt_list);
p->x_break_label = c_break_label;
p->x_cont_label = c_cont_label;
p->x_switch_stack = c_switch_stack;
return 0;
}
+/* In C, the only C-linkage public declaration is at file scope. */
+
+tree
+c_linkage_bindings (tree name)
+{
+ return identifier_global_value (name);
+}
+
/* Record a builtin type for C. If NAME is non-NULL, it is the name used;
otherwise the name is found in ridpointers from RID_INDEX. */
build_null_declspecs (void)
{
struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
+ memset (&ret->locations, 0, cdw_number_of_elements);
ret->type = 0;
ret->expr = 0;
ret->decl_attr = 0;
ret->attrs = 0;
+ ret->align_log = -1;
ret->typespec_word = cts_none;
ret->storage_class = csc_none;
ret->expr_const_operands = true;
ret->unsigned_p = false;
ret->complex_p = false;
ret->inline_p = false;
+ ret->noreturn_p = false;
ret->thread_p = false;
ret->const_p = false;
ret->volatile_p = false;
ret->restrict_p = false;
ret->saturating_p = false;
+ ret->alignas_p = false;
ret->address_space = ADDR_SPACE_GENERIC;
return ret;
}
SPECS, returning SPECS. */
struct c_declspecs *
-declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
+declspecs_add_addrspace (source_location location,
+ struct c_declspecs *specs, addr_space_t as)
{
specs->non_sc_seen_p = true;
specs->declspecs_seen_p = true;
c_addr_space_name (as),
c_addr_space_name (specs->address_space));
else
- specs->address_space = as;
+ {
+ specs->address_space = as;
+ specs->locations[cdw_address_space] = location;
+ }
return specs;
}
returning SPECS. */
struct c_declspecs *
-declspecs_add_qual (struct c_declspecs *specs, tree qual)
+declspecs_add_qual (source_location loc,
+ struct c_declspecs *specs, tree qual)
{
enum rid i;
bool dupe = false;
case RID_CONST:
dupe = specs->const_p;
specs->const_p = true;
+ specs->locations[cdw_const] = loc;
break;
case RID_VOLATILE:
dupe = specs->volatile_p;
specs->volatile_p = true;
+ specs->locations[cdw_volatile] = loc;
break;
case RID_RESTRICT:
dupe = specs->restrict_p;
specs->restrict_p = true;
+ specs->locations[cdw_restrict] = loc;
break;
default:
gcc_unreachable ();
}
if (dupe && !flag_isoc99)
- pedwarn (input_location, OPT_pedantic, "duplicate %qE", qual);
+ pedwarn (loc, OPT_Wpedantic, "duplicate %qE", qual);
return specs;
}
pedwarn_c90 (loc, OPT_Wlong_long,
"ISO C90 does not support %<long long%>");
specs->long_long_p = 1;
+ specs->locations[cdw_long_long] = loc;
break;
}
if (specs->short_p)
("both %<long%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->long_p = true;
+ {
+ specs->long_p = true;
+ specs->locations[cdw_long] = loc;
+ }
break;
case RID_SHORT:
dupe = specs->short_p;
("both %<short%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->short_p = true;
+ {
+ specs->short_p = true;
+ specs->locations[cdw_short] = loc;
+ }
break;
case RID_SIGNED:
dupe = specs->signed_p;
("both %<signed%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->signed_p = true;
+ {
+ specs->signed_p = true;
+ specs->locations[cdw_signed] = loc;
+ }
break;
case RID_UNSIGNED:
dupe = specs->unsigned_p;
("both %<unsigned%> and %<_Decimal128%> in "
"declaration specifiers"));
else
- specs->unsigned_p = true;
+ {
+ specs->unsigned_p = true;
+ specs->locations[cdw_unsigned] = loc;
+ }
break;
case RID_COMPLEX:
dupe = specs->complex_p;
- if (!flag_isoc99 && !in_system_header)
- pedwarn (loc, OPT_pedantic,
+ if (!flag_isoc99 && !in_system_header_at (loc))
+ pedwarn (loc, OPT_Wpedantic,
"ISO C90 does not support complex types");
if (specs->typespec_word == cts_void)
error_at (loc,
("both %<complex%> and %<_Sat%> in "
"declaration specifiers"));
else
- specs->complex_p = true;
+ {
+ specs->complex_p = true;
+ specs->locations[cdw_complex] = loc;
+ }
break;
case RID_SAT:
dupe = specs->saturating_p;
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C does not support saturating types");
if (specs->typespec_word == cts_int128)
{
("both %<_Sat%> and %<complex%> in "
"declaration specifiers"));
else
- specs->saturating_p = true;
+ {
+ specs->saturating_p = true;
+ specs->locations[cdw_saturating] = loc;
+ }
break;
default:
gcc_unreachable ();
return specs;
}
if (!in_system_header)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C does not support %<__int128%> type");
if (specs->long_p)
("both %<__int128%> and %<short%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_int128;
+ {
+ specs->typespec_word = cts_int128;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_VOID:
if (specs->long_p)
("both %<_Sat%> and %<void%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_void;
+ {
+ specs->typespec_word = cts_void;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_BOOL:
if (specs->long_p)
("both %<_Sat%> and %<_Bool%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_bool;
+ {
+ specs->typespec_word = cts_bool;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_CHAR:
if (specs->long_p)
("both %<_Sat%> and %<char%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_char;
+ {
+ specs->typespec_word = cts_char;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_INT:
if (specs->saturating_p)
("both %<_Sat%> and %<int%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_int;
+ {
+ specs->typespec_word = cts_int;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_FLOAT:
if (specs->long_p)
("both %<_Sat%> and %<float%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_float;
+ {
+ specs->typespec_word = cts_float;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_DOUBLE:
if (specs->long_long_p)
("both %<_Sat%> and %<double%> in "
"declaration specifiers"));
else
- specs->typespec_word = cts_double;
+ {
+ specs->typespec_word = cts_double;
+ specs->locations[cdw_typespec] = loc;
+ }
return specs;
case RID_DFLOAT32:
case RID_DFLOAT64:
specs->typespec_word = cts_dfloat64;
else
specs->typespec_word = cts_dfloat128;
+ specs->locations[cdw_typespec] = loc;
}
if (!targetm.decimal_float_supported_p ())
error_at (loc,
("decimal floating point not supported "
"for this target"));
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C does not support decimal floating point");
return specs;
case RID_FRACT:
specs->typespec_word = cts_fract;
else
specs->typespec_word = cts_accum;
+ specs->locations[cdw_typespec] = loc;
}
if (!targetm.fixed_point_supported_p ())
error_at (loc,
"fixed-point types not supported for this target");
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C does not support fixed-point types");
return specs;
default:
specs->decl_attr = DECL_ATTRIBUTES (type);
specs->typedef_p = true;
specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+ specs->locations[cdw_typedef] = loc;
/* If this typedef name is defined in a struct, then a C++
lookup would return a different value. */
else if (TREE_TYPE (t) == error_mark_node)
;
else
- specs->type = TREE_TYPE (t);
+ {
+ specs->type = TREE_TYPE (t);
+ specs->locations[cdw_typespec] = loc;
+ }
}
else
{
if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
{
specs->typedef_p = true;
+ specs->locations[cdw_typedef] = loc;
if (spec.expr)
{
if (specs->expr)
declaration specifiers SPECS, returning SPECS. */
struct c_declspecs *
-declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
+declspecs_add_scspec (source_location loc,
+ struct c_declspecs *specs,
+ tree scspec)
{
enum rid i;
enum c_storage_class n = csc_none;
difference between gnu89 and C99 inline. */
dupe = false;
specs->inline_p = true;
+ specs->locations[cdw_inline] = loc;
+ break;
+ case RID_NORETURN:
+ /* Duplicate _Noreturn is permitted. */
+ dupe = false;
+ specs->noreturn_p = true;
+ specs->locations[cdw_noreturn] = loc;
break;
case RID_THREAD:
dupe = specs->thread_p;
else if (specs->storage_class == csc_typedef)
error ("%<__thread%> used with %<typedef%>");
else
- specs->thread_p = true;
+ {
+ specs->thread_p = true;
+ specs->locations[cdw_thread] = loc;
+ }
break;
case RID_AUTO:
n = csc_auto;
else
{
specs->storage_class = n;
+ specs->locations[cdw_storage_class] = loc;
if (n != csc_extern && n != csc_static && specs->thread_p)
{
error ("%<__thread%> used with %qE", scspec);
returning SPECS. */
struct c_declspecs *
-declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
+declspecs_add_attrs (source_location loc, struct c_declspecs *specs, tree attrs)
{
specs->attrs = chainon (attrs, specs->attrs);
+ specs->locations[cdw_attributes] = loc;
specs->declspecs_seen_p = true;
return specs;
}
+/* Add an _Alignas specifier (expression ALIGN, or type whose
+ alignment is ALIGN) to the declaration specifiers SPECS, returning
+ SPECS. */
+struct c_declspecs *
+declspecs_add_alignas (source_location loc,
+ struct c_declspecs *specs, tree align)
+{
+ int align_log;
+ specs->alignas_p = true;
+ specs->locations[cdw_alignas] = loc;
+ if (align == error_mark_node)
+ return specs;
+ align_log = check_user_alignment (align, true);
+ if (align_log > specs->align_log)
+ specs->align_log = align_log;
+ return specs;
+}
+
/* Combine "long", "short", "signed", "unsigned" and "_Complex" type
specifiers with any other type specifier to determine the resulting
type. This is where ISO C checks on complex types are made, since
{
if (specs->saturating_p)
{
- error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+ error_at (specs->locations[cdw_saturating],
+ "%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
if (!targetm.fixed_point_supported_p ())
- error ("fixed-point types not supported for this target");
+ error_at (specs->locations[cdw_saturating],
+ "fixed-point types not supported for this target");
specs->typespec_word = cts_fract;
}
else if (specs->long_p || specs->short_p
else if (specs->complex_p)
{
specs->typespec_word = cts_double;
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support plain %<complex%> meaning "
"%<double complex%>");
}
specs->type = char_type_node;
if (specs->complex_p)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
: int128_integer_type_node);
if (specs->complex_p)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
: integer_type_node);
if (specs->complex_p)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
collect_source_ref (LOCATION_FILE (decl_sloc (decl, false)));
}
+/* Preserve the external declarations scope across a garbage collect. */
+static GTY(()) tree ext_block;
+
/* Collect all references relevant to SOURCE_FILE. */
static void
FOR_EACH_VEC_ELT (tree, all_translation_units, i, t)
collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file);
+
+ collect_ada_nodes (BLOCK_VARS (ext_block), source_file);
}
/* Iterate over all global declarations and call CALLBACK. */
for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
callback (decl);
}
-}
-/* Preserve the external declarations scope across a garbage collect. */
-static GTY(()) tree ext_block;
+ for (decl = BLOCK_VARS (ext_block); decl; decl = TREE_CHAIN (decl))
+ callback (decl);
+}
void
c_write_global_declarations (void)
if (pch_file)
return;
+ timevar_start (TV_PHASE_DEFERRED);
+
/* Do the Objective-C stuff. This is where all the Objective-C
module stuff gets generated (symtab, class/protocol/selector
lists etc). */
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+ timevar_stop (TV_PHASE_DEFERRED);
+ timevar_start (TV_PHASE_CGRAPH);
+
/* We're done parsing; proceed to optimize and emit assembly.
FIXME: shouldn't be the front end's responsibility to call this. */
- cgraph_finalize_compilation_unit ();
+ finalize_compilation_unit ();
+
+ timevar_stop (TV_PHASE_CGRAPH);
+ timevar_start (TV_PHASE_DBGINFO);
/* After cgraph has had a chance to emit everything that's going to
be emitted, output debug information for globals. */
}
ext_block = NULL;
+ timevar_stop (TV_PHASE_DBGINFO);
}
/* Register reserved keyword WORD as qualifier for address space AS. */