In each binding level we have a vector that we store some static-lifetime decls (inlines, generally). These are only used for namespace binding levels. At the end of compilation we then walk all the namespaces processing these statics. What's more is that we do this walk multiple times, every time the final walk instantiates more stuff.

That seems rather circuitous.

This patch replaces the per-binding-level vector with a single global vector that we can directly iterate over. Further, we when we walk it we can delete it, and thust if more things get instantiated and pushed onto it, we can see that it's been recreated on the next walk.

Committed to trunk.

nathan

--
Nathan Sidwell
2017-05-05  Nathan Sidwell  <nat...@acm.org>

	Kill per-namespace static_decls.
	* cp-tree.h (static_decls): Declare.
	(wrapup_globals_for_namespace,
	diagnose_inline_vars_for_namespace): Replace with ...
	(wrapup_namespace_globals): ... this.
	* decl.c (static_decls): Define.
	(wrapup_globals_for_namespace,
	diagnose_inline_vars_for_namespace): Replace with ...
	(wrapup_namespace_globals): ... this.
	(cxx_init_decl_processing): Initialize static_decls.
	* decl2.c (c_parse_final_cleanups): Adjust.
	* name-lookup.h (cp_binding_level): Remove static_decls member.
	* name-lookup.c (add_decl_to_level): Adjust.
	(begin_scope): Adjust.

Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 247632)
+++ cp-tree.h	(working copy)
@@ -4908,6 +4908,12 @@ extern int current_class_depth;
 /* An array of all local classes present in this translation unit, in
    declaration order.  */
 extern GTY(()) vec<tree, va_gc> *local_classes;
+
+/* in decl.c */
+
+/* An array of static vars & fns.  */
+extern GTY(()) vec<tree, va_gc> *static_decls;
+
 
 /* Here's where we control how name mangling takes place.  */
 
@@ -5899,8 +5905,7 @@ extern tree check_default_argument		(tre
 typedef int (*walk_namespaces_fn)		(tree, void *);
 extern int walk_namespaces			(walk_namespaces_fn,
 						 void *);
-extern int wrapup_globals_for_namespace		(tree, void *);
-extern int diagnose_inline_vars_for_namespace	(tree, void *);
+extern int wrapup_namespace_globals		();
 extern tree create_implicit_typedef		(tree, tree);
 extern int local_variable_p			(const_tree);
 extern tree register_dtor_fn			(tree);
Index: decl.c
===================================================================
--- decl.c	(revision 247632)
+++ decl.c	(working copy)
@@ -157,6 +157,9 @@ tree tls_aggregates;
 
 tree integer_two_node;
 
+/* vector of static decls.  */
+vec<tree, va_gc> *static_decls;
+
 /* Used only for jumps to as-yet undefined labels, since jumps to
    defined labels can have their validity checked immediately.  */
 
@@ -903,57 +906,45 @@ walk_namespaces (walk_namespaces_fn f, v
 }
 
 /* Call wrapup_globals_declarations for the globals in NAMESPACE.  */
+/* Diagnose odr-used extern inline variables without definitions
+   in the current TU.  */
 
 int
-wrapup_globals_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED)
+wrapup_namespace_globals ()
 {
-  cp_binding_level *level = NAMESPACE_LEVEL (name_space);
-  vec<tree, va_gc> *statics = level->static_decls;
-  tree *vec = statics->address ();
-  int len = statics->length ();
-
-  if (warn_unused_function)
+  if (vec<tree, va_gc> *statics = static_decls)
     {
       tree decl;
       unsigned int i;
-      FOR_EACH_VEC_SAFE_ELT (statics, i, decl)
-	if (TREE_CODE (decl) == FUNCTION_DECL
-	    && DECL_INITIAL (decl) == 0
-	    && DECL_EXTERNAL (decl)
-	    && !TREE_PUBLIC (decl)
-	    && !DECL_ARTIFICIAL (decl)
-	    && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
-	    && !TREE_NO_WARNING (decl))
-	  {
+      FOR_EACH_VEC_ELT (*statics, i, decl)
+	{
+	  if (warn_unused_function
+	      && TREE_CODE (decl) == FUNCTION_DECL
+	      && DECL_INITIAL (decl) == 0
+	      && DECL_EXTERNAL (decl)
+	      && !TREE_PUBLIC (decl)
+	      && !DECL_ARTIFICIAL (decl)
+	      && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
+	      && !TREE_NO_WARNING (decl))
 	    warning_at (DECL_SOURCE_LOCATION (decl),
 			OPT_Wunused_function,
 			"%qF declared %<static%> but never defined", decl);
-	    TREE_NO_WARNING (decl) = 1;
-	  }
-    }
-
-  /* Write out any globals that need to be output.  */
-  return wrapup_global_declarations (vec, len);
-}
 
-/* Diagnose odr-used extern inline variables without definitions
-   in the current TU.  */
-int
-diagnose_inline_vars_for_namespace (tree name_space, void *)
-{
-  cp_binding_level *level = NAMESPACE_LEVEL (name_space);
-  vec<tree, va_gc> *statics = level->static_decls;
-  tree decl;
-  unsigned int i;
-
-  FOR_EACH_VEC_SAFE_ELT (statics, i, decl)
-    if (VAR_P (decl)
-	&& DECL_EXTERNAL (decl)
-	&& DECL_INLINE_VAR_P (decl)
-	&& DECL_ODR_USED (decl))
-      error_at (DECL_SOURCE_LOCATION (decl),
-		"odr-used inline variable %qD is not defined", decl);
+	  if (VAR_P (decl)
+	      && DECL_EXTERNAL (decl)
+	      && DECL_INLINE_VAR_P (decl)
+	      && DECL_ODR_USED (decl))
+	    error_at (DECL_SOURCE_LOCATION (decl),
+		      "odr-used inline variable %qD is not defined", decl);
+	}
 
+      /* Clear out the list, so we don't rescan next time.  */
+      static_decls = NULL;
+
+      /* Write out any globals that need to be output.  */
+      return wrapup_global_declarations (statics->address (),
+					 statics->length ());
+    }
   return 0;
 }
 
