https://gcc.gnu.org/g:b66fd30e4b3943460a6cc030491043502bd3b65d

commit r17-1384-gb66fd30e4b3943460a6cc030491043502bd3b65d
Author: Patrick Palka <[email protected]>
Date:   Fri Jun 5 17:05:26 2026 -0400

    c++/modules: some dependent ADL fixes
    
    When looking at the stream-in performance regression PR c++/125334
    (caused by the dependent ADL patch r16-6311) I spotted some issues with
    add_dependent_adl_entities:
    
      1. Fix memory leak in add_dependent_adl_entities when it exits early.
      2. Only consider type-dependent calls/operator expressions.
      3. Fix early exit test for when all args are type-dependent.
      4. Add assert verifying recursive name lookup does not happen with
         tentative/dependent ADL since it avoids type completion.
    
    Plugging the memory leak reduces max memory usage by 3% when building
    the std module, besides that no significant effect towards the
    regression.
    
    gcc/cp/ChangeLog:
    
            * module.cc (dep_adl_info::args): Initializer to nullptr
            instead of immediately allocating.
            (depset::hash::add_dependent_adl_entities): Exit early
            for non-type-dependent calls and operator expressions.
            Only allocate dep_adl_info::args if we're not exiting early.
            Correct all-type-dependent args test.
            * name-lookup.cc (name_lookup::preserve_state): Replace
            propagation of tentative flag with assert that it's not
            set.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/module.cc      | 30 ++++++++++++++++++++++--------
 gcc/cp/name-lookup.cc |  3 ++-
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 1cfaa57adc35..223ab33d5454 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2645,7 +2645,7 @@ public:
       /* If not ERROR_MARK, a rewrite candidate for this operator.  */
       tree_code rewrite = ERROR_MARK;
       /* Argument list for the call.  */
-      vec<tree, va_gc>* args = make_tree_vector ();
+      vec<tree, va_gc>* args = nullptr;
     };
     vec<dep_adl_info> dep_adl_entity_list;
 
@@ -15258,10 +15258,12 @@ depset::hash::add_dependent_adl_entities (tree expr)
     return;
 
   dep_adl_info info;
+  auto_vec<tree, 3> args;
   switch (TREE_CODE (expr))
     {
     case CALL_EXPR:
-      if (!KOENIG_LOOKUP_P (expr))
+      if (!KOENIG_LOOKUP_P (expr)
+         || !type_dependent_expression_p_push (expr))
        return;
       info.name = CALL_EXPR_FN (expr);
       if (!info.name)
@@ -15273,7 +15275,7 @@ depset::hash::add_dependent_adl_entities (tree expr)
       if (!identifier_p (info.name))
        info.name = OVL_NAME (info.name);
       for (int ix = 0; ix < call_expr_nargs (expr); ix++)
-       vec_safe_push (info.args, CALL_EXPR_ARG (expr, ix));
+       args.safe_push (CALL_EXPR_ARG (expr, ix));
       break;
 
     case LE_EXPR:
@@ -15310,10 +15312,12 @@ depset::hash::add_dependent_adl_entities (tree expr)
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
     overloadable_expr:
+      if (!type_dependent_expression_p_push (expr))
+       return;
       info.name = ovl_op_identifier (TREE_CODE (expr));
       gcc_checking_assert (tree_operand_length (expr) == 2);
-      vec_safe_push (info.args, TREE_OPERAND (expr, 0));
-      vec_safe_push (info.args, TREE_OPERAND (expr, 1));
+      args.safe_push (TREE_OPERAND (expr, 0));
+      args.safe_push (TREE_OPERAND (expr, 1));
       break;
 
     default:
@@ -15322,11 +15326,21 @@ depset::hash::add_dependent_adl_entities (tree expr)
 
   /* If all arguments are type-dependent we don't need to do
      anything further, we won't find new entities.  */
-  processing_template_decl_sentinel ptds;
-  ++processing_template_decl;
-  if (!any_type_dependent_arguments_p (info.args))
+  bool all_type_dependent = true;
+  for (tree arg : args)
+    if (!type_dependent_expression_p_push (arg))
+      {
+       all_type_dependent = false;
+       break;
+      }
+  if (all_type_dependent)
     return;
 
+  gcc_checking_assert (!info.args);
+  info.args = make_tree_vector ();
+  for (tree arg : args)
+    vec_safe_push (info.args, arg);
+
   /* We need to defer name lookup until after walking, otherwise
      we get confused by stray TREE_VISITEDs.  */
   dep_adl_entity_list.safe_push (info);
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 31ade88f75b5..e12e37c35158 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -580,7 +580,8 @@ name_lookup::preserve_state ()
            }
        }
 
-      tentative = previous->tentative;
+      /* We deliberately avoid instantiation during tentative ADL.  */
+      gcc_checking_assert (!previous->tentative);
 
       /* Unmark the outer partial lookup.  */
       if (previous->deduping)

Reply via email to