diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index b2e943699c5f15..b910974d2ce612 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3883,10 +3883,46 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, if (isVisible(D)) { Visible = true; break; - } else if (getLangOpts().CPlusPlusModules && - D->isInExportDeclContext()) { + } + + if (!getLangOpts().CPlusPlusModules) + continue; + + // A partial mock implementation for instantiation context for + // modules. [module.context]p1: + // The instantiation context is a set of points within the program + // that determines which declarations are found by + // argument-dependent name lookup... + // + // FIXME: This didn't implement [module.context] well. For example, + // [module.context]p3 says: + // During the implicit instantiation of a template whose point of + // instantiation is specified as that of an enclosing + // specialization if the template is defined in a module interface + // unit of a module M and the point of instantiation is not in a + // module interface unit of M, the point at the end of the + // declaration-seq of the primary module interface unit of M. + // + // But we didn't check if the template is defined in a module + // interface unit nor we check the context for the primary module + // interface. + Module *FM = D->getOwningModule(); + if (FM && !FM->isHeaderLikeModule()) { + // LookupModules will contain all the modules we visited during the + // template instantiation (if any). And if LookupModules contains + // FM, the declarations in FM should be visible for the + // instantiation. + const auto &LookupModules = getLookupModules(); + // Note: We can't use 'Module::isModuleVisible()' since that is for + // clang modules. + if (LookupModules.count(FM->getTopLevelModule())) { + Visible = true; + break; + } + } + + if (D->isInExportDeclContext()) { // C++20 [basic.lookup.argdep] p4.3 .. are exported ... - Module *FM = D->getOwningModule(); // exports are only valid in module purview and outside of any // PMF (although a PMF should not even be present in a module // with an import). diff --git a/clang/test/Modules/named-modules-adl-2.cppm b/clang/test/Modules/named-modules-adl-2.cppm new file mode 100644 index 00000000000000..1203e693bc4f75 --- /dev/null +++ b/clang/test/Modules/named-modules-adl-2.cppm @@ -0,0 +1,41 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=%t/a.pcm -emit-module-interface -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=%t/b.pcm -fsyntax-only -verify + +//--- a.cppm +export module a; + +export template +void a(T x) { + +x; +} + +//--- b.h +struct s { +}; +void operator+(s) { +} + +//--- b.cppm +module; +#include "b.h" +export module b; +import a; + +export template +void b() { + a(s()); +} + +//--- c.cppm +// expected-no-diagnostics +export module c; +import b; + +void c() { + b(); +} diff --git a/clang/test/Modules/named-modules-adl.cppm b/clang/test/Modules/named-modules-adl.cppm new file mode 100644 index 00000000000000..91f373071ee013 --- /dev/null +++ b/clang/test/Modules/named-modules-adl.cppm @@ -0,0 +1,35 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=%t/a.pcm -fsyntax-only -verify + +//--- a.h +namespace n { + +struct s { }; + +void operator+(s, int) { +} + +} // namespace n + +//--- a.cppm +module; +#include "a.h" +export module a; + +export template +void a(T x) { + n::s() + x; +} + +//--- b.cppm +// expected-no-diagnostics +export module b; +import a; + +void b() { + a(0); +}