diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e82c17cfe630f..202e5f49ac4a1 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1877,14 +1877,14 @@ bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) { if (LookupModules.empty()) return false; + // If our lookup set contains the module, it's visible. + if (LookupModules.count(M)) + return true; + // The global module fragments are visible to its corresponding module unit. // So the global module fragment should be visible if the its corresponding // module unit is visible. - if (M->isGlobalModule()) - M = M->getTopLevelModule(); - - // If our lookup set contains the module, it's visible. - if (LookupModules.count(M)) + if (M->isGlobalModule() && LookupModules.count(M->getTopLevelModule())) return true; // For a module-private query, that's everywhere we get to look. diff --git a/clang/test/Modules/named-modules-adl-3.cppm b/clang/test/Modules/named-modules-adl-3.cppm new file mode 100644 index 0000000000000..2fc2962c926b1 --- /dev/null +++ b/clang/test/Modules/named-modules-adl-3.cppm @@ -0,0 +1,64 @@ +// 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=a=%t/a.pcm -emit-module-interface \ +// RUN: -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm \ +// RUN: -fsyntax-only -verify +// +// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/a.cppm -emit-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/b.cppm -fmodule-file=a=%t/a.pcm \ +// RUN: -emit-module-interface -o %t/b.pcm +// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/c.cppm -fmodule-file=a=%t/a.pcm \ +// RUN: -fmodule-file=b=%t/b.pcm -fsyntax-only -verify + +//--- foo.h +namespace n { + +struct s { }; + +void operator+(s, int) {} + +} // namespace n + +//--- a.cppm +module; +#include "foo.h" +export module a; +export namespace n { + using n::s; +#ifdef EXPORT_OPERATOR + using n::operator+; +#endif +} + +//--- b.cppm +export module b; +export import a; + +export template +void b(T x) { + n::s() + x; +} + +//--- c.cppm +#ifdef EXPORT_OPERATOR +// expected-no-diagnostics +#endif +export module c; +import b; + +void c(int x) { +#ifndef EXPORT_OPERATOR + // expected-error@b.cppm:6 {{invalid operands to binary expression ('n::s' and 'int')}} + // expected-note@+2 {{in instantiation of function template specialization 'b' requested here}} +#endif + b(0); + +#ifndef EXPORT_OPERATOR + // expected-error@+2 {{invalid operands to binary expression ('n::s' and 'int')}} +#endif + n::s() + x; +} diff --git a/clang/test/Modules/pr62589.cppm b/clang/test/Modules/pr62589.cppm new file mode 100644 index 0000000000000..4164c3405ac0e --- /dev/null +++ b/clang/test/Modules/pr62589.cppm @@ -0,0 +1,79 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++23 -emit-module-interface %t/a.cppm -o %t/a.pcm +// RUN: %clang_cc1 -std=c++23 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify + +//--- foo.h +class TypeA {}; + +template +concept __comparable = requires (_Tp &&__t, _Up &&__u) { + __t == __u; +}; + +namespace ranges { +namespace __end { + template + concept __member_end = + requires(_Tp&& __t) { + { __t.end() } -> __comparable; + }; + + struct __fn { + template + requires __member_end<_Tp> + constexpr auto operator()(_Tp&& __t) const + { + return true; + } + + void operator()(auto&&) const = delete; + }; +} + +inline namespace __cpo { + inline constexpr auto end = __end::__fn{}; +} +} + +template +concept range = requires(_Tp& __t) { + ranges::end(__t); +}; + +template +class a { +public: + a(T*) {} + TypeA end() { return {}; } +}; + +template +class a_view { +public: + template + a_view(a) {} +}; +template +a_view(_Range) -> a_view; + +constexpr bool operator==(TypeA, TypeA) { + return true; +} + +//--- a.cppm +module; +#include "foo.h" +export module a; +export using ::a; +export using ::a_view; + +//--- b.cpp +// expected-no-diagnostics +import a; +void use() { + auto _ = a{"char"}; + auto __ = a_view{_}; +}