/* 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.
/* 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 ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) lang_tree_node
{
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
up searching for labels when popping scopes, particularly since
labels are normally only found at function scope. */
BOOL_BITFIELD has_label_bindings : 1;
+
+ /* True if we should issue a warning if a goto statement crosses any
+ of the bindings. We still need to check the list of bindings to
+ find the specific ones we need to warn about. This is true if
+ decl_jump_unsafe would return true for any of the bindings. This
+ is used to avoid looping over all the bindings unnecessarily. */
+ BOOL_BITFIELD has_jump_unsafe_decl : 1;
};
/* The scope currently in effect. */
return t;
}
\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)
+ return false;
+
+ /* Always warn about crossing variably modified types. */
+ if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
+ && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+ return true;
+
+ /* Otherwise, only warn if -Wgoto-misses-init and this is an
+ initialized automatic decl. */
+ if (warn_jump_misses_init
+ && TREE_CODE (decl) == VAR_DECL
+ && !TREE_STATIC (decl)
+ && DECL_INITIAL (decl) != NULL_TREE)
+ return true;
+
+ return false;
+}
+\f
void
c_print_identifier (FILE *file, tree node, int indent)
b->prev = scope->bindings;
scope->bindings = b;
+ if (decl_jump_unsafe (decl))
+ scope->has_jump_unsafe_decl = 1;
+
if (!name)
return;
p->left_stmt_expr = false;
}
-/* 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)
- return false;
-
- /* Always warn about crossing variably modified types. */
- if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == TYPE_DECL)
- && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
- return true;
-
- /* Otherwise, only warn if -Wgoto-misses-init and this is an
- initialized automatic decl. */
- if (warn_jump_misses_init
- && TREE_CODE (decl) == VAR_DECL
- && !TREE_STATIC (decl)
- && DECL_INITIAL (decl) != NULL_TREE)
- return true;
-
- return false;
-}
-
/* Update spot bindings P as we pop out of SCOPE. Return true if we
should push decls for a label. */
}
}
-/* 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 && !c_override_global_bindings_to_false;
}
void
{
struct c_label_vars *label_vars;
struct c_binding *b1;
+ bool hjud;
unsigned int ix;
struct c_goto_bindings *g;
label_vars = b->u.label;
b1 = label_vars->label_bindings.bindings_in_scope;
+ if (label_vars->label_bindings.scope == NULL)
+ hjud = false;
+ else
+ hjud = label_vars->label_bindings.scope->has_jump_unsafe_decl;
if (update_spot_bindings (scope, &label_vars->label_bindings))
{
/* This label is defined in this scope. */
- for (; b1 != NULL; b1 = b1->prev)
+ if (hjud)
{
- /* A goto from later in the function to this
- label will never see the initialization of
- B1, if any. Save it to issue a warning if
- needed. */
- if (decl_jump_unsafe (b1->decl))
- VEC_safe_push (tree, gc, label_vars->decls_in_scope,
- b1->decl);
+ for (; b1 != NULL; b1 = b1->prev)
+ {
+ /* A goto from later in the function to this
+ label will never see the initialization
+ of B1, if any. Save it to issue a
+ warning if needed. */
+ if (decl_jump_unsafe (b1->decl))
+ VEC_safe_push (tree, gc,
+ label_vars->decls_in_scope,
+ b1->decl);
+ }
}
}
|| TREE_NO_WARNING (olddecl))
return true; /* Allow OLDDECL to continue in use. */
- if (pedantic && !flag_isoc1x)
+ if (variably_modified_type_p (newtype, NULL))
{
- pedwarn (input_location, OPT_pedantic,
- "redefinition of typedef %q+D", newdecl);
+ error ("redefinition of typedef %q+D with variably modified type",
+ newdecl);
locate_old_decl (olddecl);
}
- else if (variably_modified_type_p (newtype, NULL))
+ else if (pedantic && !flag_isoc1x)
{
- /* Whether there is a constraint violation for the types not
- being the same cannot be determined at compile time; a
- warning that there may be one at runtime is considered
- appropriate (WG14 reflector message 11743, 8 May 2009). */
- warning (0, "redefinition of typedef %q+D may be a constraint "
- "violation at runtime", newdecl);
+ pedwarn (input_location, OPT_pedantic,
+ "redefinition of typedef %q+D", newdecl);
locate_old_decl (olddecl);
}
/* We have a goto to this label. The goto is going forward. In
g->scope, the goto is going to skip any binding which was
defined after g->bindings_in_scope. */
- for (b = g->goto_bindings.scope->bindings;
- b != g->goto_bindings.bindings_in_scope;
- b = b->prev)
+ if (g->goto_bindings.scope->has_jump_unsafe_decl)
{
- if (decl_jump_unsafe (b->decl))
- warn_about_goto (g->loc, label, b->decl);
+ for (b = g->goto_bindings.scope->bindings;
+ b != g->goto_bindings.bindings_in_scope;
+ b = b->prev)
+ {
+ if (decl_jump_unsafe (b->decl))
+ warn_about_goto (g->loc, label, b->decl);
+ }
}
/* We also need to warn about decls defined in any scopes
scope = scope->outer)
{
gcc_assert (scope != NULL);
- if (scope == label_vars->label_bindings.scope)
- b = label_vars->label_bindings.bindings_in_scope;
- else
- b = scope->bindings;
- for (; b != NULL; b = b->prev)
+ if (scope->has_jump_unsafe_decl)
{
- if (decl_jump_unsafe (b->decl))
- warn_about_goto (g->loc, label, b->decl);
+ if (scope == label_vars->label_bindings.scope)
+ b = label_vars->label_bindings.bindings_in_scope;
+ else
+ b = scope->bindings;
+ for (; b != NULL; b = b->prev)
+ {
+ if (decl_jump_unsafe (b->decl))
+ warn_about_goto (g->loc, label, b->decl);
+ }
}
}
struct c_binding *b;
gcc_assert (scope != NULL);
+
+ if (!scope->has_jump_unsafe_decl)
+ continue;
+
for (b = scope->bindings; b != NULL; b = b->prev)
{
if (decl_jump_unsafe (b->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;
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))
{
}
}
-/* 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.
const char *errmsg;
tree expr_dummy;
bool expr_const_operands_dummy;
+ enum c_declarator_kind first_non_attr_kind;
if (TREE_CODE (type) == ERROR_MARK)
return error_mark_node;
{
const struct c_declarator *decl = declarator;
+ first_non_attr_kind = cdk_attrs;
while (decl)
switch (decl->kind)
{
case cdk_pointer:
funcdef_syntax = (decl->kind == cdk_function);
decl = decl->declarator;
+ if (first_non_attr_kind == cdk_attrs)
+ first_non_attr_kind = decl->kind;
break;
case cdk_attrs:
loc = decl->id_loc;
if (decl->u.id)
name = decl->u.id;
+ if (first_non_attr_kind == cdk_attrs)
+ first_non_attr_kind = decl->kind;
decl = 0;
break;
error_at (loc, "conflicting named address spaces (%s vs %s)",
c_addr_space_name (as1), c_addr_space_name (as2));
- if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
+ if ((TREE_CODE (type) == ARRAY_TYPE
+ || first_non_attr_kind == cdk_array)
+ && TYPE_QUALS (element_type))
type = TYPE_MAIN_VARIANT (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
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",
}
}
- /* Complain about arrays of incomplete types. */
+ /* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
{
error_at (loc, "array type has incomplete element type");
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 (storage_class == csc_register || threadp)
{
error_at (loc, "invalid storage class for function %qE", name);
- }
+ }
else if (current_scope != file_scope)
{
/* Function declaration not at file scope. Storage
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
|| TREE_CODE (type) == UNION_TYPE);
bool ok = false;
- if (type_ok)
+ if (type_ok
+ && (flag_ms_extensions
+ || flag_plan9_extensions
+ || !declspecs->typedef_p))
{
if (flag_ms_extensions || flag_plan9_extensions)
ok = true;
- else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
+ else if (TYPE_NAME (type) == NULL)
ok = true;
else
ok = false;
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. */
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
/* 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 (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. */