summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog157
-rw-r--r--gcc/c-common.h5
-rw-r--r--gcc/c-decl.c2040
-rw-r--r--gcc/c-lang.c15
-rw-r--r--gcc/c-objc-common.c8
-rw-r--r--gcc/c-opts.c37
-rw-r--r--gcc/c-parse.in104
-rw-r--r--gcc/c-tree.h71
-rw-r--r--gcc/c-typeck.c18
-rw-r--r--gcc/coverage.c1
-rw-r--r--gcc/cp/ChangeLog29
-rw-r--r--gcc/cp/cp-lang.c18
-rw-r--r--gcc/cp/parser.c9
-rw-r--r--gcc/langhooks.c2
-rw-r--r--gcc/objc/objc-act.c60
-rw-r--r--gcc/objc/objc-act.h2
-rw-r--r--gcc/objc/objc-lang.c15
-rw-r--r--gcc/testsuite/ChangeLog16
-rw-r--r--gcc/testsuite/gcc.dg/Wold-style-definition-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/Wshadow-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/builtins-30.c6
-rw-r--r--gcc/testsuite/gcc.dg/decl-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/local1.c16
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/incomplete-3.c9
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/label-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/undeclared-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/redecl-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/unused-4.c2
-rw-r--r--gcc/testsuite/objc.dg/naming-1.m4
-rw-r--r--gcc/tree.c18
31 files changed, 1383 insertions, 1319 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9b4f247b89f..b885df98dc4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,8 +1,141 @@
+2004-03-23 Zack Weinberg <zack@codesourcery.com>
+
+ PR 12267, 12391, 12560, 13129, 14114, 14113
+
+ * c-tree.h: Forward declare struct c_binding. Declare
+ c_override_bindings_to_false. Update prototypes.
+ (struct lang_identifier): Update comments. Change fields to be
+ struct c_binding *.
+ (IDENTIFIER_SYMBOL_VALUE, IDENTIFIER_TAG_VALUE)
+ (IDENTIFIER_LABEL_VALUE, C_DECL_INVISIBLE)
+ (KEEP_NO, KEEP_YES, KEEP_MAYBE): Delete.
+ (C_DECL_IN_EXTERNAL_SCOPE, C_DECL_DECLARED_BUILTIN): New.
+ * c-common.h: Update prototypes.
+ * c-decl.c (struct c_scope): Update commentary. Remove names,
+ names_last, parms, parms_last, tags, and shadowed fields. Add
+ bindings and depth fields.
+ (scope_freelist): Move to more appropriate location.
+ (c_print_identifier): Update for changes to struct lang_identifier.
+ (objc_mark_locals_volatile): Update for new bindings structures.
+ (global_bindings_p): Honor c_override_global_bindings_to_false.
+ (pushlevel): Rename to push_scope; take no arguments; use the
+ scope_freelist; initialize scope->depth and check for overflow.
+ (poplevel): Rename to pop_scope; totally rewritten for new bindings
+ structures.
+ (diagnose_mismatched_decls): Use C_DECL_DECLARED_BUILTIN, not
+ C_DECL_INVISIBLE, for certain decisions. Adjust some diagnostics.
+ Improve some commentary. Adjust handling of forward parm decls.
+ (merge_decls): Set C_DECL_DECLARED_BUILTIN when appropriate.
+ Preserve C_DECL_IN_EXTERNAL_SCOPE.
+ (warn_if_shadowing): Correct indentation. Improve diagnostics.
+ (pushdecl): Remove unnecessary assertion. Short-circuit anonymous
+ decls. Rewrite for new bindings structures. Improve commentary.
+ Eliminate the copy_node call.
+ (implicit_decl_warning): Use the "diag" idiom (as seen in
+ locate_old_decl) to reduce code duplication; call locate_old_decl
+ if appropriate. Relocate to remove need for forward declaration.
+ (implicitly_declare): Adjust for new bindings structures. Kludge
+ around Objective-C not-really-builtin functions.
+ (undeclared_variable): Improve diagnostics. If current_function_decl
+ is nonnull but current_function_scope is null, use current_scope.
+ Use bind.
+ (lookup_tag): Adjust for new bindings structures. Kludge around
+ Objective-C's tag declarations that wind up in the external scope.
+ (lookup_name): Adjust for new bindings structures. Kludge around
+ c-common.c's pseudo-typedefs that wind up in the external scope.
+ (lookup_name_current_level): Rename lookup_name_in_scope; take a
+ second argument indicating the scope to examine; rewrite for
+ new bindings structures.
+ (c_init_decl_processing): Adjust for renamed functions. Do not
+ initialize current_file_decl, first_builtin_decl, last_builtin_decl.
+ First scope pushed is the external scope, not the global scope.
+ (builtin_function): Use bind, not pushdecl. Adjust other bits
+ for new data structures. Keep track of builtins that should be
+ made visible automatically.
+ (start_decl): Adjust diagnostics. Remove unnecessary call to
+ expand_decl.
+ (grokparms): Return 0 if arg_types is error_mark_node.
+ (get_parm_info): Rename "void_at_end" argument to "ellipsis", with
+ reversed sense. Rewrite for new bindings structures. Do not
+ leave any decls in the scope, to prevent pop_scope from doing
+ contradictory things with them.
+ (finish_struct, finish_enum): Remove redundant diagnostics.
+ (build_enumerator): Don't cascade diagnostics for error_mark_node.
+ Mark location where -pedantic changes the meaning of the program.
+ (store_parm_decls_newstyle, store_parm_decls_oldstyle): Load the
+ parameter decls into the function's scope structure using bind.
+ Warn here about function definitions in the wrong style.
+ Adjust diagnostics.
+ (store_parm_decls): Correct the determination of whether a
+ function was defined with a prototype.
+ (c_write_global_declarations): Operate on all file decls and on
+ the external scope. Split body of the loop to...
+ (c_write_global_declarations_1): ... this new function, to avoid
+ code duplication.
+ (truly_local_externals, first_builtin_decl, last_builtin_decl)
+ (make_scope, pop_scope, in_parm_level_p, set_block)
+ (any_external_decl, record_external_decl, bind_label, getdecls)
+ (link_hash_hash, link_hash_eq, merge_translation_unit_decls)
+ (c_reset_state): Delete.
+ (visible_builtins, c_override_global_bindings_to_false)
+ (c_binding, I_SYMBOL_BINDING, I_SYMBOL_DECL, I_TAG_BINDING)
+ (I_TAG_DECL, I_LABEL_BINDING, I_LABEL_DECL, file_scope)
+ (external_scope, binding_freelist, bind, free_binding_and_advance)
+ (push_file_scope, pop_file_scope): New.
+ (pushtag, pushdecl_top_level, lookup_label, declare_label)
+ (define_label, c_make_fname_decl, finish_decl)
+ (mark_forward_parm_decls, build_compound_literal)
+ (grokdeclarator, start_function, check_for_loop_decls)
+ (identifier_global_value, record_builtin_type): Minor adjustments
+ for new bindings structures. Improve diagnostics and commentary.
+ * c-objc-common.c (start_cdtor, finish_cdtor): Adjust calls to
+ pushlevel/poplevel respectively.
+ (c_objc_common_finish_file): Don't call merge_translation_unit_decls.
+ * c-opts.c (c_common_parse_file): Remove spurious ATTRIBUTE_UNUSED.
+ Warn about YYDEBUG not being defined only if -dy. Remove no-longer-
+ correct loop over multiple translation units; call fatal_error if
+ requested to compile more than one file at once. (This disables
+ IMA temporarily - an up-front error being preferable to a crash.)
+ * c-parse.in (pushlevel, poplevel rules): Rename push_scope, pop_scope.
+ (all actions): Adjust calls to pushlevel/poplevel.
+ (parsing_iso_function_signature): Delete.
+ (extdef_1): Fold into extdef.
+ (old_style_parm_decls_1): Fold into old_style_parm_decls. Don't
+ warn here about function definitions in the wrong style.
+ (after_tyle_declarator, parm_declarator_starttypename)
+ (parm_declarator_nostarttypename, notype_declarator): Remove
+ commented-out productions.
+ (parmlist_1, parmlist_2): Use make_node, not tree_cons, to create
+ an empty TREE_LIST node. Adjust calls to get_parm_info.
+ (parmlist_2 : ELLIPSIS): Tag the arg-info block with error_mark_node
+ to suppress -Wold-style-definition after this error.
+ (c_parse_file): Don't clear the binding stack or call
+ finish_fname_decls here. Correct comment.
+ * c-typeck.c (same_translation_unit_p): Export.
+ (common_type): Use c_override_global_bindings_to_false, not
+ pushlevel/poplevel/declare_parm_level.
+ * c-lang.c: Override LANG_HOOKS_CLEAR_BINDING_STACK,
+ LANG_HOOKS_PUSHLEVEL, LANG_HOOKS_POPLEVEL, LANG_HOOKS_SET_BLOCK,
+ and LANG_HOOKS_GETDECLS with do-nothing stubs.
+ * objc/objc-lang.c: Likewise.
+ * objc/objc-act.c: Adjust all calls to pushlevel, poplevel,
+ get_parm_info.
+ (OBJC_VOID_AT_END): Delete; replace all uses
+ with void_list_node.
+ (generate_forward_declaration_to_string_table): Delete.
+ * objc/objc-act.h (OCTI_STRG_DECL, UOBJC_STRINGS_decl): Delete.
+
+ * coverage.c (create_coverage): Don't pushdecl anything.
+ * langhooks.c (lhd_clear_binding_stack): Call
+ lang_hooks.decls.poplevel, not poplevel.
+ * tree.c (list_length): If ENABLE_TREE_CHECKING, abort on a
+ circular list rather than going into an infinite loop.
+
2004-03-23 Olivier Hainque <hainque@act-europe.fr>
- * optabs.c (expand_binop): When synthesizing double word rotates
- from single word shifts, use a new register target if the provided
- target is not a REG already.
+ * optabs.c (expand_binop): When synthesizing double word rotates
+ from single word shifts, use a new register target if the provided
+ target is not a REG already.
2004-03-23 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
@@ -198,8 +331,8 @@
* frontends.texi: Add missing line.
2004-03-21 Zack Weinberg <zack@codesourcery.com>
- Chris Devers <cdevers@pobox.com>
- Joseph S. Myers <jsm@polyomino.org.uk>
+ Chris Devers <cdevers@pobox.com>
+ Joseph S. Myers <jsm@polyomino.org.uk>
* doc/frontends.texi: Rewrite.
* doc/gcc.texi: Update last modification date.
@@ -404,7 +537,7 @@
(ir_sr70_icmp): Delete.
2004-03-18 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-
+
* tree.h (TREE_CHECK2, TREE_CHECK3, TREE_CHECK5): New macros.
(tree_check2_failed, tree_check3_failed, tree_check5_failed): New decl.
(FUNC_OR_METHOD_CHECK, SET_ARRAY_OR_VECTOR_CHECK): New macros.
@@ -462,12 +595,12 @@
2004-03-17 Fariborz Jahanian <fjahanian@apple.com>
- * config/rs6000/rs6000.c (rs6000_stack_info): correct reg_size
- for mixed mode.
- (rs6000_emit_prologue): Ditto.
- (rs6000_emit_epilogue): Ditto.
- * config/rs6000/rs6000.h: Definition of DWARF_CIE_DATA_ALIGNMENT
- macro for mixed mode.
+ * config/rs6000/rs6000.c (rs6000_stack_info): correct reg_size
+ for mixed mode.
+ (rs6000_emit_prologue): Ditto.
+ (rs6000_emit_epilogue): Ditto.
+ * config/rs6000/rs6000.h: Definition of DWARF_CIE_DATA_ALIGNMENT
+ macro for mixed mode.
2004-03-18 Jan Hubicka <jh@suse.cz>
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 00d5d5c18d4..4326a59480f 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -329,6 +329,8 @@ extern void (*lang_expand_function_end) (void);
noreturn attribute. */
extern int (*lang_missing_noreturn_ok_p) (tree);
+extern void push_file_scope (void);
+extern void pop_file_scope (void);
extern int yyparse (void);
extern stmt_tree current_stmt_tree (void);
extern tree *current_scope_stmt_stack (void);
@@ -950,9 +952,6 @@ extern int self_promoting_args_p (tree);
extern tree strip_array_types (tree);
extern tree strip_pointer_operator (tree);
-/* This function resets the parsers' state in preparation for parsing
- a new file. */
-extern void c_reset_state (void);
/* This is the basic parsing function. */
extern void c_parse_file (void);
/* This is misnamed, it actually performs end-of-compilation processing. */
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 46863ed531a..e74347997c5 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -108,19 +108,13 @@ static GTY(()) tree c_scope_stmt_stack;
int c_in_iteration_stmt;
int c_in_case_stmt;
-/* A list of external DECLs that appeared at block scope when there was
- some other global meaning for that identifier. */
-static GTY(()) tree truly_local_externals;
-
-/* All the builtins; this is a subset of the entries of global_scope. */
-
-static GTY(()) tree first_builtin_decl;
-static GTY(()) tree last_builtin_decl;
-
/* A DECL for the current file-scope context. */
static GTY(()) tree current_file_decl;
+/* A list of decls to be made automatically visible in each file scope. */
+static GTY(()) tree visible_builtins;
+
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -144,10 +138,56 @@ static int warn_about_return_type;
/* Nonzero when starting a function declared `extern inline'. */
static int current_extern_inline;
+
+/* True means global_bindings_p should return false even if the scope stack
+ says we are in file scope. */
+bool c_override_global_bindings_to_false;
+
-/* Each c_scope structure describes the complete contents of one scope.
- Three scopes are distinguished specially: the innermost or current
- scope, the innermost function scope, and the outermost or file scope.
+/* Each c_binding structure describes one binding of an identifier to
+ a decl. All the decls in a scope - irrespective of namespace - are
+ chained together by the ->prev field, which (as the name implies)
+ runs in reverse order. All the decls in a given namespace bound to
+ a given identifier are chained by the ->shadowed field, which runs
+ from inner to outer scopes. Finally, the ->contour field points
+ back to the relevant scope structure; this is mainly used to make
+ decls in the externals scope invisible (see below).
+
+ The ->decl field usually points to a DECL node, but there are two
+ exceptions. In the namespace of type tags, the bound entity is a
+ RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node. If an undeclared
+ identifier is encountered, it is bound to error_mark_node to
+ suppress further errors about that identifier in the current
+ function. */
+
+struct c_binding GTY(())
+{
+ tree decl; /* the decl bound */
+ 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 */
+ struct c_scope *contour; /* the scope in which this decl is bound */
+};
+
+#define I_SYMBOL_BINDING(node) \
+ (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->symbol_binding)
+#define I_SYMBOL_DECL(node) \
+ (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
+
+#define I_TAG_BINDING(node) \
+ (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->tag_binding)
+#define I_TAG_DECL(node) \
+ (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
+
+#define I_LABEL_BINDING(node) \
+ (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->label_binding)
+#define I_LABEL_DECL(node) \
+ (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
+
+/* 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
+ the second to outermost) and the outermost or external scope.
Most declarations are recorded in the current scope.
@@ -157,18 +197,37 @@ static int current_extern_inline;
hence the 'innermost' qualifier.) Explicitly declared labels
(using the __label__ extension) appear in the current scope.
- Being in the global scope (current_scope == global_scope) causes
+ Being in the file scope (current_scope == file_scope) causes
special behavior in several places below. Also, under some
conditions the Objective-C front end records declarations in the
- global scope even though that isn't the current scope.
+ file scope even though that isn't the current scope.
+
+ All declarations with external linkage are recorded in the external
+ scope, even if they aren't visible there; this models the fact that
+ such declarations are visible to the entire program, and (with a
+ bit of cleverness, see pushdecl) allows diagnosis of some violations
+ of C99 6.2.2p7 and 6.2.7p2:
+
+ If, within the same translation unit, the same identifier appears
+ with both internal and external linkage, the behavior is
+ undefined.
- The order of the names, parms, and blocks lists matters, and they
- are frequently appended to. To avoid having to walk all the way to
- the end of the list on each insertion, or reverse the lists later,
- we maintain a pointer to the last list entry for each of the lists.
+ All declarations that refer to the same object or function shall
+ have compatible type; otherwise, the behavior is undefined.
+
+ Initially only the built-in declarations, which describe compiler
+ intrinsic functions plus a subset of the standard library, are in
+ this scope.
+
+ The order of the blocks list matters, and it is frequently appended
+ to. To avoid having to walk all the way to the end of the list on
+ each insertion, or reverse the list later, we maintain a pointer to
+ the last list entry. (FIXME: It should be feasible to use a reversed
+ list here.)
+
+ The bindings list is strictly in reverse order of declarations;
+ pop_scope relies on this. */
- The order of the tags, shadowed, and shadowed_tags
- lists does not matter, so we just prepend to these lists. */
struct c_scope GTY(())
{
@@ -178,35 +237,18 @@ struct c_scope GTY(())
/* The next outermost function scope. */
struct c_scope *outer_function;
- /* All variables, constants, functions, labels, and typedef names. */
- tree names;
- tree names_last;
-
- /* All parameter declarations. Used only in the outermost scope of
- a function. */
- tree parms;
- tree parms_last;
-
- /* All structure, union, and enum type tags. */
- tree tags;
-
- /* For each scope, a list of shadowed outer-scope definitions
- to be restored when this scope is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* For each scope, a list of shadowed outer-scope tag definitions
- to be restored when this scope is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */
- tree shadowed_tags;
+ /* All bindings in this scope. */
+ struct c_binding *bindings;
/* For each scope (except the global one), a chain of BLOCK nodes
for all the scopes that were entered and exited one level down. */
tree blocks;
tree blocks_last;
+ /* The depth of this scope. Used to keep the ->shadowed chain of
+ bindings sorted innermost to outermost. */
+ unsigned int depth : 28;
+
/* True if we are currently filling this scope with parameter
declarations. */
BOOL_BITFIELD parm_flag : 1;
@@ -230,20 +272,28 @@ struct c_scope GTY(())
static GTY(()) struct c_scope *current_scope;
-/* A chain of c_scope structures awaiting reuse. */
-
-static GTY((deletable (""))) struct c_scope *scope_freelist;
-
/* The innermost function scope. Ordinary (not explicitly declared)
labels, bindings to error_mark_node, and the lazily-created
bindings of __func__ and its friends get this scope. */
static GTY(()) struct c_scope *current_function_scope;
-/* The outermost scope, corresponding to the C "file scope". This is
- created when the compiler is started and exists through the entire run. */
+/* The C file scope. This is reset for each input translation unit. */
+
+static GTY(()) struct c_scope *file_scope;
+
+/* The outermost scope. This is used for all declarations with
+ external linkage, and only these, hence the name. */
+
+static GTY(()) struct c_scope *external_scope;
+
+/* A chain of c_scope structures awaiting reuse. */
+
+static GTY((deletable (""))) struct c_scope *scope_freelist;
+
+/* A chain of c_binding structures awaiting reuse. */
-static GTY(()) struct c_scope *global_scope;
+static GTY((deletable (""))) struct c_binding *binding_freelist;
/* Append VAR to LIST in scope SCOPE. */
#define SCOPE_LIST_APPEND(scope, list, decl) do { \
@@ -271,7 +321,7 @@ static GTY(()) struct c_scope *global_scope;
static bool keep_next_level_flag;
-/* True means the next call to pushlevel will be the outermost scope
+/* True means the next call to push_scope will be the outermost scope
of a function body, so do not push a new scope, merely cease
expecting parameter decls. */
@@ -282,27 +332,11 @@ static bool next_is_function_body;
tree static_ctors, static_dtors;
/* Forward declarations. */
-
-static struct c_scope *make_scope (void);
-static void pop_scope (void);
-static tree make_label (tree, location_t);
-static void bind_label (tree, tree, struct c_scope *);
-static void implicit_decl_warning (tree);
-static tree lookup_tag (enum tree_code, tree, int);
-static tree lookup_name_current_level (tree);
+static tree lookup_name_in_scope (tree, struct c_scope *);
+static tree c_make_fname_decl (tree, int);
static tree grokdeclarator (tree, tree, enum decl_context, int, tree *);
static tree grokparms (tree, int);
static void layout_array_type (tree);
-static tree c_make_fname_decl (tree, int);
-static void c_expand_body_1 (tree, int);
-static tree any_external_decl (tree);
-static void record_external_decl (tree);
-static void warn_if_shadowing (tree, tree);
-static void check_bitfield_type_and_width (tree *, tree *, const char *);
-static void clone_underlying_type (tree);
-static bool flexible_array_type_p (tree);
-static hashval_t link_hash_hash (const void *);
-static int link_hash_eq (const void *, const void *);
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
@@ -319,9 +353,9 @@ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
void
c_print_identifier (FILE *file, tree node, int indent)
{
- print_node (file, "symbol", IDENTIFIER_SYMBOL_VALUE (node), indent + 4);
- print_node (file, "tag", IDENTIFIER_TAG_VALUE (node), indent + 4);
- print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
+ print_node (file, "symbol", I_SYMBOL_DECL (node), indent + 4);
+ print_node (file, "tag", I_TAG_DECL (node), indent + 4);
+ print_node (file, "label", I_LABEL_DECL (node), indent + 4);
if (C_IS_RESERVED_WORD (node))
{
tree rid = ridpointers[C_RID_CODE (node)];
@@ -330,6 +364,80 @@ c_print_identifier (FILE *file, tree node, int indent)
(void *) rid, IDENTIFIER_POINTER (rid));
}
}
+
+/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
+ 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)
+{
+ struct c_binding *b, **here;
+
+ if (binding_freelist)
+ {
+ b = binding_freelist;
+ binding_freelist = b->prev;
+ }
+ else
+ b = ggc_alloc (sizeof (struct c_binding));
+
+ b->shadowed = 0;
+ b->decl = decl;
+ b->id = name;
+ b->contour = scope;
+
+ b->prev = scope->bindings;
+ scope->bindings = b;
+
+ if (!name)
+ return;
+
+ switch (TREE_CODE (decl))
+ {
+ case LABEL_DECL: here = &I_LABEL_BINDING (name); break;
+ case ENUMERAL_TYPE:
+ case UNION_TYPE:
+ case RECORD_TYPE: here = &I_TAG_BINDING (name); break;
+ case VAR_DECL:
+ case FUNCTION_DECL:
+ case TYPE_DECL:
+ case CONST_DECL:
+ case PARM_DECL:
+ case ERROR_MARK: here = &I_SYMBOL_BINDING (name); break;
+
+ default:
+ abort ();
+ }
+
+ /* Locate the appropriate place in the chain of shadowed decls
+ to insert this binding. Normally, scope == current_scope and
+ this does nothing. */
+ while (*here && (*here)->contour->depth > scope->depth)
+ here = &(*here)->shadowed;
+
+ b->shadowed = *here;
+ *here = b;
+}
+
+/* Clear the binding structure B, stick it on the binding_freelist,
+ and return the former value of b->prev. This is used by pop_scope
+ and get_parm_info to iterate destructively over all the bindings
+ from a given scope. */
+static struct c_binding *
+free_binding_and_advance (struct c_binding *b)
+{
+ struct c_binding *prev = b->prev;
+
+ b->id = 0;
+ b->decl = 0;
+ b->contour = 0;
+ b->shadowed = 0;
+ b->prev = binding_freelist;
+ binding_freelist = b;
+
+ return prev;
+}
+
/* Hook called at end of compilation to assume 1 elt
for a file-scope tentative array defn that wasn't complete before. */
@@ -354,40 +462,6 @@ c_finish_incomplete_decl (tree decl)
}
}
-/* Reuse or create a struct for this scope. */
-
-static struct c_scope *
-make_scope (void)
-{
- struct c_scope *result;
- if (scope_freelist)
- {
- result = scope_freelist;
- scope_freelist = result->outer;
- }
- else
- result = ggc_alloc_cleared (sizeof (struct c_scope));
-
- return result;
-}
-
-/* Remove the topmost scope from the stack and add it to the
- free list, updating current_function_scope if necessary. */
-
-static void
-pop_scope (void)
-{
- struct c_scope *scope = current_scope;
-
- current_scope = scope->outer;
- if (scope->function_body)
- current_function_scope = scope->outer_function;
-
- memset (scope, 0, sizeof (struct c_scope));
- scope->outer = scope_freelist;
- scope_freelist = scope;
-}
-
/* The Objective-C front-end often needs to determine the current scope. */
void *
@@ -403,30 +477,34 @@ void
objc_mark_locals_volatile (void *enclosing_blk)
{
struct c_scope *scope;
+ struct c_binding *b;
for (scope = current_scope;
scope && scope != enclosing_blk;
scope = scope->outer)
{
- tree decl;
-
- for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
+ for (b = scope->bindings; b; b = b->prev)
{
- DECL_REGISTER (decl) = 0;
- TREE_THIS_VOLATILE (decl) = 1;
+ if (TREE_CODE (b->decl) == VAR_DECL
+ || TREE_CODE (b->decl) == PARM_DECL)
+ {
+ DECL_REGISTER (b->decl) = 0;
+ TREE_THIS_VOLATILE (b->decl) = 1;
+ }
}
+
/* Do not climb up past the current function. */
if (scope->function_body)
break;
}
}
-/* Nonzero if we are currently in the global scope. */
+/* Nonzero if we are currently in file scope. */
int
global_bindings_p (void)
{
- return current_scope == global_scope;
+ return current_scope == file_scope && !c_override_global_bindings_to_false;
}
void
@@ -443,19 +521,8 @@ declare_parm_level (void)
current_scope->parm_flag = true;
}
-/* Nonzero if currently making parm declarations. */
-
-int
-in_parm_level_p (void)
-{
- return current_scope->parm_flag;
-}
-
-/* Enter a new scope. The dummy parameter is for signature
- compatibility with lang_hooks.decls.pushlevel. */
-
void
-pushlevel (int dummy ATTRIBUTE_UNUSED)
+push_scope (void)
{
if (next_is_function_body)
{
@@ -480,49 +547,46 @@ pushlevel (int dummy ATTRIBUTE_UNUSED)
}
else
{
- struct c_scope *scope = make_scope ();
+ struct c_scope *scope;
+ if (scope_freelist)
+ {
+ scope = scope_freelist;
+ scope_freelist = scope->outer;
+ }
+ else
+ scope = ggc_alloc_cleared (sizeof (struct c_scope));
scope->keep = keep_next_level_flag;
scope->outer = current_scope;
+ scope->depth = current_scope ? (current_scope->depth + 1) : 0;
+
+ /* Check for scope depth overflow. Unlikely (2^28 == 268,435,456) but
+ possible. */
+ if (current_scope && scope->depth == 0)
+ {
+ scope->depth--;
+ sorry ("GCC supports only %u nested scopes\n", scope->depth);
+ }
+
current_scope = scope;
keep_next_level_flag = false;
}
}
/* Exit a scope. Restore the state of the identifier-decl mappings
- that were in effect when this scope was entered.
-
- If KEEP is KEEP_YES (1), this scope had explicit declarations, so
- create a BLOCK node to record its declarations and subblocks for
- debugging output. If KEEP is KEEP_MAYBE, do so only if the names
- or tags lists are nonempty.
-
- The second parameter is ignored; it is present only for
- signature compatibility with lang_hooks.decls.poplevel.
-
- If FUNCTIONBODY is nonzero, this level is the body of a function,
- even if current_scope->function_body is not set. This is used
- by language-independent code that generates synthetic functions,
- and cannot set current_scope->function_body.
-
- FIXME: Eliminate the need for all arguments. */
+ that were in effect when this scope was entered. Return a BLOCK
+ node containing all the DECLs in this scope that are of interest
+ to debug info generation. */
tree
-poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
+pop_scope (void)
{
struct c_scope *scope = current_scope;
- tree block;
- tree decl;
- tree p;
-
- /* The following line does not use |= due to a bug in HP's C compiler. */
- scope->function_body = scope->function_body | functionbody;
+ tree block, context, p;
+ struct c_binding *b;
- if (keep == KEEP_MAYBE)
- keep = (scope->names || scope->tags);
-
- keep |= scope->keep;
- keep |= scope->function_body;
+ bool functionbody = scope->function_body;
+ bool keep = functionbody || scope->keep || scope->bindings;
/* If appropriate, create a BLOCK to record the decls for the life
of this function. */
@@ -530,28 +594,44 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
if (keep)
{
block = make_node (BLOCK);
- BLOCK_VARS (block) = scope->names;
BLOCK_SUBBLOCKS (block) = scope->blocks;
TREE_USED (block) = 1;
- }
- /* In each subblock, record that this is its superior. */
- for (p = scope->blocks; p; p = TREE_CHAIN (p))
- BLOCK_SUPERCONTEXT (p) = block;
+ /* In each subblock, record that this is its superior. */
+ for (p = scope->blocks; p; p = TREE_CHAIN (p))
+ BLOCK_SUPERCONTEXT (p) = block;
- /* Clear out the variable bindings in this scope.
+ BLOCK_VARS (block) = 0;
+ }
- Propagate TREE_ADDRESSABLE from nested functions to their
- containing functions.
+ /* The TYPE_CONTEXTs for all of the tagged types belonging to this
+ scope must be set so that they point to the appropriate
+ construct, i.e. either to the current FUNCTION_DECL node, or
+ else to the BLOCK node we just constructed.
- Issue warnings for unused variables and labels, and errors for
- undefined labels, if there are any. */
+ Note that for tagged types whose scope is just the formal
+ parameter list for some function type specification, we can't
+ properly set their TYPE_CONTEXTs here, because we don't have a
+ pointer to the appropriate FUNCTION_TYPE node readily available
+ to us. For those cases, the TYPE_CONTEXTs of the relevant tagged
+ type nodes get set in `grokdeclarator' as soon as we have created
+ the FUNCTION_TYPE node which will represent the "scope" for these
+ "parameter list local" tagged types. */
+ if (scope->function_body)
+ context = current_function_decl;
+ else if (scope == file_scope)
+ context = current_file_decl;
+ else
+ context = block;
- for (p = scope->names; p; p = TREE_CHAIN (p))
+ /* Clear all bindings in this scope. */
+ for (b = scope->bindings; b; b = free_binding_and_advance (b))
{
+ p = b->decl;
switch (TREE_CODE (p))
{
case LABEL_DECL:
+ /* Warnings for unused labels, errors for undefined labels. */
if (TREE_USED (p) && !DECL_INITIAL (p))
{
error ("%Jlabel `%D' used but not defined", p, p);
@@ -564,94 +644,101 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
else
warning ("%Jlabel `%D' declared but not defined", p, p);
}
+ /* Labels go in BLOCK_VARS. */
+ TREE_CHAIN (p) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = p;
+
+#ifdef ENABLE_CHECKING
+ if (I_LABEL_BINDING (b->id) != b) abort ();
+#endif
+ I_LABEL_BINDING (b->id) = b->shadowed;
+ break;
- IDENTIFIER_LABEL_VALUE (DECL_NAME (p)) = 0;
- break;
+ case ENUMERAL_TYPE:
+ case UNION_TYPE:
+ case RECORD_TYPE:
+ TYPE_CONTEXT (p) = context;
+
+ /* Types may not have tag-names, in which case the type
+ appears in the bindings list with b->id NULL. */
+ if (b->id)
+ {
+#ifdef ENABLE_CHECKING
+ if (I_TAG_BINDING (b->id) != b) abort ();
+#endif
+ I_TAG_BINDING (b->id) = b->shadowed;
+ }
+ break;
case FUNCTION_DECL:
+ /* Propagate TREE_ADDRESSABLE from nested functions to their
+ containing functions. */
if (! TREE_ASM_WRITTEN (p)
&& DECL_INITIAL (p) != 0
&& TREE_ADDRESSABLE (p)
&& DECL_ABSTRACT_ORIGIN (p) != 0
&& DECL_ABSTRACT_ORIGIN (p) != p)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
- goto normal;
+ goto common_symbol;
case VAR_DECL:
- /* Keep this in sync with stmt.c:warn_about_unused_variables.
- No warnings when the global scope is popped because the
- global scope isn't popped for the last translation unit,
- so the warnings are done in c_write_global_declaration. */
- if (warn_unused_variable && scope != global_scope
+ /* Warnings for unused variables. Keep this in sync with
+ stmt.c:warn_about_unused_variables, which we cannot use
+ since it expects a different data structure. */
+ if (warn_unused_variable
&& !TREE_USED (p)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
- && !DECL_ARTIFICIAL (p))
+ && !DECL_ARTIFICIAL (p)
+ && (scope != file_scope
+ || (TREE_STATIC (p) && !TREE_PUBLIC (p)
+ && !TREE_THIS_VOLATILE (p)))
+ && scope != external_scope)
warning ("%Junused variable `%D'", p, p);
+
/* Fall through. */
+ case TYPE_DECL:
+ case CONST_DECL:
+ common_symbol:
+ /* All of these go in BLOCK_VARS, but only if this is the
+ binding in the home scope. */
+ if (!C_DECL_IN_EXTERNAL_SCOPE (p) || scope == external_scope)
+ {
+ TREE_CHAIN (p) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = p;
+ }
- default:
- normal:
- if (DECL_NAME (p))
+ /* Fall through. */
+ /* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
+ already been put there by store_parm_decls. Unused-
+ parameter warnings are handled by function.c.
+ error_mark_node obviously does not go in BLOCK_VARS and
+ does not get unused-variable warnings. */
+ case PARM_DECL:
+ case ERROR_MARK:
+ /* It is possible for a decl not to have a name. We get
+ here with b->id NULL in this case. */
+ if (b->id)
{
- if (DECL_EXTERNAL (p) && scope != global_scope)
- /* External decls stay in the symbol-value slot but are
- inaccessible. */
- C_DECL_INVISIBLE (p) = 1;
- else
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
+#ifdef ENABLE_CHECKING
+ if (I_SYMBOL_BINDING (b->id) != b) abort ();
+#endif
+ I_SYMBOL_BINDING (b->id) = b->shadowed;
}
break;
+
+ default:
+ abort ();
}
}
- /* Clear out the parameter bindings in this scope, if any.
- Unused-parameter warnings are handled by function.c. */
- for (p = scope->parms; p; p = TREE_CHAIN (p))
- if (DECL_NAME (p))
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
-
- /* Clear out the tag-meanings declared in this scope.
-
- Set the TYPE_CONTEXTs for all of the tagged types belonging to
- this scope so that they point to the appropriate construct, i.e.
- either to the current FUNCTION_DECL node, or else to the BLOCK
- node we just constructed.
-
- Note that for tagged types whose scope is just the formal
- parameter list for some function type specification, we can't
- properly set their TYPE_CONTEXTs here, because we don't have a
- pointer to the appropriate FUNCTION_TYPE node readily available
- to us. For those cases, the TYPE_CONTEXTs of the relevant tagged
- type nodes get set in `grokdeclarator' as soon as we have created
- the FUNCTION_TYPE node which will represent the "scope" for these
- "parameter list local" tagged types. */
-
- decl = scope->function_body ? current_function_decl : block;
- for (p = scope->tags; p; p = TREE_CHAIN (p))
+
+ /* Dispose of the block that we just made inside some higher level. */
+ if ((scope->function_body || scope == file_scope) && context)
{
- if (TREE_PURPOSE (p))
- IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0;
- if (decl)
- TYPE_CONTEXT (TREE_VALUE (p)) = decl;
+ DECL_INITIAL (context) = block;
+ BLOCK_SUPERCONTEXT (block) = context;
}
-
- /* Restore all name- and label-meanings from outer scopes that were
- shadowed by this scope. */
- for (p = scope->shadowed; p; p = TREE_CHAIN (p))
- if (TREE_VALUE (p) && TREE_CODE (TREE_VALUE (p)) == LABEL_DECL)
- IDENTIFIER_LABEL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
- else
- IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
-
- /* Restore all tag-meanings from outer scopes that were shadowed by
- this scope. */
- for (p = scope->shadowed_tags; p; p = TREE_CHAIN (p))
- IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
-
- /* Dispose of the block that we just made inside some higher level. */
- if (scope->function_body && current_function_decl)
- DECL_INITIAL (current_function_decl) = block;
else if (scope->outer)
{
if (block)
@@ -664,11 +751,60 @@ poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
}
/* Pop the current scope, and free the structure for reuse. */
- pop_scope ();
+ current_scope = scope->outer;
+ if (scope->function_body)
+ current_function_scope = scope->outer_function;
+
+ memset (scope, 0, sizeof (struct c_scope));
+ scope->outer = scope_freelist;
+ scope_freelist = scope;
return block;
}
+void
+push_file_scope (void)
+{
+ tree decl;
+ tree file_decl = build_decl (TRANSLATION_UNIT_DECL, 0, 0);
+ TREE_CHAIN (file_decl) = current_file_decl;
+ current_file_decl = file_decl;
+
+ push_scope ();
+ file_scope = current_scope;
+
+ start_fname_decls ();
+
+ for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
+ bind (DECL_NAME (decl), decl, file_scope);
+}
+
+void
+pop_file_scope (void)
+{
+ /* In case there were missing closebraces, get us back to the global
+ binding level. */
+ while (current_scope != file_scope)
+ pop_scope ();
+
+ /* __FUNCTION__ is defined at file scope (""). This
+ call may not be necessary as my tests indicate it
+ still works without it. */
+ finish_fname_decls ();
+
+ /* Kludge: don't actually pop the file scope if generating a
+ precompiled header, so that macros and local symbols are still
+ visible to the PCH generator. */
+ if (pch_file)
+ return;
+
+ /* And pop off the file scope. */
+ pop_scope ();
+ file_scope = 0;
+
+ cpp_undef_all (parse_in);
+}
+
/* Insert BLOCK at the end of the list of subblocks of the current
scope. This is used when a BIND_EXPR is expanded, to handle the
BLOCK node inside the BIND_EXPR. */
@@ -679,15 +815,6 @@ insert_block (tree block)
TREE_USED (block) = 1;
SCOPE_LIST_APPEND (current_scope, blocks, block);
}
-
-/* Set the BLOCK node for the innermost scope (the one we are
- currently in). The RTL expansion machinery requires us to provide
- this hook, but it is not useful in function-at-a-time mode. */
-
-void
-set_block (tree block ATTRIBUTE_UNUSED)
-{
-}
/* Push a definition or a declaration of struct, union or enum tag "name".
"type" should be the type node.
@@ -696,24 +823,13 @@ set_block (tree block ATTRIBUTE_UNUSED)
Note that the definition may really be just a forward reference.
In that case, the TYPE_SIZE will be zero. */
-void
+static void
pushtag (tree name, tree type)
{
- struct c_scope *b = current_scope;
-
/* Record the identifier as the type's name if it has none. */
- if (name)
- {
- if (TYPE_NAME (type) == 0)
- TYPE_NAME (type) = name;
-
- if (IDENTIFIER_TAG_VALUE (name))
- b->shadowed_tags = tree_cons (name, IDENTIFIER_TAG_VALUE (name),
- b->shadowed_tags);
- IDENTIFIER_TAG_VALUE (name) = type;
- }
-
- b->tags = tree_cons (name, type, b->tags);
+ if (name && !TYPE_NAME (type))
+ TYPE_NAME (type) = name;
+ bind (name, type, current_scope);
/* 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
@@ -725,7 +841,7 @@ pushtag (tree name, tree type)
TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
/* An approximation for now, so we can tell this is a function-scope tag.
- This will be updated in poplevel. */
+ This will be updated in pop_scope. */
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
}
@@ -916,8 +1032,9 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
unless OLDDECL is a builtin. OLDDECL will be discarded in any case. */
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
- if (TREE_CODE (olddecl) != FUNCTION_DECL
- || !DECL_BUILT_IN (olddecl) || !C_DECL_INVISIBLE (olddecl))
+ if (!(TREE_CODE (olddecl) == FUNCTION_DECL
+ && DECL_BUILT_IN (olddecl)
+ && !C_DECL_DECLARED_BUILTIN (olddecl)))
{
error ("%J'%D' redeclared as different kind of symbol",
newdecl, newdecl);
@@ -927,7 +1044,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
warning ("%Jbuilt-in function '%D' declared as non-function",
newdecl, newdecl);
else if (warn_shadow)
- warning ("%Jshadowing built-in function '%D'",
+ warning ("%Jdeclaration of '%D' shadows a built-in function",
newdecl, newdecl);
return false;
}
@@ -935,7 +1052,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (!comptypes (oldtype, newtype, COMPARE_STRICT))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl) && C_DECL_INVISIBLE (olddecl))
+ && DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
{
/* Accept harmless mismatch in function types.
This is for the ffs and fprintf builtins. */
@@ -1013,13 +1130,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
can't validate the argument list) the built-in definition is
overridden, but optionally warn this was a bad choice of name. */
if (DECL_BUILT_IN (olddecl)
- && C_DECL_INVISIBLE (olddecl)
+ && !C_DECL_DECLARED_BUILTIN (olddecl)
&& (!TREE_PUBLIC (newdecl)
|| (DECL_INITIAL (newdecl)
&& !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
{
if (warn_shadow)
- warning ("%Jshadowing built-in function '%D'", newdecl, newdecl);
+ warning ("%Jdeclaration of '%D' shadows a built-in function",
+ newdecl, newdecl);
/* Discard the old built-in function. */
return false;
}
@@ -1190,8 +1308,15 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else /* PARM_DECL, VAR_DECL */
{
- /* Redeclaration of a PARM_DECL is invalid unless this is the
- real position of a forward-declared parameter (GCC extension). */
+ /* Redeclaration of a parameter is a constraint violation (this is
+ not explicitly stated, but follows from C99 6.7p3 [no more than
+ one declaration of the same identifier with no linkage in the
+ same scope, except type tags] and 6.2.2p6 [parameters have no
+ linkage]). We must check for a forward parameter declaration,
+ indicated by TREE_ASM_WRITTEN on the old declaration - this is
+ an extension, the mandatory diagnostic for which is handled by
+ mark_forward_parm_decls. */
+
if (TREE_CODE (newdecl) == PARM_DECL
&& (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
{
@@ -1258,13 +1383,26 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != 0);
- /* For real parm decl following a forward decl, return 1 so old decl
- will be reused. Only allow this to happen once. */
+ /* For real parm decl following a forward decl, rechain the old decl
+ in its new location and clear TREE_ASM_WRITTEN (it's not a
+ forward decl anymore). */
if (TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
{
+ struct c_binding *b, **here;
+
+ for (here = &current_scope->bindings; *here; here = &(*here)->prev)
+ if ((*here)->decl == olddecl)
+ goto found;
+ abort ();
+
+ found:
+ b = *here;
+ *here = b->prev;
+ b->prev = current_scope->bindings;
+ current_scope->bindings = b;
+
TREE_ASM_WRITTEN (olddecl) = 0;
- return;
}
DECL_ATTRIBUTES (newdecl)
@@ -1421,9 +1559,11 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (DECL_BUILT_IN (olddecl))
{
- /* If redeclaring a builtin function, it stays built in. */
+ /* If redeclaring a builtin function, it stays built in.
+ But it gets tagged as having been declared. */
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+ C_DECL_DECLARED_BUILTIN (newdecl) = 1;
}
/* Also preserve various other info from the definition. */
@@ -1454,6 +1594,9 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
}
}
+ /* This bit must not get wiped out. */
+ C_DECL_IN_EXTERNAL_SCOPE (newdecl) |= C_DECL_IN_EXTERNAL_SCOPE (olddecl);
+
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID. */
{
@@ -1495,69 +1638,49 @@ duplicate_decls (tree newdecl, tree olddecl)
}
-/* Return any external DECL associated with ID, whether or not it is
- currently in scope. */
-
-static tree
-any_external_decl (tree id)
-{
- tree decl = IDENTIFIER_SYMBOL_VALUE (id);
- tree t;
-
- if (decl == 0 || TREE_CODE (decl) == ERROR_MARK)
- return 0;
- else if (TREE_CODE (decl) != TYPE_DECL && DECL_EXTERNAL (decl))
- return decl;
-
- t = purpose_member (id, truly_local_externals);
- if (t)
- return TREE_VALUE (t);
-
- return 0;
-}
-
-/* Record an external decl DECL. This only does something if a
- shadowing decl already exists. */
+/* Check whether decl-node NEW shadows an existing declaration. */
static void
-record_external_decl (tree decl)
+warn_if_shadowing (tree new)
{
- tree name = DECL_NAME (decl);
- if (!IDENTIFIER_SYMBOL_VALUE (name))
- return;
-
- truly_local_externals = tree_cons (name, decl, truly_local_externals);
-}
+ struct c_binding *b;
-/* Check whether decl-node X shadows an existing declaration.
- OLD is the old IDENTIFIER_SYMBOL_VALUE of the DECL_NAME of X,
- which might be a NULL_TREE. */
-static void
-warn_if_shadowing (tree x, tree old)
-{
- /* Nothing to shadow? */
- if (old == 0
- /* Shadow warnings not wanted? */
- || !warn_shadow
+ /* Shadow warnings wanted? */
+ if (!warn_shadow
/* No shadow warnings for internally generated vars. */
- || DECL_SOURCE_LINE (x) == 0
+ || DECL_SOURCE_LINE (new) == 0
/* No shadow warnings for vars made for inlining. */
- || DECL_FROM_INLINE (x)
+ || DECL_FROM_INLINE (new)
/* Don't warn about the parm names in function declarator
- within a function declarator.
- It would be nice to avoid warning in any function
- declarator in a declaration, as opposed to a definition,
- but there is no way to tell it's not a definition. */
- || (TREE_CODE (x) == PARM_DECL && current_scope->outer->parm_flag))
+ within a function declarator. It would be nice to avoid
+ warning in any function declarator in a declaration, as
+ opposed to a definition, but there is no way to tell
+ it's not a definition at this point. */
+ || (TREE_CODE (new) == PARM_DECL && current_scope->outer->parm_flag))
return;
- if (TREE_CODE (old) == PARM_DECL)
- warning ("%Jdeclaration of '%D' shadows a parameter", x, x);
- else if (DECL_FILE_SCOPE_P (old))
- warning ("%Jdeclaration of '%D' shadows a global declaration", x, x);
- else
- warning ("%Jdeclaration of '%D' shadows a previous local", x, x);
+ /* Is anything being shadowed? Do not be confused by a second binding
+ to the same decl in the externals scope. */
+ for (b = I_SYMBOL_BINDING (DECL_NAME (new)); b; b = b->shadowed)
+ if (b->decl && b->decl != new && b->contour != external_scope)
+ {
+ tree old = b->decl;
+
+ if (TREE_CODE (old) == PARM_DECL)
+ warning ("%Jdeclaration of '%D' shadows a parameter", new, new);
+ else if (DECL_FILE_SCOPE_P (old))
+ warning ("%Jdeclaration of '%D' shadows a global declaration",
+ new, new);
+ else if (TREE_CODE (old) == FUNCTION_DECL && DECL_BUILT_IN (old))
+ warning ("%Jdeclaration of '%D' shadows a built-in function",
+ new, new);
+ else
+ warning ("%Jdeclaration of '%D' shadows a previous local", new, new);
+
+ if (TREE_CODE (old) != FUNCTION_DECL || !DECL_BUILT_IN (old))
+ warning ("%Jshadowed declaration is here", old);
- warning ("%Jshadowed declaration is here", old);
+ break;
+ }
}
@@ -1638,12 +1761,7 @@ pushdecl (tree x)
{
tree name = DECL_NAME (x);
struct c_scope *scope = current_scope;
-
-#ifdef ENABLE_CHECKING
- if (error_mark_node == 0)
- /* Called too early. */
- abort ();
-#endif
+ struct c_binding *b;
/* Functions need the lang_decl data. */
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
@@ -1659,130 +1777,110 @@ pushdecl (tree x)
else
DECL_CONTEXT (x) = current_function_decl;
- if (name)
+ /* Anonymous decls are just inserted in the scope. */
+ if (!name)
{
- tree old;
+ bind (name, x, scope);
+ return x;
+ }
+
+ /* First, see if there is another declaration with the same name in
+ the current scope. If there is, duplicate_decls may do all the
+ work for us. If duplicate_decls returns false, that indicates
+ two incompatible decls in the same scope; we are to silently
+ replace the old one (duplicate_decls has issued all appropriate
+ diagnostics). In particular, we should not consider possible
+ duplicates in the external scope, or shadowing. */
+ b = I_SYMBOL_BINDING (name);
+ if (b && b->contour == scope)
+ {
+ if (duplicate_decls (x, b->decl))
+ return b->decl;
+ else
+ goto skip_external_and_shadow_checks;
+ }
+
+ /* All declarations with external linkage, and all external
+ references, go in the external scope, no matter what scope is
+ current. However, the binding in that scope is ignored for
+ purposes of normal name lookup. A separate binding structure is
+ created in the requested scope; this governs the normal
+ visibility of the symbol.
+ The binding in the externals scope is used exclusively for
+ detecting duplicate declarations of the same object, no matter
+ what scope they are in; this is what we do here. (C99 6.2.7p2:
+ All declarations that refer to the same object or function shall
+ have compatible type; otherwise, the behavior is undefined.) */
+ if (DECL_EXTERNAL (x) || scope == file_scope)
+ {
if (warn_nested_externs
- && scope != global_scope
- && DECL_EXTERNAL (x)
+ && scope != file_scope
&& !DECL_IN_SYSTEM_HEADER (x))
warning ("nested extern declaration of `%s'",
IDENTIFIER_POINTER (name));
- old = lookup_name_current_level (name);
- if (old && duplicate_decls (x, old))
+ while (b && b->contour != external_scope)
+ b = b->shadowed;
+
+ /* The point of the same_translation_unit_p check here is,
+ we want to detect a duplicate decl for a construct like
+ foo() { extern bar(); } ... static bar(); but not if
+ they are in different translation units. In any case,
+ the static does not go in the externals scope. */
+ if (b
+ && (DECL_EXTERNAL (x) || TREE_PUBLIC (x)
+ || same_translation_unit_p (x, b->decl))
+ && duplicate_decls (x, b->decl))
{
- /* For PARM_DECLs, old may be a forward declaration.
- If so, we want to remove it from its old location
- (in the variables chain) and rechain it in the
- location given by the new declaration. */
- if (TREE_CODE (x) == PARM_DECL)
- {
- tree *p;
- for (p = &scope->names; *p; p = &TREE_CHAIN (*p))
- if (*p == old)
- {
- *p = TREE_CHAIN (old);
- SCOPE_LIST_APPEND (scope, parms, old);
- break;
- }
- }
- return old;
+ bind (name, b->decl, scope);
+ return b->decl;
}
- if (DECL_EXTERNAL (x) || scope == global_scope)
+ else if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
{
- /* Find and check against a previous, not-in-scope, external
- decl for this identifier. (C99 6.2.7p2: All declarations
- that refer to the same object or function shall have
- compatible type; otherwise, the behavior is undefined.) */
- tree ext = any_external_decl (name);
- if (ext)
- {
- if (duplicate_decls (x, ext))
- {
- /* XXX This copy_node call violates the basic
- assumption that there is only one DECL for any
- given object. This causes all sorts of problems
- elsewhere. To correct it we must stop chaining
- DECLs directly within the scope structure (work
- in progress). -zw 2004-03-05 */
- x = copy_node (ext);
-
- /* Kludge around one of the worst consequences of
- the above copy_node call, viz. that the arg_info
- block created by get_parm_info can survive in a
- copied FUNCTION_DECL after store_parm_decls is
- done with it, and confuse the debug info
- generators. */
- if (TREE_CODE (ext) == FUNCTION_DECL
- && DECL_ARGUMENTS (ext)
- && TREE_CODE (DECL_ARGUMENTS (ext)) == TREE_LIST)
- DECL_ARGUMENTS (ext) = 0;
- }
- }
- else
- record_external_decl (x);
+ C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
+ bind (name, x, external_scope);
}
+ }
- if (TREE_CODE (x) == TYPE_DECL)
- clone_underlying_type (x);
-
- /* If storing a local value, there may already be one
- (inherited). If so, record it for restoration when this
- scope ends. Take care not to do this if we are replacing an
- older decl in the same scope (i.e. duplicate_decls returned
- false, above). */
- if (scope != global_scope
- && IDENTIFIER_SYMBOL_VALUE (name)
- && IDENTIFIER_SYMBOL_VALUE (name) != old)
- {
- warn_if_shadowing (x, IDENTIFIER_SYMBOL_VALUE (name));
- scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
- scope->shadowed);
- }
+ warn_if_shadowing (x);
- /* Install the new declaration in the requested scope. */
- IDENTIFIER_SYMBOL_VALUE (name) = x;
- C_DECL_INVISIBLE (x) = 0;
-
- /* If x's type is incomplete because it's based on a
- structure or union which has not yet been fully declared,
- attach it to that structure or union type, so we can go
- back and complete the variable declaration later, if the
- structure or union gets fully declared.
-
- If the input is erroneous, we can have error_mark in the type
- slot (e.g. "f(void a, ...)") - that doesn't count as an
- incomplete type. */
- if (TREE_TYPE (x) != error_mark_node
- && !COMPLETE_TYPE_P (TREE_TYPE (x)))
- {
- tree element = TREE_TYPE (x);
-
- while (TREE_CODE (element) == ARRAY_TYPE)
- element = TREE_TYPE (element);
- element = TYPE_MAIN_VARIANT (element);
-
- if ((TREE_CODE (element) == RECORD_TYPE
- || TREE_CODE (element) == UNION_TYPE)
- && (TREE_CODE (x) != TYPE_DECL
- || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
- && !COMPLETE_TYPE_P (element))
- C_TYPE_INCOMPLETE_VARS (element)
- = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
- }
- }
+ skip_external_and_shadow_checks:
+ if (TREE_CODE (x) == TYPE_DECL)
+ clone_underlying_type (x);
- if (TREE_CODE (x) == PARM_DECL)
- SCOPE_LIST_APPEND (scope, parms, x);
- else
- SCOPE_LIST_APPEND (scope, names, x);
+ bind (name, x, scope);
+
+ /* If x's type is incomplete because it's based on a
+ structure or union which has not yet been fully declared,
+ attach it to that structure or union type, so we can go
+ back and complete the variable declaration later, if the
+ structure or union gets fully declared.
+ If the input is erroneous, we can have error_mark in the type
+ slot (e.g. "f(void a, ...)") - that doesn't count as an
+ incomplete type. */
+ if (TREE_TYPE (x) != error_mark_node
+ && !COMPLETE_TYPE_P (TREE_TYPE (x)))
+ {
+ tree element = TREE_TYPE (x);
+
+ while (TREE_CODE (element) == ARRAY_TYPE)
+ element = TREE_TYPE (element);
+ element = TYPE_MAIN_VARIANT (element);
+
+ if ((TREE_CODE (element) == RECORD_TYPE
+ || TREE_CODE (element) == UNION_TYPE)
+ && (TREE_CODE (x) != TYPE_DECL
+ || TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
+ && !COMPLETE_TYPE_P (element))
+ C_TYPE_INCOMPLETE_VARS (element)
+ = tree_cons (NULL_TREE, x, C_TYPE_INCOMPLETE_VARS (element));
+ }
return x;
}
-/* Record X as belonging to the global scope (C99 "file scope").
+/* Record X as belonging to file scope.
This is used only internally by the Objective-C front end,
and is limited to its needs. duplicate_decls is not called;
if there is any preexisting decl for this identifier, it is an ICE. */
@@ -1797,44 +1895,72 @@ pushdecl_top_level (tree x)
name = DECL_NAME (x);
- if (IDENTIFIER_SYMBOL_VALUE (name))
+ if (I_SYMBOL_BINDING (name))
abort ();
DECL_CONTEXT (x) = current_file_decl;
- IDENTIFIER_SYMBOL_VALUE (name) = x;
+ if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
+ {
+ C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
+ bind (name, x, external_scope);
+ }
+ if (file_scope)
+ bind (name, x, file_scope);
- SCOPE_LIST_APPEND (global_scope, names, x);
return x;
}
+static void
+implicit_decl_warning (tree id, tree olddecl)
+{
+ void (*diag) (const char *, ...);
+ switch (mesg_implicit_function_declaration)
+ {
+ case 0: return;
+ case 1: diag = warning; break;
+ case 2: diag = error; break;
+ default: abort ();
+ }
+
+ diag (N_("implicit declaration of function '%E'"), id);
+ if (olddecl)
+ locate_old_decl (olddecl, diag);
+}
+
/* Generate an implicit declaration for identifier FUNCTIONID as a
function of type int (). */
tree
implicitly_declare (tree functionid)
{
- tree decl = any_external_decl (functionid);
+ tree decl = lookup_name_in_scope (functionid, external_scope);
if (decl)
{
- /* 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;
- then recycle the old declaration. */
- if (!C_DECL_IMPLICIT (decl))
+ /* FIXME: Objective-C has weird not-really-builtin functions
+ which are supposed to be visible automatically. They wind up
+ in the external scope because they're pushed before the file
+ scope gets created. Catch this here and rebind them into the
+ file scope. */
+ if (!DECL_BUILT_IN (decl) && DECL_SOURCE_LINE (decl) == 0)
+ {
+ bind (functionid, decl, file_scope);
+ return decl;
+ }
+ else
{
- implicit_decl_warning (DECL_NAME (decl));
- if (! DECL_FILE_SCOPE_P (decl))
- warning ("%Jprevious declaration of '%D'", decl, decl);
- C_DECL_IMPLICIT (decl) = 1;
+ /* 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;
+ then recycle the old declaration. */
+ if (!C_DECL_IMPLICIT (decl))
+ {
+ implicit_decl_warning (functionid, decl);
+ C_DECL_IMPLICIT (decl) = 1;
+ }
+ bind (functionid, decl, current_scope);
+ return decl;
}
- /* If this function is global, then it must already be in the
- global scope, so there's no need to push it again. */
- if (current_scope == global_scope)
- return decl;
- /* If this is a local declaration, make a copy; we can't have
- the same DECL listed in two different scopes. */
- return pushdecl (copy_node (decl));
}
/* Not seen before. */
@@ -1842,7 +1968,7 @@ implicitly_declare (tree functionid)
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
C_DECL_IMPLICIT (decl) = 1;
- implicit_decl_warning (functionid);
+ implicit_decl_warning (functionid, 0);
/* C89 says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
@@ -1861,16 +1987,6 @@ implicitly_declare (tree functionid)
return decl;
}
-static void
-implicit_decl_warning (tree id)
-{
- const char *name = IDENTIFIER_POINTER (id);
- if (mesg_implicit_function_declaration == 2)
- error ("implicit declaration of function `%s'", name);
- else if (mesg_implicit_function_declaration == 1)
- warning ("implicit declaration of function `%s'", name);
-}
-
/* Issue an error message for a reference to an undeclared variable
ID, including a reference to a builtin outside of function-call
context. Establish a binding of the identifier to error_mark_node
@@ -1884,14 +2000,12 @@ undeclared_variable (tree id)
if (current_function_decl == 0)
{
- error ("`%s' undeclared here (not in a function)",
- IDENTIFIER_POINTER (id));
+ error ("'%E' undeclared here (not in a function)", id);
scope = current_scope;
}
else
{
- error ("`%s' undeclared (first use in this function)",
- IDENTIFIER_POINTER (id));
+ error ("'%E' undeclared (first use in this function)", id);
if (! already)
{
@@ -1900,12 +2014,11 @@ undeclared_variable (tree id)
already = true;
}
- scope = current_function_scope;
+ /* If we are parsing old-style parameter decls, current_function_decl
+ will be nonnull but current_function_scope will be null. */
+ scope = current_function_scope ? current_function_scope : current_scope;
}
-
- scope->shadowed = tree_cons (id, IDENTIFIER_SYMBOL_VALUE (id),
- scope->shadowed);
- IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node;
+ bind (id, error_mark_node, scope);
}
/* Subroutine of lookup_label, declare_label, define_label: construct a
@@ -1923,20 +2036,6 @@ make_label (tree name, location_t location)
return label;
}
-/* Another subroutine of lookup_label, declare_label, define_label:
- set up the binding of name to LABEL_DECL in the given SCOPE. */
-
-static void
-bind_label (tree name, tree label, struct c_scope *scope)
-{
- if (IDENTIFIER_LABEL_VALUE (name))
- scope->shadowed = tree_cons (name, IDENTIFIER_LABEL_VALUE (name),
- scope->shadowed);
- IDENTIFIER_LABEL_VALUE (name) = label;
-
- SCOPE_LIST_APPEND (scope, names, label);
-}
-
/* Get the LABEL_DECL corresponding to identifier NAME as a label.
Create one if none exists so far for the current function.
This is called when a label is used in a goto expression or
@@ -1957,7 +2056,7 @@ lookup_label (tree name)
/* Use a label already defined or ref'd with this name, but not if
it is inherited from a containing function and wasn't declared
using __label__. */
- label = IDENTIFIER_LABEL_VALUE (name);
+ label = I_LABEL_DECL (name);
if (label && (DECL_CONTEXT (label) == current_function_decl
|| C_DECLARED_LABEL_FLAG (label)))
{
@@ -1973,7 +2072,7 @@ lookup_label (tree name)
label = make_label (name, input_location);
/* Ordinary labels go in the current function scope. */
- bind_label (name, label, current_function_scope);
+ bind (name, label, current_function_scope);
return label;
}
@@ -1988,26 +2087,25 @@ lookup_label (tree name)
tree
declare_label (tree name)
{
- tree label = IDENTIFIER_LABEL_VALUE (name);
- tree dup;
+ struct c_binding *b = I_LABEL_BINDING (name);
+ tree label;
/* Check to make sure that the label hasn't already been declared
at this scope */
- for (dup = current_scope->names; dup; dup = TREE_CHAIN (dup))
- if (dup == label)
- {
- error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
- error ("%Jthis is a previous declaration", dup);
+ if (b && b->contour == current_scope)
+ {
+ error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
+ locate_old_decl (b->decl, error);
- /* Just use the previous declaration. */
- return dup;
- }
+ /* Just use the previous declaration. */
+ return b->decl;
+ }
label = make_label (name, input_location);
C_DECLARED_LABEL_FLAG (label) = 1;
/* Declared labels go in the current scope. */
- bind_label (name, label, current_scope);
+ bind (name, label, current_scope);
return label;
}
@@ -2018,13 +2116,11 @@ declare_label (tree name)
tree
define_label (location_t location, tree name)
{
- tree label;
-
/* Find any preexisting label with this name. It is an error
if that label has already been defined in this function, or
if there is a containing function with a declared label with
the same name. */
- label = IDENTIFIER_LABEL_VALUE (name);
+ tree label = I_LABEL_DECL (name);
if (label
&& ((DECL_CONTEXT (label) == current_function_decl
@@ -2033,10 +2129,7 @@ define_label (location_t location, tree name)
&& C_DECLARED_LABEL_FLAG (label))))
{
error ("%Hduplicate label `%D'", &location, label);
- if (DECL_INITIAL (label))
- error ("%J`%D' previously defined here", label, label);
- else
- error ("%J`%D' previously declared here", label, label);
+ locate_old_decl (label, error);
return 0;
}
else if (label && DECL_CONTEXT (label) == current_function_decl)
@@ -2052,7 +2145,7 @@ define_label (location_t location, tree name)
label = make_label (name, location);
/* Ordinary labels go in the current function scope. */
- bind_label (name, label, current_function_scope);
+ bind (name, label, current_function_scope);
}
if (warn_traditional && !in_system_header && lookup_name (name))
@@ -2065,16 +2158,6 @@ define_label (location_t location, tree name)
return label;
}
-/* Return the list of declarations of the current scope.
- This hook is optional and not implemented for C. */
-
-tree
-getdecls (void)
-{
- return 0;
-}
-
-
/* 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.
@@ -2085,25 +2168,29 @@ getdecls (void)
static tree
lookup_tag (enum tree_code code, tree name, int thislevel_only)
{
- tree tag = IDENTIFIER_TAG_VALUE (name);
+ struct c_binding *b = I_TAG_BINDING (name);
int thislevel = 0;
- if (!tag)
+ if (!b || !b->decl)
return 0;
/* We only care about whether it's in this level if
thislevel_only was set or it might be a type clash. */
- if (thislevel_only || TREE_CODE (tag) != code)
- {
- if (current_scope == global_scope
- || purpose_member (name, current_scope->tags))
+ if (thislevel_only || TREE_CODE (b->decl) != code)
+ {
+ /* For our purposes, a tag in the external scope is the same as
+ a tag in the file scope. (Primarily relevant to Objective-C
+ and its builtin structure tags, which get pushed before the
+ file scope is created.) */
+ if (b->contour == current_scope
+ || (current_scope == file_scope && b->contour == external_scope))
thislevel = 1;
}
if (thislevel_only && !thislevel)
return 0;
- if (TREE_CODE (tag) != code)
+ if (TREE_CODE (b->decl) != code)
{
/* Definition isn't the kind we were looking for. */
pending_invalid_xref = name;
@@ -2116,7 +2203,7 @@ lookup_tag (enum tree_code code, tree name, int thislevel_only)
if (thislevel)
pending_xref_error ();
}
- return tag;
+ return b->decl;
}
/* Print an error message now
@@ -2143,36 +2230,22 @@ pending_xref_error (void)
tree
lookup_name (tree name)
{
- tree decl = IDENTIFIER_SYMBOL_VALUE (name);
- if (decl == 0 || decl == error_mark_node)
- return decl;
- if (C_DECL_INVISIBLE (decl))
- return 0;
- return decl;
+ struct c_binding *b = I_SYMBOL_BINDING (name);
+ if (b && (b->contour != external_scope || TREE_CODE (b->decl) == TYPE_DECL))
+ return b->decl;
+ return 0;
}
-/* Similar to `lookup_name' but look only at the current scope. */
+/* Similar to `lookup_name' but look only at the indicated scope. */
static tree
-lookup_name_current_level (tree name)
+lookup_name_in_scope (tree name, struct c_scope *scope)
{
- tree decl = IDENTIFIER_SYMBOL_VALUE (name);
-
- if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl))
- return 0;
-
- if (current_scope == global_scope)
- return decl;
-
- /* Scan the current scope for a decl with name NAME.
- For PARM_DECLs, we have to look at both ->parms and ->names, since
- forward parameter declarations wind up on the ->names list. */
- if (TREE_CODE (decl) == PARM_DECL
- && chain_member (decl, current_scope->parms))
- return decl;
- if (chain_member (decl, current_scope->names))
- return decl;
+ struct c_binding *b;
+ for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
+ if (b->contour == scope)
+ return b->decl;
return 0;
}
@@ -2193,9 +2266,9 @@ c_init_decl_processing (void)
current_function_decl = 0;
- /* Make the c_scope structure for global names. */
- pushlevel (0);
- global_scope = current_scope;
+ /* Make the externals scope. */
+ push_scope ();
+ external_scope = current_scope;
/* Declarations from c_common_nodes_and_builtins must not be associated
with this input file, lest we get differences between using and not
@@ -2203,9 +2276,6 @@ c_init_decl_processing (void)
input_location.file = "<internal>";
input_location.line = 0;
- /* Make the DECL for the toplevel file scope. */
- current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
-
build_common_tree_nodes (flag_signed_char);
c_common_nodes_and_builtins ();
@@ -2231,9 +2301,6 @@ c_init_decl_processing (void)
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
-
- first_builtin_decl = global_scope->names;
- last_builtin_decl = global_scope->names_last;
}
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -2269,8 +2336,7 @@ c_make_fname_decl (tree id, int type_dep)
if (current_function_decl)
{
DECL_CONTEXT (decl) = current_function_decl;
- IDENTIFIER_SYMBOL_VALUE (id) = decl;
- SCOPE_LIST_APPEND (current_function_scope, names, decl);
+ bind (id, decl, current_function_scope);
}
finish_decl (decl, init, NULL_TREE);
@@ -2292,20 +2358,31 @@ builtin_function (const char *name, tree type, int function_code,
enum built_in_class class, const char *library_name,
tree attrs)
{
- tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
- DECL_EXTERNAL (decl) = 1;
+ tree id = get_identifier (name);
+ tree decl = build_decl (FUNCTION_DECL, id, type);
TREE_PUBLIC (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared (sizeof (struct lang_decl));
+ DECL_BUILT_IN_CLASS (decl) = class;
+ DECL_FUNCTION_CODE (decl) = function_code;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
make_decl_rtl (decl, NULL);
- pushdecl (decl);
- DECL_BUILT_IN_CLASS (decl) = class;
- DECL_FUNCTION_CODE (decl) = function_code;
- /* Warn if a function in the namespace for users
- is used without an occasion to consider it declared. */
- if (name[0] != '_' || name[1] != '_')
- C_DECL_INVISIBLE (decl) = 1;
+ /* Should never be called on a symbol with a preexisting meaning. */
+ if (I_SYMBOL_BINDING (id))
+ abort ();
+
+ C_DECL_IN_EXTERNAL_SCOPE (decl) = 1;
+ bind (id, decl, external_scope);
+
+ /* Builtins in the implementation namespace are made visible without
+ needing to be explicitly declared. See push_file_scope. */
+ if (name[0] == '_' && (name[1] == '_' || ISUPPER (name[1])))
+ {
+ TREE_CHAIN (decl) = visible_builtins;
+ visible_builtins = decl;
+ }
/* Possibly apply some default attributes to this built-in function. */
if (attrs)
@@ -2519,34 +2596,31 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
- tell `finish_decl' to ignore the initializer once it is parsed. */
+ tell 'finish_decl' to ignore the initializer once it is parsed. */
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- error ("typedef `%s' is initialized (use __typeof__ instead)",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("typedef '%D' is initialized (use __typeof__ instead)", decl);
initialized = 0;
break;
case FUNCTION_DECL:
- error ("function `%s' is initialized like a variable",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("function '%D' is initialized like a variable", decl);
initialized = 0;
break;
case PARM_DECL:
/* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE. */
- error ("parameter `%s' is initialized",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("parameter '%D' is initialized", decl);
initialized = 0;
break;
default:
- /* Don't allow initializations for incomplete types
- except for arrays which might be completed by the initialization. */
+ /* Don't allow initializations for incomplete types except for
+ arrays which might be completed by the initialization. */
- /* This can happen if the array size is an undefined macro. We already
- gave a warning, so we don't need another one. */
+ /* This can happen if the array size is an undefined macro.
+ We already gave a warning, so we don't need another one. */
if (TREE_TYPE (decl) == error_mark_node)
initialized = 0;
else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
@@ -2562,14 +2636,12 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
}
else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
{
- error ("variable `%s' has initializer but incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("variable '%D' has initializer but incomplete type", decl);
initialized = 0;
}
else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
{
- error ("elements of array `%s' have incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ error ("elements of array '%D' have incomplete type", decl);
initialized = 0;
}
}
@@ -2577,12 +2649,12 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
if (initialized)
{
DECL_EXTERNAL (decl) = 0;
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
TREE_STATIC (decl) = 1;
- /* Tell `pushdecl' this is an initialized decl
+ /* Tell 'pushdecl' this is an initialized decl
even though we don't yet have the initializer expression.
- Also tell `finish_decl' it may store the real initializer. */
+ Also tell 'finish_decl' it may store the real initializer. */
DECL_INITIAL (decl) = error_mark_node;
}
@@ -2643,21 +2715,6 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
- /* For a local variable, define the RTL now. */
- if (current_scope != global_scope
- /* But not if this is a duplicate decl
- and we preserved the rtl from the previous one
- (which may or may not happen). */
- && !DECL_RTL_SET_P (tem)
- && DECL_FILE_SCOPE_P (tem))
- {
- if (TREE_TYPE (tem) != error_mark_node
- && (COMPLETE_TYPE_P (TREE_TYPE (tem))
- || (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
- && DECL_INITIAL (tem) != 0)))
- expand_decl (tem);
- }
-
return tem;
}
@@ -2674,7 +2731,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
const char *asmspec = 0;
/* If a name was specified, get the string. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -2812,7 +2869,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
}
/* If #pragma weak was used, mark the decl weak now. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
maybe_apply_pragma_weak (decl);
/* Output the assembler code and/or RTL code for variables and functions,
@@ -2891,7 +2948,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
/* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use
computing them in the following function definition. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
get_pending_sizes ();
/* Install a cleanup (aka destructor) if one was given. */
@@ -2955,14 +3012,13 @@ push_parm_decl (tree parm)
immediate_size_expand = save_immediate_size_expand;
}
-/* Mark all the parameter declarations to date as forward decls,
- shift them to the variables list, and reset the parameters list.
+/* Mark all the parameter declarations to date as forward decls.
Also diagnose use of this extension. */
void
mark_forward_parm_decls (void)
{
- tree parm;
+ struct c_binding *b;
if (pedantic && !current_scope->warned_forward_parm_decls)
{
@@ -2970,12 +3026,9 @@ mark_forward_parm_decls (void)
current_scope->warned_forward_parm_decls = true;
}
- for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
- TREE_ASM_WRITTEN (parm) = 1;
-
- SCOPE_LIST_CONCAT (current_scope, names, current_scope, parms);
- current_scope->parms = 0;
- current_scope->parms_last = 0;
+ for (b = current_scope->bindings; b; b = b->prev)
+ if (TREE_CODE (b->decl) == PARM_DECL)
+ TREE_ASM_WRITTEN (b->decl) = 1;
}
static GTY(()) int compound_literal_number;
@@ -2996,7 +3049,7 @@ build_compound_literal (tree type, tree init)
tree stmt;
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
- TREE_STATIC (decl) = (current_scope == global_scope);
+ TREE_STATIC (decl) = (current_scope == file_scope);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
@@ -3316,8 +3369,7 @@ grokdeclarator (tree declarator, tree declspecs,
/* If this looks like a function definition, make it one,
even if it occurs where parms are expected.
Then store_parm_decls will reject it and not use it as a parm. */
- if (decl_context == NORMAL && !funcdef_flag
- && current_scope->parm_flag)
+ if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
decl_context = PARM;
/* Look through the decl specs and record which ones appear.
@@ -3413,11 +3465,11 @@ grokdeclarator (tree declarator, tree declspecs,
else if (TREE_CODE (id) == IDENTIFIER_NODE)
{
tree t = lookup_name (id);
- if (TREE_TYPE (t) == error_mark_node)
- ;
- else if (!t || TREE_CODE (t) != TYPE_DECL)
+ if (!t || TREE_CODE (t) != TYPE_DECL)
error ("`%s' fails to be a typedef or built in type",
IDENTIFIER_POINTER (id));
+ else if (TREE_TYPE (t) == error_mark_node)
+ ;
else
{
type = TREE_TYPE (t);
@@ -3674,7 +3726,7 @@ grokdeclarator (tree declarator, tree declspecs,
| (1 << (int) RID_THREAD))))
{
if (specbits & 1 << (int) RID_AUTO
- && (pedantic || current_scope == global_scope))
+ && (pedantic || current_scope == file_scope))
pedwarn ("function definition declared `auto'");
if (specbits & 1 << (int) RID_REGISTER)
error ("function definition declared `register'");
@@ -3712,12 +3764,12 @@ grokdeclarator (tree declarator, tree declspecs,
else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
{
/* `extern' with initialization is invalid if not at file scope. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
warning ("`%s' initialized and declared `extern'", name);
else
error ("`%s' has both `extern' and initializer", name);
}
- else if (current_scope == global_scope)
+ else if (current_scope == file_scope)
{
if (specbits & 1 << (int) RID_AUTO)
error ("file-scope declaration of `%s' specifies `auto'", name);
@@ -3970,14 +4022,15 @@ grokdeclarator (tree declarator, tree declspecs,
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{
- /* Declaring a function type. Say it's a definition only
- for the CALL_EXPR closest to the identifier. */
+ /* Say it's a definition only for the CALL_EXPR closest to
+ the identifier. */
bool really_funcdef = (funcdef_flag
&& (TREE_CODE (TREE_OPERAND (declarator, 0))
== IDENTIFIER_NODE));
tree arg_types;
- /* Make sure we have a valid type for the function to return. */
+ /* Declaring a function type.
+ Make sure we have a valid type for the function to return. */
if (type == error_mark_node)
continue;
@@ -4186,7 +4239,7 @@ grokdeclarator (tree declarator, tree declspecs,
if (VOID_TYPE_P (type) && decl_context != PARM
&& ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
&& ((specbits & (1 << (int) RID_EXTERN))
- || (current_scope == global_scope
+ || (current_scope == file_scope
&& !(specbits
& ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
{
@@ -4321,10 +4374,10 @@ grokdeclarator (tree declarator, tree declspecs,
That is a case not specified by ANSI C,
and we use it for forward declarations for nested functions. */
int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
- || current_scope == global_scope);
+ || current_scope == file_scope);
if (specbits & (1 << (int) RID_AUTO)
- && (pedantic || current_scope == global_scope))
+ && (pedantic || current_scope == file_scope))
pedwarn ("invalid storage class for function `%s'", name);
if (specbits & (1 << (int) RID_REGISTER))
error ("invalid storage class for function `%s'", name);
@@ -4333,7 +4386,7 @@ grokdeclarator (tree declarator, tree declspecs,
/* Function declaration not at file scope.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
- if (current_scope != global_scope
+ if (current_scope != file_scope
&& (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
&& pedantic)
pedwarn ("invalid storage class for function `%s'", name);
@@ -4414,20 +4467,23 @@ grokdeclarator (tree declarator, tree declspecs,
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
- /* It is invalid to create an `extern' declaration for a
+ /* C99 6.2.2p7: It is invalid (compile-time undefined
+ behavior) to create an 'extern' declaration for a
variable if there is a global declaration that is
- `static' and the global declaration is not visible. */
- if (extern_ref && current_scope != global_scope)
+ 'static' and the global declaration is not visible.
+ (If the static declaration _is_ currently visible,
+ the 'extern' declaration is taken to refer to that decl.) */
+ if (extern_ref && current_scope != file_scope)
{
- tree global_decl;
+ tree global_decl = identifier_global_value (declarator);
+ tree visible_decl = lookup_name (declarator);
- global_decl = identifier_global_value (declarator);
if (global_decl
+ && global_decl != visible_decl
&& TREE_CODE (global_decl) == VAR_DECL
- && lookup_name (declarator) != global_decl
&& !TREE_PUBLIC (global_decl))
- error ("variable previously declared `static' redeclared "
- "`extern'");
+ error ("variable previously declared 'static' redeclared "
+ "'extern'");
}
decl = build_decl (VAR_DECL, declarator, type);
@@ -4443,7 +4499,7 @@ grokdeclarator (tree declarator, tree declspecs,
class specifier, or the absence of all storage class specifiers
makes this declaration a definition (perhaps tentative). Also,
the absence of both `static' and `register' makes it public. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
{
TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
| (1 << (int) RID_REGISTER)));
@@ -4518,7 +4574,10 @@ grokparms (tree arg_info, int funcdef_flag)
&& !in_system_header)
warning ("function declaration isn't a prototype");
- if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
+ if (arg_types == error_mark_node)
+ return 0; /* don't set TYPE_ARG_TYPES in this case */
+
+ else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
{
if (! funcdef_flag)
pedwarn ("parameter names (without types) in function declaration");
@@ -4574,141 +4633,193 @@ grokparms (tree arg_info, int funcdef_flag)
}
}
-/* Return a tree_list node with info on a parameter list just parsed.
- This tree_list node should be examined using the ARG_INFO_* macros,
- defined above:
+/* Take apart the current scope and return a tree_list node with info
+ on a parameter list just parsed. This tree_list node should be
+ examined using the ARG_INFO_* macros, defined above:
+
ARG_INFO_PARMS: a list of parameter decls.
ARG_INFO_TAGS: a list of structure, union and enum tags defined.
ARG_INFO_TYPES: a list of argument types to go in the FUNCTION_TYPE.
ARG_INFO_OTHERS: a list of non-parameter decls (notably enumeration
- constants) defined with the parameters.
+ constants) defined with the parameters.
This tree_list node is later fed to 'grokparms' and 'store_parm_decls'.
- VOID_AT_END nonzero means append `void' to the end of the type-list.
- Zero means the parmlist ended with an ellipsis so don't append `void'. */
+ ELLIPSIS being true means the argument list ended in '...' so don't
+ append a sentinel (void_list_node) to the end of the type-list. */
tree
-get_parm_info (int void_at_end)
+get_parm_info (bool ellipsis)
{
- tree decl, type, list;
- tree types = 0;
- tree *last_type = &types;
- tree tags = current_scope->tags;
- tree parms = current_scope->parms;
- tree others = current_scope->names;
+ struct c_binding *b = current_scope->bindings;
+ tree arg_info = make_node (TREE_LIST);
+ tree parms = 0;
+ tree tags = 0;
+ tree types = 0;
+ tree others = 0;
+
static bool explained_incomplete_types = false;
bool gave_void_only_once_err = false;
- /* Just 'void' (and no ellipsis) is special. There are really no parms.
- But if the 'void' is qualified (by 'const' or 'volatile'), or has a
- storage class specifier ('register'), then the behavior is undefined;
- issue an error. Typedefs for 'void' are OK (see DR#157). */
- if (void_at_end && parms != 0
- && TREE_CHAIN (parms) == 0
- && VOID_TYPE_P (TREE_TYPE (parms))
- && !DECL_NAME (parms))
- {
- if (TREE_THIS_VOLATILE (parms)
- || TREE_READONLY (parms)
- || DECL_REGISTER (parms))
- error ("'void' as only parameter may not be qualified");
-
- list = make_node (TREE_LIST);
- ARG_INFO_TYPES (list) = build_tree_list (0, void_type_node);
- return list;
- }
+ /* The bindings in this scope must not get put into a block.
+ We will take care of deleting the binding nodes. */
+ current_scope->bindings = 0;
- /* Sanity check all of the parameter declarations. */
- for (decl = parms; decl; decl = TREE_CHAIN (decl))
- {
+ /* This function is only called if there was *something* on the
+ parameter list. */
#ifdef ENABLE_CHECKING
- if (TREE_CODE (decl) != PARM_DECL)
- abort ();
- if (TREE_ASM_WRITTEN (decl))
- abort ();
+ if (b == 0)
+ abort ();
#endif
- /* Since there is a prototype, args are passed in their
- declared types. The back end may override this. */
- type = TREE_TYPE (decl);
- DECL_ARG_TYPE (decl) = type;
+ /* A parameter list consisting solely of 'void' indicates that the
+ function takes no arguments. But if the 'void' is qualified
+ (by 'const' or 'volatile'), or has a storage class specifier
+ ('register'), then the behavior is undefined; issue an error.
+ Typedefs for 'void' are OK (see DR#157). */
+ if (b->prev == 0 /* one binding */
+ && TREE_CODE (b->decl) == PARM_DECL /* which is a parameter */
+ && !DECL_NAME (b->decl) /* anonymous */
+ && VOID_TYPE_P (TREE_TYPE (b->decl))) /* of void type */
+ {
+ if (TREE_THIS_VOLATILE (b->decl)
+ || TREE_READONLY (b->decl)
+ || DECL_REGISTER (b->decl))
+ error ("'void' as only parameter may not be qualified");
- /* Check for (..., void, ...) and issue an error. */
- if (VOID_TYPE_P (type) && !DECL_NAME (decl) && !gave_void_only_once_err)
- {
- error ("'void' must be the only parameter");
- gave_void_only_once_err = true;
- }
+ /* There cannot be an ellipsis. */
+ if (ellipsis)
+ error ("'void' must be the only parameter");
- type = build_tree_list (0, type);
- *last_type = type;
- last_type = &TREE_CHAIN (type);
+ ARG_INFO_TYPES (arg_info) = void_list_node;
+ return arg_info;
}
- /* Check the list of non-parameter decls for any forward parm decls
- that never got real decls. */
- for (decl = others; decl; decl = TREE_CHAIN (decl))
- if (TREE_CODE (decl) == PARM_DECL)
- {
- if (!TREE_ASM_WRITTEN (decl))
- abort ();
-
- error ("%Jparameter '%D' has just a forward declaration",
- decl, decl);
- }
+ if (!ellipsis)
+ types = void_list_node;
- /* Warn about any struct, union or enum tags defined within this
- list. The scope of such types is limited to this declaration,
- which is rarely if ever desirable (it's impossible to call such
- a function with type-correct arguments). */
- for (decl = tags; decl; decl = TREE_CHAIN (decl))
+ /* Break up the bindings list into parms, tags, types, and others;
+ apply sanity checks; purge the name-to-decl bindings. */
+ while (b)
{
- enum tree_code code = TREE_CODE (TREE_VALUE (decl));
+ tree decl = b->decl;
+ tree type = TREE_TYPE (decl);
const char *keyword;
- /* An anonymous union parm type is meaningful as a GNU extension.
- So don't warn for that. */
- if (code == UNION_TYPE && TREE_PURPOSE (decl) == 0 && !pedantic)
- continue;
- /* The keyword should not be translated. */
- switch (code)
+ switch (TREE_CODE (decl))
{
- case RECORD_TYPE: keyword = "struct"; break;
- case UNION_TYPE: keyword = "union"; break;
- case ENUMERAL_TYPE: keyword = "enum"; break;
- default: abort ();
- }
+ case PARM_DECL:
+ if (b->id)
+ {
+#ifdef ENABLE_CHECKING
+ if (I_SYMBOL_BINDING (b->id) != b) abort ();
+#endif
+ I_SYMBOL_BINDING (b->id) = b->shadowed;
+ }
- if (TREE_PURPOSE (decl))
- /* The %s will be one of 'struct', 'union', or 'enum'. */
- warning ("'%s %E' declared inside parameter list",
- keyword, TREE_PURPOSE (decl));
- else
- /* The %s will be one of 'struct', 'union', or 'enum'. */
- warning ("anonymous %s declared inside parameter list", keyword);
+ /* Check for forward decls that never got their actual decl. */
+ if (TREE_ASM_WRITTEN (decl))
+ error ("%Jparameter '%D' has just a forward declaration",
+ decl, decl);
+ /* Check for (..., void, ...) and issue an error. */
+ else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
+ {
+ if (!gave_void_only_once_err)
+ {
+ error ("'void' must be the only parameter");
+ gave_void_only_once_err = true;
+ }
+ }
+ else
+ {
+ /* Valid parameter, add it to the list. */
+ TREE_CHAIN (decl) = parms;
+ parms = decl;
+
+ /* Since there is a prototype, args are passed in their
+ declared types. The back end may override this later. */
+ DECL_ARG_TYPE (decl) = type;
+ types = tree_cons (0, type, types);
+ }
+ break;
- if (! explained_incomplete_types)
- {
- warning ("its scope is only this definition or declaration,"
- " which is probably not what you want");
- explained_incomplete_types = true;
- }
- }
+ case ENUMERAL_TYPE: keyword = "struct"; goto tag;
+ case UNION_TYPE: keyword = "union"; goto tag;
+ case RECORD_TYPE: keyword = "enum"; goto tag;
+ tag:
+ /* Types may not have tag-names, in which case the type
+ appears in the bindings list with b->id NULL. */
+ if (b->id)
+ {
+#ifdef ENABLE_CHECKING
+ if (I_TAG_BINDING (b->id) != b) abort ();
+#endif
+ I_TAG_BINDING (b->id) = b->shadowed;
+ }
+ /* Warn about any struct, union or enum tags defined in a
+ parameter list. The scope of such types is limited to
+ the parameter list, which is rarely if ever desirable
+ (it's impossible to call such a function with type-
+ correct arguments). An anonymous union parm type is
+ meaningful as a GNU extension, so don't warn for that. */
+ if (TREE_CODE (decl) != UNION_TYPE || b->id != 0)
+ {
+ if (b->id)
+ /* The %s will be one of 'struct', 'union', or 'enum'. */
+ warning ("'%s %E' declared inside parameter list",
+ keyword, b->id);
+ else
+ /* The %s will be one of 'struct', 'union', or 'enum'. */
+ warning ("anonymous %s declared inside parameter list",
+ keyword);
+
+ if (! explained_incomplete_types)
+ {
+ warning ("its scope is only this definition or declaration,"
+ " which is probably not what you want");
+ explained_incomplete_types = true;
+ }
+ }
- if (void_at_end)
- {
- type = build_tree_list (0, void_type_node);
- *last_type = type;
+ tags = tree_cons (b->id, decl, tags);
+ break;
+
+ case CONST_DECL:
+ case TYPE_DECL:
+ /* CONST_DECLs appear here when we have an embedded enum,
+ and TYPE_DECLs appear here when we have an embedded struct
+ or union. No warnings for this - we already warned about the
+ type itself. */
+ if (b->id)
+ {
+#ifdef ENABLE_CHECKING
+ if (I_SYMBOL_BINDING (b->id) != b) abort ();
+#endif
+ I_SYMBOL_BINDING (b->id) = b->shadowed;
+ }
+
+ TREE_CHAIN (decl) = others;
+ others = decl;
+ break;
+
+ /* Other things that might be encountered. */
+ case LABEL_DECL:
+ case FUNCTION_DECL:
+ case VAR_DECL:
+ case ERROR_MARK:
+ default:
+ abort ();
+ }
+
+ b = free_binding_and_advance (b);
}
- list = make_node (TREE_LIST);
- ARG_INFO_PARMS (list) = parms;
- ARG_INFO_TAGS (list) = tags;
- ARG_INFO_TYPES (list) = types;
- ARG_INFO_OTHERS (list) = others;
- return list;
+ ARG_INFO_PARMS (arg_info) = parms;
+ ARG_INFO_TAGS (arg_info) = tags;
+ ARG_INFO_TYPES (arg_info) = types;
+ ARG_INFO_OTHERS (arg_info) = others;
+ return arg_info;
}
/* Get the struct, enum or union (CODE says which) with tag NAME.
@@ -4927,7 +5038,7 @@ tree
finish_struct (tree t, tree fieldlist, tree attributes)
{
tree x;
- int toplevel = global_scope == current_scope;
+ bool toplevel = file_scope == current_scope;
int saw_named_field;
/* If this type was previously laid out as a forward reference,
@@ -4937,19 +5048,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
- /* Nameless union parm types are useful as GCC extension. */
- if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
- /* Otherwise, warn about any struct or union def. in parmlist. */
- if (in_parm_level_p ())
- {
- if (pedantic)
- pedwarn ("%s defined inside parms",
- TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
- else
- warning ("%s defined inside parms",
- TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
- }
-
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -5228,10 +5326,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
tree pair, tem;
tree minnode = 0, maxnode = 0, enum_value_type;
int precision, unsign;
- int toplevel = (global_scope == current_scope);
-
- if (in_parm_level_p ())
- warning ("enum defined inside parms");
+ bool toplevel = (file_scope == current_scope);
decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
@@ -5360,16 +5455,19 @@ build_enumerator (tree name, tree value)
if (value != 0)
{
- if (TREE_CODE (value) == INTEGER_CST)
+ /* Don't issue more errors for error_mark_node (i.e. an
+ undeclared identifier) - just ignore the value expression. */
+ if (value == error_mark_node)
+ value = 0;
+ else if (TREE_CODE (value) != INTEGER_CST)
{
- value = default_conversion (value);
- constant_expression_warning (value);
+ error ("enumerator value for '%E' is not an integer constant", name);
+ value = 0;
}
else
{
- error ("enumerator value for `%s' not integer constant",
- IDENTIFIER_POINTER (name));
- value = 0;
+ value = default_conversion (value);
+ constant_expression_warning (value);
}
}
@@ -5386,6 +5484,8 @@ build_enumerator (tree name, tree value)
if (pedantic && ! int_fits_type_p (value, integer_type_node))
{
pedwarn ("ISO C restricts enumerator values to range of `int'");
+ /* XXX This causes -pedantic to change the meaning of the program.
+ Remove? -zw 2004-03-15 */
value = convert (integer_type_node, value);
}
@@ -5472,13 +5572,13 @@ start_function (tree declspecs, tree declarator, tree attributes)
pedwarn_c99 ("return type defaults to `int'");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
- error_mark_node is replaced below (in poplevel) with the BLOCK. */
+ error_mark_node is replaced below (in pop_scope) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
/* If this definition isn't a prototype and we had a prototype declaration
before, copy the arg type info from that prototype.
But not if what we had before was a builtin function. */
- old_decl = lookup_name_current_level (DECL_NAME (decl1));
+ old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
&& !DECL_BUILT_IN (old_decl)
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
@@ -5543,7 +5643,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
#endif
/* If #pragma weak was used, mark the decl weak now. */
- if (current_scope == global_scope)
+ if (current_scope == file_scope)
maybe_apply_pragma_weak (decl1);
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
@@ -5609,7 +5709,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
current_function_decl = pushdecl (decl1);
- pushlevel (0);
+ push_scope ();
declare_parm_level ();
make_decl_rtl (current_function_decl, NULL);
@@ -5648,75 +5748,56 @@ start_function (tree declspecs, tree declarator, tree attributes)
static void
store_parm_decls_newstyle (tree fndecl, tree arg_info)
{
- tree decl, last;
-
- tree parms = ARG_INFO_PARMS (arg_info);
- tree tags = ARG_INFO_TAGS (arg_info);
+ tree decl;
+ tree parms = ARG_INFO_PARMS (arg_info);
+ tree tags = ARG_INFO_TAGS (arg_info);
tree others = ARG_INFO_OTHERS (arg_info);
- if (current_scope->parms || current_scope->names || current_scope->tags)
+ if (current_scope->bindings)
{
error ("%Jold-style parameter declarations in prototyped "
"function definition", fndecl);
/* Get rid of the old-style declarations. */
- poplevel (0, 0, 0);
- pushlevel (0);
- }
+ pop_scope ();
+ push_scope ();
+ }
+ /* Don't issue this warning for nested functions, and don't issue this
+ warning if we got here because ARG_INFO_TYPES was error_mark_node
+ (this happens when a function definition has just an ellipsis in
+ its parameter list). */
+ else if (warn_traditional && !in_system_header
+ && DECL_CONTEXT (fndecl) == current_file_decl
+ && ARG_INFO_TYPES (arg_info) != error_mark_node)
+ warning ("%Jtraditional C rejects ISO C style function definitions",
+ fndecl);
/* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */
- for (last = 0, decl = parms; decl; last = decl, decl = TREE_CHAIN (decl))
+ for (decl = parms; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
- if (DECL_NAME (decl) == 0)
- error ("%Jparameter name omitted", decl);
+ if (DECL_NAME (decl))
+ bind (DECL_NAME (decl), decl, current_scope);
else
- {
- if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
- current_scope->shadowed
- = tree_cons (DECL_NAME (decl),
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
- current_scope->shadowed);
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
- }
+ error ("%Jparameter name omitted", decl);
}
- current_scope->parms = parms;
- current_scope->parms_last = last;
/* Record the parameter list in the function declaration. */
DECL_ARGUMENTS (fndecl) = parms;
/* Now make all the ancillary declarations visible, likewise. */
- for (last = 0, decl = others; decl; last = decl, decl = TREE_CHAIN (decl))
+ for (decl = others; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
- if (DECL_NAME (decl)
- && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
- {
- if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
- current_scope->shadowed
- = tree_cons (DECL_NAME (decl),
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
- current_scope->shadowed);
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
- }
+ if (DECL_NAME (decl))
+ bind (DECL_NAME (decl), decl, current_scope);
}
- current_scope->names = others;
- current_scope->names_last = last;
/* And all the tag declarations. */
for (decl = tags; decl; decl = TREE_CHAIN (decl))
if (TREE_PURPOSE (decl))
- {
- if (IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)))
- current_scope->shadowed_tags
- = tree_cons (TREE_PURPOSE (decl),
- IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (decl)),
- current_scope->shadowed_tags);
- IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)) = TREE_VALUE (decl);
- }
- current_scope->tags = tags;
+ bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope);
}
/* Subroutine of store_parm_decls which handles old-style function
@@ -5725,19 +5806,21 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
static void
store_parm_decls_oldstyle (tree fndecl, tree arg_info)
{
+ struct c_binding *b;
tree parm, decl, last;
-
- /* This is the identifier list from the function declarator. */
tree parmids = ARG_INFO_PARMS (arg_info);
/* We use DECL_WEAK as a flag to show which parameters have been
seen already, since it is not used on PARM_DECL. */
#ifdef ENABLE_CHECKING
- for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
- if (DECL_WEAK (parm))
+ for (b = current_scope->bindings; b; b = b->prev)
+ if (TREE_CODE (b->decl) == PARM_DECL && DECL_WEAK (b->decl))
abort ();
#endif
+ if (warn_old_style_definition && !in_system_header)
+ warning ("%Jold-style function definition", fndecl);
+
/* Match each formal parameter name with its declaration. Save each
decl in the appropriate TREE_PURPOSE slot of the parmids chain. */
for (parm = parmids; parm; parm = TREE_CHAIN (parm))
@@ -5749,17 +5832,18 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
continue;
}
- decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
- if (decl && DECL_CONTEXT (decl) == fndecl)
+ b = I_SYMBOL_BINDING (TREE_VALUE (parm));
+ if (b && b->contour == current_scope)
{
+ decl = b->decl;
/* If we got something other than a PARM_DECL it is an error. */
if (TREE_CODE (decl) != PARM_DECL)
- error ("%J\"%D\" declared as a non-parameter", decl, decl);
+ error ("%J'%D' declared as a non-parameter", decl, decl);
/* If the declaration is already marked, we have a duplicate
name. Complain and ignore the duplicate. */
else if (DECL_WEAK (decl))
{
- error ("%Jmultiple parameters named \"%D\"", decl, decl);
+ error ("%Jmultiple parameters named '%D'", decl, decl);
TREE_PURPOSE (parm) = 0;
continue;
}
@@ -5767,7 +5851,7 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
an int. */
else if (VOID_TYPE_P (TREE_TYPE (decl)))
{
- error ("%Jparameter \"%D\" declared void", decl, decl);
+ error ("%Jparameter '%D' declared with void type", decl, decl);
TREE_TYPE (decl) = integer_type_node;
DECL_ARG_TYPE (decl) = integer_type_node;
layout_decl (decl, 0);
@@ -5782,9 +5866,9 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
pushdecl (decl);
if (flag_isoc99)
- pedwarn ("%Jtype of \"%D\" defaults to \"int\"", decl, decl);
+ pedwarn ("%Jtype of '%D' defaults to 'int'", decl, decl);
else if (extra_warnings)
- warning ("%Jtype of \"%D\" defaults to \"int\"", decl, decl);
+ warning ("%Jtype of '%D' defaults to 'int'", decl, decl);
}
TREE_PURPOSE (parm) = decl;
@@ -5794,17 +5878,21 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
/* Now examine the parms chain for incomplete declarations
and declarations with no corresponding names. */
- for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
+ for (b = current_scope->bindings; b; b = b->prev)
{
+ parm = b->decl;
+ if (TREE_CODE (parm) != PARM_DECL)
+ continue;
+
if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
- error ("%Jparameter \"%D\" has incomplete type", parm, parm);
+ error ("%Jparameter '%D' has incomplete type", parm, parm);
TREE_TYPE (parm) = error_mark_node;
}
if (! DECL_WEAK (parm))
{
- error ("%Jdeclaration for parameter \"%D\" but no such parameter",
+ error ("%Jdeclaration for parameter '%D' but no such parameter",
parm, parm);
/* Pretend the parameter was not missing.
@@ -5826,7 +5914,6 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
{
last = TREE_PURPOSE (parm);
DECL_ARGUMENTS (fndecl) = last;
- current_scope->parms = last;
DECL_WEAK (last) = 0;
for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
@@ -5836,7 +5923,6 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
last = TREE_PURPOSE (parm);
DECL_WEAK (last) = 0;
}
- current_scope->parms_last = last;
TREE_CHAIN (last) = 0;
}
@@ -5886,7 +5972,7 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
if (pedantic)
{
- pedwarn ("promoted argument \"%D\" "
+ pedwarn ("promoted argument '%D' "
"doesn't match prototype", parm);
pedwarn ("%Hprototype declaration",
&current_function_prototype_locus);
@@ -5894,7 +5980,7 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
}
else
{
- error ("argument \"%D\" doesn't match prototype", parm);
+ error ("argument '%D' doesn't match prototype", parm);
error ("%Hprototype declaration",
&current_function_prototype_locus);
}
@@ -5956,26 +6042,26 @@ store_parm_decls (void)
/* The argument information block for FNDECL. */
tree arg_info = DECL_ARGUMENTS (fndecl);
- /* True if this definition is written with a prototype. Since this
- is a function definition, we can treat a null parameter list
- (i.e. "foo()") as prototyped (C99 6.7.5.3p14) - this reduces
- overhead. */
- bool prototype = (!ARG_INFO_PARMS (arg_info)
- || TREE_CODE (ARG_INFO_PARMS (arg_info)) != TREE_LIST);
+ /* True if this definition is written with a prototype. Note:
+ despite C99 6.7.5.3p14, we can *not* treat an empty argument
+ list in a function definition as equivalent to (void) -- an
+ empty argument list specifies the function has no parameters,
+ but only (void) sets up a prototype for future calls. */
+ bool proto = ARG_INFO_TYPES (arg_info) != 0;
- if (prototype)
+ if (proto)
store_parm_decls_newstyle (fndecl, arg_info);
else
store_parm_decls_oldstyle (fndecl, arg_info);
- /* The next call to pushlevel will be a function body. */
+ /* The next call to push_scope will be a function body. */
next_is_function_body = true;
/* Write a record describing this function definition to the prototypes
file (if requested). */
- gen_aux_info_record (fndecl, 1, 0, prototype);
+ gen_aux_info_record (fndecl, 1, 0, proto);
/* Initialize the RTL code for the function. */
allocate_struct_function (fndecl);
@@ -6023,17 +6109,17 @@ finish_function (void)
/* When a function declaration is totally empty, e.g.
void foo(void) { }
(the argument list is irrelevant) the compstmt rule will not
- bother calling pushlevel/poplevel, which means we get here with
+ bother calling push_scope/pop_scope, which means we get here with
the scope stack out of sync. Detect this situation by noticing
that current_scope is still as store_parm_decls left it, and do
a dummy push/pop to get back to consistency.
- Note that the call to pushlevel does not actually push another
+ Note that the call to push_scope does not actually push another
scope - see there for details. */
if (current_scope->parm_flag && next_is_function_body)
{
- pushlevel (0);
- poplevel (0, 0, 0);
+ push_scope ();
+ pop_scope ();
}
if (TREE_CODE (fndecl) == FUNCTION_DECL
@@ -6177,7 +6263,7 @@ c_expand_body (tree fndecl)
void
check_for_loop_decls (void)
{
- tree t;
+ struct c_binding *b;
if (!flag_isoc99)
{
@@ -6201,35 +6287,38 @@ check_for_loop_decls (void)
interpretation, to avoid creating an extension which later causes
problems. */
- for (t = current_scope->tags; t; t = TREE_CHAIN (t))
+ for (b = current_scope->bindings; b; b = b->prev)
{
- if (TREE_PURPOSE (t) != 0)
- {
- enum tree_code code = TREE_CODE (TREE_VALUE (t));
-
- if (code == RECORD_TYPE)
- error ("'struct %s' declared in 'for' loop initial declaration",
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- else if (code == UNION_TYPE)
- error ("'union %s' declared in 'for' loop initial declaration",
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- else
- error ("'enum %s' declared in 'for' loop initial declaration",
- IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- }
+ tree id = b->id;
+ tree decl = b->decl;
- for (t = current_scope->names; t; t = TREE_CHAIN (t))
- {
- if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
- error ("%Jdeclaration of non-variable '%D' in 'for' loop "
- "initial declaration", t, t);
- else if (TREE_STATIC (t))
- error ("%Jdeclaration of static variable '%D' in 'for' loop "
- "initial declaration", t, t);
- else if (DECL_EXTERNAL (t))
- error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
- "initial declaration", t, t);
+ if (!id)
+ continue;
+
+ switch (TREE_CODE (decl))
+ {
+ case VAR_DECL:
+ if (TREE_STATIC (decl))
+ error ("%Jdeclaration of static variable '%D' in 'for' loop "
+ "initial declaration", decl, decl);
+ else if (DECL_EXTERNAL (decl))
+ error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
+ "initial declaration", decl, decl);
+ break;
+
+ case RECORD_TYPE:
+ error ("'struct %E' declared in 'for' loop initial declaration", id);
+ break;
+ case UNION_TYPE:
+ error ("'union %E' declared in 'for' loop initial declaration", id);
+ break;
+ case ENUMERAL_TYPE:
+ error ("'enum %E' declared in 'for' loop initial declaration", id);
+ break;
+ default:
+ error ("%Jdeclaration of non-variable '%D' in 'for' loop "
+ "initial declaration", decl, decl);
+ }
}
}
@@ -6382,16 +6471,12 @@ c_expand_decl_stmt (tree t)
tree
identifier_global_value (tree t)
{
- tree decl = IDENTIFIER_SYMBOL_VALUE (t);
- if (decl == 0 || DECL_FILE_SCOPE_P (decl))
- return decl;
+ struct c_binding *b;
- /* Shadowed by something else; find the true global value. */
- for (decl = global_scope->names; decl; decl = TREE_CHAIN (decl))
- if (DECL_NAME (decl) == t)
- return decl;
+ for (b = I_SYMBOL_BINDING (t); b; b = b->shadowed)
+ if (b->contour == file_scope || b->contour == external_scope)
+ return b->decl;
- /* Only local values for this decl. */
return 0;
}
@@ -6402,14 +6487,11 @@ void
record_builtin_type (enum rid rid_index, const char *name, tree type)
{
tree id;
- tree tdecl;
if (name == 0)
id = ridpointers[(int) rid_index];
else
id = get_identifier (name);
- tdecl = build_decl (TYPE_DECL, id, type);
- pushdecl (tdecl);
- debug_hooks->type_decl (tdecl, 0);
+ pushdecl (build_decl (TYPE_DECL, id, type));
}
/* Build the void_list_node (void_type_node having been created). */
@@ -6456,178 +6538,42 @@ c_static_assembler_name (tree decl)
lhd_set_decl_assembler_name (decl);
}
-/* Hash and equality functions for link_hash_table: key off
- DECL_ASSEMBLER_NAME. */
-
-static hashval_t
-link_hash_hash (const void *x_p)
-{
- tree x = (tree)x_p;
- return (hashval_t) (long)DECL_ASSEMBLER_NAME (x);
-}
-
-static int
-link_hash_eq (const void *x1_p, const void *x2_p)
-{
- tree x1 = (tree)x1_p;
- tree x2 = (tree)x2_p;
- return DECL_ASSEMBLER_NAME (x1) == DECL_ASSEMBLER_NAME (x2);
-}
-
-/* Propagate information between definitions and uses between multiple
- translation units in TU_LIST based on linkage rules. */
-
-void
-merge_translation_unit_decls (void)
+/* Perform final processing on file-scope data. */
+static void
+c_write_global_declarations_1 (tree globals)
{
- const tree tu_list = current_file_decl;
- tree tu;
+ size_t len = list_length (globals);
+ tree *vec = xmalloc (sizeof (tree) * len);
+ size_t i;
tree decl;
- htab_t link_hash_table;
- tree block;
-
- /* Create the BLOCK that poplevel would have created, but don't
- actually call poplevel since that's expensive. */
- block = make_node (BLOCK);
- BLOCK_VARS (block) = current_scope->names;
- TREE_USED (block) = 1;
- DECL_INITIAL (current_file_decl) = block;
-
- /* If only one translation unit seen, no copying necessary. */
- if (TREE_CHAIN (tu_list) == NULL_TREE)
- return;
-
- link_hash_table = htab_create (1021, link_hash_hash, link_hash_eq, NULL);
-
- /* Enter any actual definitions into the hash table. */
- for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
- for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
- if (TREE_PUBLIC (decl) && ! DECL_EXTERNAL (decl))
- {
- PTR *slot;
- slot = htab_find_slot (link_hash_table, decl, INSERT);
-
- /* If we've already got a definition, work out which one is
- the real one, put it into the hash table, and make the
- other one DECL_EXTERNAL. This is important to avoid
- putting out two definitions of the same symbol in the
- assembly output. */
- if (*slot != NULL)
- {
- tree old_decl = (tree) *slot;
-
- /* If this is weak or common or whatever, suppress it
- in favor of the other definition. */
- if (DECL_WEAK (decl))
- DECL_EXTERNAL (decl) = 1;
- else if (DECL_WEAK (old_decl) && ! DECL_WEAK (decl))
- DECL_EXTERNAL (old_decl) = 1;
- else if (DECL_COMMON (decl) || DECL_ONE_ONLY (decl))
- DECL_EXTERNAL (decl) = 1;
- else if (DECL_COMMON (old_decl) || DECL_ONE_ONLY (old_decl))
- DECL_EXTERNAL (old_decl) = 1;
-
- if (DECL_EXTERNAL (decl))
- {
- DECL_INITIAL (decl) = NULL_TREE;
- DECL_COMMON (decl) = 0;
- DECL_ONE_ONLY (decl) = 0;
- DECL_WEAK (decl) = 0;
- }
- else if (DECL_EXTERNAL (old_decl))
- {
- DECL_INITIAL (old_decl) = NULL_TREE;
- DECL_COMMON (old_decl) = 0;
- DECL_ONE_ONLY (old_decl) = 0;
- DECL_WEAK (old_decl) = 0;
- *slot = decl;
- }
- else
- {
- error ("%Jredefinition of global '%D'", decl, decl);
- error ("%J'%D' previously defined here", old_decl, old_decl);
- }
- }
- else
- *slot = decl;
- }
-
- /* Now insert the desired information from all the definitions
- into any plain declarations. */
- for (tu = tu_list; tu; tu = TREE_CHAIN (tu))
- for (decl = BLOCK_VARS (DECL_INITIAL (tu)); decl; decl = TREE_CHAIN (decl))
- if (TREE_PUBLIC (decl) && DECL_EXTERNAL (decl))
- {
- tree global_decl;
- global_decl = htab_find (link_hash_table, decl);
-
- if (! global_decl)
- continue;
-
- /* Print any appropriate error messages, and partially merge
- the decls. */
- (void) duplicate_decls (decl, global_decl);
- }
+
+ /* Process the decls in the order they were written. */
+ for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+ vec[i] = decl;
- htab_delete (link_hash_table);
+ wrapup_global_declarations (vec, len);
+ check_global_declarations (vec, len);
+
+ free (vec);
}
-/* Perform final processing on file-scope data. */
-
void
-c_write_global_declarations(void)
+c_write_global_declarations (void)
{
- tree link;
-
- for (link = current_file_decl; link; link = TREE_CHAIN (link))
- {
- tree globals = BLOCK_VARS (DECL_INITIAL (link));
- int len = list_length (globals);
- tree *vec = xmalloc (sizeof (tree) * len);
- int i;
- tree decl;
-
- /* Process the decls in the order they were written. */
-
- for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[i] = decl;
-
- wrapup_global_declarations (vec, len);
-
- check_global_declarations (vec, len);
+ tree t;
- /* Clean up. */
- free (vec);
- }
-}
+ /* We don't want to do this if generating a PCH. */
+ if (pch_file)
+ return;
-/* Reset the parser's state in preparation for a new file. */
+ /* Process all file scopes in this compilation. */
+ for (t = current_file_decl; t; t = TREE_CHAIN (t))
+ c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
-void
-c_reset_state (void)
-{
- tree link;
- tree file_scope_decl;
-
- /* Pop the global scope. */
- if (current_scope != global_scope)
- current_scope = global_scope;
- file_scope_decl = current_file_decl;
- DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0);
- BLOCK_SUPERCONTEXT (DECL_INITIAL (file_scope_decl)) = file_scope_decl;
- truly_local_externals = NULL_TREE;
-
- /* Start a new global binding level. */
- pushlevel (0);
- global_scope = current_scope;
- current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
- TREE_CHAIN (current_file_decl) = file_scope_decl;
-
- /* Reintroduce the builtin declarations. */
- for (link = first_builtin_decl;
- link != TREE_CHAIN (last_builtin_decl);
- link = TREE_CHAIN (link))
- pushdecl (copy_node (link));
+ /* Now do the same for the externals scope. */
+ t = pop_scope ();
+ if (t)
+ c_write_global_declarations_1 (BLOCK_VARS (t));
}
#include "gt-c-decl.h"
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
index 0f8bf4ea49a..391e8bddfaf 100644
--- a/gcc/c-lang.c
+++ b/gcc/c-lang.c
@@ -65,6 +65,8 @@ enum c_language_kind c_language = clk_c;
#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable
#undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_CLEAR_BINDING_STACK
+#define LANG_HOOKS_CLEAR_BINDING_STACK lhd_do_nothing
#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_objc_common_truthvalue_conversion
#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
@@ -136,6 +138,19 @@ enum c_language_kind c_language = clk_c;
#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
+/* The C front end's scoping structure is very different from
+ that expected by the language-independent code; it is best
+ to disable all of pushlevel, poplevel, set_block, and getdecls.
+ This means it must also provide its own write_globals. */
+
+#undef LANG_HOOKS_PUSHLEVEL
+#define LANG_HOOKS_PUSHLEVEL lhd_do_nothing_i
+#undef LANG_HOOKS_POPLEVEL
+#define LANG_HOOKS_POPLEVEL lhd_do_nothing_iii_return_null_tree
+#undef LANG_HOOKS_SET_BLOCK
+#define LANG_HOOKS_SET_BLOCK lhd_do_nothing_t
+#undef LANG_HOOKS_GETDECLS
+#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
#undef LANG_HOOKS_WRITE_GLOBALS
#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c
index 575407102fb..e736110e6be 100644
--- a/gcc/c-objc-common.c
+++ b/gcc/c-objc-common.c
@@ -206,7 +206,7 @@ start_cdtor (int method_type)
body = c_begin_compound_stmt ();
- pushlevel (0);
+ push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
@@ -220,7 +220,7 @@ finish_cdtor (tree body)
tree block;
scope = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
- block = poplevel (0, 0, 0);
+ block = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope)) = block;
SCOPE_STMT_BLOCK (TREE_VALUE (scope)) = block;
@@ -237,10 +237,6 @@ c_objc_common_finish_file (void)
if (pch_file)
c_common_write_pch ();
- /* If multiple translation units were built, copy information between
- them based on linkage rules. */
- merge_translation_unit_decls ();
-
cgraph_finalize_compilation_unit ();
cgraph_optimize ();
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index 4eecba91de5..ac2fe976156 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -1216,41 +1216,24 @@ c_common_init (void)
/* Initialize the integrated preprocessor after debug output has been
initialized; loop over each input file. */
void
-c_common_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
+c_common_parse_file (int set_yydebug)
{
- unsigned file_index;
-
#if YYDEBUG != 0
yydebug = set_yydebug;
#else
- warning ("YYDEBUG not defined");
+ if (set_yydebug)
+ warning ("YYDEBUG not defined");
#endif
- file_index = 0;
-
- do
- {
- if (file_index > 0)
- {
- /* Reset the state of the parser. */
- c_reset_state();
-
- /* Reset cpplib's macros and start a new file. */
- cpp_undef_all (parse_in);
- main_input_filename = this_input_filename
- = cpp_read_main_file (parse_in, in_fnames[file_index]);
- if (this_input_filename == NULL)
- break;
- }
- finish_options ();
- if (file_index == 0)
- pch_init();
- c_parse_file ();
+ if (num_in_fnames > 1)
+ fatal_error ("sorry, inter-module analysis temporarily out of commission");
- file_index++;
- } while (file_index < num_in_fnames);
-
+ finish_options ();
+ pch_init ();
+ push_file_scope ();
+ c_parse_file ();
finish_file ();
+ pop_file_scope ();
}
/* Common finish hook for the C, ObjC and C++ front ends. */
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index e628aa5fe90..91a42d91814 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -208,7 +208,7 @@ do { \
%type <ttype> any_word
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
-%type <ttype> do_stmt_start poplevel stmt label
+%type <ttype> do_stmt_start pop_scope stmt label
%type <ttype> c99_block_start c99_block_end
%type <ttype> declarator
@@ -328,8 +328,6 @@ static int objc_need_raw_identifier;
#define OBJC_NEED_RAW_IDENTIFIER(VAL) /* nothing */
@@end_ifc
-static bool parsing_iso_function_signature;
-
/* Tell yyparse how to print a token's value, if yydebug is set. */
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
@@ -368,11 +366,6 @@ extdefs:
;
extdef:
- extdef_1
- { parsing_iso_function_signature = false; } /* Reset after any external definition. */
- ;
-
-extdef_1:
fndef
| datadef
| asmdef
@@ -741,28 +734,8 @@ primary:
;
old_style_parm_decls:
- old_style_parm_decls_1
- {
- parsing_iso_function_signature = false; /* Reset after decls. */
- }
- ;
-
-old_style_parm_decls_1:
/* empty */
- {
- if (warn_traditional && !in_system_header
- && parsing_iso_function_signature)
- warning ("traditional C rejects ISO C style function definitions");
- if (warn_old_style_definition && !in_system_header
- && !parsing_iso_function_signature)
- warning ("old-style parameter declaration");
- parsing_iso_function_signature = false; /* Reset after warning. */
- }
| datadecls
- {
- if (warn_old_style_definition && !in_system_header)
- warning ("old-style parameter declaration");
- }
;
/* The following are analogous to lineno_decl, decls and decl
@@ -1555,7 +1528,6 @@ nested_function:
pop_function_context ();
YYERROR1;
}
- parsing_iso_function_signature = false; /* Don't warn about nested functions. */
}
old_style_parm_decls save_location
{ tree decl = current_function_decl;
@@ -1586,7 +1558,6 @@ notype_nested_function:
pop_function_context ();
YYERROR1;
}
- parsing_iso_function_signature = false; /* Don't warn about nested functions. */
}
old_style_parm_decls save_location
{ tree decl = current_function_decl;
@@ -1620,9 +1591,6 @@ after_type_declarator:
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
| after_type_declarator '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | after_type_declarator '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| after_type_declarator array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| '*' maybe_type_quals_attrs after_type_declarator %prec UNARY
@@ -1645,9 +1613,6 @@ parm_declarator:
parm_declarator_starttypename:
parm_declarator_starttypename '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | parm_declarator_starttypename '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| parm_declarator_starttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| TYPENAME
@@ -1659,9 +1624,6 @@ parm_declarator_starttypename:
parm_declarator_nostarttypename:
parm_declarator_nostarttypename '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | parm_declarator_nostarttypename '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| parm_declarator_nostarttypename array_declarator %prec '.'
{ $$ = set_array_declarator_type ($2, $1, 0); }
| '*' maybe_type_quals_attrs parm_declarator_starttypename %prec UNARY
@@ -1678,9 +1640,6 @@ parm_declarator_nostarttypename:
notype_declarator:
notype_declarator '(' parmlist_or_identifiers %prec '.'
{ $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
-/* | notype_declarator '(' error ')' %prec '.'
- { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
- poplevel (0, 0, 0); } */
| '(' maybe_attribute notype_declarator ')'
{ $$ = $2 ? tree_cons ($2, $3, NULL_TREE) : $3; }
| '*' maybe_type_quals_attrs notype_declarator %prec UNARY
@@ -2037,14 +1996,14 @@ lineno_stmt_decl_or_labels:
errstmt: error ';'
;
-pushlevel: /* empty */
- { pushlevel (0);
+push_scope: /* empty */
+ { push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
}
;
-poplevel: /* empty */
+pop_scope: /* empty */
{
@@ifobjc
if (c_dialect_objc ())
@@ -2059,7 +2018,7 @@ c99_block_start: /* empty */
{ if (flag_isoc99)
{
$$ = c_begin_compound_stmt ();
- pushlevel (0);
+ push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
}
@@ -2075,7 +2034,7 @@ c99_block_end: /* empty */
{ if (flag_isoc99)
{
tree scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
- $$ = poplevel (KEEP_MAYBE, 0, 0);
+ $$ = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
= $$;
@@ -2124,8 +2083,8 @@ compstmt_start: '{' { compstmt_count++;
compstmt_nostart: '}'
{ $$ = convert (void_type_node, integer_zero_node); }
- | pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel
- { $$ = poplevel (KEEP_MAYBE, 0, 0);
+ | push_scope maybe_label_decls compstmt_contents_nonempty '}' pop_scope
+ { $$ = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
= SCOPE_STMT_BLOCK (TREE_VALUE ($5))
= $$; }
@@ -2589,11 +2548,11 @@ start_string_translation:
"void bar (int (__attribute__((__mode__(SI))) int foo));". */
parmlist:
maybe_attribute
- { pushlevel (0);
+ { push_scope ();
declare_parm_level (); }
parmlist_1
{ $$ = $3;
- poplevel (0, 0, 0); }
+ pop_scope (); }
;
parmlist_1:
@@ -2606,32 +2565,23 @@ parmlist_1:
parmlist_1
{ $$ = $6; }
| error ')'
- { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
+ { $$ = make_node (TREE_LIST); }
;
/* This is what appears inside the parens in a function declarator.
Is value is represented in the format that grokdeclarator expects. */
parmlist_2: /* empty */
- { $$ = get_parm_info (0); }
+ { $$ = make_node (TREE_LIST); }
| ELLIPSIS
- { $$ = get_parm_info (0);
- /* Gcc used to allow this as an extension. However, it does
- not work for all targets, and thus has been disabled.
- Also, since func (...) and func () are indistinguishable,
- it caused problems with the code in expand_builtin which
- tries to verify that BUILT_IN_NEXT_ARG is being used
- correctly. */
+ { $$ = make_node (TREE_LIST);
+ /* Suppress -Wold-style-definition for this case. */
+ TREE_CHAIN ($$) = error_mark_node;
error ("ISO C requires a named argument before `...'");
- parsing_iso_function_signature = true;
}
| parms
- { $$ = get_parm_info (1);
- parsing_iso_function_signature = true;
- }
+ { $$ = get_parm_info (/*ellipsis=*/false); }
| parms ',' ELLIPSIS
- { $$ = get_parm_info (0);
- parsing_iso_function_signature = true;
- }
+ { $$ = get_parm_info (/*ellipsis=*/true); }
;
parms:
@@ -2706,11 +2656,11 @@ setspecs_fp:
Its value is a list of ..._TYPE nodes or a list of identifiers. */
parmlist_or_identifiers:
maybe_attribute
- { pushlevel (0);
+ { push_scope ();
declare_parm_level (); }
parmlist_or_identifiers_1
{ $$ = $3;
- poplevel (0, 0, 0); }
+ pop_scope (); }
;
parmlist_or_identifiers_1:
@@ -3128,13 +3078,13 @@ optparmlist:
}
| ','
{
- pushlevel (0);
+ push_scope ();
}
parmlist_2
{
/* returns a tree list node generated by get_parm_info */
$$ = $3;
- poplevel (0, 0, 0);
+ pop_scope ();
}
;
@@ -3799,22 +3749,14 @@ yyprint (FILE *file, int yychar, YYSTYPE yyl)
}
}
-/* This is not the ideal place to put these, but we have to get them out
- of c-lex.c because cp/lex.c has its own versions. */
+/* This is not the ideal place to put this, but we have to get it out
+ of c-lex.c because cp/lex.c has its own version. */
/* Parse the file. */
void
c_parse_file (void)
{
yyparse ();
- /* In case there were missing closebraces, get us back to the global
- binding level. */
- while (! global_bindings_p ())
- poplevel (0, 0, 0);
- /* __FUNCTION__ is defined at file scope (""). This
- call may not be necessary as my tests indicate it
- still works without it. */
- finish_fname_decls ();
if (malloced_yyss)
{
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 6da67df0f2f..bd53dbc56e9 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -24,22 +24,21 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "c-common.h"
-/* Language-dependent contents of an identifier. */
+/* Each C symbol points to three linked lists of c_binding structures.
+ These describe the values of the identifier in the three different
+ namespaces defined by the language. The contents of these lists
+ are private to c-decl.c. */
-/* The limbo_value is used for block level extern declarations, which need
- to be type checked against subsequent extern declarations. They can't
- be referenced after they fall out of scope, so they can't be global.
+struct c_binding;
- The rid_code field is used for keywords. It is in all
- lang_identifier nodes, because some keywords are only special in a
- particular context. */
+/* Language-dependent contents of an identifier. */
struct lang_identifier GTY(())
{
struct c_common_identifier common_id;
- tree symbol_value;
- tree tag_value;
- tree label_value;
+ struct c_binding *symbol_binding; /* vars, funcs, constants, typedefs */
+ struct c_binding *tag_binding; /* struct/union/enum tags */
+ struct c_binding *label_binding; /* labels */
};
/* The resulting tree type. */
@@ -64,26 +63,6 @@ struct lang_decl GTY(())
tree pending_sizes;
};
-/* Macros for access to language-specific slots in an identifier. */
-/* Each of these slots contains a DECL node or null. */
-
-/* The value of the identifier in the namespace of "ordinary identifiers"
- (data objects, enum constants, functions, typedefs). */
-#define IDENTIFIER_SYMBOL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->symbol_value)
-/* The value of the identifier in the namespace of struct, union,
- and enum tags. */
-#define IDENTIFIER_TAG_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->tag_value)
-/* The value of the identifier in the namespace of labels. */
-#define IDENTIFIER_LABEL_VALUE(NODE) \
- (((struct lang_identifier *) (NODE))->label_value)
-
-/* In identifiers, C uses the following fields in a special way:
- TREE_PUBLIC to record that there was a previous local extern decl.
- TREE_USED to record that such a decl was used.
- TREE_ADDRESSABLE to record that the address of such a decl was used. */
-
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
#define C_TYPE_FIELDS_READONLY(TYPE) TREE_LANG_FLAG_1 (TYPE)
@@ -128,11 +107,13 @@ struct lang_type GTY(())
/* For a FUNCTION_DECL, nonzero if it was an implicit declaration. */
#define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
-/* Nonzero for a declaration of an external object which is not
- currently in scope. This is either a built-in declaration of
- a library function, before a real declaration has been seen,
- or a declaration that appeared in an inner scope that has ended. */
-#define C_DECL_INVISIBLE(EXP) DECL_LANG_FLAG_3 (EXP)
+/* For any decl, nonzero if it is bound in the externals scope and
+ pop_scope mustn't chain it into any higher block. */
+#define C_DECL_IN_EXTERNAL_SCOPE(EXP) DECL_LANG_FLAG_3 (EXP)
+
+/* For FUNCTION_DECLs, evaluates true if the decl is built-in but has
+ been declared. */
+#define C_DECL_DECLARED_BUILTIN(EXP) DECL_LANG_FLAG_4 (EXP)
/* Nonzero for a decl which either doesn't exist or isn't a prototype.
N.B. Could be simplified if all built-in decls had complete prototypes
@@ -147,11 +128,6 @@ struct lang_type GTY(())
without prototypes. */
#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_BINFO (NODE)
-/* Values for the first parameter to poplevel. */
-#define KEEP_NO 0
-#define KEEP_YES 1
-#define KEEP_MAYBE 2
-
/* Save and restore the variables in this file and elsewhere
that keep track of the progress of compilation of the current function.
Used for nested functions. */
@@ -181,9 +157,9 @@ extern int c_in_case_stmt;
extern int global_bindings_p (void);
extern tree getdecls (void);
-extern void pushlevel (int);
+extern void push_scope (void);
+extern tree pop_scope (void);
extern void insert_block (tree);
-extern void set_block (tree);
extern tree pushdecl (tree);
extern void c_expand_body (tree);
@@ -203,12 +179,11 @@ extern void finish_decl (tree, tree, tree);
extern tree finish_enum (tree, tree, tree);
extern void finish_function (void);
extern tree finish_struct (tree, tree, tree);
-extern tree get_parm_info (int);
+extern tree get_parm_info (bool);
extern tree grokfield (tree, tree, tree);
extern tree groktypename (tree);
extern tree groktypename_in_parm_context (tree);
extern tree implicitly_declare (tree);
-extern int in_parm_level_p (void);
extern void keep_next_level (void);
extern tree lookup_name (tree);
extern void pending_xref_error (void);
@@ -216,7 +191,6 @@ extern void c_push_function_context (struct function *);
extern void c_pop_function_context (struct function *);
extern void push_parm_decl (tree);
extern tree pushdecl_top_level (tree);
-extern void pushtag (tree, tree);
extern tree set_array_declarator_type (tree, tree, int);
extern void shadow_tag (tree);
extern void shadow_tag_warned (tree, int);
@@ -230,7 +204,6 @@ extern tree c_begin_compound_stmt (void);
extern void c_expand_decl_stmt (tree);
extern void c_static_assembler_name (tree);
extern tree make_pointer_declarator (tree, tree);
-extern void merge_translation_unit_decls (void);
/* in c-objc-common.c */
extern int c_disregard_inline_limits (tree);
@@ -257,6 +230,7 @@ enum {
};
extern tree require_complete_type (tree);
+extern int same_translation_unit_p (tree, tree);
extern int comptypes (tree, tree, int);
extern tree c_size_in_bytes (tree);
extern bool c_mark_addressable (tree);
@@ -313,6 +287,11 @@ extern int current_function_returns_abnormally;
extern int system_header_p;
+/* True means global_bindings_p should return false even if the scope stack
+ says we are in file scope. */
+
+extern bool c_override_global_bindings_to_false;
+
/* In c-decl.c */
extern void c_finish_incomplete_decl (tree);
extern void *get_current_scope (void);
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 189ec0f580d..2e57ba7cceb 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -51,7 +51,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static int missing_braces_mentioned;
static tree qualify_type (tree, tree);
-static int same_translation_unit_p (tree, tree);
static int tagged_types_tu_compatible_p (tree, tree, int);
static int comp_target_types (tree, tree, int);
static int function_types_compatible_p (tree, tree, int);
@@ -369,9 +368,9 @@ common_type (tree t1, tree t2)
/* If both args specify argument types, we must merge the two
lists, argument by argument. */
-
- pushlevel (0);
- declare_parm_level ();
+ /* Tell global_bindings_p to return false so that variable_size
+ doesn't abort on VLAs in parameter types. */
+ c_override_global_bindings_to_false = true;
len = list_length (p1);
newargs = 0;
@@ -434,8 +433,7 @@ common_type (tree t1, tree t2)
parm_done: ;
}
- poplevel (0, 0, 0);
-
+ c_override_global_bindings_to_false = false;
t1 = build_function_type (valtype, newargs);
/* ... falls through ... */
}
@@ -614,11 +612,11 @@ comp_target_types (tree ttl, tree ttr, int reflexive)
/* Subroutines of `comptypes'. */
-/* Determine whether two types derive from the same translation unit.
- If the CONTEXT chain ends in a null, that type's context is still
- being parsed, so if two types have context chains ending in null,
+/* Determine whether two trees derive from the same translation unit.
+ If the CONTEXT chain ends in a null, that tree's context is still
+ being parsed, so if two trees have context chains ending in null,
they're in the same translation unit. */
-static int
+int
same_translation_unit_p (tree t1, tree t2)
{
while (t1 && TREE_CODE (t1) != TRANSLATION_UNIT_DECL)
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 88d677c78b8..ccc8339cb5f 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -902,7 +902,6 @@ create_coverage (void)
DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
DECL_UNINLINABLE (ctor) = 1;
- ctor = lang_hooks.decls.pushdecl (ctor);
rest_of_decl_compilation (ctor, 0, 1, 0);
announce_function (ctor);
current_function_decl = ctor;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0f900f53f84..008aa4adf74 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2004-03-23 Zack Weinberg <zack@codesourcery.com>
+
+ PR 12267, 12391, 12560, 13129, 14114, 14113
+ * cp-lang.c (c_reset_state): Delete.
+ (push_file_scope, pop_file_scope): New stubs.
+ * parser.c (c_parse_file): Call sorry() here if called more than once.
+
2004-03-23 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* typeck.c (build_c_cast): Only look at TREE_CONSTANT_OVERFLOW
@@ -17,13 +24,13 @@
(dump_simple_decl): Likewise.
(dump_function_decl): Likewise.
(cv_to_string): Likewise.
- (dump_type_prefix): Likewise. Adjust return void.
+ (dump_type_prefix): Likewise. Adjust return void.
* cxx-pretty-print.c (pp_cxx_cv_qualifier_seq): Move to
cxx_pretty_print.h.
(pp_cxx_template_keyword_if_needed): Document.
(pp_cxx_qualified_id): Document case FUNCTION_DECL. Tidy.
(pp_cxx_expression): Handle NON_DEPENDENT_EXPR and
- MUST_NOT_THROW_EXPR.
+ MUST_NOT_THROW_EXPR.
2004-03-21 Mark Mitchell <mark@codesourcery.com>
@@ -69,7 +76,7 @@
* typeck.c (lookup_destructor): Allow the use of destructors from
base classes.
-
+
2004-03-19 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* cxx-pretty-print.c (pp_cxx_unqualified_id): Use
@@ -194,7 +201,7 @@
* pt.c (do_type_instantiation): On systems where weak symbols
don't go in a static archive's TOC, explicit instantiation of a
class must imply *explicit* instantiation of its memeber.
-
+
2004-03-11 Kazu Hirata <kazu@cs.umass.edu>
* call.c, cp-tree.h, pt.c: Fix comment typos.
@@ -203,7 +210,7 @@
PR c++/14510
* decl.c (xref_tag): Disregard non-type declarations when
- looking up a tagged type.
+ looking up a tagged type.
2004-03-09 Nathan Sidwell <nathan@codesourcery.com>
@@ -294,7 +301,7 @@
PR debug/14079
* name-lookup.c (add_decl_to_level): Add extern variables, as well
as static, to static_decls array.
-
+
2004-03-05 Jason Merrill <jason@redhat.com>
* tree.c (list_hash_pieces): s/TYPE_HASH/TREE_HASH/.
@@ -326,7 +333,7 @@
* parser.c (cp_parser_late_parsing_default_args): Check that there
are no extra tokens after the end of the default-argument
expression.
-
+
2004-03-01 Mark Mitchell <mark@codesourcery.com>
PR c++/14324
@@ -341,7 +348,7 @@
PR c++/14337
* pt.c (tsubst_qualified_id): Handle dependent qualifying scopes.
(tsubst_expr): Do not call tsubst_copy, even when
- processing_template_decl.
+ processing_template_decl.
2004-03-01 Jeff Law <law@redhat.com>
@@ -429,7 +436,7 @@
2004-02-23 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/14143
- * name-lookup.c (arg_assoc_class): Don't look into template
+ * name-lookup.c (arg_assoc_class): Don't look into template
arguments if it is not a primary template.
2004-02-20 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
@@ -464,7 +471,7 @@
2004-02-19 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/14181
- * parser.c (cp_parser_new_expression): Parse an ill-formed
+ * parser.c (cp_parser_new_expression): Parse an ill-formed
direct-new-declarator after a parenthesized type-id to emit good
diagnostic.
@@ -640,7 +647,7 @@
whether or not a friend template is a definition.
(tsubst_decl): Clear DECL_INITIAL for new FUNCTION_DECLs.
* tree.c (build_zc_wrapper): Remove.
-
+
2004-02-12 Zack Weinberg <zack@codesourcery.com>
* cp-lang.c: Don't define LANG_HOOKS_BUILTIN_TYPE_DECLS.
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 176a145f3ee..b0b927b850e 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -388,13 +388,6 @@ cp_var_mod_type_p (tree type)
return false;
}
-/* Stub routine to tell people that this doesn't work yet. */
-void
-c_reset_state (void)
-{
- sorry ("inter-module optimisations not implemented yet");
-}
-
/* Construct a C++-aware pretty-printer for CONTEXT. It is assumed
that CONTEXT->printer is an already constructed basic pretty_printer. */
static void
@@ -409,3 +402,14 @@ cxx_initialize_diagnostics (diagnostic_context *context)
/* It is safe to free this object because it was previously malloc()'d. */
free (base);
}
+
+/* Stubs to keep c-opts.c happy. */
+void
+push_file_scope (void)
+{
+}
+
+void
+pop_file_scope (void)
+{
+}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e964f48753f..e58fda4cc4f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -15347,7 +15347,6 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
}
-
/* The parser. */
static GTY (()) cp_parser *the_parser;
@@ -15360,6 +15359,14 @@ void
c_parse_file (void)
{
bool error_occurred;
+ static bool already_called = false;
+
+ if (already_called)
+ {
+ sorry ("inter-module optimizations not implemented for C++");
+ return;
+ }
+ already_called = true;
the_parser = cp_parser_new ();
push_deferring_access_checks (flag_access_control
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 4e9c3e983be..3e15a359333 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -216,7 +216,7 @@ void
lhd_clear_binding_stack (void)
{
while (! lang_hooks.decls.global_bindings_p ())
- poplevel (0, 0, 0);
+ lang_hooks.decls.poplevel (0, 0, 0);
}
/* Type promotion for variable arguments. */
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 1d76cc4d989..89abaf4c198 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -64,8 +64,6 @@ Boston, MA 02111-1307, USA. */
#include "diagnostic.h"
#include "cgraph.h"
-#define OBJC_VOID_AT_END build_tree_list (NULL_TREE, void_type_node)
-
/* This is the default way of generating a method name. */
/* I am not sure it is really correct.
Perhaps there's a danger that it will make name conflicts
@@ -161,7 +159,6 @@ static void generate_ivar_lists (void);
static void generate_dispatch_tables (void);
static void generate_shared_structures (void);
static tree generate_protocol_list (tree);
-static void generate_forward_declaration_to_string_table (void);
static void build_protocol_reference (tree);
static tree build_keyword_selector (tree);
@@ -1238,7 +1235,7 @@ synth_module_prologue (void)
= build_function_type (IMP_type,
tree_cons (NULL_TREE, id_type,
tree_cons (NULL_TREE, selector_type,
- OBJC_VOID_AT_END)));
+ void_list_node)));
umsg_decl = builtin_function (TAG_MSGSEND,
temp_type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
@@ -1248,7 +1245,7 @@ synth_module_prologue (void)
= build_function_type (IMP_type,
tree_cons (NULL_TREE, super_type,
tree_cons (NULL_TREE, selector_type,
- OBJC_VOID_AT_END)));
+ void_list_node)));
umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
temp_type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
@@ -1259,7 +1256,7 @@ synth_module_prologue (void)
temp_type = build_function_type (id_type,
tree_cons (NULL_TREE,
const_string_type_node,
- OBJC_VOID_AT_END));
+ void_list_node));
objc_get_class_decl
= builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
@@ -1305,8 +1302,6 @@ synth_module_prologue (void)
TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
}
- generate_forward_declaration_to_string_table ();
-
/* Forward declare constant_string_id and constant_string_type. */
if (!constant_string_class_name)
constant_string_class_name = default_constant_string_class_name;
@@ -1877,7 +1872,7 @@ build_module_descriptor (void)
get_identifier (TAG_EXECCLASS),
build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node,
- OBJC_VOID_AT_END)));
+ void_list_node)));
DECL_EXTERNAL (execclass_decl) = 1;
DECL_ARTIFICIAL (execclass_decl) = 1;
@@ -1892,7 +1887,7 @@ build_module_descriptor (void)
start_function (void_list_node_1,
build_nt (CALL_EXPR, init_function_name,
tree_cons (NULL_TREE, NULL_TREE,
- OBJC_VOID_AT_END),
+ void_list_node),
NULL_TREE),
NULL_TREE);
store_parm_decls ();
@@ -1919,22 +1914,6 @@ build_module_descriptor (void)
}
}
-/* extern const char _OBJC_STRINGS[]; */
-
-static void
-generate_forward_declaration_to_string_table (void)
-{
- tree sc_spec, decl_specs, expr_decl;
-
- sc_spec = tree_cons (NULL_TREE, ridpointers[(int) RID_EXTERN], NULL_TREE);
- decl_specs = tree_cons (NULL_TREE, ridpointers[(int) RID_CHAR], sc_spec);
-
- expr_decl
- = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULL_TREE);
-
- UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
-}
-
/* Return the DECL of the string IDENT in the SECTION. */
static tree
@@ -2699,7 +2678,7 @@ objc_enter_block (void)
block = begin_compound_stmt (0);
#else
block = c_begin_compound_stmt ();
- pushlevel (0);
+ push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
#endif
@@ -2724,7 +2703,7 @@ objc_exit_block (void)
finish_compound_stmt (0, block);
#else
scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
- inner = poplevel (KEEP_MAYBE, 1, 0);
+ inner = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
@@ -3331,7 +3310,7 @@ build_objc_exception_stuff (void)
= build_function_type (id_type,
tree_cons (NULL_TREE,
build_pointer_type (objc_exception_data_template),
- OBJC_VOID_AT_END));
+ void_list_node));
objc_exception_extract_decl
= builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
/* void objc_exception_try_enter(struct _objc_exception_data *); */
@@ -3340,7 +3319,7 @@ build_objc_exception_stuff (void)
= build_function_type (void_type_node,
tree_cons (NULL_TREE,
build_pointer_type (objc_exception_data_template),
- OBJC_VOID_AT_END));
+ void_list_node));
objc_exception_try_enter_decl
= builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
objc_exception_try_exit_decl
@@ -3350,7 +3329,7 @@ build_objc_exception_stuff (void)
/* void objc_sync_exit(id); */
temp_type = build_function_type (void_type_node,
tree_cons (NULL_TREE, id_type,
- OBJC_VOID_AT_END));
+ void_list_node));
objc_exception_throw_decl
= builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
DECL_ATTRIBUTES (objc_exception_throw_decl)
@@ -3363,7 +3342,7 @@ build_objc_exception_stuff (void)
temp_type = build_function_type (integer_type_node,
tree_cons (NULL_TREE, id_type,
tree_cons (NULL_TREE, id_type,
- OBJC_VOID_AT_END)));
+ void_list_node)));
objc_exception_match_decl
= builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
@@ -5463,7 +5442,7 @@ get_arg_type_list (tree meth, int context, int superflag)
if (METHOD_ADD_ARGS (meth) == objc_ellipsis_node)
/* We have a `, ...' immediately following the selector,
- finalize the arglist...simulate get_parm_info (0). */
+ finalize the arglist...simulate get_parm_info (true). */
;
else if (METHOD_ADD_ARGS (meth))
{
@@ -5472,8 +5451,8 @@ get_arg_type_list (tree meth, int context, int superflag)
chainon (arglist, add_arg_list);
}
else
- /* finalize the arglist...simulate get_parm_info (1) */
- chainon (arglist, OBJC_VOID_AT_END);
+ /* finalize the arglist...simulate get_parm_info (false) */
+ chainon (arglist, void_list_node);
return arglist;
}
@@ -7539,7 +7518,8 @@ start_method_def (tree method)
UOBJC_SUPER_decl = NULL_TREE;
/* Must be called BEFORE start_function. */
- pushlevel (0);
+ push_scope ();
+ declare_parm_level ();
/* Generate prototype declarations for arguments..."new-style". */
synth_self_and_ucmd_args ();
@@ -7819,9 +7799,9 @@ continue_method_def (void)
if (METHOD_ADD_ARGS (objc_method_context) == objc_ellipsis_node)
/* We have a `, ...' immediately following the selector. */
- parmlist = get_parm_info (0);
+ parmlist = get_parm_info (/*ellipsis=*/true);
else
- parmlist = get_parm_info (1); /* place a `void_at_end' */
+ parmlist = get_parm_info (/*ellipsis=*/false);
#ifndef OBJCPLUS
/* Set self_decl from the first argument...this global is used by
@@ -7829,7 +7809,7 @@ continue_method_def (void)
self_decl = TREE_PURPOSE (parmlist);
#endif /* !OBJCPLUS */
- poplevel (0, 0, 0);
+ pop_scope ();
really_start_method (objc_method_context, parmlist);
store_parm_decls ();
}
@@ -8801,8 +8781,6 @@ finish_objc (void)
objc_implementation_context = NULL_TREE;
}
- generate_forward_declaration_to_string_table ();
-
/* Process the static instances here because initialization of objc_symtab
depends on them. */
if (objc_static_instances)
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index abbf6562731..db7eeca5141 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -234,7 +234,6 @@ enum objc_tree_index
OCTI_MCLS_DECL,
OCTI_SEL_TABLE_DECL,
OCTI_MODULES_DECL,
- OCTI_STRG_DECL,
OCTI_INTF_CTX,
OCTI_IMPL_CTX,
@@ -360,7 +359,6 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define UOBJC_METACLASS_decl objc_global_trees[OCTI_MCLS_DECL]
#define UOBJC_SELECTOR_TABLE_decl objc_global_trees[OCTI_SEL_TABLE_DECL]
#define UOBJC_MODULES_decl objc_global_trees[OCTI_MODULES_DECL]
-#define UOBJC_STRINGS_decl objc_global_trees[OCTI_STRG_DECL]
/* The following are used when compiling a class implementation.
implementation_template will normally be an interface, however if
diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c
index 72c772c40b4..877867ac39d 100644
--- a/gcc/objc/objc-lang.c
+++ b/gcc/objc/objc-lang.c
@@ -55,6 +55,8 @@ enum c_language_kind c_language = clk_objc;
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
#undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_CLEAR_BINDING_STACK
+#define LANG_HOOKS_CLEAR_BINDING_STACK lhd_do_nothing
#undef LANG_HOOKS_EXPAND_EXPR
#define LANG_HOOKS_EXPAND_EXPR c_expand_expr
#undef LANG_HOOKS_MARK_ADDRESSABLE
@@ -130,6 +132,19 @@ enum c_language_kind c_language = clk_objc;
#undef LANG_HOOKS_TYPE_PROMOTES_TO
#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
+/* The C front end's scoping structure is very different from
+ that expected by the language-independent code; it is best
+ to disable all of pushlevel, poplevel, set_block, and getdecls.
+ This means it must also provide its own write_globals. */
+
+#undef LANG_HOOKS_PUSHLEVEL
+#define LANG_HOOKS_PUSHLEVEL lhd_do_nothing_i
+#undef LANG_HOOKS_POPLEVEL
+#define LANG_HOOKS_POPLEVEL lhd_do_nothing_iii_return_null_tree
+#undef LANG_HOOKS_SET_BLOCK
+#define LANG_HOOKS_SET_BLOCK lhd_do_nothing_t
+#undef LANG_HOOKS_GETDECLS
+#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
#undef LANG_HOOKS_WRITE_GLOBALS
#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c111369c3e3..de52f548e68 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2004-03-23 Zack Weinberg <zack@codesourcery.com>
+
+ PR 12267, 12391, 12560, 13129, 14114, 14113
+ * gcc.dg/Wold-style-definition-1.c, gcc.dg/builtins-30.c
+ * gcc.dg/unused-4.c, gcc.dg/noncompile/label-1.c
+ * gcc.dg/noncompile/label-lineno-1.c, objc.dg/naming-1.m:
+ Adjust error regexps.
+ * gcc.dg/Wshadow-2.c, gcc.dg/noncompile/incomplete-3.c
+ * gcc.dg/noncompile/undeclared-1.c: New test cases.
+ * gcc.dg/decl-5.c, gcc.dg/redecl-1.c: Remove XFAIL.
+ * gcc.dg/local1.c: Add explanatory comment.
+
2004-03-23 Roger Sayle <roger@eyesopen.com>
PR optimization/14669
@@ -55,11 +67,11 @@
* g++.dg/template/spec13.C: New test.
* g++.dg/lookup/using11.C: New test.
-
+
* g++.dg/lookup/koenig3.C: New test.
* g++.dg/template/operator2.C: New test.
-
+
* g++.dg/expr/dtor3.C: New test.
* g++.old-deja/g++.brendan/crash15.C: Remove incorrect dg-error
marker.
diff --git a/gcc/testsuite/gcc.dg/Wold-style-definition-1.c b/gcc/testsuite/gcc.dg/Wold-style-definition-1.c
index d4fb8bd8da1..aa016338b5e 100644
--- a/gcc/testsuite/gcc.dg/Wold-style-definition-1.c
+++ b/gcc/testsuite/gcc.dg/Wold-style-definition-1.c
@@ -5,19 +5,19 @@
/* { dg-options "-Wold-style-definition" } */
void
-bar (a) int a; { } /* { dg-warning "old-style parameter declaration" } */
+bar (a) int a; { } /* { dg-warning "old-style function definition" } */
-void bar1 () {} /* { dg-warning "old-style parameter declaration" } */
+void bar1 () {} /* { dg-warning "old-style function definition" } */
extern void bar2 (void);
-void bar2 () {} /* { dg-warning "old-style parameter declaration" } */
+void bar2 () {} /* { dg-warning "old-style function definition" } */
extern void bar3 (int);
-void bar3 (a) {} /* { dg-warning "old-style parameter declaration" } */
+void bar3 (a) {} /* { dg-warning "old-style function definition" } */
-void bar4 (a) {} /* { dg-warning "old-style parameter declaration" } */
+void bar4 (a) {} /* { dg-warning "old-style function definition" } */
void bar5 (int a) {}
diff --git a/gcc/testsuite/gcc.dg/Wshadow-2.c b/gcc/testsuite/gcc.dg/Wshadow-2.c
new file mode 100644
index 00000000000..b0c051271ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-2.c
@@ -0,0 +1,10 @@
+/* Bogus warning for a double declaration of the same extern variable,
+ first at file scope, then at block scope. PR 13129. */
+
+/* { dg-options "-Wshadow" } */
+
+extern struct foo bar;
+void dummy()
+{
+ extern struct foo bar; /* { dg-bogus "shadows" } */
+}
diff --git a/gcc/testsuite/gcc.dg/builtins-30.c b/gcc/testsuite/gcc.dg/builtins-30.c
index 9ed0be53c40..7c700c514dc 100644
--- a/gcc/testsuite/gcc.dg/builtins-30.c
+++ b/gcc/testsuite/gcc.dg/builtins-30.c
@@ -7,20 +7,20 @@ extern double strtod (const char *, char **);
/* A built-in function may be overridden by an old-style definition
specifying too few arguments... */
double cos ()
-{ /* { dg-warning "shadowing built-in" } */
+{ /* { dg-warning "shadows a built-in" } */
return strtod ("nan", 0);
}
/* the right number, but the wrong type, arguments... */
double sin (foo)
- int foo UNUSED; /* { dg-warning "shadowing built-in" } */
+ int foo UNUSED; /* { dg-warning "shadows a built-in" } */
{
return strtod ("nan", 0);
}
/* or too many arguments. */
long double cosl (foo, bar)
- long double foo UNUSED; /* { dg-warning "shadowing built-in" } */
+ const char *foo UNUSED; /* { dg-warning "shadows a built-in" } */
int bar UNUSED;
{
return strtod ("nan", 0);
diff --git a/gcc/testsuite/gcc.dg/decl-5.c b/gcc/testsuite/gcc.dg/decl-5.c
index d7c36a4a1bc..9b778246459 100644
--- a/gcc/testsuite/gcc.dg/decl-5.c
+++ b/gcc/testsuite/gcc.dg/decl-5.c
@@ -10,7 +10,7 @@ void a()
{
void c();
c();
-} /* { dg-bogus "error" "PR c/14114" { xfail *-*-* } } */
+}
void b()
{
diff --git a/gcc/testsuite/gcc.dg/local1.c b/gcc/testsuite/gcc.dg/local1.c
index 700070ae1d6..9d6fdb16752 100644
--- a/gcc/testsuite/gcc.dg/local1.c
+++ b/gcc/testsuite/gcc.dg/local1.c
@@ -1,3 +1,19 @@
+/* This is allowed, with the effect that the 'extern' declaration at block
+ scope refers to the same object as the 'static' declaration at file scope.
+
+ C90 6.1.2.2 [as corrected by TC1], C99 6.2.2:
+
+ For an identifier declared with the storage-class specifier
+ extern in a scope in which a prior declaration of that
+ identifier is visible, if the prior declaration specifies
+ internal or external linkage, the linkage of the identifier at
+ the later daclaration is the same as the linkage specified at
+ the prior declaration. If no prior declaration is visible,
+ or if the prior declaration specifies no linkage, then the
+ identifer has external linkage.
+
+ This is PR 14366. */
+
static int i;
extern int i;
diff --git a/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c b/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c
new file mode 100644
index 00000000000..735ef465b38
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c
@@ -0,0 +1,9 @@
+/* Both occurrences of "c" should get diagnostics. PR 12391. */
+typedef struct { int a; } b_t;
+
+int foo (void)
+{
+ b_t d;
+ struct b_t *c = &d; /* { dg-warning "incompatible pointer type" } */
+ c->a; /* { dg-error "incomplete type" } */
+}
diff --git a/gcc/testsuite/gcc.dg/noncompile/label-1.c b/gcc/testsuite/gcc.dg/noncompile/label-1.c
index c646b48fb8d..e9bde7b3b7b 100644
--- a/gcc/testsuite/gcc.dg/noncompile/label-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/label-1.c
@@ -28,7 +28,7 @@ void c(void)
/* can't have two labels with the same name in the same function */
void d(void)
{
- l: dummy(); /* { dg-error "previously defined" "prev def same scope" } */
+ l: dummy(); /* { dg-error "previous definition" "prev def same scope" } */
l: dummy(); /* { dg-error "duplicate label" "dup label same scope" } */
goto l;
}
@@ -36,7 +36,7 @@ void d(void)
/* even at different scopes */
void e(void)
{
- l: dummy(); /* { dg-error "previously defined" "prev def diff scope" } */
+ l: dummy(); /* { dg-error "previous definition" "prev def diff scope" } */
{
l: dummy(); /* { dg-error "duplicate label" "dup label diff scope" } */
}
@@ -150,7 +150,7 @@ void m(void)
void n(void)
{
- __label__ l; /* { dg-error "previously declared" "outer label decl" } */
+ __label__ l; /* { dg-error "previous declaration" "outer label decl" } */
void nest(void)
{
l: goto l; /* { dg-error "duplicate label" "inner label defn" } */
diff --git a/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c b/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c
index 0c5599434f8..76d4d96edaf 100644
--- a/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/label-lineno-1.c
@@ -4,7 +4,7 @@
void
foo(int i)
{
- my_label: /* { dg-error "previously defined" "prev label" } */
+ my_label: /* { dg-error "previous definition" "prev label" } */
i++;
diff --git a/gcc/testsuite/gcc.dg/noncompile/undeclared-1.c b/gcc/testsuite/gcc.dg/noncompile/undeclared-1.c
new file mode 100644
index 00000000000..5bb7c2a4df9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/noncompile/undeclared-1.c
@@ -0,0 +1,8 @@
+/* Test for no ICE with an undeclared identifier in an enum in old-style
+ parameter decls. PR 12560. */
+/* { dg-options "-w" } */
+
+foo(c)
+ enum { a = b } c; /* { dg-error "undeclared|for each" } */
+{
+}
diff --git a/gcc/testsuite/gcc.dg/redecl-1.c b/gcc/testsuite/gcc.dg/redecl-1.c
index 09b70d7b6cd..14877667e91 100644
--- a/gcc/testsuite/gcc.dg/redecl-1.c
+++ b/gcc/testsuite/gcc.dg/redecl-1.c
@@ -64,7 +64,7 @@ void test4(void)
void prime5(void)
{
- extern double bar5(double); /* { dg-error "previous" "" { xfail *-*-* } } */
+ extern double bar5(double); /* { dg-error "previous" "" } */
}
void test5(void)
diff --git a/gcc/testsuite/gcc.dg/unused-4.c b/gcc/testsuite/gcc.dg/unused-4.c
index 99e845f45a3..4b33a7fbb69 100644
--- a/gcc/testsuite/gcc.dg/unused-4.c
+++ b/gcc/testsuite/gcc.dg/unused-4.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-Wunused -O3" } */
-static const int i = 0;
+static const int i = 0; /* { dg-warning "unused variable" } */
static void f() { } /* { dg-warning "defined but not used" } */
static inline void g() { }
diff --git a/gcc/testsuite/objc.dg/naming-1.m b/gcc/testsuite/objc.dg/naming-1.m
index 69d98b7be51..1be7eba664c 100644
--- a/gcc/testsuite/objc.dg/naming-1.m
+++ b/gcc/testsuite/objc.dg/naming-1.m
@@ -9,9 +9,7 @@ void foo(void)
{
int View; /* ok */
View = 1; /* ok */
- View *view; /* { dg-error "`view' undeclared" } */
- /* { dg-error "is reported only once" "" { target *-*-* } 12 } */
- /* { dg-error "function it appears in" "" { target *-*-* } 12 } */
+ View *view; /* { dg-error "undeclared|only once|it appears" } */
}
void bar(void)
diff --git a/gcc/tree.c b/gcc/tree.c
index bca58f04c01..eca5f20dd7b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -941,11 +941,23 @@ chain_member (tree elem, tree chain)
int
list_length (tree t)
{
- tree tail;
+ tree p = t;
+#ifdef ENABLE_TREE_CHECKING
+ tree q = t;
+#endif
int len = 0;
- for (tail = t; tail; tail = TREE_CHAIN (tail))
- len++;
+ while (p)
+ {
+ p = TREE_CHAIN (p);
+#ifdef ENABLE_TREE_CHECKING
+ if (len % 2)
+ q = TREE_CHAIN (q);
+ if (p == q)
+ abort ();
+#endif
+ len++;
+ }
return len;
}
OpenPOWER on IntegriCloud