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]

C front end: Kill IDENTIFIER_ERROR_LOCUS


IDENTIFIER_ERROR_LOCUS is used only to limit undeclared-identifier
errors to one per function.  Thus it is always NULL in a correct
program, but takes up a word in struct lang_identifier anyway.  This
patch removes it.  Instead, the first time we encounter an undeclared
identifier in a function, its IDENTIFIER_LOCAL_VALUE is set to
error_mark_node, an entry is added to the function-scope shadows list
so it gets cleared again on exit, and we don't complain if I_L_V is
already error_mark_node.

I needed "get the function-scope binding_level structure" in another
place for this patch so I pulled it out of c_make_fname_decl to its
own function.

Bootstrapped/tested on i686-linux.

zw

        * c-tree.h (struct lang_identifier): Remove error_locus field.
        (IDENTIFIER_ERROR_LOCUS): Kill.
        (record_function_scope_shadow): New prototype.
        * c-typeck.c (build_external_ref): Don't complain if
        decl is error_mark_node.  When not at file scope, bind the
        decl's local value to error_mark_node to suppress further
        warnings, instead of setting IDENTIFIER_ERROR_LOCUS.

        * c-decl.c (get_function_binding_level): New static function.
        (record_function_scope_shadow): New exported function.
        (c_make_fname_decl): Use get_function_binding_level.

===================================================================
Index: c-decl.c
--- c-decl.c	12 Mar 2003 09:54:33 -0000	1.369
+++ c-decl.c	17 Mar 2003 21:02:48 -0000
@@ -268,7 +268,8 @@ tree static_ctors, static_dtors;
 
 /* Forward declarations.  */
 
-static struct binding_level * make_binding_level	PARAMS ((void));
+static struct binding_level *make_binding_level		PARAMS ((void));
+static struct binding_level *get_function_binding_level PARAMS ((void));
 static void pop_binding_level		PARAMS ((struct binding_level **));
 static void clear_limbo_values		PARAMS ((tree));
 static int duplicate_decls		PARAMS ((tree, tree, int));
@@ -309,7 +310,6 @@ c_print_identifier (file, node, indent)
   print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
   print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
   print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
-  print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
   print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
   if (C_IS_RESERVED_WORD (node))
     {
@@ -360,6 +360,17 @@ make_binding_level ()
     return (struct binding_level *) ggc_alloc (sizeof (struct binding_level));
 }
 
+/* Return the outermost binding level for the current function.  */
+static struct binding_level *
+get_function_binding_level ()
+{
+  struct binding_level *b = current_binding_level;
+
+  while (b->level_chain->parm_flag == 0)
+    b = b->level_chain;
+  return b;
+}
+
 /* Remove a binding level from a list and add it to the level chain.  */
 
 static void
@@ -2016,6 +2027,17 @@ pushdecl (x)
   return x;
 }
 
+/* Record that the local value of NAME is shadowed at function scope.
+   This is used by build_external_ref in c-typeck.c.  */
+void
+record_function_scope_shadow (name)
+     tree name;
+{
+  struct binding_level *b = get_function_binding_level ();
+  b->shadowed = tree_cons (name, IDENTIFIER_LOCAL_VALUE (name),
+			   b->shadowed);
+}
+
 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate.  */
 
 tree
@@ -2557,11 +2579,8 @@ c_make_fname_decl (id, type_dep)
   if (current_function_decl)
     {
       /* Add the decls to the outermost block.  */
-      struct binding_level *b = current_binding_level;
-      struct binding_level *old = b;
-      while (b->level_chain->parm_flag == 0)
-	b = b->level_chain;
-      current_binding_level = b;
+      struct binding_level *old = current_binding_level;
+      current_binding_level = get_function_binding_level ();
       pushdecl (decl);
       current_binding_level = old;
     }	
===================================================================
Index: c-tree.h
--- c-tree.h	8 Mar 2003 21:12:21 -0000	1.111
+++ c-tree.h	17 Mar 2003 21:02:50 -0000
@@ -41,7 +41,6 @@ struct lang_identifier GTY(())
   tree local_value;
   tree label_value;
   tree implicit_decl;
-  tree error_locus;
   tree limbo_value;
 };
 
@@ -91,10 +90,6 @@ struct lang_decl GTY(())
    has had one at any point in this compilation.  */
 #define IDENTIFIER_IMPLICIT_DECL(NODE)	\
   (((struct lang_identifier *) (NODE))->implicit_decl)
-/* This is the last function in which we printed an "undefined variable"
-   message for this identifier.  Value is a FUNCTION_DECL or null.  */
-#define IDENTIFIER_ERROR_LOCUS(NODE)	\
-  (((struct lang_identifier *) (NODE))->error_locus)
 
 /* In identifiers, C uses the following fields in a special way:
    TREE_PUBLIC        to record that there was a previous local extern decl.
@@ -226,6 +221,7 @@ extern void push_label_level            
 extern void push_parm_decl                      PARAMS ((tree));
 extern tree pushdecl_top_level                  PARAMS ((tree));
 extern void pushtag                             PARAMS ((tree, tree));
+extern void record_function_scope_shadow	PARAMS ((tree));
 extern tree set_array_declarator_type           PARAMS ((tree, tree, int));
 extern tree shadow_label                        PARAMS ((tree));
 extern void shadow_tag                          PARAMS ((tree));
===================================================================
Index: c-typeck.c
--- c-typeck.c	16 Mar 2003 13:54:22 -0000	1.225
+++ c-typeck.c	17 Mar 2003 21:02:51 -0000
@@ -1412,6 +1412,11 @@ build_external_ref (id, fun)
 	}
       else
 	{
+	  /* Don't complain about something that's already been
+	     complained about.  */
+	  if (decl == error_mark_node)
+	    return error_mark_node;
+
 	  /* Reference to undeclared variable, including reference to
 	     builtin outside of function-call context.  */
 	  if (current_function_decl == 0)
@@ -1419,21 +1424,22 @@ build_external_ref (id, fun)
 		   IDENTIFIER_POINTER (id));
 	  else
 	    {
-	      if (IDENTIFIER_GLOBAL_VALUE (id) != error_mark_node
-		  || IDENTIFIER_ERROR_LOCUS (id) != current_function_decl)
-		{
-		  error ("`%s' undeclared (first use in this function)",
-			 IDENTIFIER_POINTER (id));
+	      error ("`%s' undeclared (first use in this function)",
+		     IDENTIFIER_POINTER (id));
 
-		  if (! undeclared_variable_notice)
-		    {
-		      error ("(Each undeclared identifier is reported only once");
-		      error ("for each function it appears in.)");
-		      undeclared_variable_notice = 1;
-		    }
+	      if (! undeclared_variable_notice)
+		{
+		  error ("(Each undeclared identifier is reported only once");
+		  error ("for each function it appears in.)");
+		  undeclared_variable_notice = 1;
 		}
-	      IDENTIFIER_GLOBAL_VALUE (id) = error_mark_node;
-	      IDENTIFIER_ERROR_LOCUS (id) = current_function_decl;
+
+	      /* Set IDENTIFIER_LOCAL_VALUE (id) to error_mark_node and
+		 add a function-scope shadow entry which will undo that.
+		 This suppresses further warnings about this undeclared
+		 identifier in this function.  */
+	      record_function_scope_shadow (id);
+	      IDENTIFIER_LOCAL_VALUE (id) = error_mark_node;
 	    }
 	  return error_mark_node;
 	}


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