Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: gcc/gcc/c-decl.c

Issue 3050029: [gcc] GCC 4.5.0=>4.5.1 (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/nacl-toolchain.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gcc/gcc/c-cppbuiltin.c ('k') | gcc/gcc/c-format.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gcc/gcc/c-decl.c
diff --git a/gcc/gcc/c-decl.c b/gcc/gcc/c-decl.c
index 64f8c939936de525d67de3a1324819166e6f0e05..b6ff3f476e6f57ad9372cd37ef71179e9a4a495c 100644
--- a/gcc/gcc/c-decl.c
+++ b/gcc/gcc/c-decl.c
@@ -1,6 +1,6 @@
/* 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.
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
+#include "c-lang.h"
#include "langhooks.h"
#include "tree-mudflap.h"
#include "gimple.h"
@@ -63,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks-def.h"
#include "pointer-set.h"
#include "gimple.h"
+#include "plugin.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -90,9 +92,6 @@ tree pending_invalid_xref;
/* File and line to appear in the eventual error message. */
location_t pending_invalid_xref_location;
-/* True means we've initialized exception handling. */
-bool c_eh_initialized_p;
-
/* The file and line that the prototype came from if this is an
old-style definition; used for diagnostics in
store_parm_decls_oldstyle. */
@@ -178,7 +177,7 @@ bool c_override_global_bindings_to_false;
suppress further errors about that identifier in the current
function.
- The ->type field stores the type of the declaration in this scope;
+ The ->u.type field stores the type of the declaration in this scope;
if NULL, the type is the type of the ->decl field. This is only of
relevance for objects with external or internal linkage which may
be redeclared in inner scopes, forming composite types that only
@@ -188,6 +187,9 @@ bool c_override_global_bindings_to_false;
scope) stores whether an incomplete array type at file scope was
completed at an inner scope to an array size other than 1.
+ The ->u.label field is used for labels. It points to a structure
+ which stores additional information used for warnings.
+
The depth field is copied from the scope structure that holds this
decl. It is used to preserve the proper ordering of the ->shadowed
field (see bind()) and also for a handful of special-case checks.
@@ -197,10 +199,12 @@ bool c_override_global_bindings_to_false;
in all such cases, the binding in the outer scope will have its
invisible bit true. */
-struct c_binding GTY((chain_next ("%h.prev")))
-{
+struct GTY((chain_next ("%h.prev"))) c_binding {
+ union GTY(()) { /* first so GTY desc can use decl */
+ tree GTY((tag ("0"))) type; /* the type in this scope */
+ struct c_label_vars * GTY((tag ("1"))) label; /* for warnings */
+ } GTY((desc ("TREE_CODE (%0.decl) == LABEL_DECL"))) u;
tree decl; /* the decl bound */
- tree type; /* the type in this scope */
tree id; /* the identifier it's bound to */
struct c_binding *prev; /* the previous decl in this scope */
struct c_binding *shadowed; /* the innermost decl shadowed by this one */
@@ -208,7 +212,8 @@ struct c_binding GTY((chain_next ("%h.prev")))
BOOL_BITFIELD invisible : 1; /* normal lookup should ignore this binding */
BOOL_BITFIELD nested : 1; /* do not set DECL_CONTEXT when popping */
BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
- /* one free bit */
+ BOOL_BITFIELD in_struct : 1; /* currently defined as struct field */
+ location_t locus; /* location for nested bindings */
};
#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
@@ -234,8 +239,7 @@ struct c_binding GTY((chain_next ("%h.prev")))
These describe the values of the identifier in the three different
namespaces defined by the language. */
-struct lang_identifier GTY(())
-{
+struct GTY(()) lang_identifier {
struct c_common_identifier common_id;
struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
struct c_binding *tag_binding; /* struct/union/enum tags */
@@ -248,16 +252,76 @@ extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
/* The resulting tree type. */
-union lang_tree_node
- 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))")))
-{
+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
+ {
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
generic;
struct lang_identifier GTY ((tag ("1"))) identifier;
};
+/* Track bindings and other things that matter for goto warnings. For
+ efficiency, we do not gather all the decls at the point of
+ definition. Instead, we point into the bindings structure. As
+ scopes are popped, we update these structures and gather the decls
+ that matter at that time. */
+
+struct GTY(()) c_spot_bindings {
+ /* The currently open scope which holds bindings defined when the
+ label was defined or the goto statement was found. */
+ struct c_scope *scope;
+ /* The bindings in the scope field which were defined at the point
+ of the label or goto. This lets us look at older or newer
+ bindings in the scope, as appropriate. */
+ struct c_binding *bindings_in_scope;
+ /* The number of statement expressions that have started since this
+ label or goto statement was defined. This is zero if we are at
+ the same statement expression level. It is positive if we are in
+ a statement expression started since this spot. It is negative
+ if this spot was in a statement expression and we have left
+ it. */
+ int stmt_exprs;
+ /* Whether we started in a statement expression but are no longer in
+ it. This is set to true if stmt_exprs ever goes negative. */
+ bool left_stmt_expr;
+};
+
+/* This structure is used to keep track of bindings seen when a goto
+ statement is defined. This is only used if we see the goto
+ statement before we see the label. */
+
+struct GTY(()) c_goto_bindings {
+ /* The location of the goto statement. */
+ location_t loc;
+ /* The bindings of the goto statement. */
+ struct c_spot_bindings goto_bindings;
+};
+
+typedef struct c_goto_bindings *c_goto_bindings_p;
+DEF_VEC_P(c_goto_bindings_p);
+DEF_VEC_ALLOC_P(c_goto_bindings_p,gc);
+
+/* The additional information we keep track of for a label binding.
+ These fields are updated as scopes are popped. */
+
+struct GTY(()) c_label_vars {
+ /* The shadowed c_label_vars, when one label shadows another (which
+ can only happen using a __label__ declaration). */
+ struct c_label_vars *shadowed;
+ /* The bindings when the label was defined. */
+ struct c_spot_bindings label_bindings;
+ /* A list of decls that we care about: decls about which we should
+ warn if a goto branches to this label from later in the function.
+ Decls are added to this list as scopes are popped. We only add
+ the decls that matter. */
+ VEC(tree,gc) *decls_in_scope;
+ /* A list of goto statements to this label. This is only used for
+ goto statements seen before the label was defined, so that we can
+ issue appropriate warnings for them. */
+ VEC(c_goto_bindings_p,gc) *gotos;
+};
+
/* Each c_scope structure describes the complete contents of one
scope. Four scopes are distinguished specially: the innermost or
current scope, the innermost function scope, the file scope (always
@@ -303,8 +367,7 @@ union lang_tree_node
pop_scope relies on this. */
-struct c_scope GTY((chain_next ("%h.outer")))
-{
+struct GTY((chain_next ("%h.outer"))) c_scope {
/* The scope containing this one. */
struct c_scope *outer;
@@ -344,6 +407,14 @@ struct c_scope GTY((chain_next ("%h.outer")))
/* True means make a BLOCK for this scope no matter what. */
BOOL_BITFIELD keep : 1;
+
+ /* True means that an unsuffixed float constant is _Decimal64. */
+ BOOL_BITFIELD float_const_decimal64 : 1;
+
+ /* True if this scope has any label bindings. This is used to speed
+ up searching for labels when popping scopes, particularly since
+ labels are normally only found at function scope. */
+ BOOL_BITFIELD has_label_bindings : 1;
};
/* The scope currently in effect. */
@@ -395,6 +466,32 @@ static GTY((deletable)) struct c_binding *binding_freelist;
t_->to##_last = f_->from##_last; \
} while (0)
+/* A c_inline_static structure stores details of a static identifier
+ referenced in a definition of a function that may be an inline
+ definition if no subsequent declaration of that function uses
+ "extern" or does not use "inline". */
+
+struct GTY((chain_next ("%h.next"))) c_inline_static {
+ /* The location for a diagnostic. */
+ location_t location;
+
+ /* The function that may be an inline definition. */
+ tree function;
+
+ /* The object or function referenced. */
+ tree static_decl;
+
+ /* What sort of reference this is. */
+ enum c_inline_static_type type;
+
+ /* The next such structure or NULL. */
+ struct c_inline_static *next;
+};
+
+/* List of static identifiers used or referenced in functions that may
+ be inline definitions. */
+static GTY(()) struct c_inline_static *c_inline_statics;
+
/* True means unconditionally make a BLOCK for the next scope pushed. */
static bool keep_next_level_flag;
@@ -405,13 +502,41 @@ static bool keep_next_level_flag;
static bool next_is_function_body;
+/* A VEC of pointers to c_binding structures. */
+
+typedef struct c_binding *c_binding_ptr;
+DEF_VEC_P(c_binding_ptr);
+DEF_VEC_ALLOC_P(c_binding_ptr,heap);
+
+/* Information that we keep for a struct or union while it is being
+ parsed. */
+
+struct c_struct_parse_info
+{
+ /* If warn_cxx_compat, a list of types defined within this
+ struct. */
+ VEC(tree,heap) *struct_types;
+ /* If warn_cxx_compat, a list of field names which have bindings,
+ and which are defined in this struct, but which are not defined
+ in any enclosing struct. This is used to clear the in_struct
+ field of the c_bindings structure. */
+ VEC(c_binding_ptr,heap) *fields;
+ /* If warn_cxx_compat, a list of typedef names used when defining
+ fields in this struct. */
+ VEC(tree,heap) *typedefs_seen;
+};
+
+/* Information for the struct or union currently being parsed, or
+ NULL if not parsing a struct or union. */
+static struct c_struct_parse_info *struct_parse_info;
+
/* Forward declarations. */
static tree lookup_name_in_scope (tree, struct c_scope *);
-static tree c_make_fname_decl (tree, int);
+static tree c_make_fname_decl (location_t, tree, int);
static tree grokdeclarator (const struct c_declarator *,
struct c_declspecs *,
- enum decl_context, bool, tree *, tree *,
- enum deprecated_states);
+ enum decl_context, bool, tree *, tree *, tree *,
+ bool *, enum deprecated_states);
static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
@@ -451,7 +576,7 @@ c_print_identifier (FILE *file, tree node, int indent)
{
tree rid = ridpointers[C_RID_CODE (node)];
indent_to (file, indent + 4);
- fprintf (file, "rid %p \"%s\"",
+ fprintf (file, "rid " HOST_PTR_PRINTF " \"%s\"",
(void *) rid, IDENTIFIER_POINTER (rid));
}
}
@@ -460,7 +585,8 @@ c_print_identifier (FILE *file, tree node, int indent)
which may be any of several kinds of DECL or TYPE or error_mark_node,
in the scope SCOPE. */
static void
-bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
+bind (tree name, tree decl, struct c_scope *scope, bool invisible,
+ bool nested, location_t locus)
{
struct c_binding *b, **here;
@@ -479,8 +605,10 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
b->invisible = invisible;
b->nested = nested;
b->inner_comp = 0;
+ b->in_struct = 0;
+ b->locus = locus;
- b->type = 0;
+ b->u.type = NULL;
b->prev = scope->bindings;
scope->bindings = b;
@@ -531,6 +659,24 @@ free_binding_and_advance (struct c_binding *b)
return prev;
}
+/* Bind a label. Like bind, but skip fields which aren't used for
+ labels, and add the LABEL_VARS value. */
+static void
+bind_label (tree name, tree label, struct c_scope *scope,
+ struct c_label_vars *label_vars)
+{
+ struct c_binding *b;
+
+ bind (name, label, scope, /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
+
+ scope->has_label_bindings = true;
+
+ b = scope->bindings;
+ gcc_assert (b->decl == label);
+ label_vars->shadowed = b->u.label;
+ b->u.label = label_vars;
+}
/* Hook called at end of compilation to assume 1 elt
for a file-scope tentative array defn that wasn't complete before. */
@@ -546,7 +692,8 @@ c_finish_incomplete_decl (tree decl)
&& !DECL_EXTERNAL (decl)
&& TYPE_DOMAIN (type) == 0)
{
- warning (0, "array %q+D assumed to have one element", decl);
+ warning_at (DECL_SOURCE_LOCATION (decl),
+ 0, "array %q+D assumed to have one element", decl);
complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
@@ -555,6 +702,120 @@ c_finish_incomplete_decl (tree decl)
}
}
+/* Record that inline function FUNC contains a reference (location
+ LOC) to static DECL (file-scope or function-local according to
+ TYPE). */
+
+void
+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);
+ csi->location = loc;
+ csi->function = func;
+ csi->static_decl = decl;
+ csi->type = type;
+ csi->next = c_inline_statics;
+ c_inline_statics = csi;
+}
+
+/* Check for references to static declarations in inline functions at
+ the end of the translation unit and diagnose them if the functions
+ are still inline definitions. */
+
+static void
+check_inline_statics (void)
+{
+ struct c_inline_static *csi;
+ for (csi = c_inline_statics; csi; csi = csi->next)
+ {
+ if (DECL_EXTERNAL (csi->function))
+ switch (csi->type)
+ {
+ case csi_internal:
+ pedwarn (csi->location, 0,
+ "%qD is static but used in inline function %qD "
+ "which is not static", csi->static_decl, csi->function);
+ break;
+ case csi_modifiable:
+ pedwarn (csi->location, 0,
+ "%q+D is static but declared in inline function %qD "
+ "which is not static", csi->static_decl, csi->function);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ c_inline_statics = NULL;
+}
+
+/* Fill in a c_spot_bindings structure. If DEFINING is true, set it
+ for the current state, otherwise set it to uninitialized. */
+
+static void
+set_spot_bindings (struct c_spot_bindings *p, bool defining)
+{
+ if (defining)
+ {
+ p->scope = current_scope;
+ p->bindings_in_scope = current_scope->bindings;
+ }
+ else
+ {
+ p->scope = NULL;
+ p->bindings_in_scope = NULL;
+ }
+ p->stmt_exprs = 0;
+ 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. */
+
+static bool
+update_spot_bindings (struct c_scope *scope, struct c_spot_bindings *p)
+{
+ if (p->scope != scope)
+ {
+ /* This label or goto is defined in some other scope, or it is a
+ label which is not yet defined. There is nothing to
+ update. */
+ return false;
+ }
+
+ /* Adjust the spot bindings to refer to the bindings already defined
+ in the enclosing scope. */
+ p->scope = scope->outer;
+ p->bindings_in_scope = p->scope->bindings;
+
+ return true;
+}
+
/* The Objective-C front-end often needs to determine the current scope. */
void *
@@ -590,7 +851,9 @@ objc_mark_locals_volatile (void *enclosing_blk)
int
global_bindings_p (void)
{
- return current_scope == file_scope && !c_override_global_bindings_to_false;
+ return (current_scope == file_scope && !c_override_global_bindings_to_false
+ ? -1
+ : 0);
}
void
@@ -599,6 +862,30 @@ keep_next_level (void)
keep_next_level_flag = true;
}
+/* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON. */
+
+void
+set_float_const_decimal64 (void)
+{
+ current_scope->float_const_decimal64 = true;
+}
+
+/* Clear the flag for the FLOAT_CONST_DECIMAL64 pragma. */
+
+void
+clear_float_const_decimal64 (void)
+{
+ current_scope->float_const_decimal64 = false;
+}
+
+/* Return nonzero if an unsuffixed float constant is _Decimal64. */
+
+bool
+float_const_decimal64_p (void)
+{
+ return current_scope->float_const_decimal64;
+}
+
/* Identify this scope as currently being filled with parameters. */
void
@@ -630,6 +917,13 @@ push_scope (void)
keep_next_level_flag = false;
next_is_function_body = false;
+
+ /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */
+ if (current_scope->outer)
+ current_scope->float_const_decimal64
+ = current_scope->outer->float_const_decimal64;
+ else
+ current_scope->float_const_decimal64 = false;
}
else
{
@@ -642,6 +936,12 @@ push_scope (void)
else
scope = GGC_CNEW (struct c_scope);
+ /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes. */
+ if (current_scope)
+ scope->float_const_decimal64 = current_scope->float_const_decimal64;
+ else
+ scope->float_const_decimal64 = false;
+
scope->keep = keep_next_level_flag;
scope->outer = current_scope;
scope->depth = current_scope ? (current_scope->depth + 1) : 0;
@@ -659,6 +959,67 @@ push_scope (void)
}
}
+/* This is called when we are leaving SCOPE. For each label defined
+ in SCOPE, add any appropriate decls to its decls_in_scope fields.
+ These are the decls whose initialization will be skipped by a goto
+ later in the function. */
+
+static void
+update_label_decls (struct c_scope *scope)
+{
+ struct c_scope *s;
+
+ s = scope;
+ while (s != NULL)
+ {
+ if (s->has_label_bindings)
+ {
+ struct c_binding *b;
+
+ for (b = s->bindings; b != NULL; b = b->prev)
+ {
+ struct c_label_vars *label_vars;
+ struct c_binding *b1;
+ unsigned int ix;
+ struct c_goto_bindings *g;
+
+ if (TREE_CODE (b->decl) != LABEL_DECL)
+ continue;
+ label_vars = b->u.label;
+
+ b1 = label_vars->label_bindings.bindings_in_scope;
+ if (update_spot_bindings (scope, &label_vars->label_bindings))
+ {
+ /* This label is defined in this scope. */
+ 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);
+ }
+ }
+
+ /* 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)
+ update_spot_bindings (scope, &g->goto_bindings);
+ }
+ }
+
+ /* Don't search beyond the current function. */
+ if (s == current_function_scope)
+ break;
+
+ s = s->outer;
+ }
+}
+
/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT. */
static void
@@ -684,7 +1045,7 @@ pop_scope (void)
bool functionbody = scope->function_body;
bool keep = functionbody || scope->keep || scope->bindings;
- c_end_vm_scope (scope->depth);
+ update_label_decls (scope);
/* If appropriate, create a BLOCK to record the decls for the life
of this function. */
@@ -719,7 +1080,8 @@ pop_scope (void)
context = current_function_decl;
else if (scope == file_scope)
{
- tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
+ tree file_decl = build_decl (UNKNOWN_LOCATION,
+ TRANSLATION_UNIT_DECL, 0, 0);
TREE_CHAIN (file_decl) = all_translation_units;
all_translation_units = file_decl;
context = file_decl;
@@ -740,7 +1102,7 @@ pop_scope (void)
error ("label %q+D used but not defined", p);
DECL_INITIAL (p) = error_mark_node;
}
- else
+ else
warn_for_unused_label (p);
/* Labels go in BLOCK_VARS. */
@@ -748,6 +1110,10 @@ pop_scope (void)
BLOCK_VARS (block) = p;
gcc_assert (I_LABEL_BINDING (b->id) == b);
I_LABEL_BINDING (b->id) = b->shadowed;
+
+ /* Also pop back to the shadowed label_vars. */
+ release_tree_vector (b->u.label->decls_in_scope);
+ b->u.label = b->u.label->shadowed;
break;
case ENUMERAL_TYPE:
@@ -824,6 +1190,29 @@ pop_scope (void)
TREE_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
}
+ else if (VAR_OR_FUNCTION_DECL_P (p))
+ {
+ /* For block local externs add a special
+ DECL_EXTERNAL decl for debug info generation. */
+ tree extp = copy_node (p);
+
+ DECL_EXTERNAL (extp) = 1;
+ TREE_STATIC (extp) = 0;
+ TREE_PUBLIC (extp) = 1;
+ DECL_INITIAL (extp) = NULL_TREE;
+ DECL_LANG_SPECIFIC (extp) = NULL;
+ DECL_CONTEXT (extp) = current_function_decl;
+ if (TREE_CODE (p) == FUNCTION_DECL)
+ {
+ DECL_RESULT (extp) = NULL_TREE;
+ DECL_SAVED_TREE (extp) = NULL_TREE;
+ DECL_STRUCT_FUNCTION (extp) = NULL;
+ }
+ if (b->locus != UNKNOWN_LOCATION)
+ DECL_SOURCE_LOCATION (extp) = b->locus;
+ TREE_CHAIN (extp) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = extp;
+ }
/* If this is the file scope, and we are processing more
than one translation unit in this compilation, set
DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
@@ -850,8 +1239,8 @@ pop_scope (void)
{
gcc_assert (I_SYMBOL_BINDING (b->id) == b);
I_SYMBOL_BINDING (b->id) = b->shadowed;
- if (b->shadowed && b->shadowed->type)
- TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
+ if (b->shadowed && b->shadowed->u.type)
+ TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type;
}
break;
@@ -905,7 +1294,7 @@ push_file_scope (void)
for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
bind (DECL_NAME (decl), decl, file_scope,
- /*invisible=*/false, /*nested=*/true);
+ /*invisible=*/false, /*nested=*/true, DECL_SOURCE_LOCATION (decl));
}
void
@@ -921,6 +1310,8 @@ pop_file_scope (void)
still works without it. */
finish_fname_decls ();
+ check_inline_statics ();
+
/* This is the point to write out a PCH if we're doing that.
In that case we do not want to do anything else. */
if (pch_file)
@@ -934,24 +1325,108 @@ pop_file_scope (void)
file_scope = 0;
maybe_apply_pending_pragma_weaks ();
- cgraph_finalize_compilation_unit ();
}
+
+/* Adjust the bindings for the start of a statement expression. */
+
+void
+c_bindings_start_stmt_expr (struct c_spot_bindings* switch_bindings)
+{
+ struct c_scope *scope;
+
+ for (scope = current_scope; scope != NULL; scope = scope->outer)
+ {
+ struct c_binding *b;
+
+ if (!scope->has_label_bindings)
+ continue;
+
+ for (b = scope->bindings; b != NULL; b = b->prev)
+ {
+ struct c_label_vars *label_vars;
+ unsigned int ix;
+ struct c_goto_bindings *g;
+
+ if (TREE_CODE (b->decl) != LABEL_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)
+ ++g->goto_bindings.stmt_exprs;
+ }
+ }
+
+ if (switch_bindings != NULL)
+ ++switch_bindings->stmt_exprs;
+}
+
+/* Adjust the bindings for the end of a statement expression. */
+
+void
+c_bindings_end_stmt_expr (struct c_spot_bindings *switch_bindings)
+{
+ struct c_scope *scope;
+
+ for (scope = current_scope; scope != NULL; scope = scope->outer)
+ {
+ struct c_binding *b;
+
+ if (!scope->has_label_bindings)
+ continue;
+
+ for (b = scope->bindings; b != NULL; b = b->prev)
+ {
+ struct c_label_vars *label_vars;
+ unsigned int ix;
+ struct c_goto_bindings *g;
+
+ if (TREE_CODE (b->decl) != LABEL_DECL)
+ continue;
+ label_vars = b->u.label;
+ --label_vars->label_bindings.stmt_exprs;
+ if (label_vars->label_bindings.stmt_exprs < 0)
+ {
+ 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)
+ {
+ --g->goto_bindings.stmt_exprs;
+ if (g->goto_bindings.stmt_exprs < 0)
+ {
+ g->goto_bindings.left_stmt_expr = true;
+ g->goto_bindings.stmt_exprs = 0;
+ }
+ }
+ }
+ }
+ if (switch_bindings != NULL)
+ {
+ --switch_bindings->stmt_exprs;
+ gcc_assert (switch_bindings->stmt_exprs >= 0);
+ }
+}
/* Push a definition or a declaration of struct, union or enum tag "name".
"type" should be the type node.
- We assume that the tag "name" is not already defined.
+ We assume that the tag "name" is not already defined, and has a location
+ of LOC.
Note that the definition may really be just a forward reference.
In that case, the TYPE_SIZE will be zero. */
static void
-pushtag (tree name, tree type)
+pushtag (location_t loc, tree name, tree type)
{
/* Record the identifier as the type's name if it has none. */
if (name && !TYPE_NAME (type))
TYPE_NAME (type) = name;
- bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false);
+ bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false, loc);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
tagged type we just added to the current scope. This fake
@@ -960,11 +1435,33 @@ pushtag (tree name, tree type)
us a convenient place to record the "scope start" address for the
tagged type. */
- TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
+ TYPE_STUB_DECL (type) = pushdecl (build_decl (loc,
+ TYPE_DECL, NULL_TREE, type));
/* An approximation for now, so we can tell this is a function-scope tag.
This will be updated in pop_scope. */
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
+
+ if (warn_cxx_compat && name != NULL_TREE)
+ {
+ struct c_binding *b = I_SYMBOL_BINDING (name);
+
+ if (b != NULL
+ && b->decl != NULL_TREE
+ && TREE_CODE (b->decl) == TYPE_DECL
+ && (B_IN_CURRENT_SCOPE (b)
+ || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (b->decl))
+ != TYPE_MAIN_VARIANT (type)))
+ {
+ warning_at (loc, OPT_Wc___compat,
+ ("using %qD as both a typedef and a tag is "
+ "invalid in C++"),
+ b->decl);
+ if (b->locus != UNKNOWN_LOCATION)
+ inform (b->locus, "originally defined here");
+ }
+ }
}
/* Subroutine of compare_decls. Allow harmless mismatches in return
@@ -1249,8 +1746,35 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else
{
- if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
- error ("conflicting type qualifiers for %q+D", newdecl);
+ int new_quals = TYPE_QUALS (newtype);
+ int old_quals = TYPE_QUALS (oldtype);
+
+ if (new_quals != old_quals)
+ {
+ addr_space_t new_addr = DECODE_QUAL_ADDR_SPACE (new_quals);
+ addr_space_t old_addr = DECODE_QUAL_ADDR_SPACE (old_quals);
+ if (new_addr != old_addr)
+ {
+ if (ADDR_SPACE_GENERIC_P (new_addr))
+ error ("conflicting named address spaces (generic vs %s) "
+ "for %q+D",
+ c_addr_space_name (old_addr), newdecl);
+ else if (ADDR_SPACE_GENERIC_P (old_addr))
+ error ("conflicting named address spaces (%s vs generic) "
+ "for %q+D",
+ c_addr_space_name (new_addr), newdecl);
+ else
+ error ("conflicting named address spaces (%s vs %s) "
+ "for %q+D",
+ c_addr_space_name (new_addr),
+ c_addr_space_name (old_addr),
+ newdecl);
+ }
+
+ if (CLEAR_QUAL_ADDR_SPACE (new_quals)
+ != CLEAR_QUAL_ADDR_SPACE (old_quals))
+ error ("conflicting type qualifiers for %q+D", newdecl);
+ }
else
error ("conflicting types for %q+D", newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
@@ -1373,7 +1897,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else if (warn_traditional)
{
- warned |= warning (OPT_Wtraditional,
+ warned |= warning (OPT_Wtraditional,
"non-static declaration of %q+D "
"follows static declaration", newdecl);
}
@@ -1390,9 +1914,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
DECL_ATTRIBUTES (olddecl)) != NULL;
if (newa != olda)
{
- error ("%<gnu_inline%> attribute present on %q+D",
- newa ? newdecl : olddecl);
- error ("%Jbut not here", newa ? olddecl : newdecl);
+ error_at (input_location, "%<gnu_inline%> attribute present on %q+D",
+ newa ? newdecl : olddecl);
+ error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl),
+ "but not here");
}
}
}
@@ -1450,7 +1975,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else if (warn_traditional)
{
- warned |= warning (OPT_Wtraditional,
+ warned |= warning (OPT_Wtraditional,
"non-static declaration of %q+D "
"follows static declaration", newdecl);
}
@@ -1491,6 +2016,18 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
return false;
}
+
+ /* C++ does not permit a decl to appear multiple times at file
+ scope. */
+ if (warn_cxx_compat
+ && DECL_FILE_SCOPE_P (newdecl)
+ && !DECL_EXTERNAL (newdecl)
+ && !DECL_EXTERNAL (olddecl))
+ warned |= warning_at (DECL_SOURCE_LOCATION (newdecl),
+ OPT_Wc___compat,
+ ("duplicate declaration of %qD is "
+ "invalid in C++"),
+ newdecl);
}
/* warnings */
@@ -1509,14 +2046,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warned |= warning (OPT_Wattributes,
+ warned |= warning (OPT_Wattributes,
"inline declaration of %qD follows "
"declaration with attribute noinline", newdecl);
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warned |= warning (OPT_Wattributes,
+ warned |= warning (OPT_Wattributes,
"declaration of %q+D with attribute "
"noinline follows inline declaration ", newdecl);
}
@@ -1826,12 +2363,15 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
/* Also preserve various other info from the definition. */
if (!new_is_definition)
{
+ tree t;
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
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) = DECL_ARGUMENTS (olddecl);
+ DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
+ for (t = DECL_ARGUMENTS (newdecl); t ; t = TREE_CHAIN (t))
+ DECL_CONTEXT (t) = newdecl;
/* See if we've got a function to instantiate from. */
if (DECL_SAVED_TREE (olddecl))
@@ -1840,19 +2380,27 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
}
}
- extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
+ extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
- /* Merge the USED information. */
- if (TREE_USED (olddecl))
- TREE_USED (newdecl) = 1;
- else if (TREE_USED (newdecl))
- TREE_USED (olddecl) = 1;
+ /* Merge the USED information. */
+ if (TREE_USED (olddecl))
+ TREE_USED (newdecl) = 1;
+ else if (TREE_USED (newdecl))
+ TREE_USED (olddecl) = 1;
+ 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 and DECL_CONTEXT. */
+ But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
+ DECL_ARGUMENTS (if appropriate). */
{
unsigned olddecl_uid = DECL_UID (olddecl);
tree olddecl_context = DECL_CONTEXT (olddecl);
+ tree olddecl_arguments = NULL;
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ olddecl_arguments = DECL_ARGUMENTS (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
@@ -1883,6 +2431,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
}
DECL_UID (olddecl) = olddecl_uid;
DECL_CONTEXT (olddecl) = olddecl_context;
+ if (TREE_CODE (olddecl) == FUNCTION_DECL)
+ DECL_ARGUMENTS (olddecl) = olddecl_arguments;
}
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
@@ -1969,73 +2519,13 @@ warn_if_shadowing (tree new_decl)
warning (OPT_Wshadow, "declaration of %q+D shadows a previous local",
new_decl);
- warning (OPT_Wshadow, "%Jshadowed declaration is here", old_decl);
+ warning_at (DECL_SOURCE_LOCATION (old_decl), OPT_Wshadow,
+ "shadowed declaration is here");
break;
}
}
-
-/* Subroutine of pushdecl.
-
- X is a TYPE_DECL for a typedef statement. Create a brand new
- ..._TYPE node (which will be just a variant of the existing
- ..._TYPE node with identical properties) and then install X
- as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
-
- The whole point here is to end up with a situation where each
- and every ..._TYPE node the compiler creates will be uniquely
- associated with AT MOST one node representing a typedef name.
- This way, even though the compiler substitutes corresponding
- ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
- early on, later parts of the compiler can always do the reverse
- translation and get back the corresponding typedef name. For
- example, given:
-
- typedef struct S MY_TYPE;
- MY_TYPE object;
-
- Later parts of the compiler might only know that `object' was of
- type `struct S' if it were not for code just below. With this
- code however, later parts of the compiler see something like:
-
- struct S' == struct S
- typedef struct S' MY_TYPE;
- struct S' object;
-
- And they can then deduce (from the node for type struct S') that
- the original object declaration was:
-
- MY_TYPE object;
-
- Being able to do this is important for proper support of protoize,
- and also for generating precise symbolic debugging information
- which takes full account of the programmer's (typedef) vocabulary.
-
- Obviously, we don't want to generate a duplicate ..._TYPE node if
- the TYPE_DECL node that we are now processing really represents a
- standard built-in type. */
-
-static void
-clone_underlying_type (tree x)
-{
- if (DECL_IS_BUILTIN (x))
- {
- if (TYPE_NAME (TREE_TYPE (x)) == 0)
- TYPE_NAME (TREE_TYPE (x)) = x;
- }
- else if (TREE_TYPE (x) != error_mark_node
- && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
- {
- tree tt = TREE_TYPE (x);
- DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_variant_type_copy (tt);
- TYPE_NAME (tt) = x;
- TREE_USED (tt) = TREE_USED (x);
- TREE_TYPE (x) = tt;
- }
-}
-
/* Record a decl-node X as belonging to the current lexical scope.
Check for errors (such as an incompatible declaration for the same
name already seen in the same scope).
@@ -2051,6 +2541,7 @@ pushdecl (tree x)
struct c_scope *scope = current_scope;
struct c_binding *b;
bool nested = false;
+ location_t locus = DECL_SOURCE_LOCATION (x);
/* Must set DECL_CONTEXT for everything not at file scope or
DECL_FILE_SCOPE_P won't work. Local externs don't count
@@ -2060,16 +2551,11 @@ pushdecl (tree x)
|| DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
DECL_CONTEXT (x) = current_function_decl;
- /* If this is of variably modified type, prevent jumping into its
- scope. */
- if ((TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == TYPE_DECL)
- && variably_modified_type_p (TREE_TYPE (x), NULL_TREE))
- c_begin_vm_scope (scope->depth);
-
/* Anonymous decls are just inserted in the scope. */
if (!name)
{
- bind (name, x, scope, /*invisible=*/false, /*nested=*/false);
+ bind (name, x, scope, /*invisible=*/false, /*nested=*/false,
+ locus);
return x;
}
@@ -2103,8 +2589,8 @@ pushdecl (tree x)
if (b_ext)
{
b_use = b_ext;
- if (b_use->type)
- TREE_TYPE (b_use->decl) = b_use->type;
+ if (b_use->u.type)
+ TREE_TYPE (b_use->decl) = b_use->u.type;
}
}
if (duplicate_decls (x, b_use->decl))
@@ -2118,13 +2604,13 @@ pushdecl (tree x)
thistype = composite_type (vistype, type);
else
thistype = TREE_TYPE (b_use->decl);
- b_use->type = TREE_TYPE (b_use->decl);
+ b_use->u.type = TREE_TYPE (b_use->decl);
if (TREE_CODE (b_use->decl) == FUNCTION_DECL
&& DECL_BUILT_IN (b_use->decl))
thistype
= build_type_attribute_variant (thistype,
TYPE_ATTRIBUTES
- (b_use->type));
+ (b_use->u.type));
TREE_TYPE (b_use->decl) = thistype;
}
return b_use->decl;
@@ -2175,7 +2661,7 @@ pushdecl (tree x)
their scopes will not have been re-entered. */
if (DECL_P (b->decl) && DECL_FILE_SCOPE_P (b->decl) && !type_saved)
{
- b->type = TREE_TYPE (b->decl);
+ b->u.type = TREE_TYPE (b->decl);
type_saved = true;
}
if (B_IN_FILE_SCOPE (b)
@@ -2201,8 +2687,8 @@ pushdecl (tree x)
After the consistency checks, it will be reset to the
composite of the visible types only. */
if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
- && b->type)
- TREE_TYPE (b->decl) = b->type;
+ && b->u.type)
+ TREE_TYPE (b->decl) = b->u.type;
/* The point of the same_translation_unit_p check here is,
we want to detect a duplicate decl for a construct like
@@ -2223,13 +2709,14 @@ pushdecl (tree x)
}
else
thistype = type;
- b->type = TREE_TYPE (b->decl);
+ b->u.type = TREE_TYPE (b->decl);
if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
thistype
= build_type_attribute_variant (thistype,
- TYPE_ATTRIBUTES (b->type));
+ TYPE_ATTRIBUTES (b->u.type));
TREE_TYPE (b->decl) = thistype;
- bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
+ bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
+ locus);
return b->decl;
}
else if (TREE_PUBLIC (x))
@@ -2247,7 +2734,7 @@ pushdecl (tree x)
else
{
bind (name, x, external_scope, /*invisible=*/true,
- /*nested=*/false);
+ /*nested=*/false, locus);
nested = true;
}
}
@@ -2258,9 +2745,9 @@ pushdecl (tree x)
skip_external_and_shadow_checks:
if (TREE_CODE (x) == TYPE_DECL)
- clone_underlying_type (x);
+ set_underlying_type (x);
- bind (name, x, scope, /*invisible=*/false, nested);
+ bind (name, x, scope, /*invisible=*/false, nested, locus);
/* If x's type is incomplete because it's based on a
structure or union which has not yet been fully declared,
@@ -2309,11 +2796,12 @@ pushdecl_top_level (tree x)
if (TREE_PUBLIC (x))
{
- bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
+ bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false,
+ UNKNOWN_LOCATION);
nested = true;
}
if (file_scope)
- bind (name, x, file_scope, /*invisible=*/false, nested);
+ bind (name, x, file_scope, /*invisible=*/false, nested, UNKNOWN_LOCATION);
return x;
}
@@ -2328,19 +2816,19 @@ implicit_decl_warning (tree id, tree olddecl)
if (flag_isoc99)
warned = pedwarn (input_location, OPT_Wimplicit_function_declaration,
"implicit declaration of function %qE", id);
- else
- warned = warning (OPT_Wimplicit_function_declaration,
+ else
+ warned = warning (OPT_Wimplicit_function_declaration,
G_("implicit declaration of function %qE"), id);
if (olddecl && warned)
locate_old_decl (olddecl);
}
}
-/* Generate an implicit declaration for identifier FUNCTIONID as a
+/* Generate an implicit declaration for identifier FUNCTIONID at LOC as a
function of type int (). */
tree
-implicitly_declare (tree functionid)
+implicitly_declare (location_t loc, tree functionid)
{
struct c_binding *b;
tree decl = 0;
@@ -2368,14 +2856,15 @@ implicitly_declare (tree functionid)
if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
{
bind (functionid, decl, file_scope,
- /*invisible=*/false, /*nested=*/true);
+ /*invisible=*/false, /*nested=*/true,
+ DECL_SOURCE_LOCATION (decl));
return decl;
}
else
{
tree newtype = default_function_type;
- if (b->type)
- TREE_TYPE (decl) = b->type;
+ if (b->u.type)
+ TREE_TYPE (decl) = b->u.type;
/* Implicit declaration of a function already declared
(somehow) in a different scope, or as a built-in.
If this is the first time this has happened, warn;
@@ -2392,8 +2881,8 @@ implicitly_declare (tree functionid)
(TREE_TYPE (decl)));
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- warning (0, "incompatible implicit declaration of built-in"
- " function %qD", decl);
+ warning_at (loc, 0, "incompatible implicit declaration of "
+ "built-in function %qD", decl);
newtype = TREE_TYPE (decl);
}
}
@@ -2401,21 +2890,21 @@ implicitly_declare (tree functionid)
{
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- error ("incompatible implicit declaration of function %qD",
- decl);
+ error_at (loc, "incompatible implicit declaration of function %qD", decl);
locate_old_decl (decl);
}
}
- b->type = TREE_TYPE (decl);
+ b->u.type = TREE_TYPE (decl);
TREE_TYPE (decl) = newtype;
bind (functionid, decl, current_scope,
- /*invisible=*/false, /*nested=*/true);
+ /*invisible=*/false, /*nested=*/true,
+ DECL_SOURCE_LOCATION (decl));
return decl;
}
}
/* Not seen before. */
- decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
+ decl = build_decl (loc, FUNCTION_DECL, functionid, default_function_type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
C_DECL_IMPLICIT (decl) = 1;
@@ -2447,24 +2936,23 @@ implicitly_declare (tree functionid)
in an appropriate scope, which will suppress further errors for the
same identifier. The error message should be given location LOC. */
void
-undeclared_variable (tree id, location_t loc)
+undeclared_variable (location_t loc, tree id)
{
static bool already = false;
struct c_scope *scope;
if (current_function_decl == 0)
{
- error ("%H%qE undeclared here (not in a function)", &loc, id);
+ error_at (loc, "%qE undeclared here (not in a function)", id);
scope = current_scope;
}
else
{
- error ("%H%qE undeclared (first use in this function)", &loc, id);
-
+ error_at (loc, "%qE undeclared (first use in this function)", id);
if (!already)
{
- error ("%H(Each undeclared identifier is reported only once", &loc);
- error ("%Hfor each function it appears in.)", &loc);
+ inform (loc, "each undeclared identifier is reported only"
+ " once for each function it appears in");
already = true;
}
@@ -2472,20 +2960,30 @@ undeclared_variable (tree id, location_t loc)
will be nonnull but current_function_scope will be null. */
scope = current_function_scope ? current_function_scope : current_scope;
}
- bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false);
+ bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
}
/* Subroutine of lookup_label, declare_label, define_label: construct a
- LABEL_DECL with all the proper frills. */
+ LABEL_DECL with all the proper frills. Also create a struct
+ c_label_vars initialized for the current scope. */
static tree
-make_label (tree name, location_t location)
+make_label (location_t location, tree name, bool defining,
+ struct c_label_vars **p_label_vars)
{
- tree label = build_decl (LABEL_DECL, name, void_type_node);
+ tree label = build_decl (location, LABEL_DECL, name, void_type_node);
+ struct c_label_vars *label_vars;
DECL_CONTEXT (label) = current_function_decl;
DECL_MODE (label) = VOIDmode;
- DECL_SOURCE_LOCATION (label) = location;
+
+ label_vars = GGC_NEW (struct c_label_vars);
+ label_vars->shadowed = NULL;
+ set_spot_bindings (&label_vars->label_bindings, defining);
+ label_vars->decls_in_scope = make_tree_vector ();
+ label_vars->gotos = VEC_alloc (c_goto_bindings_p, gc, 0);
+ *p_label_vars = label_vars;
return label;
}
@@ -2499,6 +2997,7 @@ tree
lookup_label (tree name)
{
tree label;
+ struct c_label_vars *label_vars;
if (current_function_decl == 0)
{
@@ -2516,17 +3015,91 @@ lookup_label (tree name)
/* If the label has only been declared, update its apparent
location to point here, for better diagnostics if it
turns out not to have been defined. */
- if (!TREE_USED (label))
+ if (DECL_INITIAL (label) == NULL_TREE)
DECL_SOURCE_LOCATION (label) = input_location;
return label;
}
/* No label binding for that identifier; make one. */
- label = make_label (name, input_location);
+ label = make_label (input_location, name, false, &label_vars);
/* Ordinary labels go in the current function scope. */
- bind (name, label, current_function_scope,
- /*invisible=*/false, /*nested=*/false);
+ bind_label (name, label, current_function_scope, label_vars);
+
+ return label;
+}
+
+/* Issue a warning about DECL for a goto statement at GOTO_LOC going
+ to LABEL. */
+
+static void
+warn_about_goto (location_t goto_loc, tree label, tree decl)
+{
+ if (variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+ error_at (goto_loc,
+ "jump into scope of identifier with variably modified type");
+ else
+ warning_at (goto_loc, OPT_Wjump_misses_init,
+ "jump skips variable initialization");
+ inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label);
+ inform (DECL_SOURCE_LOCATION (decl), "%qD declared here", decl);
+}
+
+/* Look up a label because of a goto statement. This is like
+ lookup_label, but also issues any appropriate warnings. */
+
+tree
+lookup_label_for_goto (location_t loc, tree name)
+{
+ tree label;
+ struct c_label_vars *label_vars;
+ unsigned int ix;
+ tree decl;
+
+ label = lookup_label (name);
+ if (label == NULL_TREE)
+ return NULL_TREE;
+
+ /* If we are jumping to a different function, we can't issue any
+ useful warnings. */
+ if (DECL_CONTEXT (label) != current_function_decl)
+ {
+ gcc_assert (C_DECLARED_LABEL_FLAG (label));
+ return label;
+ }
+
+ label_vars = I_LABEL_BINDING (name)->u.label;
+
+ /* If the label has not yet been defined, then push this goto on a
+ list for possible later warnings. */
+ if (label_vars->label_bindings.scope == NULL)
+ {
+ struct c_goto_bindings *g;
+
+ g = GGC_NEW (struct 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);
+ return label;
+ }
+
+ /* If there are any decls in label_vars->decls_in_scope, then this
+ goto has missed the declaration of the decl. This happens for a
+ case like
+ int i = 1;
+ lab:
+ ...
+ goto lab;
+ Issue a warning or error. */
+ for (ix = 0; VEC_iterate (tree, label_vars->decls_in_scope, ix, decl); ++ix)
+ warn_about_goto (loc, label, decl);
+
+ if (label_vars->label_bindings.left_stmt_expr)
+ {
+ error_at (loc, "jump into statement expression");
+ inform (DECL_SOURCE_LOCATION (label), "label %qD defined here", label);
+ }
+
return label;
}
@@ -2539,6 +3112,7 @@ declare_label (tree name)
{
struct c_binding *b = I_LABEL_BINDING (name);
tree label;
+ struct c_label_vars *label_vars;
/* Check to make sure that the label hasn't already been declared
at this scope */
@@ -2551,15 +3125,74 @@ declare_label (tree name)
return b->decl;
}
- label = make_label (name, input_location);
+ label = make_label (input_location, name, false, &label_vars);
C_DECLARED_LABEL_FLAG (label) = 1;
/* Declared labels go in the current scope. */
- bind (name, label, current_scope,
- /*invisible=*/false, /*nested=*/false);
+ bind_label (name, label, current_scope, label_vars);
+
return label;
}
+/* When we define a label, issue any appropriate warnings if there are
+ any gotos earlier in the function which jump to this label. */
+
+static void
+check_earlier_gotos (tree label, struct c_label_vars* label_vars)
+{
+ unsigned int ix;
+ struct c_goto_bindings *g;
+
+ for (ix = 0;
+ VEC_iterate (c_goto_bindings_p, label_vars->gotos, ix, g);
+ ++ix)
+ {
+ struct c_binding *b;
+ struct c_scope *scope;
+
+ /* 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 (decl_jump_unsafe (b->decl))
+ warn_about_goto (g->loc, label, b->decl);
+ }
+
+ /* We also need to warn about decls defined in any scopes
+ between the scope of the label and the scope of the goto. */
+ for (scope = label_vars->label_bindings.scope;
+ scope != g->goto_bindings.scope;
+ 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 (decl_jump_unsafe (b->decl))
+ warn_about_goto (g->loc, label, b->decl);
+ }
+ }
+
+ if (g->goto_bindings.stmt_exprs > 0)
+ {
+ error_at (g->loc, "jump into statement expression");
+ inform (DECL_SOURCE_LOCATION (label), "label %qD defined here",
+ label);
+ }
+ }
+
+ /* Now that the label is defined, we will issue warnings about
+ subsequent gotos to this label when we see them. */
+ VEC_truncate (c_goto_bindings_p, label_vars->gotos, 0);
+ label_vars->gotos = NULL;
+}
+
/* Define a label, specifying the location in the source file.
Return the LABEL_DECL node for the label, if the definition is valid.
Otherwise return 0. */
@@ -2572,7 +3205,6 @@ define_label (location_t location, tree name)
if there is a containing function with a declared label with
the same name. */
tree label = I_LABEL_DECL (name);
- struct c_label_list *nlist_se, *nlist_vm;
if (label
&& ((DECL_CONTEXT (label) == current_function_decl
@@ -2580,60 +3212,128 @@ define_label (location_t location, tree name)
|| (DECL_CONTEXT (label) != current_function_decl
&& C_DECLARED_LABEL_FLAG (label))))
{
- error ("%Hduplicate label %qD", &location, label);
+ error_at (location, "duplicate label %qD", label);
locate_old_decl (label);
return 0;
}
else if (label && DECL_CONTEXT (label) == current_function_decl)
{
+ struct c_label_vars *label_vars = I_LABEL_BINDING (name)->u.label;
+
/* The label has been used or declared already in this function,
but not defined. Update its location to point to this
definition. */
- if (C_DECL_UNDEFINABLE_STMT_EXPR (label))
- error ("%Jjump into statement expression", label);
- if (C_DECL_UNDEFINABLE_VM (label))
- error ("%Jjump into scope of identifier with variably modified type",
- label);
DECL_SOURCE_LOCATION (label) = location;
+ set_spot_bindings (&label_vars->label_bindings, true);
+
+ /* Issue warnings as required about any goto statements from
+ earlier in the function. */
+ check_earlier_gotos (label, label_vars);
}
else
{
+ struct c_label_vars *label_vars;
+
/* No label binding for that identifier; make one. */
- label = make_label (name, location);
+ label = make_label (location, name, true, &label_vars);
/* Ordinary labels go in the current function scope. */
- bind (name, label, current_function_scope,
- /*invisible=*/false, /*nested=*/false);
+ bind_label (name, label, current_function_scope, label_vars);
}
if (!in_system_header && lookup_name (name))
- warning (OPT_Wtraditional, "%Htraditional C lacks a separate namespace "
- "for labels, identifier %qE conflicts", &location, name);
-
- nlist_se = XOBNEW (&parser_obstack, struct c_label_list);
- nlist_se->next = label_context_stack_se->labels_def;
- nlist_se->label = label;
- label_context_stack_se->labels_def = nlist_se;
-
- nlist_vm = XOBNEW (&parser_obstack, struct c_label_list);
- nlist_vm->next = label_context_stack_vm->labels_def;
- nlist_vm->label = label;
- label_context_stack_vm->labels_def = nlist_vm;
+ warning_at (location, OPT_Wtraditional,
+ "traditional C lacks a separate namespace "
+ "for labels, identifier %qE conflicts", name);
/* Mark label as having been defined. */
DECL_INITIAL (label) = error_mark_node;
return label;
}
+/* Get the bindings for a new switch statement. This is used to issue
+ warnings as appropriate for jumps from the switch to case or
+ default labels. */
+
+struct c_spot_bindings *
+c_get_switch_bindings (void)
+{
+ struct c_spot_bindings *switch_bindings;
+
+ switch_bindings = XNEW (struct c_spot_bindings);
+ set_spot_bindings (switch_bindings, true);
+ return switch_bindings;
+}
+
+void
+c_release_switch_bindings (struct c_spot_bindings *bindings)
+{
+ gcc_assert (bindings->stmt_exprs == 0 && !bindings->left_stmt_expr);
+ XDELETE (bindings);
+}
+
+/* This is called at the point of a case or default label to issue
+ warnings about decls as needed. It returns true if it found an
+ error, not just a warning. */
+
+bool
+c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings,
+ location_t switch_loc, location_t case_loc)
+{
+ bool saw_error;
+ struct c_scope *scope;
+
+ saw_error = false;
+ for (scope = current_scope;
+ scope != switch_bindings->scope;
+ scope = scope->outer)
+ {
+ struct c_binding *b;
+
+ gcc_assert (scope != NULL);
+ for (b = scope->bindings; b != NULL; b = b->prev)
+ {
+ if (decl_jump_unsafe (b->decl))
+ {
+ if (variably_modified_type_p (TREE_TYPE (b->decl), NULL_TREE))
+ {
+ saw_error = true;
+ error_at (case_loc,
+ ("switch jumps into scope of identifier with "
+ "variably modified type"));
+ }
+ else
+ warning_at (case_loc, OPT_Wjump_misses_init,
+ "switch jumps over variable initialization");
+ inform (switch_loc, "switch starts here");
+ inform (DECL_SOURCE_LOCATION (b->decl), "%qD declared here",
+ b->decl);
+ }
+ }
+ }
+
+ if (switch_bindings->stmt_exprs > 0)
+ {
+ saw_error = true;
+ error_at (case_loc, "switch jumps into statement expression");
+ inform (switch_loc, "switch starts here");
+ }
+
+ return saw_error;
+}
+
/* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name.
If THISLEVEL_ONLY is nonzero, searches only the current_scope.
CODE says which kind of type the caller wants;
it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
+ If PLOC is not NULL and this returns non-null, it sets *PLOC to the
+ location where the tag was defined.
If the wrong kind of type is found, an error is reported. */
static tree
-lookup_tag (enum tree_code code, tree name, int thislevel_only)
+lookup_tag (enum tree_code code, tree name, int thislevel_only,
+ location_t *ploc)
{
struct c_binding *b = I_TAG_BINDING (name);
int thislevel = 0;
@@ -2670,6 +3370,10 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only)
if (thislevel)
pending_xref_error ();
}
+
+ if (ploc != NULL)
+ *ploc = b->locus;
+
return b->decl;
}
@@ -2682,8 +3386,8 @@ void
pending_xref_error (void)
{
if (pending_invalid_xref != 0)
- error ("%H%qE defined as wrong kind of tag",
- &pending_invalid_xref_location, pending_invalid_xref);
+ error_at (pending_invalid_xref_location, "%qE defined as wrong kind of tag",
+ pending_invalid_xref);
pending_invalid_xref = 0;
}
@@ -2751,7 +3455,7 @@ c_init_decl_processing (void)
truthvalue_false_node = integer_zero_node;
/* Even in C99, which has a real boolean type. */
- pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
+ pushdecl (build_decl (UNKNOWN_LOCATION, TYPE_DECL, get_identifier ("_Bool"),
boolean_type_node));
input_location = save_loc;
@@ -2762,15 +3466,16 @@ c_init_decl_processing (void)
start_fname_decls ();
}
-/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
- decl, NAME is the initialization string and TYPE_DEP indicates whether
- NAME depended on the type of the function. As we don't yet implement
- delayed emission of static data, we mark the decl as emitted
- so it is not placed in the output. Anything using it must therefore pull
- out the STRING_CST initializer directly. FIXME. */
+/* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to
+ give the decl, NAME is the initialization string and TYPE_DEP
+ indicates whether NAME depended on the type of the function. As we
+ don't yet implement delayed emission of static data, we mark the
+ decl as emitted so it is not placed in the output. Anything using
+ it must therefore pull out the STRING_CST initializer directly.
+ FIXME. */
static tree
-c_make_fname_decl (tree id, int type_dep)
+c_make_fname_decl (location_t loc, tree id, int type_dep)
{
const char *name = fname_as_string (type_dep);
tree decl, type, init;
@@ -2780,7 +3485,7 @@ c_make_fname_decl (tree id, int type_dep)
build_index_type (size_int (length)));
type = c_build_qualified_type (type, TYPE_QUAL_CONST);
- decl = build_decl (VAR_DECL, id, type);
+ decl = build_decl (loc, VAR_DECL, id, type);
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
@@ -2795,10 +3500,10 @@ c_make_fname_decl (tree id, int type_dep)
if (current_function_decl
/* For invalid programs like this:
-
+
void foo()
const char* p = __FUNCTION__;
-
+
the __FUNCTION__ is believed to appear in K&R style function
parameter declarator. In that case we still don't have
function_scope. */
@@ -2806,10 +3511,10 @@ c_make_fname_decl (tree id, int type_dep)
{
DECL_CONTEXT (decl) = current_function_decl;
bind (id, decl, current_function_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
}
- finish_decl (decl, init, NULL_TREE);
+ finish_decl (decl, loc, init, NULL_TREE, NULL_TREE);
return decl;
}
@@ -2826,7 +3531,8 @@ c_builtin_function (tree decl)
/* Should never be called on a symbol with a preexisting meaning. */
gcc_assert (!I_SYMBOL_BINDING (id));
- bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
+ bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false,
+ UNKNOWN_LOCATION);
/* Builtins in the implementation namespace are made visible without
needing to be explicitly declared. See push_file_scope. */
@@ -2851,7 +3557,8 @@ c_builtin_function_ext_scope (tree decl)
/* Should never be called on a symbol with a preexisting meaning. */
gcc_assert (!I_SYMBOL_BINDING (id));
- bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false);
+ bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
/* Builtins in the implementation namespace are made visible without
needing to be explicitly declared. See push_file_scope. */
@@ -2899,6 +3606,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
found_tag = true;
+ if (declspecs->restrict_p)
+ {
+ error ("invalid use of %<restrict%>");
+ warned = 1;
+ }
+
if (name == 0)
{
if (warned != 1 && code != ENUMERAL_TYPE)
@@ -2922,7 +3635,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
else if (!declspecs->tag_defined_p
&& (declspecs->const_p
|| declspecs->volatile_p
- || declspecs->restrict_p))
+ || declspecs->restrict_p
+ || declspecs->address_space))
{
if (warned != 1)
pedwarn (input_location, 0,
@@ -2934,12 +3648,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
else
{
pending_invalid_xref = 0;
- t = lookup_tag (code, name, 1);
+ t = lookup_tag (code, name, 1, NULL);
if (t == 0)
{
t = make_node (code);
- pushtag (name, t);
+ pushtag (input_location, name, t);
}
}
}
@@ -2993,7 +3707,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
if (!warned && !in_system_header && (declspecs->const_p
|| declspecs->volatile_p
- || declspecs->restrict_p))
+ || declspecs->restrict_p
+ || declspecs->address_space))
{
warning (0, "useless type qualifier in empty declaration");
warned = 2;
@@ -3016,7 +3731,8 @@ quals_from_declspecs (const struct c_declspecs *specs)
{
int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
| (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
- | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+ | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+ | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
gcc_assert (!specs->type
&& !specs->decl_attr
&& specs->typespec_word == cts_none
@@ -3035,21 +3751,24 @@ quals_from_declspecs (const struct c_declspecs *specs)
return quals;
}
-/* Construct an array declarator. EXPR is the expression inside [],
- or NULL_TREE. QUALS are the type qualifiers inside the [] (to be
- applied to the pointer to which a parameter array is converted).
- STATIC_P is true if "static" is inside the [], false otherwise.
- VLA_UNSPEC_P is true if the array is [*], a VLA of unspecified
- length which is nevertheless a complete type, false otherwise. The
- field for the contained declarator is left to be filled in by
- set_array_declarator_inner. */
+/* Construct an array declarator. LOC is the location of the
+ beginning of the array (usually the opening brace). EXPR is the
+ expression inside [], or NULL_TREE. QUALS are the type qualifiers
+ inside the [] (to be applied to the pointer to which a parameter
+ array is converted). STATIC_P is true if "static" is inside the
+ [], false otherwise. VLA_UNSPEC_P is true if the array is [*], a
+ VLA of unspecified length which is nevertheless a complete type,
+ false otherwise. The field for the contained declarator is left to
+ be filled in by set_array_declarator_inner. */
struct c_declarator *
-build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
+build_array_declarator (location_t loc,
+ tree expr, struct c_declspecs *quals, bool static_p,
bool vla_unspec_p)
{
struct c_declarator *declarator = XOBNEW (&parser_obstack,
struct c_declarator);
+ declarator->id_loc = loc;
declarator->kind = cdk_array;
declarator->declarator = 0;
declarator->u.array.dimen = expr;
@@ -3068,11 +3787,11 @@ build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
if (!flag_isoc99)
{
if (static_p || quals != NULL)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C90 does not support %<static%> or type "
"qualifiers in parameter array declarators");
if (vla_unspec_p)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C90 does not support %<[*]%> array declarators");
}
if (vla_unspec_p)
@@ -3080,7 +3799,8 @@ build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
if (!current_scope->parm_flag)
{
/* C99 6.7.5.2p4 */
- error ("%<[*]%> not allowed in other than function prototype scope");
+ error_at (loc, "%<[*]%> not allowed in other than "
+ "function prototype scope");
declarator->u.array.vla_unspec_p = false;
return NULL;
}
@@ -3128,10 +3848,15 @@ add_flexible_array_elts_to_size (tree decl, tree init)
}
}
-/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
+/* Decode a "typename", such as "int **", returning a ..._TYPE node.
+ Set *EXPR, if EXPR not NULL, to any expression to be evaluated
+ before the type name, and set *EXPR_CONST_OPERANDS, if
+ EXPR_CONST_OPERANDS not NULL, to indicate whether the type name may
+ appear in a constant expression. */
tree
-groktypename (struct c_type_name *type_name)
+groktypename (struct c_type_name *type_name, tree *expr,
+ bool *expr_const_operands)
{
tree type;
tree attrs = type_name->specs->attrs;
@@ -3139,7 +3864,8 @@ groktypename (struct c_type_name *type_name)
type_name->specs->attrs = NULL_TREE;
type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
- false, NULL, &attrs, DEPRECATED_NORMAL);
+ false, NULL, &attrs, expr, expr_const_operands,
+ DEPRECATED_NORMAL);
/* Apply attributes. */
decl_attributes (&type, attrs, 0);
@@ -3168,6 +3894,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
{
tree decl;
tree tem;
+ tree expr = NULL_TREE;
enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
/* An object declared as __attribute__((deprecated)) suppresses
@@ -3176,11 +3903,14 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
deprecated_state = DEPRECATED_SUPPRESS;
decl = grokdeclarator (declarator, declspecs,
- NORMAL, initialized, NULL, &attributes,
+ NORMAL, initialized, NULL, &attributes, &expr, NULL,
deprecated_state);
if (!decl)
return 0;
+ if (expr)
+ add_stmt (expr);
+
if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl)))
warning (OPT_Wmain, "%q+D is usually a function", decl);
@@ -3328,9 +4058,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
&& !TREE_READONLY (decl)
&& DECL_DECLARED_INLINE_P (current_function_decl)
&& DECL_EXTERNAL (current_function_decl))
- pedwarn (input_location, 0,
- "%q+D is static but declared in inline function %qD "
- "which is not static", decl, current_function_decl);
+ record_inline_static (input_location, current_function_decl,
+ decl, csi_modifiable);
/* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
@@ -3345,33 +4074,20 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
return tem;
}
-/* Initialize EH if not initialized yet and exceptions are enabled. */
-
-void
-c_maybe_initialize_eh (void)
-{
- if (!flag_exceptions || c_eh_initialized_p)
- return;
-
- c_eh_initialized_p = true;
- eh_personality_libfunc
- = init_one_libfunc (USING_SJLJ_EXCEPTIONS
- ? "__gcc_personality_sj0"
- : "__gcc_personality_v0");
- default_init_unwind_resume_libfunc ();
- using_eh_for_cleanups ();
-}
-
/* Finish processing of a declaration;
install its initial value.
+ If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
If the length of an array type is not known before,
- it must be determined now, from the initial value, or it is an error. */
+ it must be determined now, from the initial value, or it is an error.
+
+ INIT_LOC is the location of the initial value. */
void
-finish_decl (tree decl, tree init, tree asmspec_tree)
+finish_decl (tree decl, location_t init_loc, tree init,
+ tree origtype, tree asmspec_tree)
{
tree type;
- int was_incomplete = (DECL_SIZE (decl) == 0);
+ bool was_incomplete = (DECL_SIZE (decl) == 0);
const char *asmspec = 0;
/* If a name was specified, get the string. */
@@ -3397,7 +4113,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
init = 0;
if (init)
- store_init_value (decl, init);
+ store_init_value (init_loc, decl, init, origtype);
if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL
@@ -3457,10 +4173,10 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
b_ext = b_ext->shadowed;
if (b_ext)
{
- if (b_ext->type)
- b_ext->type = composite_type (b_ext->type, type);
+ if (b_ext->u.type)
+ b_ext->u.type = composite_type (b_ext->u.type, type);
else
- b_ext->type = type;
+ b_ext->u.type = type;
}
}
break;
@@ -3605,7 +4321,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
add_stmt (bind);
BIND_EXPR_BODY (bind) = push_stmt_list ();
}
- add_stmt (build_stmt (DECL_EXPR, decl));
+ add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl),
+ DECL_EXPR, decl));
}
}
@@ -3630,7 +4347,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
{
if (!DECL_FILE_SCOPE_P (decl)
&& variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
- add_stmt (build_stmt (DECL_EXPR, decl));
+ add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
}
@@ -3650,22 +4367,31 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
tree cleanup_decl = lookup_name (cleanup_id);
tree cleanup;
+ VEC(tree,gc) *vec;
/* Build "cleanup(&decl)" for the destructor. */
cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
- cleanup = build_tree_list (NULL_TREE, cleanup);
- cleanup = build_function_call (cleanup_decl, cleanup);
+ vec = VEC_alloc (tree, gc, 1);
+ VEC_quick_push (tree, vec, cleanup);
+ cleanup = build_function_call_vec (DECL_SOURCE_LOCATION (decl),
+ cleanup_decl, vec, NULL);
+ VEC_free (tree, gc, vec);
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
TREE_USED (cleanup_decl) = 1;
- /* Initialize EH, if we've been told to do so. */
- c_maybe_initialize_eh ();
-
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);
}
/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
@@ -3675,7 +4401,7 @@ grokparm (const struct c_parm *parm)
{
tree attrs = parm->attrs;
tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
- NULL, &attrs, DEPRECATED_NORMAL);
+ NULL, &attrs, NULL, NULL, DEPRECATED_NORMAL);
decl_attributes (&decl, attrs, 0);
@@ -3692,12 +4418,12 @@ push_parm_decl (const struct c_parm *parm)
tree decl;
decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
- &attrs, DEPRECATED_NORMAL);
+ &attrs, NULL, NULL, DEPRECATED_NORMAL);
decl_attributes (&decl, attrs, 0);
decl = pushdecl (decl);
- finish_decl (decl, NULL_TREE, NULL_TREE);
+ finish_decl (decl, input_location, NULL_TREE, NULL_TREE, NULL_TREE);
}
/* Mark all the parameter declarations to date as forward decls.
@@ -3722,11 +4448,12 @@ mark_forward_parm_decls (void)
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
literal, which may be an incomplete array type completed by the
- initializer; INIT is a CONSTRUCTOR that initializes the compound
- literal. */
+ initializer; INIT is a CONSTRUCTOR at LOC that initializes the compound
+ literal. NON_CONST is true if the initializers contain something
+ that cannot occur in a constant expression. */
tree
-build_compound_literal (tree type, tree init)
+build_compound_literal (location_t loc, tree type, tree init, bool non_const)
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
@@ -3735,10 +4462,11 @@ build_compound_literal (tree type, tree init)
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 (VAR_DECL, NULL_TREE, type);
+ decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
TREE_STATIC (decl) = (current_scope == file_scope);
@@ -3746,7 +4474,7 @@ build_compound_literal (tree type, tree init)
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
TREE_READONLY (decl) = TYPE_READONLY (type);
- store_init_value (decl, init);
+ store_init_value (loc, decl, init, NULL_TREE);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
@@ -3761,7 +4489,7 @@ build_compound_literal (tree type, tree init)
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
- stmt = build_stmt (DECL_EXPR, decl);
+ stmt = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl);
complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt);
TREE_SIDE_EFFECTS (complit) = 1;
@@ -3779,8 +4507,25 @@ build_compound_literal (tree type, tree init)
rest_of_decl_compilation (decl, 1, 0);
}
+ if (non_const)
+ {
+ complit = build2 (C_MAYBE_CONST_EXPR, type, NULL, complit);
+ C_MAYBE_CONST_EXPR_NON_CONST (complit) = 1;
+ }
+
return complit;
}
+
+/* Check the type of a compound literal. Here we just check that it
+ is valid for C++. */
+
+void
+check_compound_literal_type (location_t loc, struct c_type_name *type_name)
+{
+ if (warn_cxx_compat && type_name->specs->tag_defined_p)
+ warning_at (loc, OPT_Wc___compat,
+ "defining a type in a compound literal is invalid in C++");
+}
/* Determine whether TYPE is a structure with a flexible array member,
or a union containing such a structure (possibly recursively). */
@@ -3818,23 +4563,37 @@ flexible_array_type_p (tree type)
/* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
replacing with appropriate values if they are invalid. */
static void
-check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
+check_bitfield_type_and_width (tree *type, tree *width, tree orig_name)
{
tree type_mv;
unsigned int max_width;
unsigned HOST_WIDE_INT w;
- const char *name = orig_name ? orig_name: _("<anonymous>");
+ const char *name = (orig_name
+ ? identifier_to_locale (IDENTIFIER_POINTER (orig_name))
+ : _("<anonymous>"));
/* Detect and ignore out of range field width and process valid
field widths. */
- if (!INTEGRAL_TYPE_P (TREE_TYPE (*width))
- || TREE_CODE (*width) != INTEGER_CST)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (*width)))
{
error ("bit-field %qs width not an integer constant", name);
*width = integer_one_node;
}
else
{
+ if (TREE_CODE (*width) != INTEGER_CST)
+ {
+ *width = c_fully_fold (*width, false, NULL);
+ if (TREE_CODE (*width) == INTEGER_CST)
+ pedwarn (input_location, OPT_pedantic,
+ "bit-field %qs width not an integer constant expression",
+ name);
+ }
+ if (TREE_CODE (*width) != INTEGER_CST)
+ {
+ error ("bit-field %qs width not an integer constant", name);
+ *width = integer_one_node;
+ }
constant_expression_warning (*width);
if (tree_int_cst_sgn (*width) < 0)
{
@@ -3891,7 +4650,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
/* Print warning about variable length array if necessary. */
static void
-warn_variable_length_array (const char *name, tree size)
+warn_variable_length_array (tree name, tree size)
{
int const_size = TREE_CONSTANT (size);
@@ -3900,7 +4659,8 @@ warn_variable_length_array (const char *name, tree size)
if (const_size)
{
if (name)
- pedwarn (input_location, OPT_Wvla, "ISO C90 forbids array %qs whose size "
+ pedwarn (input_location, OPT_Wvla,
+ "ISO C90 forbids array %qE whose size "
"can%'t be evaluated",
name);
else
@@ -3909,8 +4669,9 @@ warn_variable_length_array (const char *name, tree size)
}
else
{
- if (name)
- pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array %qs",
+ if (name)
+ pedwarn (input_location, OPT_Wvla,
+ "ISO C90 forbids variable length array %qE",
name);
else
pedwarn (input_location, OPT_Wvla, "ISO C90 forbids variable length array");
@@ -3922,7 +4683,7 @@ warn_variable_length_array (const char *name, tree size)
{
if (name)
warning (OPT_Wvla,
- "the size of array %qs can"
+ "the size of array %qE can"
"%'t be evaluated", name);
else
warning (OPT_Wvla,
@@ -3932,7 +4693,7 @@ warn_variable_length_array (const char *name, tree size)
{
if (name)
warning (OPT_Wvla,
- "variable length array %qs is used",
+ "variable length array %qE is used",
name);
else
warning (OPT_Wvla,
@@ -3941,6 +4702,34 @@ warn_variable_length_array (const char *name, tree size)
}
}
+/* 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.
@@ -3965,6 +4754,11 @@ warn_variable_length_array (const char *name, tree size)
DECL_ATTRS points to the list of attributes that should be added to this
decl. Any nested attributes that belong on the decl itself will be
added to this list.
+ If EXPR is not NULL, any expressions that need to be evaluated as
+ part of evaluating variably modified types will be stored in *EXPR.
+ If EXPR_CONST_OPERANDS is not NULL, *EXPR_CONST_OPERANDS will be
+ set to indicate whether operands in *EXPR can be used in constant
+ expressions.
DEPRECATED_STATE is a deprecated_states value indicating whether
deprecation warnings should be suppressed.
@@ -3979,7 +4773,8 @@ static tree
grokdeclarator (const struct c_declarator *declarator,
struct c_declspecs *declspecs,
enum decl_context decl_context, bool initialized, tree *width,
- tree *decl_attrs, enum deprecated_states deprecated_state)
+ tree *decl_attrs, tree *expr, bool *expr_const_operands,
+ enum deprecated_states deprecated_state)
{
tree type = declspecs->type;
bool threadp = declspecs->thread_p;
@@ -3988,10 +4783,10 @@ grokdeclarator (const struct c_declarator *declarator,
int restrictp;
int volatilep;
int type_quals = TYPE_UNQUALIFIED;
- const char *name, *orig_name;
+ tree name = NULL_TREE;
bool funcdef_flag = false;
bool funcdef_syntax = false;
- int size_varies = 0;
+ bool size_varies = false;
tree decl_attr = declspecs->decl_attr;
int array_ptr_quals = TYPE_UNQUALIFIED;
tree array_ptr_attrs = NULL_TREE;
@@ -4001,21 +4796,36 @@ grokdeclarator (const struct c_declarator *declarator,
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
+ addr_space_t as1, as2, address_space;
+ location_t loc = UNKNOWN_LOCATION;
+ const char *errmsg;
+ tree expr_dummy;
+ bool expr_const_operands_dummy;
+
+ if (expr == NULL)
+ expr = &expr_dummy;
+ if (expr_const_operands == NULL)
+ expr_const_operands = &expr_const_operands_dummy;
+
+ *expr = declspecs->expr;
+ *expr_const_operands = declspecs->expr_const_operands;
if (decl_context == FUNCDEF)
funcdef_flag = true, decl_context = NORMAL;
/* Look inside a declarator for the name being declared
- and get it as a string, for an error message. */
+ and get it as an IDENTIFIER_NODE, for an error message. */
{
const struct c_declarator *decl = declarator;
- name = 0;
while (decl)
switch (decl->kind)
{
- case cdk_function:
case cdk_array:
+ loc = decl->id_loc;
+ /* FALL THRU. */
+
+ case cdk_function:
case cdk_pointer:
funcdef_syntax = (decl->kind == cdk_function);
decl = decl->declarator;
@@ -4026,17 +4836,23 @@ grokdeclarator (const struct c_declarator *declarator,
break;
case cdk_id:
+ loc = decl->id_loc;
if (decl->u.id)
- name = IDENTIFIER_POINTER (decl->u.id);
+ name = decl->u.id;
decl = 0;
break;
default:
gcc_unreachable ();
}
- orig_name = name;
if (name == 0)
- name = "type name";
+ {
+ gcc_assert (decl_context == PARM
+ || decl_context == TYPENAME
+ || (decl_context == FIELD
+ && declarator->kind == cdk_id));
+ gcc_assert (!initialized);
+ }
}
/* A function definition's declarator must have the form of
@@ -4052,17 +4868,20 @@ grokdeclarator (const struct c_declarator *declarator,
decl_context = PARM;
if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (declspecs->type);
+ warn_deprecated_use (declspecs->type, declspecs->decl_attr);
if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope
&& variably_modified_type_p (type, NULL_TREE))
{
- error ("variably modified %qs at file scope", name);
+ if (name)
+ error_at (loc, "variably modified %qE at file scope", name);
+ else
+ error_at (loc, "variably modified field at file scope");
type = integer_type_node;
}
- size_varies = C_TYPE_VARIABLE_SIZE (type);
+ size_varies = C_TYPE_VARIABLE_SIZE (type) != 0;
/* Diagnose defaulting to "int". */
@@ -4074,9 +4893,16 @@ grokdeclarator (const struct c_declarator *declarator,
if ((warn_implicit_int || warn_return_type || flag_isoc99)
&& funcdef_flag)
warn_about_return_type = 1;
- else
- pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
- "type defaults to %<int%> in declaration of %qs", name);
+ else
+ {
+ if (name)
+ pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wimplicit_int,
+ "type defaults to %<int%> in declaration of %qE",
+ name);
+ else
+ pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wimplicit_int,
+ "type defaults to %<int%> in type name");
+ }
}
/* Adjust the type if a bit-field is being declared,
@@ -4101,20 +4927,30 @@ grokdeclarator (const struct c_declarator *declarator,
constp = declspecs->const_p + TYPE_READONLY (element_type);
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+ as1 = declspecs->address_space;
+ as2 = TYPE_ADDR_SPACE (element_type);
+ address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
+
if (pedantic && !flag_isoc99)
{
if (constp > 1)
- pedwarn (input_location, OPT_pedantic, "duplicate %<const%>");
+ pedwarn (loc, OPT_pedantic, "duplicate %<const%>");
if (restrictp > 1)
- pedwarn (input_location, OPT_pedantic, "duplicate %<restrict%>");
+ pedwarn (loc, OPT_pedantic, "duplicate %<restrict%>");
if (volatilep > 1)
- pedwarn (input_location, OPT_pedantic, "duplicate %<volatile%>");
+ pedwarn (loc, OPT_pedantic, "duplicate %<volatile%>");
}
+
+ if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
+ 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)))
type = TYPE_MAIN_VARIANT (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+ | (volatilep ? TYPE_QUAL_VOLATILE : 0)
+ | ENCODE_QUAL_ADDR_SPACE (address_space));
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
@@ -4126,15 +4962,15 @@ grokdeclarator (const struct c_declarator *declarator,
|| storage_class == csc_typedef))
{
if (storage_class == csc_auto)
- pedwarn (input_location,
- (current_scope == file_scope) ? 0 : OPT_pedantic,
+ pedwarn (loc,
+ (current_scope == file_scope) ? 0 : OPT_pedantic,
"function definition declared %<auto%>");
if (storage_class == csc_register)
- error ("function definition declared %<register%>");
+ error_at (loc, "function definition declared %<register%>");
if (storage_class == csc_typedef)
- error ("function definition declared %<typedef%>");
+ error_at (loc, "function definition declared %<typedef%>");
if (threadp)
- error ("function definition declared %<__thread%>");
+ error_at (loc, "function definition declared %<__thread%>");
threadp = false;
if (storage_class == csc_auto
|| storage_class == csc_register
@@ -4150,14 +4986,21 @@ grokdeclarator (const struct c_declarator *declarator,
switch (decl_context)
{
case FIELD:
- error ("storage class specified for structure field %qs",
- name);
+ if (name)
+ error_at (loc, "storage class specified for structure "
+ "field %qE", name);
+ else
+ error_at (loc, "storage class specified for structure field");
break;
case PARM:
- error ("storage class specified for parameter %qs", name);
+ if (name)
+ error_at (loc, "storage class specified for parameter %qE",
+ name);
+ else
+ error_at (loc, "storage class specified for unnamed parameter");
break;
default:
- error ("storage class specified for typename");
+ error_at (loc, "storage class specified for typename");
break;
}
storage_class = csc_none;
@@ -4174,28 +5017,30 @@ grokdeclarator (const struct c_declarator *declarator,
/* It is fine to have 'extern const' when compiling at C
and C++ intersection. */
if (!(warn_cxx_compat && constp))
- warning (0, "%qs initialized and declared %<extern%>", name);
+ warning_at (loc, 0, "%qE initialized and declared %<extern%>",
+ name);
}
else
- error ("%qs has both %<extern%> and initializer", name);
+ error_at (loc, "%qE has both %<extern%> and initializer", name);
}
else if (current_scope == file_scope)
{
if (storage_class == csc_auto)
- error ("file-scope declaration of %qs specifies %<auto%>", name);
+ error_at (loc, "file-scope declaration of %qE specifies %<auto%>",
+ name);
if (pedantic && storage_class == csc_register)
pedwarn (input_location, OPT_pedantic,
- "file-scope declaration of %qs specifies %<register%>", name);
+ "file-scope declaration of %qE specifies %<register%>", name);
}
else
{
if (storage_class == csc_extern && funcdef_flag)
- error ("nested function %qs declared %<extern%>", name);
+ error_at (loc, "nested function %qE declared %<extern%>", name);
else if (threadp && storage_class == csc_none)
{
- error ("function-scope %qs implicitly auto and declared "
- "%<__thread%>",
- name);
+ error_at (loc, "function-scope %qE implicitly auto and declared "
+ "%<__thread%>",
+ name);
threadp = false;
}
}
@@ -4240,7 +5085,7 @@ grokdeclarator (const struct c_declarator *declarator,
/* Only the innermost declarator (making a parameter be of
array type which is converted to pointer type)
may have static or type qualifiers. */
- error ("static or type qualifiers in non-parameter array declarator");
+ error_at (loc, "static or type qualifiers in non-parameter array declarator");
array_ptr_quals = TYPE_UNQUALIFIED;
array_ptr_attrs = NULL_TREE;
array_parm_static = 0;
@@ -4287,18 +5132,26 @@ grokdeclarator (const struct c_declarator *declarator,
if (VOID_TYPE_P (type))
{
- error ("declaration of %qs as array of voids", name);
+ if (name)
+ error_at (loc, "declaration of %qE as array of voids", name);
+ else
+ error_at (loc, "declaration of type name as array of voids");
type = error_mark_node;
}
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("declaration of %qs as array of functions", name);
+ if (name)
+ error_at (loc, "declaration of %qE as array of functions",
+ name);
+ else
+ error_at (loc, "declaration of type name as array of "
+ "functions");
type = error_mark_node;
}
if (pedantic && !in_system_header && flexible_array_type_p (type))
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"invalid use of structure with flexible array member");
if (size == error_mark_node)
@@ -4313,33 +5166,72 @@ grokdeclarator (const struct c_declarator *declarator,
if (size)
{
+ bool size_maybe_const = true;
+ bool size_int_const = (TREE_CODE (size) == INTEGER_CST
+ && !TREE_OVERFLOW (size));
+ bool this_size_varies = false;
+
/* Strip NON_LVALUE_EXPRs since we aren't using as an
lvalue. */
STRIP_TYPE_NOPS (size);
if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
{
- error ("size of array %qs has non-integer type", name);
+ if (name)
+ error_at (loc, "size of array %qE has non-integer type",
+ name);
+ else
+ error_at (loc,
+ "size of unnamed array has non-integer type");
size = integer_one_node;
}
- if (pedantic && integer_zerop (size))
- pedwarn (input_location, OPT_pedantic,
- "ISO C forbids zero-size array %qs", name);
+ size = c_fully_fold (size, false, &size_maybe_const);
- if (TREE_CODE (size) == INTEGER_CST)
+ if (pedantic && size_maybe_const && integer_zerop (size))
+ {
+ if (name)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C forbids zero-size array %qE", name);
+ else
+ pedwarn (loc, OPT_pedantic,
+ "ISO C forbids zero-size array");
+ }
+
+ if (TREE_CODE (size) == INTEGER_CST && size_maybe_const)
{
constant_expression_warning (size);
if (tree_int_cst_sgn (size) < 0)
{
- error ("size of array %qs is negative", name);
+ if (name)
+ error_at (loc, "size of array %qE is negative", name);
+ else
+ error_at (loc, "size of unnamed array is negative");
size = integer_one_node;
}
+ /* Handle a size folded to an integer constant but
+ not an integer constant expression. */
+ if (!size_int_const)
+ {
+ /* If this is a file scope declaration of an
+ ordinary identifier, this is invalid code;
+ diagnosing it here and not subsequently
+ treating the type as variable-length avoids
+ more confusing diagnostics later. */
+ if ((decl_context == NORMAL || decl_context == FIELD)
+ && current_scope == file_scope)
+ pedwarn (input_location, 0,
+ "variably modified %qE at file scope",
+ name);
+ else
+ this_size_varies = size_varies = true;
+ warn_variable_length_array (name, size);
+ }
}
else if ((decl_context == NORMAL || decl_context == FIELD)
&& current_scope == file_scope)
{
- error ("variably modified %qs at file scope", name);
+ error_at (loc, "variably modified %qE at file scope", name);
size = integer_one_node;
}
else
@@ -4347,11 +5239,11 @@ grokdeclarator (const struct c_declarator *declarator,
/* Make sure the array size remains visibly
nonconstant even if it is (eg) a const variable
with known value. */
- size_varies = 1;
- warn_variable_length_array (orig_name, size);
+ this_size_varies = size_varies = true;
+ warn_variable_length_array (name, size);
}
- if (integer_zerop (size))
+ if (integer_zerop (size) && !this_size_varies)
{
/* A zero-length array cannot be represented with
an unsigned index type, which is what we'll
@@ -4365,16 +5257,19 @@ grokdeclarator (const struct c_declarator *declarator,
MINUS_EXPR, which allows the -1 to get folded
with the +1 that happens when building TYPE_SIZE. */
if (size_varies)
- size = variable_size (size);
+ size = c_variable_size (size);
+ if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
+ size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+ integer_zero_node, size);
/* Compute the maximum valid index, that is, size
- 1. Do the calculation in index_type, so that
if it is a variable the computations will be
done in the proper mode. */
- itype = fold_build2 (MINUS_EXPR, index_type,
- convert (index_type, size),
- convert (index_type,
- size_one_node));
+ itype = fold_build2_loc (loc, MINUS_EXPR, index_type,
+ convert (index_type, 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
@@ -4386,13 +5281,26 @@ grokdeclarator (const struct c_declarator *declarator,
if (TREE_CODE (itype) == INTEGER_CST
&& TREE_OVERFLOW (itype))
{
- error ("size of array %qs is too large", name);
+ if (name)
+ error_at (loc, "size of array %qE is too large",
+ name);
+ else
+ error_at (loc, "size of unnamed array is too large");
type = error_mark_node;
continue;
}
itype = build_index_type (itype);
}
+ if (this_size_varies)
+ {
+ if (*expr)
+ *expr = build2 (COMPOUND_EXPR, TREE_TYPE (size),
+ *expr, size);
+ else
+ *expr = size;
+ *expr_const_operands &= size_maybe_const;
+ }
}
else if (decl_context == FIELD)
{
@@ -4403,7 +5311,7 @@ grokdeclarator (const struct c_declarator *declarator,
the field variably modified, not through being
something other than a declaration with function
prototype scope. */
- size_varies = 1;
+ size_varies = true;
else
{
const struct c_declarator *t = declarator;
@@ -4413,7 +5321,7 @@ grokdeclarator (const struct c_declarator *declarator,
}
if (flexible_array_member
&& pedantic && !flag_isoc99 && !in_system_header)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C90 does not support flexible array members");
/* ISO C99 Flexible array members are effectively
@@ -4427,7 +5335,7 @@ grokdeclarator (const struct c_declarator *declarator,
if (array_parm_vla_unspec_p)
{
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
- size_varies = 1;
+ size_varies = true;
}
}
else if (decl_context == TYPENAME)
@@ -4441,14 +5349,14 @@ grokdeclarator (const struct c_declarator *declarator,
otherwise be modified below. */
itype = build_range_type (sizetype, size_zero_node,
NULL_TREE);
- size_varies = 1;
+ size_varies = true;
}
}
/* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
{
- error ("array type has incomplete element type");
+ error_at (loc, "array type has incomplete element type");
type = error_mark_node;
}
else
@@ -4458,7 +5366,14 @@ grokdeclarator (const struct c_declarator *declarator,
it, but here we want to make sure we don't ever
modify the shared type, so we gcc_assert (itype)
below. */
- type = build_array_type (type, itype);
+ {
+ addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
+ if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
+ type = build_qualified_type (type,
+ ENCODE_QUAL_ADDR_SPACE (as));
+
+ type = build_array_type (type, itype);
+ }
if (type != error_mark_node)
{
@@ -4483,6 +5398,7 @@ grokdeclarator (const struct c_declarator *declarator,
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)
{
@@ -4490,6 +5406,7 @@ grokdeclarator (const struct c_declarator *declarator,
/* 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);
}
}
@@ -4498,7 +5415,7 @@ grokdeclarator (const struct c_declarator *declarator,
|| array_ptr_attrs != NULL_TREE
|| array_parm_static))
{
- error ("static or type qualifiers in non-parameter array declarator");
+ error_at (loc, "static or type qualifiers in non-parameter array declarator");
array_ptr_quals = TYPE_UNQUALIFIED;
array_ptr_attrs = NULL_TREE;
array_parm_static = 0;
@@ -4525,17 +5442,33 @@ grokdeclarator (const struct c_declarator *declarator,
if (type == error_mark_node)
continue;
- size_varies = 0;
+ size_varies = false;
/* Warn about some types functions can't return. */
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("%qs declared as function returning a function", name);
+ if (name)
+ error_at (loc, "%qE declared as function returning a "
+ "function", name);
+ else
+ error_at (loc, "type name declared as function "
+ "returning a function");
type = integer_type_node;
}
if (TREE_CODE (type) == ARRAY_TYPE)
{
- error ("%qs declared as function returning an array", name);
+ if (name)
+ error_at (loc, "%qE declared as function returning an array",
+ name);
+ else
+ error_at (loc, "type name declared as function returning "
+ "an array");
+ type = integer_type_node;
+ }
+ errmsg = targetm.invalid_return_type (type);
+ if (errmsg)
+ {
+ error (errmsg);
type = integer_type_node;
}
@@ -4557,10 +5490,10 @@ grokdeclarator (const struct c_declarator *declarator,
function definitions in ISO C; GCC used to used
them for noreturn functions. */
if (VOID_TYPE_P (type) && really_funcdef)
- pedwarn (input_location, 0,
+ pedwarn (loc, 0,
"function definition has qualified void return type");
else
- warning (OPT_Wignored_qualifiers,
+ warning_at (loc, OPT_Wignored_qualifiers,
"type qualifiers ignored on function return type");
type = c_build_qualified_type (type, type_quals);
@@ -4590,11 +5523,11 @@ grokdeclarator (const struct c_declarator *declarator,
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- size_varies = 0;
+ size_varies = false;
/* When the pointed-to type involves components of variable size,
care must be taken to ensure that the size evaluation code is
@@ -4623,10 +5556,10 @@ grokdeclarator (const struct c_declarator *declarator,
&& (decl_context == NORMAL || decl_context == FIELD)
&& variably_modified_type_p (type, NULL_TREE))
{
- tree decl = build_decl (TYPE_DECL, NULL_TREE, type);
+ tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (decl) = 1;
pushdecl (decl);
- finish_decl (decl, NULL_TREE, NULL_TREE);
+ finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
TYPE_NAME (type) = decl;
}
@@ -4648,9 +5581,62 @@ grokdeclarator (const struct c_declarator *declarator,
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
+ /* Warn about address space used for things other than static memory or
+ pointers. */
+ address_space = DECODE_QUAL_ADDR_SPACE (type_quals);
+ if (!ADDR_SPACE_GENERIC_P (address_space))
+ {
+ if (decl_context == NORMAL)
+ {
+ switch (storage_class)
+ {
+ case csc_auto:
+ error ("%qs combined with %<auto%> qualifier for %qE",
+ c_addr_space_name (address_space), name);
+ break;
+ case csc_register:
+ error ("%qs combined with %<register%> qualifier for %qE",
+ c_addr_space_name (address_space), name);
+ break;
+ case csc_none:
+ if (current_function_scope)
+ {
+ error ("%qs specified for auto variable %qE",
+ c_addr_space_name (address_space), name);
+ break;
+ }
+ break;
+ case csc_static:
+ case csc_extern:
+ case csc_typedef:
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
+ {
+ if (name)
+ error ("%qs specified for parameter %qE",
+ c_addr_space_name (address_space), name);
+ else
+ error ("%qs specified for unnamed parameter",
+ c_addr_space_name (address_space));
+ }
+ else if (decl_context == FIELD)
+ {
+ if (name)
+ error ("%qs specified for structure field %qE",
+ c_addr_space_name (address_space), name);
+ else
+ error ("%qs specified for structure field",
+ c_addr_space_name (address_space));
+ }
+ }
+
/* Check the type and width of a bit-field. */
if (bitfield)
- check_bitfield_type_and_width (&type, width, orig_name);
+ check_bitfield_type_and_width (&type, width, name);
/* Did array size calculations overflow? */
@@ -4659,7 +5645,10 @@ grokdeclarator (const struct c_declarator *declarator,
&& TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
&& TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
{
- error ("size of array %qs is too large", name);
+ if (name)
+ error_at (loc, "size of array %qE is too large", name);
+ else
+ error_at (loc, "size of unnamed array is too large");
/* If we proceed with the array type as it is, we'll eventually
crash in tree_low_cst(). */
type = error_mark_node;
@@ -4672,16 +5661,36 @@ grokdeclarator (const struct c_declarator *declarator,
tree decl;
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl = build_decl (TYPE_DECL, declarator->u.id, type);
- DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ decl = build_decl (declarator->id_loc,
+ TYPE_DECL, declarator->u.id, type);
if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (declspecs->inline_p)
- pedwarn (input_location, 0,"typedef %q+D declared %<inline%>", decl);
+ pedwarn (loc, 0,"typedef %q+D declared %<inline%>", decl);
+
+ if (warn_cxx_compat && declarator->u.id != NULL_TREE)
+ {
+ struct c_binding *b = I_TAG_BINDING (declarator->u.id);
+
+ if (b != NULL
+ && b->decl != NULL_TREE
+ && (B_IN_CURRENT_SCOPE (b)
+ || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
+ && TYPE_MAIN_VARIANT (b->decl) != TYPE_MAIN_VARIANT (type))
+ {
+ warning_at (declarator->id_loc, OPT_Wc___compat,
+ ("using %qD as both a typedef and a tag is "
+ "invalid in C++"),
+ decl);
+ if (b->locus != UNKNOWN_LOCATION)
+ inform (b->locus, "originally defined here");
+ }
+ }
+
return decl;
}
@@ -4696,7 +5705,7 @@ grokdeclarator (const struct c_declarator *declarator,
&& !declspecs->inline_p);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
@@ -4707,8 +5716,8 @@ grokdeclarator (const struct c_declarator *declarator,
&& variably_modified_type_p (type, NULL_TREE))
{
/* C99 6.7.2.1p8 */
- pedwarn (input_location, OPT_pedantic,
- "a member of a structure or union cannot have a variably modified type");
+ pedwarn (loc, OPT_pedantic, "a member of a structure or union cannot "
+ "have a variably modified type");
}
/* Aside from typedefs and type names (handle above),
@@ -4724,7 +5733,7 @@ grokdeclarator (const struct c_declarator *declarator,
&& !(storage_class == csc_static
|| storage_class == csc_register)))))
{
- error ("variable or field %qs declared void", name);
+ error_at (loc, "variable or field %qE declared void", name);
type = integer_type_node;
}
@@ -4754,15 +5763,15 @@ grokdeclarator (const struct c_declarator *declarator,
/* We don't yet implement attributes in this context. */
if (array_ptr_attrs != NULL_TREE)
- warning (OPT_Wattributes,
- "attributes in parameter array declarator ignored");
+ warning_at (loc, OPT_Wattributes,
+ "attributes in parameter array declarator ignored");
- size_varies = 0;
+ size_varies = false;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (type_quals)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
@@ -4772,8 +5781,8 @@ grokdeclarator (const struct c_declarator *declarator,
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl = build_decl (PARM_DECL, declarator->u.id, type);
- DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ decl = build_decl (declarator->id_loc,
+ PARM_DECL, declarator->u.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -4789,7 +5798,7 @@ grokdeclarator (const struct c_declarator *declarator,
DECL_ARG_TYPE (decl) = promoted_type;
if (declspecs->inline_p)
- pedwarn (input_location, 0, "parameter %q+D declared %<inline%>", decl);
+ pedwarn (loc, 0, "parameter %q+D declared %<inline%>", decl);
}
else if (decl_context == FIELD)
{
@@ -4802,18 +5811,21 @@ grokdeclarator (const struct c_declarator *declarator,
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("field %qs declared as a function", name);
+ error_at (loc, "field %qE declared as a function", name);
type = build_pointer_type (type);
}
else if (TREE_CODE (type) != ERROR_MARK
&& !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
{
- error ("field %qs has incomplete type", name);
+ if (name)
+ error_at (loc, "field %qE has incomplete type", name);
+ else
+ error_at (loc, "unnamed field has incomplete type");
type = error_mark_node;
}
type = c_build_qualified_type (type, type_quals);
- decl = build_decl (FIELD_DECL, declarator->u.id, type);
- DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ decl = build_decl (declarator->id_loc,
+ FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !declarator->u.id)
TREE_NO_WARNING (decl) = 1;
@@ -4825,7 +5837,7 @@ grokdeclarator (const struct c_declarator *declarator,
{
if (storage_class == csc_register || threadp)
{
- error ("invalid storage class for function %qs", name);
+ error_at (loc, "invalid storage class for function %qE", name);
}
else if (current_scope != file_scope)
{
@@ -4835,10 +5847,11 @@ grokdeclarator (const struct c_declarator *declarator,
GCC allows 'auto', perhaps with 'inline', to support
nested functions. */
if (storage_class == csc_auto)
- pedwarn (input_location, OPT_pedantic, "invalid storage class for function %qs", name);
+ pedwarn (loc, OPT_pedantic,
+ "invalid storage class for function %qE", name);
else if (storage_class == csc_static)
{
- error ("invalid storage class for function %qs", name);
+ error_at (loc, "invalid storage class for function %qE", name);
if (funcdef_flag)
storage_class = declspecs->storage_class = csc_none;
else
@@ -4846,19 +5859,19 @@ grokdeclarator (const struct c_declarator *declarator,
}
}
- decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
- DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ decl = build_decl (declarator->id_loc,
+ FUNCTION_DECL, declarator->u.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
- pedwarn (input_location, OPT_pedantic,
+ 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 (0, "%<noreturn%> function returns non-void value");
+ 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
@@ -4894,7 +5907,7 @@ grokdeclarator (const struct c_declarator *declarator,
if (flag_hosted && MAIN_NAME_P (declarator->u.id))
{
if (declspecs->inline_p)
- pedwarn (input_location, 0, "cannot inline function %<main%>");
+ pedwarn (loc, 0, "cannot inline function %<main%>");
}
else if (declspecs->inline_p)
/* Record that the function is declared `inline'. */
@@ -4923,17 +5936,17 @@ grokdeclarator (const struct c_declarator *declarator,
&& global_decl != visible_decl
&& TREE_CODE (global_decl) == VAR_DECL
&& !TREE_PUBLIC (global_decl))
- error ("variable previously declared %<static%> redeclared "
- "%<extern%>");
+ error_at (loc, "variable previously declared %<static%> "
+ "redeclared %<extern%>");
}
- decl = build_decl (VAR_DECL, declarator->u.id, type);
- DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ decl = build_decl (declarator->id_loc,
+ VAR_DECL, declarator->u.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
if (declspecs->inline_p)
- pedwarn (input_location, 0, "variable %q+D declared %<inline%>", decl);
+ pedwarn (loc, 0, "variable %q+D declared %<inline%>", decl);
/* At file scope, an initialized extern declaration may follow
a static declaration. In that case, DECL_EXTERNAL will be
@@ -4960,11 +5973,18 @@ grokdeclarator (const struct c_declarator *declarator,
DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
}
- if (storage_class == csc_extern
+ if ((storage_class == csc_extern
+ || (storage_class == csc_none
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && !funcdef_flag))
&& variably_modified_type_p (type, NULL_TREE))
{
/* C99 6.7.5.2p2 */
- error ("object with variably modified type must have no linkage");
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ error_at (loc, "non-nested function with variably modified type");
+ else
+ error_at (loc, "object with variably modified type must have "
+ "no linkage");
}
/* Record `register' declaration for warnings on &
@@ -5001,6 +6021,19 @@ grokdeclarator (const struct c_declarator *declarator,
name of a variable. Thus, if it's known before this, die horribly. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
+ if (warn_cxx_compat
+ && TREE_CODE (decl) == VAR_DECL
+ && TREE_PUBLIC (decl)
+ && TREE_STATIC (decl)
+ && (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ && TYPE_NAME (TREE_TYPE (decl)) == NULL_TREE)
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+ ("non-local variable %qD with anonymous type is "
+ "questionable in C++"),
+ decl);
+
return decl;
}
}
@@ -5051,6 +6084,7 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
{
tree parm, type, typelt;
unsigned int parmno;
+ const char *errmsg;
/* If there is a parameter of incomplete type in a definition,
this is an error. In a declaration this is valid, and a
@@ -5074,26 +6108,40 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
if (funcdef_flag)
{
if (DECL_NAME (parm))
- error ("parameter %u (%q+D) has incomplete type",
- parmno, parm);
+ error_at (input_location,
+ "parameter %u (%q+D) has incomplete type",
+ parmno, parm);
else
- error ("%Jparameter %u has incomplete type",
- parm, parmno);
+ error_at (DECL_SOURCE_LOCATION (parm),
+ "parameter %u has incomplete type",
+ parmno);
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
+ arg_types = NULL_TREE;
}
else if (VOID_TYPE_P (type))
{
if (DECL_NAME (parm))
- warning (0, "parameter %u (%q+D) has void type",
- parmno, parm);
+ warning_at (input_location, 0,
+ "parameter %u (%q+D) has void type",
+ parmno, parm);
else
- warning (0, "%Jparameter %u has void type",
- parm, parmno);
+ warning_at (DECL_SOURCE_LOCATION (parm), 0,
+ "parameter %u has void type",
+ parmno);
}
}
+ errmsg = targetm.invalid_parameter_type (type);
+ if (errmsg)
+ {
+ 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))
warn_if_shadowing (parm);
}
@@ -5255,6 +6303,11 @@ get_parm_info (bool ellipsis)
type itself. FUNCTION_DECLs appear when there is an implicit
function declaration in the parameter list. */
+ /* 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);
TREE_CHAIN (decl) = others;
others = decl;
/* fall through */
@@ -5288,17 +6341,24 @@ get_parm_info (bool ellipsis)
}
/* Get the struct, enum or union (CODE says which) with tag NAME.
- Define the tag as a forward-reference if it is not defined.
- Return a c_typespec structure for the type specifier. */
+ Define the tag as a forward-reference with location LOC if it is
+ not defined. Return a c_typespec structure for the type
+ specifier. */
struct c_typespec
-parser_xref_tag (enum tree_code code, tree name)
+parser_xref_tag (location_t loc, enum tree_code code, tree name)
{
struct c_typespec ret;
+ tree ref;
+ location_t refloc;
+
+ ret.expr = NULL_TREE;
+ ret.expr_const_operands = true;
+
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
- tree ref = lookup_tag (code, name, 0);
+ ref = lookup_tag (code, name, 0, &refloc);
/* If this is the right type of tag, return what we found.
(This reference will be shadowed by shadow_tag later if appropriate.)
If this is the wrong type of tag, do not return it. If it was the
@@ -5313,6 +6373,35 @@ parser_xref_tag (enum tree_code code, tree name)
ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
if (ref && TREE_CODE (ref) == code)
{
+ if (C_TYPE_DEFINED_IN_STRUCT (ref)
+ && loc != UNKNOWN_LOCATION
+ && warn_cxx_compat)
+ {
+ switch (code)
+ {
+ case ENUMERAL_TYPE:
+ warning_at (loc, OPT_Wc___compat,
+ ("enum type defined in struct or union "
+ "is not visible in C++"));
+ inform (refloc, "enum type defined here");
+ break;
+ case RECORD_TYPE:
+ warning_at (loc, OPT_Wc___compat,
+ ("struct defined in struct or union "
+ "is not visible in C++"));
+ inform (refloc, "struct defined here");
+ break;
+ case UNION_TYPE:
+ warning_at (loc, OPT_Wc___compat,
+ ("union defined in struct or union "
+ "is not visible in C++"));
+ inform (refloc, "union defined here");
+ break;
+ default:
+ gcc_unreachable();
+ }
+ }
+
ret.spec = ref;
return ret;
}
@@ -5336,7 +6425,7 @@ parser_xref_tag (enum tree_code code, tree name)
TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
}
- pushtag (name, ref);
+ pushtag (loc, name, ref);
ret.spec = ref;
return ret;
@@ -5349,40 +6438,53 @@ parser_xref_tag (enum tree_code code, tree name)
tree
xref_tag (enum tree_code code, tree name)
{
- return parser_xref_tag (code, name).spec;
+ return parser_xref_tag (input_location, code, name).spec;
}
/* Make sure that the tag NAME is defined *in the current scope*
at least as a forward reference.
- CODE says which kind of tag NAME ought to be. */
+ LOC is the location of the struct's definition.
+ CODE says which kind of tag NAME ought to be.
+
+ This stores the current value of the file static STRUCT_PARSE_INFO
+ in *ENCLOSING_STRUCT_PARSE_INFO, and points STRUCT_PARSE_INFO at a
+ new c_struct_parse_info structure. The old value of
+ STRUCT_PARSE_INFO is restored in finish_struct. */
tree
-start_struct (enum tree_code code, tree name)
+start_struct (location_t loc, enum tree_code code, tree name,
+ struct c_struct_parse_info **enclosing_struct_parse_info)
{
/* If there is already a tag defined at this scope
(as a forward reference), just return it. */
- tree ref = 0;
+ tree ref = NULL_TREE;
+ location_t refloc = UNKNOWN_LOCATION;
- if (name != 0)
- ref = lookup_tag (code, name, 1);
+ if (name != NULL_TREE)
+ ref = lookup_tag (code, name, 1, &refloc);
if (ref && TREE_CODE (ref) == code)
{
if (TYPE_SIZE (ref))
{
if (code == UNION_TYPE)
- error ("redefinition of %<union %E%>", name);
+ error_at (loc, "redefinition of %<union %E%>", name);
else
- error ("redefinition of %<struct %E%>", name);
+ error_at (loc, "redefinition of %<struct %E%>", name);
+ if (refloc != UNKNOWN_LOCATION)
+ inform (refloc, "originally defined here");
/* Don't create structures using a name already in use. */
ref = NULL_TREE;
}
else if (C_TYPE_BEING_DEFINED (ref))
{
if (code == UNION_TYPE)
- error ("nested redefinition of %<union %E%>", name);
+ error_at (loc, "nested redefinition of %<union %E%>", name);
else
- error ("nested redefinition of %<struct %E%>", name);
+ error_at (loc, "nested redefinition of %<struct %E%>", name);
+ /* Don't bother to report "originally defined here" for a
+ nested redefinition; the original definition should be
+ obvious. */
/* Don't create structures that contain themselves. */
ref = NULL_TREE;
}
@@ -5393,11 +6495,29 @@ start_struct (enum tree_code code, tree name)
if (ref == NULL_TREE || TREE_CODE (ref) != code)
{
ref = make_node (code);
- pushtag (name, ref);
+ pushtag (loc, name, ref);
}
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
+
+ *enclosing_struct_parse_info = struct_parse_info;
+ struct_parse_info = XNEW (struct c_struct_parse_info);
+ struct_parse_info->struct_types = VEC_alloc (tree, heap, 0);
+ struct_parse_info->fields = VEC_alloc (c_binding_ptr, heap, 0);
+ struct_parse_info->typedefs_seen = VEC_alloc (tree, heap, 0);
+
+ /* FIXME: This will issue a warning for a use of a type defined
+ within a statement expr used within sizeof, et. al. This is not
+ terribly serious as C++ doesn't permit statement exprs within
+ sizeof anyhow. */
+ if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+ warning_at (loc, OPT_Wc___compat,
+ "defining type in %qs expression is invalid in C++",
+ (in_sizeof
+ ? "sizeof"
+ : (in_typeof ? "typeof" : "alignof")));
+
return ref;
}
@@ -5467,12 +6587,31 @@ grokfield (location_t loc,
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
- width ? &width : NULL, decl_attrs,
+ width ? &width : NULL, decl_attrs, NULL, NULL,
DEPRECATED_NORMAL);
- finish_decl (value, NULL_TREE, NULL_TREE);
+ finish_decl (value, loc, NULL_TREE, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
+ if (warn_cxx_compat && DECL_NAME (value) != NULL_TREE)
+ {
+ /* If we currently have a binding for this field, set the
+ in_struct field in the binding, so that we warn about lookups
+ which find it. */
+ struct c_binding *b = I_SYMBOL_BINDING (DECL_NAME (value));
+ if (b != NULL)
+ {
+ /* If the in_struct field is not yet set, push it on a list
+ to be cleared when this struct is finished. */
+ if (!b->in_struct)
+ {
+ VEC_safe_push (c_binding_ptr, heap,
+ struct_parse_info->fields, b);
+ b->in_struct = 1;
+ }
+ }
+ }
+
return value;
}
@@ -5533,12 +6672,76 @@ detect_field_duplicates (tree fieldlist)
}
}
+/* Finish up struct info used by -Wc++-compat. */
+
+static void
+warn_cxx_compat_finish_struct (tree fieldlist)
+{
+ unsigned int ix;
+ tree x;
+ struct c_binding *b;
+
+ /* Set the C_TYPE_DEFINED_IN_STRUCT flag for each type defined in
+ the current struct. We do this now at the end of the struct
+ 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)
+ C_TYPE_DEFINED_IN_STRUCT (x) = 1;
+
+ /* The TYPEDEFS_SEEN field of STRUCT_PARSE_INFO is a list of
+ typedefs used when declaring fields in this struct. If the name
+ of any of the fields is also a typedef name then the struct would
+ not parse in C++, because the C++ lookup rules say that the
+ typedef name would be looked up in the context of the struct, and
+ would thus be the field rather than the typedef. */
+ if (!VEC_empty (tree, struct_parse_info->typedefs_seen)
+ && fieldlist != NULL_TREE)
+ {
+ /* Use a pointer_set using the name of the typedef. We can use
+ 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)
+ pointer_set_insert (tset, DECL_NAME (x));
+
+ for (x = fieldlist; x != NULL_TREE; x = TREE_CHAIN (x))
+ {
+ if (pointer_set_contains (tset, DECL_NAME (x)))
+ {
+ warning_at (DECL_SOURCE_LOCATION (x), OPT_Wc___compat,
+ ("using %qD as both field and typedef name is "
+ "invalid in C++"),
+ x);
+ /* FIXME: It would be nice to report the location where
+ the typedef name is used. */
+ }
+ }
+
+ pointer_set_destroy (tset);
+ }
+
+ /* 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)
+ b->in_struct = 0;
+}
+
/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
+ LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
FIELDLIST is a chain of FIELD_DECL nodes for the fields.
- ATTRIBUTES are attributes to be applied to the structure. */
+ ATTRIBUTES are attributes to be applied to the structure.
+
+ ENCLOSING_STRUCT_PARSE_INFO is the value of STRUCT_PARSE_INFO when
+ the struct was started. */
tree
-finish_struct (tree t, tree fieldlist, tree attributes)
+finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
+ struct c_struct_parse_info *enclosing_struct_parse_info)
{
tree x;
bool toplevel = file_scope == current_scope;
@@ -5562,16 +6765,16 @@ finish_struct (tree t, tree fieldlist, tree attributes)
if (TREE_CODE (t) == UNION_TYPE)
{
if (fieldlist)
- pedwarn (input_location, OPT_pedantic, "union has no named members");
+ pedwarn (loc, OPT_pedantic, "union has no named members");
else
- pedwarn (input_location, OPT_pedantic, "union has no members");
+ pedwarn (loc, OPT_pedantic, "union has no members");
}
else
{
if (fieldlist)
- pedwarn (input_location, OPT_pedantic, "struct has no named members");
+ pedwarn (loc, OPT_pedantic, "struct has no named members");
else
- pedwarn (input_location, OPT_pedantic, "struct has no members");
+ pedwarn (loc, OPT_pedantic, "struct has no members");
}
}
}
@@ -5635,25 +6838,28 @@ finish_struct (tree t, tree fieldlist, tree attributes)
{
if (TREE_CODE (t) == UNION_TYPE)
{
- error ("%Jflexible array member in union", x);
+ error_at (DECL_SOURCE_LOCATION (x),
+ "flexible array member in union");
TREE_TYPE (x) = error_mark_node;
}
else if (TREE_CHAIN (x) != NULL_TREE)
{
- error ("%Jflexible array member not at end of struct", x);
+ error_at (DECL_SOURCE_LOCATION (x),
+ "flexible array member not at end of struct");
TREE_TYPE (x) = error_mark_node;
}
else if (!saw_named_field)
{
- error ("%Jflexible array member in otherwise empty struct", x);
+ error_at (DECL_SOURCE_LOCATION (x),
+ "flexible array member in otherwise empty struct");
TREE_TYPE (x) = error_mark_node;
}
}
- if (pedantic && !in_system_header && TREE_CODE (t) == RECORD_TYPE
+ if (pedantic && TREE_CODE (t) == RECORD_TYPE
&& flexible_array_type_p (TREE_TYPE (x)))
- pedwarn (input_location, OPT_pedantic,
- "%Jinvalid use of structure with flexible array member", x);
+ pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic,
+ "invalid use of structure with flexible array member");
if (DECL_NAME (x))
saw_named_field = 1;
@@ -5758,11 +6964,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
/* 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;
- warning (0, "union cannot be made transparent");
+ TYPE_TRANSPARENT_AGGR (t) = 0;
+ warning_at (loc, 0, "union cannot be made transparent");
}
/* If this structure or union completes the type of any previous
@@ -5786,6 +6992,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
}
C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)) = 0;
+ /* Update type location to the one of the definition, instead of e.g.
+ a forward declaration. */
+ if (TYPE_STUB_DECL (t))
+ DECL_SOURCE_LOCATION (TYPE_STUB_DECL (t)) = loc;
+
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel);
@@ -5793,7 +7004,25 @@ finish_struct (tree t, tree fieldlist, tree attributes)
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))
- add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t)));
+ add_stmt (build_stmt (loc,
+ DECL_EXPR, build_decl (loc, TYPE_DECL, NULL, t)));
+
+ if (warn_cxx_compat)
+ warn_cxx_compat_finish_struct (fieldlist);
+
+ VEC_free (tree, heap, struct_parse_info->struct_types);
+ VEC_free (c_binding_ptr, heap, struct_parse_info->fields);
+ VEC_free (tree, heap, struct_parse_info->typedefs_seen);
+ XDELETE (struct_parse_info);
+
+ struct_parse_info = enclosing_struct_parse_info;
+
+ /* If this struct is defined inside a struct, add it to
+ struct_types. */
+ if (warn_cxx_compat
+ && struct_parse_info != NULL
+ && !in_sizeof && !in_typeof && !in_alignof)
+ VEC_safe_push (tree, heap, struct_parse_info->struct_types, t);
return t;
}
@@ -5810,37 +7039,41 @@ layout_array_type (tree t)
/* Begin compiling the definition of an enumeration type.
NAME is its name (or null if anonymous).
+ LOC is the enum's location.
Returns the type object, as yet incomplete.
Also records info about it so that build_enumerator
may be used to declare the individual values as they are read. */
tree
-start_enum (struct c_enum_contents *the_enum, tree name)
+start_enum (location_t loc, struct c_enum_contents *the_enum, tree name)
{
- tree enumtype = 0;
+ tree enumtype = NULL_TREE;
+ location_t enumloc = UNKNOWN_LOCATION;
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
forward reference. */
- if (name != 0)
- enumtype = lookup_tag (ENUMERAL_TYPE, name, 1);
+ if (name != NULL_TREE)
+ enumtype = lookup_tag (ENUMERAL_TYPE, name, 1, &enumloc);
if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
{
enumtype = make_node (ENUMERAL_TYPE);
- pushtag (name, enumtype);
+ pushtag (loc, name, enumtype);
}
if (C_TYPE_BEING_DEFINED (enumtype))
- error ("nested redefinition of %<enum %E%>", name);
+ error_at (loc, "nested redefinition of %<enum %E%>", name);
C_TYPE_BEING_DEFINED (enumtype) = 1;
if (TYPE_VALUES (enumtype) != 0)
{
/* This enum is a named one that has been declared already. */
- error ("redeclaration of %<enum %E%>", name);
+ error_at (loc, "redeclaration of %<enum %E%>", name);
+ if (enumloc != UNKNOWN_LOCATION)
+ inform (enumloc, "originally defined here");
/* Completely replace its old definition.
The old enumerators remain defined, however. */
@@ -5853,6 +7086,16 @@ start_enum (struct c_enum_contents *the_enum, tree name)
if (flag_short_enums)
TYPE_PACKED (enumtype) = 1;
+ /* FIXME: This will issue a warning for a use of a type defined
+ within sizeof in a statement expr. This is not terribly serious
+ as C++ doesn't permit statement exprs within sizeof anyhow. */
+ if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
+ warning_at (loc, OPT_Wc___compat,
+ "defining type in %qs expression is invalid in C++",
+ (in_sizeof
+ ? "sizeof"
+ : (in_typeof ? "typeof" : "alignof")));
+
return enumtype;
}
@@ -5992,17 +7235,25 @@ finish_enum (tree enumtype, tree values, tree attributes)
/* Finish debugging output for this type. */
rest_of_type_compilation (enumtype, toplevel);
+ /* If this enum is defined inside a struct, add it to
+ struct_types. */
+ if (warn_cxx_compat
+ && struct_parse_info != NULL
+ && !in_sizeof && !in_typeof && !in_alignof)
+ VEC_safe_push (tree, heap, struct_parse_info->struct_types, enumtype);
+
return enumtype;
}
/* 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.
Return a tree-list containing the CONST_DECL and its value.
Assignment of sequential values by default is handled here. */
tree
-build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
- location_t value_loc)
+build_enumerator (location_t loc,
+ struct c_enum_contents *the_enum, tree name, tree value)
{
tree decl, type;
@@ -6014,16 +7265,33 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
undeclared identifier) - just ignore the value expression. */
if (value == error_mark_node)
value = 0;
- else if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
- || TREE_CODE (value) != INTEGER_CST)
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
{
- error ("enumerator value for %qE is not an integer constant", name);
+ error_at (loc, "enumerator value for %qE is not an integer constant",
+ name);
value = 0;
}
else
{
- value = default_conversion (value);
- constant_expression_warning (value);
+ if (TREE_CODE (value) != INTEGER_CST)
+ {
+ value = c_fully_fold (value, false, NULL);
+ if (TREE_CODE (value) == INTEGER_CST)
+ pedwarn (loc, OPT_pedantic,
+ "enumerator value for %qE is not an integer "
+ "constant expression", name);
+ }
+ if (TREE_CODE (value) != INTEGER_CST)
+ {
+ error ("enumerator value for %qE is not an integer constant",
+ name);
+ value = 0;
+ }
+ else
+ {
+ value = default_conversion (value);
+ constant_expression_warning (value);
+ }
}
}
@@ -6034,14 +7302,14 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
{
value = the_enum->enum_next_value;
if (the_enum->enum_overflow)
- error ("overflow in enumeration values");
+ error_at (loc, "overflow in enumeration values");
}
/* Even though the underlying type of an enum is unspecified, the
type of enumeration constants is explicitly defined as int
(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 (value_loc, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C restricts enumerator values to range of %<int%>");
/* The ISO C Standard mandates enumerators to have type int, even
@@ -6072,7 +7340,7 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
>= TYPE_PRECISION (integer_type_node)
&& TYPE_UNSIGNED (type)));
- decl = build_decl (CONST_DECL, name, type);
+ decl = build_decl (loc, CONST_DECL, name, type);
DECL_INITIAL (decl) = convert (type, value);
pushdecl (decl);
@@ -6098,8 +7366,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
{
tree decl1, old_decl;
tree restype, resdecl;
- struct c_label_context_se *nstack_se;
- struct c_label_context_vm *nstack_vm;
+ location_t loc;
current_function_returns_value = 0; /* Assume, until we see it does. */
current_function_returns_null = 0;
@@ -6107,43 +7374,29 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
warn_about_return_type = 0;
c_switch_stack = NULL;
- nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se);
- nstack_se->labels_def = NULL;
- nstack_se->labels_used = NULL;
- nstack_se->next = label_context_stack_se;
- label_context_stack_se = nstack_se;
-
- nstack_vm = XOBNEW (&parser_obstack, struct c_label_context_vm);
- nstack_vm->labels_def = NULL;
- nstack_vm->labels_used = NULL;
- nstack_vm->scope = 0;
- nstack_vm->next = label_context_stack_vm;
- label_context_stack_vm = nstack_vm;
-
/* Indicate no valid break/continue context by setting these variables
to some non-null, non-label value. We'll notice and emit the proper
error message in c_finish_bc_stmt. */
c_break_label = c_cont_label = size_zero_node;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
- &attributes, DEPRECATED_NORMAL);
+ &attributes, NULL, NULL, DEPRECATED_NORMAL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
if (decl1 == 0)
- {
- label_context_stack_se = label_context_stack_se->next;
- label_context_stack_vm = label_context_stack_vm->next;
- return 0;
- }
+ return 0;
+
+ loc = DECL_SOURCE_LOCATION (decl1);
decl_attributes (&decl1, attributes, 0);
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
- warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
- decl1);
+ warning_at (loc, OPT_Wattributes,
+ "inline function %qD given attribute noinline",
+ decl1);
/* Handle gnu_inline attribute. */
if (declspecs->inline_p
@@ -6160,7 +7413,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
{
- error ("return type is an incomplete type");
+ error_at (loc, "return type is an incomplete type");
/* Make it return void instead. */
TREE_TYPE (decl1)
= build_function_type (void_type_node,
@@ -6168,7 +7421,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
}
if (warn_about_return_type)
- pedwarn_c99 (input_location, flag_isoc99 ? 0
+ pedwarn_c99 (loc, flag_isoc99 ? 0
: (warn_return_type ? OPT_Wreturn_type : OPT_Wimplicit_int),
"return type defaults to %<int%>");
@@ -6214,7 +7467,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
{
tree ext_decl, ext_type;
ext_decl = b->decl;
- ext_type = b->type ? b->type : TREE_TYPE (ext_decl);
+ ext_type = b->u.type ? b->u.type : TREE_TYPE (ext_decl);
if (TREE_CODE (ext_type) == FUNCTION_TYPE
&& comptypes (TREE_TYPE (TREE_TYPE (decl1)),
TREE_TYPE (ext_type)))
@@ -6235,15 +7488,16 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
&& old_decl != error_mark_node
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
&& C_DECL_ISNT_PROTOTYPE (old_decl))
- warning (OPT_Wstrict_prototypes,
- "function declaration isn%'t a prototype");
+ warning_at (loc, OPT_Wstrict_prototypes,
+ "function declaration isn%'t a prototype");
/* Optionally warn of any global def with no previous prototype. */
else if (warn_missing_prototypes
&& old_decl != error_mark_node
&& TREE_PUBLIC (decl1)
&& !MAIN_NAME_P (DECL_NAME (decl1))
&& C_DECL_ISNT_PROTOTYPE (old_decl))
- warning (OPT_Wmissing_prototypes, "no previous prototype for %q+D", decl1);
+ warning_at (loc, OPT_Wmissing_prototypes,
+ "no previous prototype for %qD", decl1);
/* Optionally warn of any def with no previous prototype
if the function has already been used. */
else if (warn_missing_prototypes
@@ -6251,15 +7505,16 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
&& old_decl != error_mark_node
&& TREE_USED (old_decl)
&& TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
- warning (OPT_Wmissing_prototypes,
- "%q+D was used with no prototype before its definition", decl1);
+ 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. */
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
&& !MAIN_NAME_P (DECL_NAME (decl1)))
- warning (OPT_Wmissing_declarations, "no previous declaration for %q+D",
- decl1);
+ warning_at (loc, OPT_Wmissing_declarations,
+ "no previous declaration for %qD",
+ decl1);
/* Optionally warn of any def with no previous declaration
if the function has already been used. */
else if (warn_missing_declarations
@@ -6267,8 +7522,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
&& old_decl != error_mark_node
&& TREE_USED (old_decl)
&& C_DECL_IMPLICIT (old_decl))
- warning (OPT_Wmissing_declarations,
- "%q+D was used with no declaration before its definition", decl1);
+ warning_at (loc, OPT_Wmissing_declarations,
+ "%qD was used with no declaration before its definition", decl1);
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
@@ -6291,12 +7546,13 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
- pedwarn (input_location, OPT_Wmain, "return type of %q+D is not %<int%>", decl1);
+ pedwarn (loc, OPT_Wmain, "return type of %qD is not %<int%>", decl1);
check_main_parameter_types (decl1);
if (!TREE_PUBLIC (decl1))
- pedwarn (input_location, OPT_Wmain, "%q+D is normally a non-static function", decl1);
+ pedwarn (loc, OPT_Wmain,
+ "%qD is normally a non-static function", decl1);
}
/* Record the decl so that the function name is defined.
@@ -6309,7 +7565,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
declare_parm_level ();
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
- resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
+ resdecl = build_decl (loc, RESULT_DECL, NULL_TREE, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
DECL_RESULT (current_function_decl) = resdecl;
@@ -6330,8 +7586,9 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
if (current_scope->bindings)
{
- error ("%Jold-style parameter declarations in prototyped "
- "function definition", fndecl);
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "old-style parameter declarations in prototyped "
+ "function definition");
/* Get rid of the old-style declarations. */
pop_scope ();
@@ -6343,9 +7600,8 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
its parameter list). */
else if (!in_system_header && !current_function_scope
&& arg_info->types != error_mark_node)
- warning (OPT_Wtraditional,
- "%Jtraditional C rejects ISO C style function definitions",
- fndecl);
+ warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional,
+ "traditional C rejects ISO C style function definitions");
/* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */
@@ -6355,12 +7611,13 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
if (DECL_NAME (decl))
{
bind (DECL_NAME (decl), decl, current_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false,
+ UNKNOWN_LOCATION);
if (!TREE_USED (decl))
warn_if_shadowing (decl);
}
else
- error ("%Jparameter name omitted", decl);
+ error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted");
}
/* Record the parameter list in the function declaration. */
@@ -6372,14 +7629,16 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
bind (DECL_NAME (decl), decl, current_scope,
- /*invisible=*/false, /*nested=*/false);
+ /*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,
- /*invisible=*/false, /*nested=*/false);
+ /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
}
/* Subroutine of store_parm_decls which handles old-style function
@@ -6394,8 +7653,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
struct pointer_set_t *seen_args = pointer_set_create ();
if (!in_system_header)
- warning (OPT_Wold_style_definition, "%Jold-style function definition",
- fndecl);
+ warning_at (DECL_SOURCE_LOCATION (fndecl),
+ OPT_Wold_style_definition, "old-style function definition");
/* Match each formal parameter name with its declaration. Save each
decl in the appropriate TREE_PURPOSE slot of the parmids chain. */
@@ -6403,7 +7662,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
{
if (TREE_VALUE (parm) == 0)
{
- error ("%Jparameter name missing from parameter list", fndecl);
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "parameter name missing from parameter list");
TREE_PURPOSE (parm) = 0;
continue;
}
@@ -6414,12 +7674,14 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
decl = b->decl;
/* If we got something other than a PARM_DECL it is an error. */
if (TREE_CODE (decl) != PARM_DECL)
- error ("%q+D declared as a non-parameter", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qD declared as a non-parameter", decl);
/* If the declaration is already marked, we have a duplicate
name. Complain and ignore the duplicate. */
else if (pointer_set_contains (seen_args, decl))
{
- error ("multiple parameters named %q+D", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "multiple parameters named %qD", decl);
TREE_PURPOSE (parm) = 0;
continue;
}
@@ -6427,7 +7689,8 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
an int. */
else if (VOID_TYPE_P (TREE_TYPE (decl)))
{
- error ("parameter %q+D declared with void type", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "parameter %qD declared with void type", decl);
TREE_TYPE (decl) = integer_type_node;
DECL_ARG_TYPE (decl) = integer_type_node;
layout_decl (decl, 0);
@@ -6437,16 +7700,30 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
/* If no declaration found, default to int. */
else
{
- decl = build_decl (PARM_DECL, TREE_VALUE (parm), integer_type_node);
+ /* FIXME diagnostics: This should be the location of the argument,
+ not the FNDECL. E.g., for an old-style declaration
+
+ int f10(v) { blah; }
+
+ We should use the location of the V, not the F10.
+ Unfortunately, the V is an IDENTIFIER_NODE which has no
+ location. In the future we need locations for c_arg_info
+ entries.
+
+ See gcc.dg/Wshadow-3.c for an example of this problem. */
+ decl = build_decl (DECL_SOURCE_LOCATION (fndecl),
+ PARM_DECL, TREE_VALUE (parm), integer_type_node);
DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
- DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (fndecl);
pushdecl (decl);
warn_if_shadowing (decl);
if (flag_isoc99)
- pedwarn (input_location, 0, "type of %q+D defaults to %<int%>", decl);
- else
- warning (OPT_Wmissing_parameter_type, "type of %q+D defaults to %<int%>", decl);
+ pedwarn (DECL_SOURCE_LOCATION (decl),
+ 0, "type of %qD defaults to %<int%>", decl);
+ else
+ warning_at (DECL_SOURCE_LOCATION (decl),
+ OPT_Wmissing_parameter_type,
+ "type of %qD defaults to %<int%>", decl);
}
TREE_PURPOSE (parm) = decl;
@@ -6465,13 +7742,16 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
if (TREE_TYPE (parm) != error_mark_node
&& !COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
- error ("parameter %q+D has incomplete type", parm);
+ error_at (DECL_SOURCE_LOCATION (parm),
+ "parameter %qD has incomplete type", parm);
TREE_TYPE (parm) = error_mark_node;
}
if (!pointer_set_contains (seen_args, parm))
{
- error ("declaration for parameter %q+D but no such parameter", parm);
+ error_at (DECL_SOURCE_LOCATION (parm),
+ "declaration for parameter %qD but no such parameter",
+ parm);
/* Pretend the parameter was not missing.
This gets us to a standard state and minimizes
@@ -6521,13 +7801,22 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
if (current_function_prototype_built_in)
- warning (0, "number of arguments doesn%'t match "
- "built-in prototype");
+ warning_at (DECL_SOURCE_LOCATION (fndecl),
+ 0, "number of arguments doesn%'t match "
+ "built-in prototype");
else
{
- error ("number of arguments doesn%'t match prototype");
- error ("%Hprototype declaration",
- &current_function_prototype_locus);
+ /* FIXME diagnostics: This should be the location of
+ FNDECL, but there is bug when a prototype is
+ declared inside function context, but defined
+ outside of it (e.g., gcc.dg/pr15698-2.c). In
+ which case FNDECL gets the location of the
+ prototype, not the definition. */
+ error_at (input_location,
+ "number of arguments doesn%'t match prototype");
+
+ error_at (current_function_prototype_locus,
+ "prototype declaration");
}
break;
}
@@ -6560,11 +7849,13 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
been diagnosed as conflicting with an
old-style definition and discarded? */
if (current_function_prototype_built_in)
- warning (OPT_pedantic, "promoted argument %qD "
- "doesn%'t match built-in prototype", parm);
+ warning_at (DECL_SOURCE_LOCATION (parm),
+ OPT_pedantic, "promoted argument %qD "
+ "doesn%'t match built-in prototype", parm);
else
{
- pedwarn (input_location, OPT_pedantic, "promoted argument %qD "
+ pedwarn (DECL_SOURCE_LOCATION (parm),
+ OPT_pedantic, "promoted argument %qD "
"doesn%'t match prototype", parm);
pedwarn (current_function_prototype_locus, OPT_pedantic,
"prototype declaration");
@@ -6573,13 +7864,15 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
else
{
if (current_function_prototype_built_in)
- warning (0, "argument %qD doesn%'t match "
- "built-in prototype", parm);
+ warning_at (DECL_SOURCE_LOCATION (parm),
+ 0, "argument %qD doesn%'t match "
+ "built-in prototype", parm);
else
{
- error ("argument %qD doesn%'t match prototype", parm);
- error ("%Hprototype declaration",
- &current_function_prototype_locus);
+ error_at (DECL_SOURCE_LOCATION (parm),
+ "argument %qD doesn%'t match prototype", parm);
+ error_at (current_function_prototype_locus,
+ "prototype declaration");
}
}
}
@@ -6695,27 +7988,6 @@ store_parm_decls (void)
cfun->dont_save_pending_sizes_p = 1;
}
-/* Emit diagnostics that require gimple input for detection. Operate on
- FNDECL and all its nested functions. */
-
-static void
-c_gimple_diagnostics_recursively (tree fndecl)
-{
- struct cgraph_node *cgn;
- gimple_seq body = gimple_body (fndecl);
-
- /* Handle attribute((warn_unused_result)). Relies on gimple input. */
- c_warn_unused_result (body);
-
- /* Notice when OpenMP structured block constraints are violated. */
- if (flag_openmp)
- diagnose_omp_structured_block_errors (fndecl);
-
- /* Finalize all nested functions now. */
- cgn = cgraph_node (fndecl);
- for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
- c_gimple_diagnostics_recursively (cgn->decl);
-}
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
@@ -6728,9 +8000,6 @@ finish_function (void)
{
tree fndecl = current_function_decl;
- label_context_stack_se = label_context_stack_se->next;
- label_context_stack_vm = label_context_stack_vm->next;
-
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
@@ -6756,14 +8025,13 @@ finish_function (void)
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
== integer_type_node && flag_isoc99)
{
- tree stmt = c_finish_return (integer_zero_node);
/* Hack. We don't want the middle-end to warn that this return
is unreachable, so we mark its location as special. Using
UNKNOWN_LOCATION has the problem that it gets clobbered in
annotate_one_with_locus. A cleaner solution might be to
ensure ! should_carry_locus_p (stmt), but that needs a flag.
*/
- SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION);
+ c_finish_return (BUILTINS_LOCATION, integer_zero_node, NULL_TREE);
}
/* Tie off the statement tree for this function. */
@@ -6800,7 +8068,7 @@ finish_function (void)
c_determine_visibility (fndecl);
/* For GNU C extern inline functions disregard inline limits. */
- if (DECL_EXTERNAL (fndecl)
+ if (DECL_EXTERNAL (fndecl)
&& DECL_DECLARED_INLINE_P (fndecl))
DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
@@ -6813,8 +8081,8 @@ finish_function (void)
{
if (!decl_function_context (fndecl))
{
+ invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
c_genericize (fndecl);
- c_gimple_diagnostics_recursively (fndecl);
/* ??? Objc emits functions after finalizing the compilation unit.
This should be cleaned up later and this conditional removed. */
@@ -6823,7 +8091,6 @@ finish_function (void)
cgraph_add_new_function (fndecl, false);
return;
}
-
cgraph_finalize_function (fndecl, false);
}
else
@@ -6846,10 +8113,11 @@ finish_function (void)
}
/* Check the declarations given in a for-loop for satisfying the C99
- constraints. If exactly one such decl is found, return it. */
+ constraints. If exactly one such decl is found, return it. LOC is
+ the location of the opening parenthesis of the for loop. */
tree
-check_for_loop_decls (void)
+check_for_loop_decls (location_t loc)
{
struct c_binding *b;
tree one_decl = NULL_TREE;
@@ -6861,10 +8129,11 @@ check_for_loop_decls (void)
/* If we get here, declarations have been used in a for loop without
the C99 for loop scope. This doesn't make much sense, so don't
allow it. */
- error ("%<for%> loop initial declarations are only allowed in C99 mode");
+ error_at (loc, "%<for%> loop initial declarations "
+ "are only allowed in C99 mode");
if (hint)
{
- inform (input_location,
+ inform (loc,
"use option -std=c99 or -std=gnu99 to compile your code");
hint = false;
}
@@ -6895,29 +8164,36 @@ check_for_loop_decls (void)
switch (TREE_CODE (decl))
{
case VAR_DECL:
- if (TREE_STATIC (decl))
- error ("declaration of static variable %q+D in %<for%> loop "
- "initial declaration", decl);
- else if (DECL_EXTERNAL (decl))
- error ("declaration of %<extern%> variable %q+D in %<for%> loop "
- "initial declaration", decl);
+ {
+ location_t decl_loc = DECL_SOURCE_LOCATION (decl);
+ if (TREE_STATIC (decl))
+ error_at (decl_loc,
+ "declaration of static variable %qD in %<for%> loop "
+ "initial declaration", decl);
+ else if (DECL_EXTERNAL (decl))
+ error_at (decl_loc,
+ "declaration of %<extern%> variable %qD in %<for%> loop "
+ "initial declaration", decl);
+ }
break;
case RECORD_TYPE:
- error ("%<struct %E%> declared in %<for%> loop initial declaration",
- id);
+ error_at (loc,
+ "%<struct %E%> declared in %<for%> loop initial "
+ "declaration", id);
break;
case UNION_TYPE:
- error ("%<union %E%> declared in %<for%> loop initial declaration",
- id);
+ error_at (loc,
+ "%<union %E%> declared in %<for%> loop initial declaration",
+ id);
break;
case ENUMERAL_TYPE:
- error ("%<enum %E%> declared in %<for%> loop initial declaration",
- id);
+ error_at (loc, "%<enum %E%> declared in %<for%> loop "
+ "initial declaration", id);
break;
default:
- error ("declaration of non-variable %q+D in %<for%> loop "
- "initial declaration", decl);
+ error_at (loc, "declaration of non-variable "
+ "%qD in %<for%> loop initial declaration", decl);
}
n_decls++;
@@ -6982,21 +8258,6 @@ c_pop_function_context (void)
warn_about_return_type = p->warn_about_return_type;
}
-/* Copy the DECL_LANG_SPECIFIC data associated with DECL. */
-
-void
-c_dup_lang_specific_decl (tree decl)
-{
- struct lang_decl *ld;
-
- if (!DECL_LANG_SPECIFIC (decl))
- return;
-
- ld = GGC_NEW (struct lang_decl);
- memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
- DECL_LANG_SPECIFIC (decl) = ld;
-}
-
/* The functions below are required for functionality of doing
function at once processing in the C front end. Currently these
functions are not called from anywhere in the C front end, but as
@@ -7037,7 +8298,7 @@ record_builtin_type (enum rid rid_index, const char *name, tree type)
id = ridpointers[(int) rid_index];
else
id = get_identifier (name);
- decl = build_decl (TYPE_DECL, id, type);
+ decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL, id, type);
pushdecl (decl);
if (debug_hooks->type_decl)
debug_hooks->type_decl (decl, false);
@@ -7141,10 +8402,12 @@ build_null_declspecs (void)
{
struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
ret->type = 0;
+ ret->expr = 0;
ret->decl_attr = 0;
ret->attrs = 0;
ret->typespec_word = cts_none;
ret->storage_class = csc_none;
+ ret->expr_const_operands = true;
ret->declspecs_seen_p = false;
ret->type_seen_p = false;
ret->non_sc_seen_p = false;
@@ -7165,9 +8428,29 @@ build_null_declspecs (void)
ret->volatile_p = false;
ret->restrict_p = false;
ret->saturating_p = false;
+ ret->address_space = ADDR_SPACE_GENERIC;
return ret;
}
+/* Add the address space ADDRSPACE to the declaration specifiers
+ SPECS, returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_addrspace (struct c_declspecs *specs, addr_space_t as)
+{
+ specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
+
+ if (!ADDR_SPACE_GENERIC_P (specs->address_space)
+ && specs->address_space != as)
+ error ("incompatible address space qualifiers %qs and %qs",
+ c_addr_space_name (as),
+ c_addr_space_name (specs->address_space));
+ else
+ specs->address_space = as;
+ return specs;
+}
+
/* Add the type qualifier QUAL to the declaration specifiers SPECS,
returning SPECS. */
@@ -7207,7 +8490,8 @@ declspecs_add_qual (struct c_declspecs *specs, tree qual)
returning SPECS. */
struct c_declspecs *
-declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
+declspecs_add_type (location_t loc, struct c_declspecs *specs,
+ struct c_typespec spec)
{
tree type = spec.spec;
specs->non_sc_seen_p = true;
@@ -7224,7 +8508,7 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
enum rid i = C_RID_CODE (type);
if (specs->type)
{
- error ("two or more data types in declaration specifiers");
+ error_at (loc, "two or more data types in declaration specifiers");
return specs;
}
if ((int) i <= (int) RID_LAST_MODIFIER)
@@ -7236,203 +8520,257 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
case RID_LONG:
if (specs->long_long_p)
{
- error ("%<long long long%> is too long for GCC");
+ error_at (loc, "%<long long long%> is too long for GCC");
break;
}
if (specs->long_p)
{
if (specs->typespec_word == cts_double)
{
- error ("both %<long long%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long long%> and %<double%> in "
+ "declaration specifiers"));
break;
}
- if (pedantic && !flag_isoc99 && !in_system_header)
- pedwarn (input_location, OPT_Wlong_long, "ISO C90 does not support %<long long%>");
+ pedwarn_c90 (loc, OPT_Wlong_long,
+ "ISO C90 does not support %<long long%>");
specs->long_long_p = 1;
break;
}
if (specs->short_p)
- error ("both %<long%> and %<short%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<short%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<long%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<long%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
- error ("both %<long%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<long%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<long%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<long%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<long%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->long_p = true;
break;
case RID_SHORT:
dupe = specs->short_p;
if (specs->long_p)
- error ("both %<long%> and %<short%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<short%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<short%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<short%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
- error ("both %<short%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<short%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<short%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<short%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<short%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<short%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->short_p = true;
break;
case RID_SIGNED:
dupe = specs->signed_p;
if (specs->unsigned_p)
- error ("both %<signed%> and %<unsigned%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<signed%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<signed%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<signed%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<signed%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<signed%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<signed%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<signed%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->signed_p = true;
break;
case RID_UNSIGNED:
dupe = specs->unsigned_p;
if (specs->signed_p)
- error ("both %<signed%> and %<unsigned%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_void)
- error ("both %<unsigned%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<unsigned%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<unsigned%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<unsigned%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<unsigned%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<unsigned%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<unsigned%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else
specs->unsigned_p = true;
break;
case RID_COMPLEX:
dupe = specs->complex_p;
if (!flag_isoc99 && !in_system_header)
- pedwarn (input_location, OPT_pedantic, "ISO C90 does not support complex types");
+ pedwarn (loc, OPT_pedantic,
+ "ISO C90 does not support complex types");
if (specs->typespec_word == cts_void)
- error ("both %<complex%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<complex%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<complex%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<complex%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<complex%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_fract)
- error ("both %<complex%> and %<_Fract%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Fract%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_accum)
- error ("both %<complex%> and %<_Accum%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Accum%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<complex%> and %<_Sat%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Sat%> in "
+ "declaration specifiers"));
else
specs->complex_p = true;
break;
case RID_SAT:
dupe = specs->saturating_p;
- pedwarn (input_location, OPT_pedantic, "ISO C does not support saturating types");
+ pedwarn (loc, OPT_pedantic,
+ "ISO C does not support saturating types");
if (specs->typespec_word == cts_void)
- error ("both %<_Sat%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_bool)
- error ("both %<_Sat%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
- error ("both %<_Sat%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_int)
- error ("both %<_Sat%> and %<int%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_float)
- error ("both %<_Sat%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_double)
- error ("both %<_Sat%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
- error ("both %<_Sat%> and %<_Decimal32%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Decimal32%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat64)
- error ("both %<_Sat%> and %<_Decimal64%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Decimal64%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat128)
- error ("both %<_Sat%> and %<_Decimal128%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Decimal128%> in "
+ "declaration specifiers"));
else if (specs->complex_p)
- error ("both %<_Sat%> and %<complex%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<complex%> in "
+ "declaration specifiers"));
else
specs->saturating_p = true;
break;
@@ -7441,7 +8779,7 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
}
if (dupe)
- error ("duplicate %qE", type);
+ error_at (loc, "duplicate %qE", type);
return specs;
}
@@ -7451,117 +8789,144 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
"_Decimal64", "_Decimal128", "_Fract" or "_Accum". */
if (specs->typespec_word != cts_none)
{
- error ("two or more data types in declaration specifiers");
+ error_at (loc,
+ "two or more data types in declaration specifiers");
return specs;
}
switch (i)
{
case RID_VOID:
if (specs->long_p)
- error ("both %<long%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->complex_p)
- error ("both %<complex%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<void%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<void%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<void%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_void;
return specs;
case RID_BOOL:
if (specs->long_p)
- error ("both %<long%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->complex_p)
- error ("both %<complex%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<_Bool%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<_Bool%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_bool;
return specs;
case RID_CHAR:
if (specs->long_p)
- error ("both %<long%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<char%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<char%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<char%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_char;
return specs;
case RID_INT:
if (specs->saturating_p)
- error ("both %<_Sat%> and %<int%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<int%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_int;
return specs;
case RID_FLOAT:
if (specs->long_p)
- error ("both %<long%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<float%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<float%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_float;
return specs;
case RID_DOUBLE:
if (specs->long_long_p)
- error ("both %<long long%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<long long%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->short_p)
- error ("both %<short%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<short%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->signed_p)
- error ("both %<signed%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<signed%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers"));
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<double%> in "
- "declaration specifiers");
+ error_at (loc,
+ ("both %<_Sat%> and %<double%> in "
+ "declaration specifiers"));
else
specs->typespec_word = cts_double;
return specs;
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
- {
+ {
const char *str;
if (i == RID_DFLOAT32)
str = "_Decimal32";
@@ -7570,26 +8935,40 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
else
str = "_Decimal128";
if (specs->long_long_p)
- error ("both %<long long%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<long long%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
if (specs->long_p)
- error ("both %<long%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<long%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->short_p)
- error ("both %<short%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<short%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->signed_p)
- error ("both %<signed%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<signed%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->unsigned_p)
- error ("both %<unsigned%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<unsigned%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->complex_p)
- error ("both %<complex%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<complex%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (specs->saturating_p)
- error ("both %<_Sat%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<_Sat%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (i == RID_DFLOAT32)
specs->typespec_word = cts_dfloat32;
else if (i == RID_DFLOAT64)
@@ -7598,8 +8977,10 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
specs->typespec_word = cts_dfloat128;
}
if (!targetm.decimal_float_supported_p ())
- error ("decimal floating point not supported for this target");
- pedwarn (input_location, OPT_pedantic,
+ error_at (loc,
+ ("decimal floating point not supported "
+ "for this target"));
+ pedwarn (loc, OPT_pedantic,
"ISO C does not support decimal floating point");
return specs;
case RID_FRACT:
@@ -7611,16 +8992,19 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
else
str = "_Accum";
if (specs->complex_p)
- error ("both %<complex%> and %<%s%> in "
- "declaration specifiers", str);
+ error_at (loc,
+ ("both %<complex%> and %<%s%> in "
+ "declaration specifiers"),
+ str);
else if (i == RID_FRACT)
specs->typespec_word = cts_fract;
else
specs->typespec_word = cts_accum;
}
if (!targetm.fixed_point_supported_p ())
- error ("fixed-point types not supported for this target");
- pedwarn (input_location, OPT_pedantic,
+ error_at (loc,
+ "fixed-point types not supported for this target");
+ pedwarn (loc, OPT_pedantic,
"ISO C does not support fixed-point types");
return specs;
default:
@@ -7638,7 +9022,7 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
if (specs->type || specs->typespec_word != cts_none
|| specs->long_p || specs->short_p || specs->signed_p
|| specs->unsigned_p || specs->complex_p)
- error ("two or more data types in declaration specifiers");
+ error_at (loc, "two or more data types in declaration specifiers");
else if (TREE_CODE (type) == TYPE_DECL)
{
if (TREE_TYPE (type) == error_mark_node)
@@ -7649,13 +9033,26 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
specs->decl_attr = DECL_ATTRIBUTES (type);
specs->typedef_p = true;
specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+
+ /* If this typedef name is defined in a struct, then a C++
+ lookup would return a different value. */
+ if (warn_cxx_compat
+ && I_SYMBOL_BINDING (DECL_NAME (type))->in_struct)
+ warning_at (loc, OPT_Wc___compat,
+ "C++ lookup of %qD would return a field, not a type",
+ type);
+
+ /* If we are parsing a struct, record that a struct field
+ used a typedef. */
+ if (warn_cxx_compat && struct_parse_info != NULL)
+ VEC_safe_push (tree, heap, struct_parse_info->typedefs_seen, type);
}
}
else if (TREE_CODE (type) == IDENTIFIER_NODE)
{
tree t = lookup_name (type);
if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("%qE fails to be a typedef or built in type", type);
+ error_at (loc, "%qE fails to be a typedef or built in type", type);
else if (TREE_TYPE (t) == error_mark_node)
;
else
@@ -7666,7 +9063,18 @@ declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
specs->tag_defined_p = true;
if (spec.kind == ctsk_typeof)
- specs->typedef_p = true;
+ {
+ specs->typedef_p = true;
+ if (spec.expr)
+ {
+ if (specs->expr)
+ specs->expr = build2 (COMPOUND_EXPR, TREE_TYPE (spec.expr),
+ specs->expr, spec.expr);
+ else
+ specs->expr = spec.expr;
+ specs->expr_const_operands &= spec.expr_const_operands;
+ }
+ }
specs->type = type;
}
@@ -7687,7 +9095,7 @@ declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
&& C_IS_RESERVED_WORD (scspec));
i = C_RID_CODE (scspec);
if (specs->non_sc_seen_p)
- warning (OPT_Wold_style_declaration,
+ warning (OPT_Wold_style_declaration,
"%qE is not at beginning of declaration", scspec);
switch (i)
{
@@ -7809,7 +9217,7 @@ finish_declspecs (struct c_declspecs *specs)
else if (specs->complex_p)
{
specs->typespec_word = cts_double;
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_pedantic,
"ISO C does not support plain %<complex%> meaning "
"%<double complex%>");
}
@@ -7854,7 +9262,7 @@ finish_declspecs (struct c_declspecs *specs)
specs->type = char_type_node;
if (specs->complex_p)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_pedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
@@ -7880,7 +9288,7 @@ finish_declspecs (struct c_declspecs *specs)
: integer_type_node);
if (specs->complex_p)
{
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_pedantic,
"ISO C does not support complex integer types");
specs->type = build_complex_type (specs->type);
}
@@ -8078,9 +9486,9 @@ c_write_global_declarations (void)
if (pch_file)
return;
- /* Don't waste time on further processing if -fsyntax-only or we've
- encountered errors. */
- if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in))
+ /* 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. */
@@ -8108,7 +9516,7 @@ c_write_global_declarations (void)
/* We're done parsing; proceed to optimize and emit assembly.
FIXME: shouldn't be the front end's responsibility to call this. */
- cgraph_optimize ();
+ cgraph_finalize_compilation_unit ();
/* After cgraph has had a chance to emit everything that's going to
be emitted, output debug information for globals. */
« no previous file with comments | « gcc/gcc/c-cppbuiltin.c ('k') | gcc/gcc/c-format.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698