#include "opts.h"
#include "timevar.h"
#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
#include "c-family/c-pragma.h"
#include "c-lang.h"
#include "langhooks.h"
/* 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. */
{
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);
+ }
}
}
if (TREE_CODE (olddecl) != FUNCTION_DECL
|| !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
- || !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
- ||
- (TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
+ || !((!prototype_p (oldtype) && DECL_INITIAL (olddecl) == 0)
+ || (!prototype_p (newtype) && DECL_INITIAL (newdecl) == 0)))
return;
t = TYPE_ARG_TYPES (oldtype);
|| 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);
}
&& !C_DECL_DECLARED_BUILTIN (olddecl)
&& (!TREE_PUBLIC (newdecl)
|| (DECL_INITIAL (newdecl)
- && !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
+ && !prototype_p (TREE_TYPE (newdecl)))))
{
warning (OPT_Wshadow, "declaration of %q+D shadows "
"a built-in function", newdecl);
/* If we have a prototype after an old-style function definition,
the argument types must be checked specially. */
else if (DECL_INITIAL (olddecl)
- && !TYPE_ARG_TYPES (oldtype) && TYPE_ARG_TYPES (newtype)
+ && !prototype_p (oldtype) && prototype_p (newtype)
&& TYPE_ACTUAL_ARG_TYPES (oldtype)
&& !validate_proto_after_old_defn (newdecl, newtype, oldtype))
{
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);
+ && prototype_p (TREE_TYPE (newdecl)));
bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
- && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
+ && prototype_p (TREE_TYPE (olddecl)));
bool extern_changed = false;
/* For real parm decl following a forward decl, rechain the old decl
tree label;
struct c_label_vars *label_vars;
- if (current_function_decl == 0)
+ if (current_function_scope == 0)
{
error ("label %qE referenced outside of any function", name);
return 0;
/* 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))
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
- C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
+ C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
/* Should never be called on a symbol with a preexisting meaning. */
gcc_assert (!I_SYMBOL_BINDING (id));
tree id = DECL_NAME (decl);
const char *name = IDENTIFIER_POINTER (id);
- C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
+ C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type);
/* Should never be called on a symbol with a preexisting meaning. */
gcc_assert (!I_SYMBOL_BINDING (id));
warned = 1;
}
}
- else if (!declspecs->tag_defined_p
+ else if (declspecs->typespec_kind != ctsk_tagdef
+ && declspecs->typespec_kind != ctsk_tagfirstref
&& declspecs->storage_class != csc_none)
{
if (warned != 1)
warned = 1;
pending_xref_error ();
}
- else if (!declspecs->tag_defined_p
+ else if (declspecs->typespec_kind != ctsk_tagdef
+ && declspecs->typespec_kind != ctsk_tagfirstref
&& (declspecs->const_p
|| declspecs->volatile_p
|| declspecs->restrict_p
prototypes file (if requested). */
if (TREE_CODE (decl) == FUNCTION_DECL)
- gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0);
+ gen_aux_info_record (decl, 0, 0, prototype_p (TREE_TYPE (decl)));
/* ANSI specifies that a tentative definition which is not merged with
a non-tentative definition behaves exactly like a definition with an
void
check_compound_literal_type (location_t loc, struct c_type_name *type_name)
{
- if (warn_cxx_compat && type_name->specs->tag_defined_p)
+ if (warn_cxx_compat
+ && (type_name->specs->typespec_kind == ctsk_tagdef
+ || type_name->specs->typespec_kind == ctsk_tagfirstref))
warning_at (loc, OPT_Wc___compat,
"defining a type in a compound literal is invalid in C++");
}
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;
if (expr == NULL)
expr = &expr_dummy;
if (expr_const_operands == NULL)
{
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)
}
}
- /* 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");
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
else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
{
if (!funcdef_flag)
- pedwarn (input_location, 0, "parameter names (without types) in function declaration");
+ {
+ pedwarn (input_location, 0, "parameter names (without types) in function declaration");
+ arg_info->parms = NULL_TREE;
+ }
+ else
+ arg_info->parms = arg_info->types;
- arg_info->parms = arg_info->types;
arg_info->types = 0;
return 0;
}
|| 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;
/* First, see if there are more than "a few" fields.
This is trivially true if there are zero or one fields. */
- if (!fieldlist)
- return;
- x = DECL_CHAIN (fieldlist);
- if (!x)
+ if (!fieldlist || !DECL_CHAIN (fieldlist))
return;
+ x = fieldlist;
do {
timeout--;
if (DECL_NAME (x) == NULL_TREE
current_function_prototype_locus = UNKNOWN_LOCATION;
current_function_prototype_built_in = false;
current_function_prototype_arg_types = NULL_TREE;
- if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
+ if (!prototype_p (TREE_TYPE (decl1)))
{
if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
&& comptypes (TREE_TYPE (TREE_TYPE (decl1)),
/* Optionally warn of old-fashioned def with no previous prototype. */
if (warn_strict_prototypes
&& old_decl != error_mark_node
- && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
+ && !prototype_p (TREE_TYPE (decl1))
&& C_DECL_ISNT_PROTOTYPE (old_decl))
warning_at (loc, OPT_Wstrict_prototypes,
"function declaration isn%'t a prototype");
&& old_decl != 0
&& old_decl != error_mark_node
&& TREE_USED (old_decl)
- && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
+ && !prototype_p (TREE_TYPE (old_decl)))
warning_at (loc, OPT_Wmissing_prototypes,
"%qD was used with no prototype before its definition", decl1);
/* Optionally warn of any global def with no previous declaration. */
if (b && B_IN_CURRENT_SCOPE (b))
{
decl = b->decl;
+ /* Skip erroneous parameters. */
+ if (decl == error_mark_node)
+ continue;
/* If we got something other than a PARM_DECL it is an error. */
if (TREE_CODE (decl) != PARM_DECL)
error_at (DECL_SOURCE_LOCATION (decl),
finish_function (void)
{
tree fndecl = current_function_decl;
+
+ if (c_dialect_objc ())
+ objc_finish_function ();
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
/* 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);
}
}
ret->storage_class = csc_none;
ret->expr_const_operands = true;
ret->declspecs_seen_p = false;
- ret->type_seen_p = false;
+ ret->typespec_kind = ctsk_none;
ret->non_sc_seen_p = false;
ret->typedef_p = false;
- ret->tag_defined_p = false;
ret->explicit_signed_p = false;
ret->deprecated_p = false;
ret->default_int_p = false;
tree type = spec.spec;
specs->non_sc_seen_p = true;
specs->declspecs_seen_p = true;
- specs->type_seen_p = true;
+ specs->typespec_kind = spec.kind;
if (TREE_DEPRECATED (type))
specs->deprecated_p = true;
else
specs->type = TREE_TYPE (t);
}
- else if (TREE_CODE (type) != ERROR_MARK)
+ else
{
- if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
- specs->tag_defined_p = true;
- if (spec.kind == ctsk_typeof)
+ if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
{
specs->typedef_p = true;
if (spec.expr)
gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
&& !specs->signed_p && !specs->unsigned_p
&& !specs->complex_p);
+
+ /* Set a dummy type. */
+ if (TREE_CODE (specs->type) == ERROR_MARK)
+ specs->type = integer_type_node;
return specs;
}