This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Revised c-decl.c patch - ObjC still not quite right


Zack,

I'll make you a deal. :-) Why don't you review and approve

http://gcc.gnu.org/ml/gcc-patches/2004-03/msg00222.html

and I'll give you temporary absolution for breaking comp-types-1.m and fix the issue once your patch is in. You game? :-)

--Zem

On 20 Mar 2004, at 0.42, Zack Weinberg wrote:


Here's my revisions to date. libobjc now builds, but I still see a few regressions in the objc testsuite:

FAIL: objc.dg/comp-types-1.m  (test for warnings, line 37)
FAIL: objc.dg/comp-types-1.m  (test for warnings, line 53)
FAIL: objc.dg/comp-types-1.m  (test for warnings, line 71)
FAIL: objc.dg/comp-types-1.m  (test for warnings, line 72)
FAIL: objc.dg/comp-types-1.m  (test for warnings, line 82)
FAIL: objc.dg/comp-types-1.m  (test for warnings, line 83)

I can't see any obvious reason why these would have been caused by my
patch, but neither can I see any obvious other cause for them.

Java works now, I think.  I got the dreaded segfault-that-disappears-
on-retry building libjava.  *Might* have been an out-of-memory
condition.

C, C++, F77 are in good shape. Haven't yet incorporated the
suggestions for better commentary.

All testing is on i686-linux btw.

zw

===================================================================
Index: c-common.h
--- c-common.h	17 Feb 2004 18:32:32 -0000	1.222
+++ c-common.h	20 Mar 2004 08:40:29 -0000
@@ -329,6 +329,8 @@ extern void (*lang_expand_function_end)
    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. */
===================================================================
Index: c-decl.c
--- c-decl.c 18 Mar 2004 18:58:01 -0000 1.485
+++ c-decl.c 20 Mar 2004 08:40:29 -0000
@@ -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.
+
+ 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 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.
+   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;


