Kill interface_unknown/only globals

Zack Weinberg zack@codesourcery.com
Sat Sep 11 00:24:00 GMT 2004


The lexer patch I'm working on causes the parser's position in the
token stream to become desynchronized from the position set by
the file_change hook.  There's already logic to cope with this by
updating source_position from the position stored in each token; that
works fine except for #pragma interface/implementation, which rely on
other globals, interface_unknown and interface_only.

This patch extirpates those globals, replacing all uses with lookups
in the c_fileinfo splay tree; this uses source_position (via
input_filename) and is therefore accurate.  Since a splay tree is
used, lookups are cheap except at file boundaries; and none of this
code is on critical paths anyway.

I had to make the initialization of the splay tree be on-demand,
because the C++ front end now calls get_fileinfo before init_c_lex,
and I didn't want to mess with initialization ordering more than
absolutely necessary.

start_cleanup_fn used to reset these globals to "no #pragma int/impl
in effect" around the generation of a static-object destructor-caller
function.  I talked to Mark about this and we concluded that this was
not only unnecessary, but wrong (the function itself cannot be
affected, and templates instantiated from within it should get the
same #pragma int/impl treatment as templates instantiated from
wherever we were when we decided we needed a static-object
destructor-caller).  So it's been nuked.

Bootstrapped i686-linux, no regressions.  The test suite does test
#pragma interface, albeit only lightly.  Please let me know if there
are problems.

zw

        * c-common.h (struct c_fileinfo): Comment moved here from cp-tree.h.
        (extract_interface_info): Delete prototype.
        * c-decl.c (extract_interface_info): Delete stub.
        * c-lex.c (get_fileinfo): Initialize file_info_tree here, if
        it's not already been done ...
        (init_c_lex): ... not here.
        (fe_file_change): Don't call extract_interface_info.
cp:
        * cp-tree.h (interface_only, interface_unknown): Delete declarations;
        comment explaining them moved to c-common.h.
        * lex.c (interface_only, interface_unknown, extract_interface_info):
        Delete definitions.
        (cxx_finish): Don't reset interface_unknown.
        (handle_pragma_interface): Don't set interface_only and
        interface_unknown; just the like-named fields in finfo.
        (handle_pragma_implementation): Adjust comment.
        * decl2.c (cp_finish_file): Don't reset interface_only and
        interface_unknown.
        * method.c (synthesize_method): Don't reset interface_unknown or
        call extract_interface_info.
        * pt.c (pop_tinst_level): Don't call extract_interface_info.
        * decl.c (start_cleanup_fn): Don't save or restore interface_only
        and interface_unknown.
        (make_rtl_for_nonlocal_decl): Call get_fileinfo on input_filename
        and use the result instead of the interface_only/interface_unknown
        globals.
        (start_preparsed_function): Likewise.
        * lex.c (cxx_make_type): Likewise.
        * semantics.c (begin_class_definition): Likewise.
        (expand_body): Don't call extract_interface_info.


===================================================================
Index: c-common.h
--- c-common.h	3 Sep 2004 19:04:05 -0000	1.263
+++ c-common.h	10 Sep 2004 23:36:16 -0000
@@ -820,10 +820,6 @@ extern tree decl_constant_value (tree);
 /* Handle increment and decrement of boolean types.  */
 extern tree boolean_increment (enum tree_code, tree);
 
-/* Hook currently used only by the C++ front end to reset internal state
-   after entering or leaving a header file.  */
-extern void extract_interface_info (void);
-
 extern int case_compare (splay_tree_key, splay_tree_key);
 
 extern tree c_add_case_label (splay_tree, tree, tree, tree, tree);
@@ -859,7 +855,14 @@ extern GTY(()) int pending_lang_change;
 struct c_fileinfo
 {
   int time;	/* Time spent in the file.  */
-  short interface_only;		/* Flags - used only by C++ */
+
+  /* Flags used only by C++.
+     INTERFACE_ONLY nonzero means that we are in an "interface" section
+     of the compiler.  INTERFACE_UNKNOWN nonzero means we cannot trust
+     the value of INTERFACE_ONLY.  If INTERFACE_UNKNOWN is zero and
+     INTERFACE_ONLY is zero, it means that we are responsible for
+     exporting definitions that others might need.  */
+  short interface_only;
   short interface_unknown;
 };
 
