/* 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
Free Software Foundation, Inc.
This file is part of GCC.
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;
-
\f
/* Each c_binding structure describes one binding of an identifier to
a decl. All the decls in a scope - irrespective of namespace - are
/* 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;
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. */
}
}
-/* 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_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)
+ switch (DECL_FUNCTION_CODE (newdecl))
+ {
+ /* If a compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with the
+ expected semantics. */
+ case BUILT_IN_STPCPY:
+ implicit_built_in_decls[DECL_FUNCTION_CODE (newdecl)]
+ = built_in_decls[DECL_FUNCTION_CODE (newdecl)];
+ default:
+ break;
+ }
+ }
else
C_DECL_BUILTIN_PROTOTYPE (newdecl)
= C_DECL_BUILTIN_PROTOTYPE (olddecl);
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;
}
+ 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");
&& !specs->unsigned_p
&& !specs->complex_p
&& !specs->inline_p
+ && !specs->noreturn_p
&& !specs->thread_p);
return quals;
}
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;
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);
{
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.
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",
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. */
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,
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. */
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_isoc1x)
+ {
+ if (flag_isoc99)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C99 does not support %<_Noreturn%>");
+ else
+ pedwarn (loc, OPT_pedantic,
+ "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
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
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 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)));
/* 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. */
void
c_push_function_context (void)
{
- struct language_function *p;
- p = ggc_alloc_language_function ();
- cfun->language = p;
+ struct language_function *p = cfun->language;
+ /* cfun->language might have been already allocated by the use of
+ -Wunused-local-typedefs. In that case, just re-use it. */
+ if (p == NULL)
+ cfun->language = p = ggc_alloc_cleared_language_function ();
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;
pop_function_context ();
p = cfun->language;
- cfun->language = NULL;
+ /* When -Wunused-local-typedefs is in effect, cfun->languages is
+ used to store data throughout the life time of the current cfun,
+ So don't deallocate it. */
+ if (!warn_unused_local_typedefs)
+ cfun->language = NULL;
if (DECL_STRUCT_FUNCTION (current_function_decl) == 0
&& DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
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. */
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;
dupe = false;
specs->inline_p = true;
break;
+ case RID_NORETURN:
+ /* Duplicate _Noreturn is permitted. */
+ dupe = false;
+ specs->noreturn_p = true;
+ break;
case RID_THREAD:
dupe = specs->thread_p;
if (specs->storage_class == csc_auto)
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 ();
+ 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. */
if (!seen_error ())
}
ext_block = NULL;
+ timevar_stop (TV_PHASE_DBGINFO);
}
/* Register reserved keyword WORD as qualifier for address space AS. */