/* 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
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "intl.h"
#include "tree.h"
#include "tree-inline.h"
-#include "rtl.h"
#include "flags.h"
#include "function.h"
#include "output.h"
-#include "expr.h"
#include "c-tree.h"
#include "toplev.h"
-#include "ggc.h"
#include "tm_p.h"
#include "cpplib.h"
#include "target.h"
#include "debug.h"
#include "opts.h"
#include "timevar.h"
-#include "c-common.h"
-#include "c-pragma.h"
+#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
#include "c-lang.h"
#include "langhooks.h"
#include "tree-mudflap.h"
-#include "gimple.h"
#include "tree-iterator.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
#include "tree-dump.h"
#include "cgraph.h"
#include "hashtab.h"
-#include "libfuncs.h"
-#include "except.h"
#include "langhooks-def.h"
#include "pointer-set.h"
-#include "gimple.h"
#include "plugin.h"
+#include "c-family/c-ada-spec.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
binding_freelist = b->prev;
}
else
- b = GGC_NEW (struct c_binding);
+ b = ggc_alloc_c_binding ();
b->shadowed = 0;
b->decl = decl;
record_inline_static (location_t loc, tree func, tree decl,
enum c_inline_static_type type)
{
- struct c_inline_static *csi = GGC_NEW (struct c_inline_static);
+ struct c_inline_static *csi = ggc_alloc_c_inline_static ();
csi->location = loc;
csi->function = func;
csi->static_decl = decl;
scope_freelist = scope->outer;
}
else
- scope = GGC_CNEW (struct c_scope);
+ scope = ggc_alloc_cleared_c_scope ();
/* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */
if (current_scope)
/* Update the bindings of any goto statements associated
with this label. */
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
update_spot_bindings (scope, &g->goto_bindings);
}
}
{
tree file_decl = build_decl (UNKNOWN_LOCATION,
TRANSLATION_UNIT_DECL, 0, 0);
- TREE_CHAIN (file_decl) = all_translation_units;
+ DECL_CHAIN (file_decl) = all_translation_units;
all_translation_units = file_decl;
context = file_decl;
}
warn_for_unused_label (p);
/* Labels go in BLOCK_VARS. */
- TREE_CHAIN (p) = BLOCK_VARS (block);
+ DECL_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
gcc_assert (I_LABEL_BINDING (b->id) == b);
I_LABEL_BINDING (b->id) = b->shadowed;
case VAR_DECL:
/* Warnings for unused variables. */
- if (!TREE_USED (p)
+ if ((!TREE_USED (p) || !DECL_READ_P (p))
&& !TREE_NO_WARNING (p)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p)
&& scope != file_scope
&& scope != external_scope)
- warning (OPT_Wunused_variable, "unused variable %q+D", p);
+ {
+ if (!TREE_USED (p))
+ warning (OPT_Wunused_variable, "unused variable %q+D", p);
+ else if (DECL_CONTEXT (p) == current_function_decl)
+ warning_at (DECL_SOURCE_LOCATION (p),
+ OPT_Wunused_but_set_variable,
+ "variable %qD set but not used", p);
+ }
if (b->inner_comp)
{
binding in the home scope. */
if (!b->nested)
{
- TREE_CHAIN (p) = BLOCK_VARS (block);
+ DECL_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
}
else if (VAR_OR_FUNCTION_DECL_P (p))
}
if (b->locus != UNKNOWN_LOCATION)
DECL_SOURCE_LOCATION (extp) = b->locus;
- TREE_CHAIN (extp) = BLOCK_VARS (block);
+ DECL_CHAIN (extp) = BLOCK_VARS (block);
BLOCK_VARS (block) = extp;
}
/* If this is the file scope, and we are processing more
start_fname_decls ();
- for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
+ for (decl = visible_builtins; decl; decl = DECL_CHAIN (decl))
bind (DECL_NAME (decl), decl, file_scope,
/*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
}
continue;
label_vars = b->u.label;
++label_vars->label_bindings.stmt_exprs;
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
++g->goto_bindings.stmt_exprs;
}
}
label_vars->label_bindings.left_stmt_expr = true;
label_vars->label_bindings.stmt_exprs = 0;
}
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
{
--g->goto_bindings.stmt_exprs;
if (g->goto_bindings.stmt_exprs < 0)
/* 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.) */
+ header. (Conflicting redeclarations were handled above.) This
+ is allowed for C1X if the types are the same, not just
+ compatible. */
if (TREE_CODE (newdecl) == TYPE_DECL)
{
+ bool types_different = false;
+ int comptypes_result;
+
+ comptypes_result
+ = comptypes_check_different_types (oldtype, newtype, &types_different);
+
+ if (comptypes_result != 1 || types_different)
+ {
+ error ("redefinition of typedef %q+D with different type", newdecl);
+ locate_old_decl (olddecl);
+ return false;
+ }
+
if (DECL_IN_SYSTEM_HEADER (newdecl)
|| DECL_IN_SYSTEM_HEADER (olddecl)
|| TREE_NO_WARNING (newdecl)
|| TREE_NO_WARNING (olddecl))
return true; /* Allow OLDDECL to continue in use. */
- error ("redefinition of typedef %q+D", newdecl);
- locate_old_decl (olddecl);
- return false;
+ if (pedantic && !flag_isoc1x)
+ {
+ pedwarn (input_location, OPT_pedantic,
+ "redefinition of typedef %q+D", newdecl);
+ locate_old_decl (olddecl);
+ }
+ else if (variably_modified_type_p (newtype, NULL))
+ {
+ /* 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);
+ locate_old_decl (olddecl);
+ }
+
+ return true;
}
/* Function declarations can either be 'static' or 'extern' (no
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
- gimple_set_body (newdecl, gimple_body (olddecl));
DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
- for (t = DECL_ARGUMENTS (newdecl); t ; t = TREE_CHAIN (t))
+ for (t = DECL_ARGUMENTS (newdecl); t ; t = DECL_CHAIN (t))
DECL_CONTEXT (t) = newdecl;
/* See if we've got a function to instantiate from. */
TREE_USED (newdecl) = 1;
else if (TREE_USED (newdecl))
TREE_USED (olddecl) = 1;
+ if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
+ DECL_READ_P (newdecl) |= DECL_READ_P (olddecl);
+ if (DECL_PRESERVE_P (olddecl))
+ DECL_PRESERVE_P (newdecl) = 1;
+ else if (DECL_PRESERVE_P (newdecl))
+ DECL_PRESERVE_P (olddecl) = 1;
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
switch (TREE_CODE (olddecl))
{
case FUNCTION_DECL:
- gimple_set_body (olddecl, gimple_body (newdecl));
- /* fall through */
-
case FIELD_DECL:
case VAR_DECL:
case PARM_DECL:
else
{
error_at (loc, "%qE undeclared (first use in this function)", id);
-
if (!already)
{
- error_at (loc, "(Each undeclared identifier is reported only once");
- error_at (loc, "for each function it appears in.)");
+ inform (loc, "each undeclared identifier is reported only"
+ " once for each function it appears in");
already = true;
}
DECL_CONTEXT (label) = current_function_decl;
DECL_MODE (label) = VOIDmode;
- label_vars = GGC_NEW (struct c_label_vars);
+ label_vars = ggc_alloc_c_label_vars ();
label_vars->shadowed = NULL;
set_spot_bindings (&label_vars->label_bindings, defining);
label_vars->decls_in_scope = make_tree_vector ();
{
struct c_goto_bindings *g;
- g = GGC_NEW (struct c_goto_bindings);
+ g = ggc_alloc_c_goto_bindings ();
g->loc = loc;
set_spot_bindings (&g->goto_bindings, true);
VEC_safe_push (c_goto_bindings_p, gc, label_vars->gotos, g);
...
goto lab;
Issue a warning or error. */
- for (ix = 0; VEC_iterate (tree, label_vars->decls_in_scope, ix, decl); ++ix)
+ FOR_EACH_VEC_ELT (tree, label_vars->decls_in_scope, ix, decl)
warn_about_goto (loc, label, decl);
if (label_vars->label_bindings.left_stmt_expr)
unsigned int ix;
struct c_goto_bindings *g;
- for (ix = 0;
- VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
- ++ix)
+ FOR_EACH_VEC_ELT (c_goto_bindings_p, label_vars->gotos, ix, g)
{
struct c_binding *b;
struct c_scope *scope;
using preprocessed headers. */
input_location = BUILTINS_LOCATION;
- build_common_tree_nodes (flag_signed_char, false);
+ build_common_tree_nodes (flag_signed_char);
c_common_nodes_and_builtins ();
the __FUNCTION__ is believed to appear in K&R style function
parameter declarator. In that case we still don't have
function_scope. */
- && (!errorcount || current_function_scope))
+ && (!seen_error () || current_function_scope))
{
DECL_CONTEXT (decl) = current_function_decl;
bind (id, decl, current_function_scope,
needing to be explicitly declared. See push_file_scope. */
if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
{
- TREE_CHAIN (decl) = visible_builtins;
+ DECL_CHAIN (decl) = visible_builtins;
visible_builtins = decl;
}
needing to be explicitly declared. See push_file_scope. */
if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
{
- TREE_CHAIN (decl) = visible_builtins;
+ DECL_CHAIN (decl) = visible_builtins;
visible_builtins = decl;
}
if (ce->kind == cdk_function)
{
tree args = ce->u.arg_info->parms;
- for (; args; args = TREE_CHAIN (args))
+ for (; args; args = DECL_CHAIN (args))
{
tree type = TREE_TYPE (args);
if (type && INTEGRAL_TYPE_P (type)
return tem;
}
+/* Subroutine of finish_decl. TYPE is the type of an uninitialized object
+ DECL or the non-array element type if DECL is an uninitialized array.
+ If that type has a const member, diagnose this. */
+
+static void
+diagnose_uninitialized_cst_member (tree decl, tree type)
+{
+ tree field;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ tree field_type;
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ field_type = strip_array_types (TREE_TYPE (field));
+
+ if (TYPE_QUALS (field_type) & TYPE_QUAL_CONST)
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+ "uninitialized const member in %qT is invalid in C++",
+ strip_array_types (TREE_TYPE (decl)));
+ inform (DECL_SOURCE_LOCATION (field), "%qD should be initialized", field);
+ }
+
+ if (TREE_CODE (field_type) == RECORD_TYPE
+ || TREE_CODE (field_type) == UNION_TYPE)
+ diagnose_uninitialized_cst_member (decl, field_type);
+ }
+}
+
/* Finish processing of a declaration;
install its initial value.
If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
}
if (TREE_USED (type))
- TREE_USED (decl) = 1;
+ {
+ TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
+ }
}
/* If this is a function and an assembler name is specified, reset DECL_RTL
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
TREE_USED (cleanup_decl) = 1;
+ DECL_READ_P (decl) = 1;
push_cleanup (decl, cleanup, false);
}
if (warn_cxx_compat
&& TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl)
&& !DECL_EXTERNAL (decl)
&& DECL_INITIAL (decl) == NULL_TREE)
- warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
- "uninitialized const %qD is invalid in C++", decl);
+ {
+ type = strip_array_types (type);
+ if (TREE_READONLY (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+ "uninitialized const %qD is invalid in C++", decl);
+ else if ((TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
+ && C_TYPE_FIELDS_READONLY (type))
+ diagnose_uninitialized_cst_member (decl, type);
+ }
}
/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
tree complit;
tree stmt;
- if (type == error_mark_node)
+ if (type == error_mark_node
+ || init == error_mark_node)
return error_mark_node;
decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
TREE_STATIC (decl) = (current_scope == file_scope);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
TREE_TYPE (decl) = type;
TREE_READONLY (decl) = TYPE_READONLY (type);
store_init_value (loc, decl, init, NULL_TREE);
x = TYPE_FIELDS (type);
if (x == NULL_TREE)
return false;
- while (TREE_CHAIN (x) != NULL_TREE)
- x = TREE_CHAIN (x);
+ while (DECL_CHAIN (x) != NULL_TREE)
+ x = DECL_CHAIN (x);
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
return true;
return false;
case UNION_TYPE:
- for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
+ for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
{
if (flexible_array_type_p (TREE_TYPE (x)))
return true;
gcc_assert (itype);
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
}
if (array_parm_vla_unspec_p)
{
/* The type is complete. C99 6.7.5.2p4 */
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
}
}
the formal parameter list of this FUNCTION_TYPE to point to
the FUNCTION_TYPE node itself. */
{
- tree link;
+ c_arg_tag *tag;
+ unsigned ix;
- for (link = arg_info->tags;
- link;
- link = TREE_CHAIN (link))
- TYPE_CONTEXT (TREE_VALUE (link)) = type;
+ FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+ TYPE_CONTEXT (tag->type) = type;
}
break;
}
pedwarn (loc, OPT_pedantic,
"ISO C forbids qualified function types");
- /* GNU C interprets a volatile-qualified function type to indicate
- that the function does not return. */
- if ((type_quals & TYPE_QUAL_VOLATILE)
- && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
- warning_at (loc, 0, "%<noreturn%> function returns non-void value");
-
/* Every function declaration is an external reference
(DECL_EXTERNAL) except for those which are not at file
scope and are explicitly declared "auto". This is
for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
parm;
- parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
+ parm = DECL_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
{
type = TREE_VALUE (typelt);
if (type == error_mark_node)
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
+ arg_types = NULL_TREE;
}
else if (VOID_TYPE_P (type))
{
error (errmsg);
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
+ arg_types = NULL_TREE;
}
if (DECL_NAME (parm) && TREE_USED (parm))
}
}
+/* Allocate and initialize a c_arg_info structure from the parser's
+ obstack. */
+
+struct c_arg_info *
+build_arg_info (void)
+{
+ struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info);
+ ret->parms = NULL_TREE;
+ ret->tags = NULL;
+ ret->types = NULL_TREE;
+ ret->others = NULL_TREE;
+ ret->pending_sizes = NULL;
+ ret->had_vla_unspec = 0;
+ return ret;
+}
+
/* Take apart the current scope and return a c_arg_info structure with
info on a parameter list just parsed.
get_parm_info (bool ellipsis)
{
struct c_binding *b = current_scope->bindings;
- struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
- struct c_arg_info);
+ struct c_arg_info *arg_info = build_arg_info ();
+
tree parms = 0;
- tree tags = 0;
+ VEC(c_arg_tag,gc) *tags = NULL;
tree types = 0;
tree others = 0;
static bool explained_incomplete_types = false;
bool gave_void_only_once_err = false;
- arg_info->parms = 0;
- arg_info->tags = 0;
- arg_info->types = 0;
- arg_info->others = 0;
- arg_info->pending_sizes = 0;
arg_info->had_vla_unspec = current_scope->had_vla_unspec;
/* The bindings in this scope must not get put into a block.
{
tree decl = b->decl;
tree type = TREE_TYPE (decl);
+ c_arg_tag *tag;
const char *keyword;
switch (TREE_CODE (decl))
else
{
/* Valid parameter, add it to the list. */
- TREE_CHAIN (decl) = parms;
+ DECL_CHAIN (decl) = parms;
parms = decl;
/* Since there is a prototype, args are passed in their
}
}
- tags = tree_cons (b->id, decl, tags);
+ tag = VEC_safe_push (c_arg_tag, gc, tags, NULL);
+ tag->id = b->id;
+ tag->type = decl;
break;
case CONST_DECL:
type itself. FUNCTION_DECLs appear when there is an implicit
function declaration in the parameter list. */
- TREE_CHAIN (decl) = others;
+ /* When we reinsert this decl in the function body, we need
+ to reconstruct whether it was marked as nested. */
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ ? b->nested
+ : !b->nested);
+ DECL_CHAIN (decl) = others;
others = decl;
/* fall through */
Otherwise this is a forward declaration of a structure tag.
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).
If MS extensions are enabled and foo names a structure, then
again this is an anonymous struct.
Otherwise this is an error.
|| TREE_CODE (type) == UNION_TYPE);
bool ok = false;
- if (type_ok
- && (flag_ms_extensions || !declspecs->typedef_p))
+ if (type_ok)
{
if (flag_ms_extensions)
ok = true;
- else if (flag_iso)
- ok = false;
- else if (TYPE_NAME (type) == NULL)
+ else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
ok = true;
else
ok = false;
pedwarn (loc, 0, "declaration does not declare anything");
return NULL_TREE;
}
- pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions");
+ if (!flag_isoc1x)
+ {
+ if (flag_isoc99)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C99 doesn%'t support unnamed structs/unions");
+ else
+ pedwarn (loc, OPT_pedantic,
+ "ISO C90 doesn%'t support unnamed structs/unions");
+ }
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
return value;
}
\f
+/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
+ to HTAB, giving errors for any duplicates. */
+
+static void
+detect_field_duplicates_hash (tree fieldlist, htab_t htab)
+{
+ tree x, y;
+ void **slot;
+
+ for (x = fieldlist; x ; x = DECL_CHAIN (x))
+ if ((y = DECL_NAME (x)) != 0)
+ {
+ slot = htab_find_slot (htab, y, INSERT);
+ if (*slot)
+ {
+ error ("duplicate member %q+D", x);
+ DECL_NAME (x) = NULL_TREE;
+ }
+ *slot = y;
+ }
+ else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+ detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+}
+
/* Generate an error for any duplicate field names in FIELDLIST. Munge
the list such that this does not present a problem later. */
This is trivially true if there are zero or one fields. */
if (!fieldlist)
return;
- x = TREE_CHAIN (fieldlist);
+ x = DECL_CHAIN (fieldlist);
if (!x)
return;
do {
timeout--;
- x = TREE_CHAIN (x);
+ if (DECL_NAME (x) == NULL_TREE
+ && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+ timeout = 0;
+ x = DECL_CHAIN (x);
} while (timeout > 0 && x);
- /* If there were "few" fields, avoid the overhead of allocating
- a hash table. Instead just do the nested traversal thing. */
+ /* If there were "few" fields and no anonymous structures or unions,
+ avoid the overhead of allocating a hash table. Instead just do
+ the nested traversal thing. */
if (timeout > 0)
{
- for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x))
+ for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
if (DECL_NAME (x))
{
for (y = fieldlist; y != x; y = TREE_CHAIN (y))
else
{
htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
- void **slot;
-
- for (x = fieldlist; x ; x = TREE_CHAIN (x))
- if ((y = DECL_NAME (x)) != 0)
- {
- slot = htab_find_slot (htab, y, INSERT);
- if (*slot)
- {
- error ("duplicate member %q+D", x);
- DECL_NAME (x) = NULL_TREE;
- }
- *slot = y;
- }
+ detect_field_duplicates_hash (fieldlist, htab);
htab_delete (htab);
}
}
because the flag is used to issue visibility warnings, and we
only want to issue those warnings if the type is referenced
outside of the struct declaration. */
- for (ix = 0; VEC_iterate (tree, struct_parse_info->struct_types, ix, x); ++ix)
+ FOR_EACH_VEC_ELT (tree, struct_parse_info->struct_types, ix, x)
C_TYPE_DEFINED_IN_STRUCT (x) = 1;
/* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of
a pointer_set because identifiers are interned. */
struct pointer_set_t *tset = pointer_set_create ();
- for (ix = 0;
- VEC_iterate (tree, struct_parse_info->typedefs_seen, ix, x);
- ++ix)
+ FOR_EACH_VEC_ELT (tree, struct_parse_info->typedefs_seen, ix, x)
pointer_set_insert (tset, DECL_NAME (x));
- for (x = fieldlist; x != NULL_TREE; x = TREE_CHAIN (x))
+ for (x = fieldlist; x != NULL_TREE; x = DECL_CHAIN (x))
{
if (pointer_set_contains (tset, DECL_NAME (x)))
{
/* For each field which has a binding and which was not defined in
an enclosing struct, clear the in_struct field. */
- for (ix = 0;
- VEC_iterate (c_binding_ptr, struct_parse_info->fields, ix, b);
- ++ix)
+ FOR_EACH_VEC_ELT (c_binding_ptr, struct_parse_info->fields, ix, b)
b->in_struct = 0;
}
if (pedantic)
{
- for (x = fieldlist; x; x = TREE_CHAIN (x))
- if (DECL_NAME (x) != 0)
- break;
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
+ {
+ if (DECL_NAME (x) != 0)
+ break;
+ if (flag_isoc1x
+ && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+ break;
+ }
if (x == 0)
{
until now.) */
saw_named_field = 0;
- for (x = fieldlist; x; x = TREE_CHAIN (x))
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
{
if (TREE_TYPE (x) == error_mark_node)
continue;
else
{
/* A field that is pseudo-const makes the structure likewise. */
- tree t1 = TREE_TYPE (x);
- while (TREE_CODE (t1) == ARRAY_TYPE)
- t1 = TREE_TYPE (t1);
+ tree t1 = strip_array_types (TREE_TYPE (x));
if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (t1))
C_TYPE_FIELDS_READONLY (t) = 1;
"flexible array member in union");
TREE_TYPE (x) = error_mark_node;
}
- else if (TREE_CHAIN (x) != NULL_TREE)
+ else if (DECL_CHAIN (x) != NULL_TREE)
{
error_at (DECL_SOURCE_LOCATION (x),
"flexible array member not at end of struct");
pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic,
"invalid use of structure with flexible array member");
- if (DECL_NAME (x))
+ if (DECL_NAME (x)
+ || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
saw_named_field = 1;
}
DECL_INITIAL (*fieldlistp) = 0;
}
else
- fieldlistp = &TREE_CHAIN (*fieldlistp);
+ fieldlistp = &DECL_CHAIN (*fieldlistp);
}
/* Now we have the truly final field list.
{
int len = 0;
- for (x = fieldlist; x; x = TREE_CHAIN (x))
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
{
if (len > 15 || DECL_NAME (x) == NULL)
break;
ensure that this lives as long as the rest of the struct decl.
All decls in an inline function need to be saved. */
- space = GGC_CNEW (struct lang_type);
- space2 = GGC_NEWVAR (struct sorted_fields_type,
- sizeof (struct sorted_fields_type) + len * sizeof (tree));
+ space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+ space2 = ggc_alloc_sorted_fields_type
+ (sizeof (struct sorted_fields_type) + len * sizeof (tree));
len = 0;
space->s = space2;
field_array = &space2->elts[0];
- for (x = fieldlist; x; x = TREE_CHAIN (x))
+ for (x = fieldlist; x; x = DECL_CHAIN (x))
{
field_array[len++] = x;
/* If this was supposed to be a transparent union, but we can't
make it one, warn and turn off the flag. */
if (TREE_CODE (t) == UNION_TYPE
- && TYPE_TRANSPARENT_UNION (t)
+ && TYPE_TRANSPARENT_AGGR (t)
&& (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
{
- TYPE_TRANSPARENT_UNION (t) = 0;
+ TYPE_TRANSPARENT_AGGR (t) = 0;
warning_at (loc, 0, "union cannot be made transparent");
}
/* Record the min/max values so that we can warn about bit-field
enumerations that are too small for the values. */
- lt = GGC_CNEW (struct lang_type);
+ lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
lt->enum_min = minnode;
lt->enum_max = maxnode;
TYPE_LANG_SPECIFIC (enumtype) = lt;
/* Build and install a CONST_DECL for one value of the
current enumeration type (one that was begun with start_enum).
- LOC is the location of the enumerator.
+ DECL_LOC is the location of the enumerator.
+ LOC is the location of the '=' operator if any, DECL_LOC otherwise.
Return a tree-list containing the CONST_DECL and its value.
Assignment of sequential values by default is handled here. */
tree
-build_enumerator (location_t loc,
+build_enumerator (location_t decl_loc, location_t loc,
struct c_enum_contents *the_enum, tree name, tree value)
{
tree decl, type;
>= TYPE_PRECISION (integer_type_node)
&& TYPE_UNSIGNED (type)));
- decl = build_decl (loc, CONST_DECL, name, type);
+ decl = build_decl (decl_loc, CONST_DECL, name, type);
DECL_INITIAL (decl) = convert (type, value);
pushdecl (decl);
error_mark_node is replaced below (in pop_scope) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
+ /* A nested function is not global. */
+ if (current_function_decl != 0)
+ TREE_PUBLIC (decl1) = 0;
+
/* If this definition isn't a prototype and we had a prototype declaration
before, copy the arg type info from that prototype. */
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
- /* A nested function is not global. */
- if (current_function_decl != 0)
- TREE_PUBLIC (decl1) = 0;
-
/* This is the earliest point at which we might know the assembler
name of the function. Thus, if it's set before this, die horribly. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
{
tree decl;
+ c_arg_tag *tag;
+ unsigned ix;
if (current_scope->bindings)
{
/* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */
- for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->parms; decl; decl = DECL_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
DECL_ARGUMENTS (fndecl) = arg_info->parms;
/* Now make all the ancillary declarations visible, likewise. */
- for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->others; decl; decl = DECL_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
bind (DECL_NAME (decl), decl, current_scope,
- /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
+ /*invisible=*/false,
+ /*nested=*/(TREE_CODE (decl) == FUNCTION_DECL),
+ UNKNOWN_LOCATION);
}
/* And all the tag declarations. */
- for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
- if (TREE_PURPOSE (decl))
- bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
+ FOR_EACH_VEC_ELT_REVERSE (c_arg_tag, arg_info->tags, ix, tag)
+ if (tag->id)
+ bind (tag->id, tag->type, current_scope,
/*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
}
for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
- TREE_CHAIN (last) = TREE_PURPOSE (parm);
+ DECL_CHAIN (last) = TREE_PURPOSE (parm);
last = TREE_PURPOSE (parm);
}
- TREE_CHAIN (last) = 0;
+ DECL_CHAIN (last) = 0;
}
pointer_set_destroy (seen_args);
type = current_function_prototype_arg_types;
parm || (type && TREE_VALUE (type) != error_mark_node
&& (TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node));
- parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
+ parm = DECL_CHAIN (parm), type = TREE_CHAIN (type))
{
if (parm == 0 || type == 0
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
tree actual = 0, last = 0, type;
- for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
+ for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
{
type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
if (last)
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;
- for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
- add_stmt (TREE_VALUE (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
\f
/* Finish up a function declaration and compile that function
- all the way to assembler language output. The free the storage
+ all the way to assembler language output. Then free the storage
for the function definition.
This is called after parsing the body of the function definition. */
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
tree args = DECL_ARGUMENTS (fndecl);
- for (; args; args = TREE_CHAIN (args))
+ for (; args; args = DECL_CHAIN (args))
{
tree type = TREE_TYPE (args);
if (INTEGRAL_TYPE_P (type)
&& !current_function_returns_value && !current_function_returns_null
/* Don't complain if we are no-return. */
&& !current_function_returns_abnormally
+ /* Don't complain if we are declared noreturn. */
+ && !TREE_THIS_VOLATILE (fndecl)
/* Don't warn for main(). */
&& !MAIN_NAME_P (DECL_NAME (fndecl))
/* Or if they didn't actually specify a return type. */
TREE_NO_WARNING (fndecl) = 1;
}
+ /* Complain about parameters that are only set, but never otherwise used. */
+ if (warn_unused_but_set_parameter)
+ {
+ tree decl;
+
+ for (decl = DECL_ARGUMENTS (fndecl);
+ decl;
+ decl = DECL_CHAIN (decl))
+ if (TREE_USED (decl)
+ && TREE_CODE (decl) == PARM_DECL
+ && !DECL_READ_P (decl)
+ && DECL_NAME (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !TREE_NO_WARNING (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl),
+ OPT_Wunused_but_set_parameter,
+ "parameter %qD set but not used", decl);
+ }
+
/* Store the end of the function, so that we get good line number
info for the epilogue. */
cfun->function_end_locus = input_location;
c_push_function_context (void)
{
struct language_function *p;
- p = GGC_NEW (struct language_function);
+ p = ggc_alloc_language_function ();
cfun->language = p;
p->base.x_stmt_tree = c_stmt_tree;
error_at (loc,
("both %<long%> and %<void%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_int128)
+ error_at (loc,
+ ("both %<long%> and %<__int128%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
error_at (loc,
("both %<long%> and %<_Bool%> in "
error_at (loc,
("both %<short%> and %<void%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_int128)
+ error_at (loc,
+ ("both %<short%> and %<__int128%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
error_at (loc,
("both %<short%> and %<_Bool%> in "
dupe = specs->saturating_p;
pedwarn (loc, OPT_pedantic,
"ISO C does not support saturating types");
- if (specs->typespec_word == cts_void)
+ if (specs->typespec_word == cts_int128)
+ {
+ error_at (loc,
+ ("both %<_Sat%> and %<__int128%> in "
+ "declaration specifiers"));
+ }
+ else if (specs->typespec_word == cts_void)
error_at (loc,
("both %<_Sat%> and %<void%> in "
"declaration specifiers"));
else
{
/* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
- "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
+ "__int128", "_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
if (specs->typespec_word != cts_none)
{
error_at (loc,
}
switch (i)
{
+ case RID_INT128:
+ if (int128_integer_type_node == NULL_TREE)
+ {
+ error_at (loc, "%<__int128%> is not supported for this target");
+ return specs;
+ }
+ if (!in_system_header)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C does not support %<__int128%> type");
+
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<__int128%> and %<long%> in "
+ "declaration specifiers"));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<__int128%> in "
+ "declaration specifiers"));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<__int128%> and %<short%> in "
+ "declaration specifiers"));
+ else
+ specs->typespec_word = cts_int128;
+ return specs;
case RID_VOID:
if (specs->long_p)
error_at (loc,
specs->type = build_complex_type (specs->type);
}
break;
+ case cts_int128:
+ gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
+ gcc_assert (!(specs->signed_p && specs->unsigned_p));
+ specs->type = (specs->unsigned_p
+ ? int128_unsigned_type_node
+ : int128_integer_type_node);
+ if (specs->complex_p)
+ {
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C does not support complex integer types");
+ specs->type = build_complex_type (specs->type);
+ }
+ break;
case cts_int:
gcc_assert (!(specs->long_p && specs->short_p));
gcc_assert (!(specs->signed_p && specs->unsigned_p));
bool reconsider;
/* Process the decls in the order they were written. */
- for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl; decl = DECL_CHAIN (decl))
{
/* Check for used but undefined static functions using the C
standard's definition of "used", and set TREE_NO_WARNING so
do
{
reconsider = false;
- for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl; decl = DECL_CHAIN (decl))
reconsider |= wrapup_global_declaration_2 (decl);
}
while (reconsider);
- for (decl = globals; decl; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl; decl = DECL_CHAIN (decl))
check_global_declaration_1 (decl);
}
{
tree decl;
- for (decl = globals; decl ; decl = TREE_CHAIN (decl))
+ for (decl = globals; decl ; decl = DECL_CHAIN (decl))
debug_hooks->global_decl (decl);
}
+/* Callback to collect a source_ref from a DECL. */
+
+static void
+collect_source_ref_cb (tree decl)
+{
+ if (!DECL_IS_BUILTIN (decl))
+ collect_source_ref (LOCATION_FILE (decl_sloc (decl, false)));
+}
+
+/* Collect all references relevant to SOURCE_FILE. */
+
+static void
+collect_all_refs (const char *source_file)
+{
+ tree t;
+
+ for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ collect_ada_nodes (BLOCK_VARS (DECL_INITIAL (t)), source_file);
+}
+
+/* Iterate over all global declarations and call CALLBACK. */
+
+static void
+for_each_global_decl (void (*callback) (tree decl))
+{
+ tree t;
+ tree decls;
+ tree decl;
+
+ for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ {
+ decls = DECL_INITIAL (t);
+ 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;
if (pch_file)
return;
- /* Don't waste time on further processing if -fsyntax-only.
- Continue for warning and errors issued during lowering though. */
- if (flag_syntax_only)
- return;
-
/* Close the external scope. */
ext_block = pop_scope ();
external_scope = 0;
gcc_assert (!current_scope);
+ /* Handle -fdump-ada-spec[-slim]. */
+ if (dump_enabled_p (TDI_ada))
+ {
+ /* Build a table of files to generate specs for */
+ if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM)
+ collect_source_ref (main_input_filename);
+ else
+ for_each_global_decl (collect_source_ref_cb);
+
+ dump_ada_specs (collect_all_refs, NULL);
+ }
+
if (ext_block)
{
tree tmp = BLOCK_VARS (ext_block);
/* Process all file scopes in this compilation, and the external_scope,
through wrapup_global_declarations and check_global_declarations. */
- for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ for (t = all_translation_units; t; t = DECL_CHAIN (t))
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block));
/* After cgraph has had a chance to emit everything that's going to
be emitted, output debug information for globals. */
- if (errorcount == 0 && sorrycount == 0)
+ if (!seen_error ())
{
timevar_push (TV_SYMOUT);
- for (t = all_translation_units; t; t = TREE_CHAIN (t))
+ for (t = all_translation_units; t; t = DECL_CHAIN (t))
c_write_global_declarations_2 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_2 (BLOCK_VARS (ext_block));
timevar_pop (TV_SYMOUT);
ext_block = NULL;
}
+/* Register reserved keyword WORD as qualifier for address space AS. */
+
+void
+c_register_addr_space (const char *word, addr_space_t as)
+{
+ int rid = RID_FIRST_ADDR_SPACE + as;
+ tree id;
+
+ /* Address space qualifiers are only supported
+ in C with GNU extensions enabled. */
+ if (c_dialect_objc () || flag_no_asm)
+ return;
+
+ id = get_identifier (word);
+ C_SET_RID_CODE (id, rid);
+ C_IS_RESERVED_WORD (id) = 1;
+ ridpointers [rid] = id;
+}
+
#include "gt-c-decl.h"