https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117658
Nathaniel Shead <nshead at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- See Also| |https://gcc.gnu.org/bugzill | |a/show_bug.cgi?id=101140 CC| |jason at gcc dot gnu.org, | |nshead at gcc dot gnu.org --- Comment #2 from Nathaniel Shead <nshead at gcc dot gnu.org> --- Specifically, a minimal example would be: // a.cpp export module A; export template <typename T> void test(T t) { foo(t); } namespace ns { export struct S {}; /* not exported */ void foo(S) {} } // b.cpp import A; int main() { ns::S s; test(s); // OK? } Clang compiles this, but GCC complains: In module A, imported at b.cpp:1: a.cpp: In instantiation of 'void test@A(T) [with T = ns::S@A]': b.cpp:4:7: required from here 4 | test(ns::S{}); | ~~~~^~~~~~~~~ a.cpp:2:50: error: 'foo' was not declared in this scope 2 | export template <typename T> void test(T t) { foo(t); } | ~~~^~~ If `ns::foo` is exported then GCC also compiles this example. Relevant seems to be https://eel.is/c++draft/basic.lookup.argdep#4. The first set of bullet points don't apply, but since `t` is a dependent name lookup should also be performed from each point in the instantiation context. This is not an instantiation of a template in an enclosing specialisation, so it looks to me that the instantiation context here is just the point of instantiation of `test` (https://eel.is/c++draft/module.context#5), i.e. main.cpp, but Clang seems to think that it should also include the point at the end of `a.cpp`. This latter interpretation seems to be supported by the example here https://eel.is/c++draft/basic.lookup.argdep#5 so I'm probably missing something! CCing Jason in case he has any thoughts.