===================================================================
Index: c-decl.c
--- c-decl.c	10 Sep 2004 23:09:59 -0000	1.578
+++ c-decl.c	10 Sep 2004 23:36:16 -0000
@@ -6591,13 +6591,6 @@ anon_aggr_type_p (tree ARG_UNUSED (node)
   return 0;
 }
 
-/* Dummy function in place of callback used by C++.  */
-
-void
-extract_interface_info (void)
-{
-}
-
 /* Return the global value of T as a symbol.  */
 
 tree
===================================================================
Index: c-lex.c
--- c-lex.c	7 Sep 2004 10:18:58 -0000	1.235
+++ c-lex.c	10 Sep 2004 23:36:16 -0000
@@ -82,10 +82,8 @@ init_c_lex (void)
   struct cpp_callbacks *cb;
   struct c_fileinfo *toplevel;
 
-  /* Set up filename timing.  Must happen before cpp_read_main_file.  */
-  file_info_tree = splay_tree_new ((splay_tree_compare_fn)strcmp,
-				   0,
-				   (splay_tree_delete_value_fn)free);
+  /* The get_fileinfo data structure must be initialized before
+     cpp_read_main_file is called.  */
   toplevel = get_fileinfo ("<top level>");
   if (flag_detailed_statistics)
     {
@@ -118,6 +116,11 @@ get_fileinfo (const char *name)
   splay_tree_node n;
   struct c_fileinfo *fi;
 
+  if (!file_info_tree)
+    file_info_tree = splay_tree_new ((splay_tree_compare_fn)strcmp,
+				     0,
+				     (splay_tree_delete_value_fn)free);
+
   n = splay_tree_lookup (file_info_tree, (splay_tree_key) name);
   if (n)
     return (struct c_fileinfo *) n->value;
@@ -266,9 +269,6 @@ fe_file_change (const struct line_map *n
   input_filename = new_map->to_file;
   input_line = new_map->to_line;
 #endif
-
-  /* Hook for C++.  */
-  extract_interface_info ();
 }
 
 static void
===================================================================
Index: cp/cp-tree.h
--- cp/cp-tree.h	10 Sep 2004 11:12:11 -0000	1.1045
+++ cp/cp-tree.h	10 Sep 2004 23:36:16 -0000
@@ -813,13 +813,6 @@ struct language_function GTY(())
 #define error_operand_p(NODE)					\
   ((NODE) == error_mark_node 					\
    || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
-
-/* INTERFACE_ONLY nonzero means that we are in an "interface"
-   section of the compiler.  INTERFACE_UNKNOWN nonzero means
-   we cannot trust the value of INTERFACE_ONLY.  If INTERFACE_UNKNOWN
-   is zero and INTERFACE_ONLY is zero, it means that we are responsible
-   for exporting definitions that others might need.  */
-extern int interface_only, interface_unknown;
 
 /* C++ language-specific tree codes.  */
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
===================================================================
Index: cp/decl.c
--- cp/decl.c	10 Sep 2004 22:11:48 -0000	1.1292
+++ cp/decl.c	10 Sep 2004 23:36:16 -0000
@@ -4599,10 +4599,11 @@ make_rtl_for_nonlocal_decl (tree decl, t
     {
       /* Fool with the linkage of static consts according to #pragma
 	 interface.  */
-      if (!interface_unknown && !TREE_PUBLIC (decl))
+      struct c_fileinfo *finfo = get_fileinfo (input_filename);
+      if (!finfo->interface_unknown && !TREE_PUBLIC (decl))
 	{
 	  TREE_PUBLIC (decl) = 1;
-	  DECL_EXTERNAL (decl) = interface_only;
+	  DECL_EXTERNAL (decl) = finfo->interface_only;
 	}
 
       defer_p = 1;
@@ -5060,8 +5061,6 @@ static GTY(()) int start_cleanup_cnt;
 static tree
 start_cleanup_fn (void)
 {
-  int old_interface_only = interface_only;
-  int old_interface_unknown = interface_unknown;
   char name[32];
   tree parmtypes;
   tree fntype;
@@ -5072,9 +5071,6 @@ start_cleanup_fn (void)
   /* No need to mangle this.  */
   push_lang_context (lang_name_c);
 
-  interface_only = 0;
-  interface_unknown = 1;
-
   /* Build the parameter-types.  */
   parmtypes = void_list_node;
   /* Functions passed to __cxa_atexit take an additional parameter.
@@ -5114,9 +5110,6 @@ start_cleanup_fn (void)
   pushdecl (fndecl);
   start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
 
-  interface_unknown = old_interface_unknown;
-  interface_only = old_interface_only;
-
   pop_lang_context ();
 
   return current_function_decl;
@@ -9698,6 +9691,7 @@ start_preparsed_function (tree decl1, tr
   int doing_friend = 0;
   struct cp_binding_level *bl;
   tree current_function_parms;
+  struct c_fileinfo *finfo = get_fileinfo (input_filename);
 
   /* Sanity check.  */
   gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
@@ -9924,7 +9918,7 @@ start_preparsed_function (tree decl1, tr
   /* If this function belongs to an interface, it is public.
      If it belongs to someone else's interface, it is also external.
      This only affects inlines and template instantiations.  */
-  else if (interface_unknown == 0
+  else if (finfo->interface_unknown == 0
 	   && ! DECL_TEMPLATE_INSTANTIATION (decl1))
     {
       if (DECL_DECLARED_INLINE_P (decl1)
@@ -9932,7 +9926,7 @@ start_preparsed_function (tree decl1, tr
 	  || processing_template_decl)
 	{
 	  DECL_EXTERNAL (decl1)
-	    = (interface_only
+	    = (finfo->interface_only
 	       || (DECL_DECLARED_INLINE_P (decl1)
 		   && ! flag_implement_inlines
 		   && !DECL_VINDEX (decl1)));
@@ -9950,14 +9944,15 @@ start_preparsed_function (tree decl1, tr
       if (!DECL_EXTERNAL (decl1))
 	mark_needed (decl1);
     }
-  else if (interface_unknown && interface_only
+  else if (finfo->interface_unknown && finfo->interface_only
 	   && ! DECL_TEMPLATE_INSTANTIATION (decl1))
     {
       /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
-	 interface, we will have interface_only set but not
-	 interface_known.  In that case, we don't want to use the normal
-	 heuristics because someone will supply a #pragma implementation
-	 elsewhere, and deducing it here would produce a conflict.  */
+	 interface, we will have both finfo->interface_unknown and
+	 finfo->interface_only set.  In that case, we don't want to
+	 use the normal heuristics because someone will supply a
+	 #pragma implementation elsewhere, and deducing it here would
+	 produce a conflict.  */
       comdat_linkage (decl1);
       DECL_EXTERNAL (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
===================================================================
Index: cp/decl2.c
--- cp/decl2.c	10 Sep 2004 11:12:13 -0000	1.745
+++ cp/decl2.c	10 Sep 2004 23:36:16 -0000
@@ -2750,9 +2750,6 @@ cp_finish_file (void)
   input_line -= 1;
 #endif
 
-  interface_unknown = 1;
-  interface_only = 0;
-
   /* We now have to write out all the stuff we put off writing out.
      These include:
 
===================================================================
Index: cp/lex.c
--- cp/lex.c	9 Sep 2004 17:11:18 -0000	1.343
+++ cp/lex.c	10 Sep 2004 23:36:16 -0000
@@ -82,12 +82,6 @@ struct impl_files
 static struct impl_files *impl_file_chain;
 
 
-int interface_only;		/* whether or not current file is only for
-				   interface definitions.  */
-int interface_unknown;		/* whether or not we know this class
-				   to behave according to #pragma interface.  */
-
-
 void
 cxx_finish (void)
 {
@@ -360,8 +354,6 @@ cxx_init (void)
   TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
   ridpointers[RID_NULL] = null_node;
 
-  interface_unknown = 1;
-
   /* The fact that G++ uses COMDAT for many entities (inline
      functions, template instantiations, virtual tables, etc.) mean
      that it is fundamentally unreliable to try to make decisions
@@ -387,19 +379,6 @@ cxx_init (void)
   return true;
 }
 
-/* Helper function to load global variables with interface
-   information.  */
-
-void
-extract_interface_info (void)
-{
-  struct c_fileinfo *finfo;
-
-  finfo = get_fileinfo (input_filename);
-  interface_only = finfo->interface_only;
-  interface_unknown = finfo->interface_unknown;
-}
-
 /* Return nonzero if S is not considered part of an
    INTERFACE/IMPLEMENTATION pair.  Otherwise, return 0.  */
 
@@ -504,14 +483,11 @@ handle_pragma_interface (cpp_reader* dfi
 	main_input_filename = input_filename;
     }
 
-  interface_only = interface_strcmp (main_filename);
+  finfo->interface_only = interface_strcmp (main_filename);
   /* If MULTIPLE_SYMBOL_SPACES is set, we cannot assume that we can see
      a definition in another file.  */
-  if (!MULTIPLE_SYMBOL_SPACES || !interface_only)
-    interface_unknown = 0;
-
-  finfo->interface_only = interface_only;
-  finfo->interface_unknown = interface_unknown;
+  if (!MULTIPLE_SYMBOL_SPACES || !finfo->interface_only)
+    finfo->interface_unknown = 0;
 }
 
 /* Note that we have seen a #pragma implementation for the key MAIN_FILENAME.
@@ -519,8 +495,9 @@ handle_pragma_interface (cpp_reader* dfi
    in older compilers and it seems reasonable to allow it in the headers
    themselves, too.  It only needs to precede the matching #p interface.
 
-   We don't touch interface_only or interface_unknown; the user must specify
-   a matching #p interface for this to have any effect.  */
+   We don't touch finfo->interface_only or finfo->interface_unknown;
+   the user must specify a matching #p interface for this to have
+   any effect.  */
 
 static void
 handle_pragma_implementation (cpp_reader* dfile ATTRIBUTE_UNUSED )
@@ -791,8 +768,9 @@ cxx_make_type (enum tree_code code)
   /* Set up some flags that give proper default behavior.  */
   if (IS_AGGR_TYPE_CODE (code))
     {
-      SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
-      CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
+      struct c_fileinfo *finfo = get_fileinfo (input_filename);
+      SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, finfo->interface_unknown);
+      CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
     }
   else
     /* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits.  But,
===================================================================
Index: cp/method.c
--- cp/method.c	30 Aug 2004 15:28:48 -0000	1.314
+++ cp/method.c	10 Sep 2004 23:36:16 -0000
@@ -725,7 +725,6 @@ synthesize_method (tree fndecl)
      function.  */
   DECL_SOURCE_LOCATION (fndecl) = input_location;
 
-  interface_unknown = 1;
   start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
   stmt = begin_function_body ();
 
@@ -755,7 +754,6 @@ synthesize_method (tree fndecl)
   finish_function_body (stmt);
   expand_or_defer_fn (finish_function (0));
 
-  extract_interface_info ();
   if (! context)
     pop_from_top_level ();
   else if (nested)
===================================================================
Index: cp/pt.c
--- cp/pt.c	31 Aug 2004 17:39:55 -0000	1.919
+++ cp/pt.c	10 Sep 2004 23:36:17 -0000
@@ -4966,8 +4966,6 @@ pop_tinst_level (void)
   /* Restore the filename and line number stashed away when we started
      this instantiation.  */
   input_location = TINST_LOCATION (old);
-  extract_interface_info ();
-  
   current_tinst_level = TREE_CHAIN (old);
   --tinst_depth;
   ++tinst_level_tick;
===================================================================
Index: cp/semantics.c
--- cp/semantics.c	10 Sep 2004 11:12:14 -0000	1.433
+++ cp/semantics.c	10 Sep 2004 23:36:17 -0000
@@ -2106,9 +2106,10 @@ begin_class_definition (tree t)
      before.  */
   if (! TYPE_ANONYMOUS_P (t))
     {
-      CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
+      struct c_fileinfo *finfo = get_fileinfo (input_filename);
+      CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
       SET_CLASSTYPE_INTERFACE_UNKNOWN_X
-	(t, interface_unknown);
+	(t, finfo->interface_unknown);
     }
   reset_specialization();
   
@@ -2897,8 +2898,6 @@ expand_body (tree fn)
 
   current_function_decl = saved_function;
 
-  extract_interface_info ();
-
   if (DECL_CLONED_FUNCTION_P (fn))
     {
       /* If this is a clone, go through the other clones now and mark



More information about the Gcc-patches mailing list