I discovered template typedef access checking was more expensive than it need be. The call of get_types_needed_access_check in the FOR_EACH_VEC_SAFE_ELT is the moral equivalent of

  for (size_t pos = 0; pos != strlen (string); pos++)'

Let's not do that.

nathan

--
Nathan Sidwell
2020-05-13  Nathan Sidwell  <nat...@acm.org>

	* pt.c (perform_typedefs_access_check): Cache expensively
	calculated object references.
	(check_auto_in_tmpl_args): Just assert we do not get unexpected
	nodes, rather than silently do nothing.
	(append_type_to_template_for_access): Likewise, cache expensie
	object reference.

diff --git i/gcc/cp/pt.c w/gcc/cp/pt.c
index a732ced2d8d..a36f603761c 100644
--- i/gcc/cp/pt.c
+++ w/gcc/cp/pt.c
@@ -11521,26 +11512,28 @@ perform_typedefs_access_check (tree tmpl, tree targs)
 	  && TREE_CODE (tmpl) != FUNCTION_DECL))
     return;
 
-  FOR_EACH_VEC_SAFE_ELT (get_types_needing_access_check (tmpl), i, iter)
-    {
-      tree type_decl = iter->typedef_decl;
-      tree type_scope = iter->context;
-
-      if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
-	continue;
+  if (vec<qualified_typedef_usage_t, va_gc> *tdefs
+      = get_types_needing_access_check (tmpl))
+    FOR_EACH_VEC_ELT (*tdefs, i, iter)
+      {
+	tree type_decl = iter->typedef_decl;
+	tree type_scope = iter->context;
 
-      if (uses_template_parms (type_decl))
-	type_decl = tsubst (type_decl, targs, tf_error, NULL_TREE);
-      if (uses_template_parms (type_scope))
-	type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
+	if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
+	  continue;
 
-      /* Make access check error messages point to the location
-         of the use of the typedef.  */
-      iloc_sentinel ils (iter->locus);
-      perform_or_defer_access_check (TYPE_BINFO (type_scope),
-				     type_decl, type_decl,
-				     tf_warning_or_error);
-    }
+	if (uses_template_parms (type_decl))
+	  type_decl = tsubst (type_decl, targs, tf_error, NULL_TREE);
+	if (uses_template_parms (type_scope))
+	  type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
+
+	/* Make access check error messages point to the location
+	   of the use of the typedef.  */
+	iloc_sentinel ils (iter->locus);
+	perform_or_defer_access_check (TYPE_BINFO (type_scope),
+				       type_decl, type_decl,
+				       tf_warning_or_error);
+      }
 }
 
 static tree
@@ -29225,25 +29218,13 @@ check_auto_in_tmpl_args (tree tmpl, tree args)
 vec<qualified_typedef_usage_t, va_gc> *
 get_types_needing_access_check (tree t)
 {
-  tree ti;
-  vec<qualified_typedef_usage_t, va_gc> *result = NULL;
-
-  if (!t || t == error_mark_node)
-    return NULL;
-
-  if (!(ti = get_template_info (t)))
-    return NULL;
+  gcc_checking_assert ((CLASS_TYPE_P (t) || TREE_CODE (t) == FUNCTION_DECL));
+  
+  if (tree ti = get_template_info (t))
+    if (TI_TEMPLATE (ti))
+      return TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
 
-  if (CLASS_TYPE_P (t)
-      || TREE_CODE (t) == FUNCTION_DECL)
-    {
-      if (!TI_TEMPLATE (ti))
-	return NULL;
-
-      result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
-    }
-
-  return result;
+  return NULL;
 }
 
 /* Append the typedef TYPE_DECL used in template T to a list of typedefs
@@ -29328,9 +29309,11 @@ append_type_to_template_for_access_check (tree templ,
   gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
 
   /* Make sure we don't append the type to the template twice.  */
-  FOR_EACH_VEC_SAFE_ELT (get_types_needing_access_check (templ), i, iter)
-    if (iter->typedef_decl == type_decl && scope == iter->context)
-      return;
+  if (vec<qualified_typedef_usage_t, va_gc> *tdefs
+      = get_types_needing_access_check (templ))
+    FOR_EACH_VEC_ELT (*tdefs, i, iter)
+      if (iter->typedef_decl == type_decl && scope == iter->context)
+	return;
 
   append_type_to_template_for_access_check_1 (templ, type_decl,
 					      scope, location);

Reply via email to