-static GTY(()) struct c_scope *global_scope;
+/* A chain of c_binding structures awaiting reuse.  */
+
+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_sc

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
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 nod
(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;
-
- if (keep == KEEP_MAYBE)
- keep = (scope->names || scope->tags);
+ tree block, context, p;
+ struct c_binding *b;


-  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_
   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_
 	      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_
}


   /* 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,
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,
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,
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,
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,
}
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,
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,

       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,
 	}
     }

+ /* 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 oldd
}



-/* 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;


- warning ("%Jshadowed declaration is here", old);
+ 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);
+
+ 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))
-	{
-	  /* 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;
-	}
-      if (DECL_EXTERNAL (x) || scope == global_scope)
-	{
-	  /* 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);
-	}
-
-      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);
-	}
-
-      /* 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);
+      while (b && b->contour != external_scope)
+	b = b->shadowed;

-	  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));
+      /* 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))
+	{
+	  bind (name, b->decl, scope);
+	  return b->decl;
+	}
+      else if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
+	{
+	  C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
+	  bind (name, x, external_scope);
 	}
     }

-  if (TREE_CODE (x) == PARM_DECL)
-    SCOPE_LIST_APPEND (scope, parms, x);
-  else
-    SCOPE_LIST_APPEND (scope, names, x);
-
+  warn_if_shadowing (x);
+
+ skip_external_and_shadow_checks:
+  if (TREE_CODE (x) == TYPE_DECL)
+    clone_underlying_type (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))
-	{
-	  implicit_decl_warning (DECL_NAME (decl));
-	  if (! DECL_FILE_SCOPE_P (decl))
-	    warning ("%Jprevious declaration of '%D'", decl, decl);
-	  C_DECL_IMPLICIT (decl) = 1;
-	}
-      /* 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));
+      /* 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 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;
+	}
     }

   /* 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 locati
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
 	      && 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
       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
   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 (thislevel_only || TREE_CODE (b->decl) != code)
     {
-      if (current_scope == global_scope
-	  || purpose_member (name, current_scope->tags))
+      /* 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 na
       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
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 declsp
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 declsp
}
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 declsp
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 declsp
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
   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
     }

   /* 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
/* 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
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 de
/* 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 de
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 de
| (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 de
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 de
}
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 de
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 de
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 de
/* 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 de
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 de
 	   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_fl
       && !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_fl
}
}


-/* 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, t

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))
@@ -5219,10 +5317,7 @@ finish_enum (tree enumtype, tree values,
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);

@@ -5351,16 +5446,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);
}
}


@@ -5377,6 +5475,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);
}


@@ -5463,13 +5563,13 @@ start_function (tree declspecs, tree dec
     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)))
@@ -5534,7 +5634,7 @@ start_function (tree declspecs, tree dec
#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'. */
@@ -5600,7 +5700,7 @@ start_function (tree declspecs, tree dec


current_function_decl = pushdecl (decl1);

-  pushlevel (0);
+  push_scope ();
   declare_parm_level ();

   make_decl_rtl (current_function_decl, NULL);
@@ -5639,75 +5739,56 @@ start_function (tree declspecs, tree dec
 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
@@ -5716,19 +5797,21 @@ store_parm_decls_newstyle (tree fndecl,
 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))
@@ -5740,17 +5823,18 @@ store_parm_decls_oldstyle (tree fndecl,
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;
 	    }
@@ -5758,7 +5842,7 @@ store_parm_decls_oldstyle (tree fndecl,
 	     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);
@@ -5773,9 +5857,9 @@ store_parm_decls_oldstyle (tree fndecl,
 	  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;
@@ -5785,17 +5869,21 @@ store_parm_decls_oldstyle (tree fndecl,
   /* 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.
@@ -5817,7 +5905,6 @@ store_parm_decls_oldstyle (tree fndecl,
     {
       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))
@@ -5827,7 +5914,6 @@ store_parm_decls_oldstyle (tree fndecl,
 	    last = TREE_PURPOSE (parm);
 	    DECL_WEAK (last) = 0;
 	  }
-      current_scope->parms_last = last;
       TREE_CHAIN (last) = 0;
     }

@@ -5877,7 +5963,7 @@ store_parm_decls_oldstyle (tree fndecl,

 		  if (pedantic)
 		    {
-		      pedwarn ("promoted argument \"%D\" "
+		      pedwarn ("promoted argument '%D' "
 			       "doesn't match prototype", parm);
 		      pedwarn ("%Hprototype declaration",
 			       &current_function_prototype_locus);
@@ -5885,7 +5971,7 @@ store_parm_decls_oldstyle (tree fndecl,
 		}
 	      else
 		{
-		  error ("argument \"%D\" doesn't match prototype", parm);
+		  error ("argument '%D' doesn't match prototype", parm);
 		  error ("%Hprototype declaration",
 			 &current_function_prototype_locus);
 		}
@@ -5947,26 +6033,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);
@@ -6014,17 +6100,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
@@ -6168,7 +6254,7 @@ c_expand_body (tree fndecl)
 void
 check_for_loop_decls (void)
 {
-  tree t;
+  struct c_binding *b;

   if (!flag_isoc99)
     {
@@ -6192,35 +6278,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));
+      tree id = b->id;
+      tree decl = b->decl;

- 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)));
- }
- }
+ if (!id)
+ continue;


- 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);
+ 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);
+ }
}
}

@@ -6373,16 +6462,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;
 }

@@ -6393,14 +6478,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).  */
@@ -6447,178 +6529,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);
-
- /* Clean up. */
- free (vec);
- }
-}
+ tree t;


-/* Reset the parser's state in preparation for a new file.  */
+  /* We don't want to do this if generating a PCH.  */
+  if (pch_file)
+    return;

-void
-c_reset_state (void)
-{
-  tree link;
-  tree file_scope_decl;
+  /* 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)));

- /* 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"
===================================================================
Index: c-lang.c
--- c-lang.c 4 Feb 2004 19:15:16 -0000 1.121
+++ c-lang.c 20 Mar 2004 08:40:29 -0000
@@ -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

===================================================================
Index: c-objc-common.c
--- c-objc-common.c	14 Mar 2004 22:26:00 -0000	1.41
+++ c-objc-common.c	20 Mar 2004 08:40:29 -0000
@@ -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;

@@ -236,10 +236,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 ();
===================================================================
Index: c-opts.c
--- c-opts.c	4 Mar 2004 02:39:37 -0000	1.107
+++ c-opts.c	20 Mar 2004 08:40:29 -0000
@@ -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();
+ if (num_in_fnames > 1)
+ fatal_error ("sorry, inter-module analysis temporarily out of commission");


-	  /* 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 ();
-
-      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.  */
===================================================================
Index: c-parse.in
--- c-parse.in	27 Feb 2004 02:01:06 -0000	1.202
+++ c-parse.in	20 Mar 2004 08:40:29 -0000
@@ -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
}
}

