https://gcc.gnu.org/g:bb26018080699913959526c89ce2e618c97768ec
commit r17-1791-gbb26018080699913959526c89ce2e618c97768ec Author: Jason Merrill <[email protected]> Date: Tue Jun 23 17:28:36 2026 -0400 c++/modules: dependent ADL laziness [PR125334] I was digging into modules for another bug and remembered an earlier thought that a possible further improvement for this PR would be to just mark the ADL functions as reachable, not actual dependencies of the current entity. This turns out to be as simple as removing the call to add_dependency; the test still passes, but now the ADL functions are loaded lazily because they have their own dependency groups instead of being tightly coupled to the call site. This provides a speed-up of about 24% on the performance test in this PR with my debugging build of trunk. PR c++/125334 gcc/cp/ChangeLog: * module.cc (depset::hash::find_dependencies): Don't add_dependency dependent ADL functions. gcc/testsuite/ChangeLog: * g++.dg/modules/adl-12_b.C: Check for lazy loading. Diff: --- gcc/cp/module.cc | 6 ++++-- gcc/testsuite/g++.dg/modules/adl-12_b.C | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 17390356b09c..060d2ba344c7 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -15730,7 +15730,9 @@ depset::hash::find_dependencies (module_state *module) tree lookup = lookup_arg_dependent (info.name, NULL_TREE, info.args, true); for (tree fn : lkp_range (lookup)) - add_dependency (make_dependency (fn, EK_DECL)); + /* We don't need to add_dependency, just have + make_dependency build an ADL binding. */ + make_dependency (fn, EK_DECL); if (info.rewrite) { @@ -15738,7 +15740,7 @@ depset::hash::find_dependencies (module_state *module) lookup = lookup_arg_dependent (rewrite_name, NULL_TREE, info.args, true); for (tree fn : lkp_range (lookup)) - add_dependency (make_dependency (fn, EK_DECL)); + make_dependency (fn, EK_DECL); } release_tree_vector (info.args); } diff --git a/gcc/testsuite/g++.dg/modules/adl-12_b.C b/gcc/testsuite/g++.dg/modules/adl-12_b.C index abe772d49c71..66d2af56d92c 100644 --- a/gcc/testsuite/g++.dg/modules/adl-12_b.C +++ b/gcc/testsuite/g++.dg/modules/adl-12_b.C @@ -1,4 +1,4 @@ -// { dg-additional-options "-fmodules" } +// { dg-additional-options "-fmodules -fdump-lang-module" } // Example from [temp.dep.candidate] namespace Q { @@ -12,8 +12,12 @@ import M; void test(Q::X x) { g(x); // OK + // { dg-final { scan-lang-dump "Lazily binding '::Q::g_impl'" module } } + // { dg-final { scan-lang-dump "Lazily binding '::Q::operator-'" module } } Partial<Q::X>::f<int>(); + // { dg-final { scan-lang-dump "Lazily binding '::Q::go_partial'" module } } Partial<Q::X>::o<int>(); + // { dg-final { scan-lang-dump "Lazily binding '::Q::operator/'" module } } incomplete(0); // OK needs_completion(0); // { dg-bogus "required from here" "PR123235" { xfail *-*-* } } // { dg-prune-output "not declared in this scope" } @@ -22,5 +26,7 @@ void test(Q::X x) { rewrite_ops(0); // OK rewrite_ops_error(0); // { dg-message "required from here" "" { target c++20 } } // { dg-prune-output "no match for" } + // { dg-final { scan-lang-dump {Lazily binding '::ops1::operator<=>'} module { target c++20 } } } + // { dg-final { scan-lang-dump {Lazily binding '::ops1::operator=='} module { target c++20 } } } #endif }