@@ -4097,6 +4088,9 @@ cxx_init_decl_processing (void)
 
   integer_two_node = build_int_cst (NULL_TREE, 2);
 
+  /* Guess at the initial static decls size.  */
+  vec_alloc (static_decls, 500);
+
   record_builtin_type (RID_BOOL, "bool", boolean_type_node);
   truthvalue_type_node = boolean_type_node;
   truthvalue_false_node = boolean_false_node;
Index: decl2.c
===================================================================
--- decl2.c	(revision 247632)
+++ decl2.c	(working copy)
@@ -4724,7 +4724,7 @@ c_parse_final_cleanups (void)
 	    }
 	}
 
-      if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0))
+      if (wrapup_namespace_globals ())
 	reconsider = true;
 
       /* Static data members are just like namespace-scope globals.  */
@@ -4749,8 +4749,6 @@ c_parse_final_cleanups (void)
     }
   while (reconsider);
 
-  walk_namespaces (diagnose_inline_vars_for_namespace, /*data=*/0);
-
   lower_var_init ();
 
   generate_mangling_aliases ();
Index: name-lookup.c
===================================================================
--- name-lookup.c	(revision 247632)
+++ name-lookup.c	(working copy)
@@ -94,7 +94,7 @@ add_decl_to_level (tree decl, cp_binding
 		&& (!TREE_PUBLIC (decl)
 		    || decl_anon_ns_mem_p (decl)
 		    || DECL_DECLARED_INLINE_P (decl))))
-	  vec_safe_push (b->static_decls, decl);
+	  vec_safe_push (static_decls, decl);
     }
 }
 
@@ -2162,9 +2162,6 @@ begin_scope (scope_kind kind, tree entit
 
     case sk_namespace:
       NAMESPACE_LEVEL (entity) = scope;
-      vec_alloc (scope->static_decls,
-		 (DECL_NAME (entity) == std_identifier
-		  || DECL_NAME (entity) == global_identifier) ? 200 : 10);
       break;
 
     default:
Index: name-lookup.h
===================================================================
--- name-lookup.h	(revision 247632)
+++ name-lookup.h	(working copy)
@@ -191,9 +191,6 @@ struct GTY(()) cp_binding_level {
   /* A chain of NAMESPACE_DECL nodes.  */
   tree namespaces;
 
-  /* An array of static functions and variables (for namespaces only) */
-  vec<tree, va_gc> *static_decls;
-
   /* A list of USING_DECL nodes.  */
   tree usings;
 

Reply via email to