-/* 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)
     {
===================================================================
Index: c-tree.h
--- c-tree.h	29 Feb 2004 23:43:20 -0000	1.141
+++ c-tree.h	20 Mar 2004 08:40:29 -0000
@@ -24,22 +24,21 @@ Software Foundation, 59 Temple Place - S

#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.  */
+
+struct c_binding;

-/* 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.
-
- 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, tre
 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 (str
 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);
@@ -312,6 +286,11 @@ extern int current_function_returns_abno
/* Nonzero means we are reading code that came from a system header file. */


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);
===================================================================
Index: c-typeck.c
--- c-typeck.c	18 Mar 2004 20:58:34 -0000	1.289
+++ c-typeck.c	20 Mar 2004 08:40:30 -0000
@@ -51,7 +51,6 @@ Software Foundation, 59 Temple Place - S
 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, i
 
 /* 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)
@@ -633,7 +631,7 @@ same_translation_unit_p (tree t1, tree t
while (t2 && TREE_CODE (t2) != TRANSLATION_UNIT_DECL)
switch (TREE_CODE_CLASS (TREE_CODE (t2)))
{
- case 'd': t2 = DECL_CONTEXT (t1); break;
+ case 'd': t2 = DECL_CONTEXT (t2); break;
case 't': t2 = TYPE_CONTEXT (t2); break;
case 'b': t2 = BLOCK_SUPERCONTEXT (t2); break;
default: abort ();
===================================================================
Index: coverage.c
--- coverage.c 14 Mar 2004 22:26:01 -0000 1.31
+++ coverage.c 20 Mar 2004 08:40:30 -0000
@@ -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;
===================================================================
Index: langhooks.c
--- langhooks.c	14 Mar 2004 22:26:06 -0000	1.60
+++ langhooks.c	20 Mar 2004 08:40:30 -0000
@@ -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.  */
===================================================================
Index: tree.c
--- tree.c	19 Mar 2004 19:36:52 -0000	1.358
+++ tree.c	20 Mar 2004 08:40:30 -0000
@@ -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;
 }
