https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121705

--- Comment #7 from Nathaniel Shead <nshead at gcc dot gnu.org> ---
Minimal repro:

  // a.cpp
  module;
  namespace ns {
    struct S {};
    bool operator==(S, int) { return true; }
  }
  export module M;
  export template <typename T> bool foo(T t, int x) { return t == x; }
  export using ns::S;

  // b.cpp
  import M;
  int main() {
    foo(S{}, 0);
  }

That said, it's worth noting this may fall afoul of
https://eel.is/c++draft/module.global.frag#4 if we don't have any 'obvious'
usages of ns::operator== (i.e. selected via overload resolution in a mostly
non-dependent way at least once) visible from the module purview, as it may
cause the function to be discarded.  So not relying on this may be a wise
option anyway?

Regardless, here's a WIP patch on top of
https://gcc.gnu.org/pipermail/gcc-patches/2025-August/693178.html that causes
at least the repro to pass locally, though it needs some further work+testing:

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 099e4f74811..23d59d2bba4 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2503,6 +2503,10 @@ public:
   {
     clear_flag_bit<DB_HIDDEN_BIT> ();
   }
+  void set_needs_reaching ()
+  {
+    set_flag_bit<DB_UNREACHED_BIT> ();
+  }

 public:
   bool is_special () const
@@ -14486,8 +14490,10 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags
flags, void *data_)
         inner = DECL_TEMPLATE_RESULT (inner);

       if ((!DECL_LANG_SPECIFIC (inner) || !DECL_MODULE_PURVIEW_P (inner))
-          && !((flags & WMB_Using) && (flags & WMB_Purview)))
-        /* Ignore entities not within the module purview.  */
+          && !((flags & WMB_Using) && (flags & WMB_Purview))
+          && !DECL_DECLARES_FUNCTION_P (inner))
+        /* Ignore entities not within the module purview, except functions
+           (we always need to create bindings for ADL purposes).  */
         return false;

       if (!header_module_p () && data->hash->is_tu_local_entity (decl))
@@ -14591,6 +14597,9 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags
flags, void *data_)
         (decl, flags & WMB_Using ? EK_USING : EK_FOR_BINDING);
       if (flags & WMB_Hidden)
         dep->set_hidden_binding ();
+      if (!(flags & WMB_Purview)
+          && !DECL_LANG_SPECIFIC (inner) && !DECL_MODULE_PURVIEW_P (inner))
+        dep->set_needs_reaching ();
       data->binding->deps.safe_push (dep);
       /* Binding and contents are mutually dependent.  */
       dep->deps.safe_push (data->binding);

Reply via email to