===================================================================
Index: cp/cp-lang.c
--- cp/cp-lang.c	15 Mar 2004 18:20:51 -0000	1.74
+++ cp/cp-lang.c	20 Mar 2004 08:40:32 -0000
@@ -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
@@ -408,4 +401,15 @@ cxx_initialize_diagnostics (diagnostic_c


/* 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)
+{
}
===================================================================
Index: cp/parser.c
--- cp/parser.c 19 Mar 2004 09:58:41 -0000 1.186
+++ cp/parser.c 20 Mar 2004 08:40:32 -0000
@@ -15347,7 +15347,6 @@ cp_parser_allow_gnu_extensions_p (cp_par
}


 
-
 /* 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
===================================================================
Index: objc/objc-act.c
--- objc/objc-act.c	6 Mar 2004 00:26:42 -0000	1.207
+++ objc/objc-act.c	20 Mar 2004 08:40:34 -0000
@@ -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 contex


   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 contex
       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 ();
 }
@@ -8800,8 +8780,6 @@ finish_objc (void)
       objc_ivar_chain = NULL_TREE;
       objc_implementation_context = NULL_TREE;
     }
-
-  generate_forward_declaration_to_string_table ();

/* Process the static instances here because initialization of objc_symtab
depends on them. */
===================================================================
Index: objc/objc-act.h
--- objc/objc-act.h 15 Oct 2003 00:10:27 -0000 1.20
+++ objc/objc-act.h 20 Mar 2004 08:40:34 -0000
@@ -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[OC
#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
===================================================================
Index: objc/objc-lang.c
--- objc/objc-lang.c	3 Feb 2004 11:22:41 -0000	1.40
+++ objc/objc-lang.c	20 Mar 2004 08:40:34 -0000
@@ -55,6 +55,8 @@ enum c_language_kind c_language = clk_ob
 #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_ob
 #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

===================================================================
Index: testsuite/gcc.dg/Wold-style-definition-1.c
--- testsuite/gcc.dg/Wold-style-definition-1.c 15 Sep 2003 09:31:16 -0000 1.1
+++ testsuite/gcc.dg/Wold-style-definition-1.c 20 Mar 2004 08:40:41 -0000
@@ -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) {}

===================================================================
Index: testsuite/gcc.dg/Wshadow-2.c
--- testsuite/gcc.dg/Wshadow-2.c	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/Wshadow-2.c	20 Mar 2004 08:40:41 -0000
@@ -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" } */
+}
===================================================================
Index: testsuite/gcc.dg/builtins-30.c
--- testsuite/gcc.dg/builtins-30.c	24 Jan 2004 05:27:45 -0000	1.2
+++ testsuite/gcc.dg/builtins-30.c	20 Mar 2004 08:40:41 -0000
@@ -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 nan ()
-{  /* { dg-warning "shadowing built-in" } */
+{  /* { dg-warning "shadows a built-in" } */
   return strtod ("nan", 0);
 }

 /* the right number, but the wrong type, arguments... */
 float nanf (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 nanl (foo, bar)
- const char *foo UNUSED; /* { dg-warning "shadowing built-in" } */
+ const char *foo UNUSED; /* { dg-warning "shadows a built-in" } */
int bar UNUSED;
{
return strtod ("nan", 0);
===================================================================
Index: testsuite/gcc.dg/decl-5.c
--- testsuite/gcc.dg/decl-5.c 6 Mar 2004 09:28:51 -0000 1.1
+++ testsuite/gcc.dg/decl-5.c 20 Mar 2004 08:40:41 -0000
@@ -10,7 +10,7 @@ void a()
{
void c();
c();
-} /* { dg-bogus "error" "PR c/14114" { xfail *-*-* } } */
+}


void b()
{
===================================================================
Index: testsuite/gcc.dg/local1.c
--- testsuite/gcc.dg/local1.c 18 Mar 2004 18:58:07 -0000 1.2
+++ testsuite/gcc.dg/local1.c 20 Mar 2004 08:40:41 -0000
@@ -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;
===================================================================
Index: testsuite/gcc.dg/redecl-1.c
--- testsuite/gcc.dg/redecl-1.c	11 Jan 2004 01:18:58 -0000	1.2
+++ testsuite/gcc.dg/redecl-1.c	20 Mar 2004 08:40:41 -0000
@@ -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)
===================================================================
Index: testsuite/gcc.dg/unused-4.c
--- testsuite/gcc.dg/unused-4.c	13 Nov 2003 19:40:19 -0000	1.2
+++ testsuite/gcc.dg/unused-4.c	20 Mar 2004 08:40:41 -0000
@@ -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() { }
===================================================================
Index: testsuite/gcc.dg/noncompile/incomplete-3.c
--- testsuite/gcc.dg/noncompile/incomplete-3.c 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/noncompile/incomplete-3.c 20 Mar 2004 08:40:41 -0000
@@ -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" } */
+}
===================================================================
Index: testsuite/gcc.dg/noncompile/label-1.c
--- testsuite/gcc.dg/noncompile/label-1.c 19 Jul 2003 23:32:55 -0000 1.1
+++ testsuite/gcc.dg/noncompile/label-1.c 20 Mar 2004 08:40:41 -0000
@@ -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" } */
===================================================================
Index: testsuite/gcc.dg/noncompile/label-lineno-1.c
--- testsuite/gcc.dg/noncompile/label-lineno-1.c 19 Jul 2003 23:32:55 -0000 1.3
+++ testsuite/gcc.dg/noncompile/label-lineno-1.c 20 Mar 2004 08:40:41 -0000
@@ -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++;

===================================================================
Index: testsuite/gcc.dg/noncompile/undeclared-1.c
--- testsuite/gcc.dg/noncompile/undeclared-1.c 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/noncompile/undeclared-1.c 20 Mar 2004 08:40:41 -0000
@@ -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" } */
+{
+}
===================================================================
Index: testsuite/objc.dg/naming-1.m
--- testsuite/objc.dg/naming-1.m 17 Mar 2003 20:58:44 -0000 1.2
+++ testsuite/objc.dg/naming-1.m 20 Mar 2004 08:40:42 -0000
@@ -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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]