iains updated this revision to Diff 443194.
iains retitled this revision from "[C++20][Modules] Invalidate internal-linkage 
functions in overload sets [P1815R2 part 1]" to "[C++20][Modules] Update ADL to 
handle basic.lookup.argdep p4 [P1815R2 part 1]".
iains edited the summary of this revision.
iains added a comment.

updated after clarification of the provisions of basic.lookup.argdep p4


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129174/new/

https://reviews.llvm.org/D129174

Files:
  clang/include/clang/Sema/Overload.h
  clang/lib/Sema/SemaLookup.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/basic/basic.link/p10-ex2.cpp
  clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp

Index: clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 N.cpp -emit-module-interface -o N.pcm \
+// RUN:   -fmodule-file=M.pcm
+// RUN: %clang_cc1 -std=c++20 Q.cpp -emit-module-interface -o Q.pcm
+// RUN: %clang_cc1 -std=c++20 Q-impl.cpp -fsyntax-only -fmodule-file=Q.pcm \
+// RUN:   -fmodule-file=N.pcm -verify
+
+//--- M.cpp
+export module M;
+namespace R {
+export struct X {};
+export void f(X);
+} // namespace R
+namespace S {
+export void f(R::X, R::X);
+}
+
+//--- N.cpp
+export module N;
+import M;
+export R::X make();
+namespace R {
+static int g(X);
+}
+export template <typename T, typename U>
+void apply(T t, U u) {
+  f(t, u);
+  g(t);
+}
+
+//--- Q.cpp
+export module Q;
+
+//--- Q-impl.cpp
+module Q;
+import N;
+
+namespace S {
+struct Z {
+  template <typename T> operator T();
+};
+} // namespace S
+void test() {
+  // OK, decltype(x) is R::X in module M
+  auto x = make();
+
+  // error: R and R::f are not visible here
+  R::f(x); // expected-error {{declaration of 'R' must be imported from module 'N' before it is required}}
+  // expected-n...@n.cpp:4 {{declaration here is not visible}}
+  // expected-error@-2 {{no type named 'f' in namespace 'R'}}
+
+  f(x); // Found by [basic.lookup.argdep] / p4.3
+
+  // error: S::f in module M not considered even though S is an associated
+  // namespace, since the entity Z is in a different module from f.
+  f(x, S::Z()); // expected-error {{no matching function for call to 'f'}}
+  // expected-n...@m.cpp:4 {{candidate function not viable: requires 1 argument, but 2 were provided}}
+
+  // error: S::f is visible in instantiation context, but  R::g has internal
+  // linkage and cannot be used outside N.cpp
+  apply(x, S::Z()); // expected-er...@n.cpp:10 {{no matching function for call to 'g'}}
+                    // expected-note@-1 {{in instantiation of function template specialization 'apply<R::X, S::Z>' requested here}}
+}
Index: clang/test/CXX/basic/basic.link/p10-ex2.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/basic/basic.link/p10-ex2.cpp
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -fsyntax-only -DTEST_INTERFACE -verify
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M.pcm -verify
+
+//--- decls.h
+int f(); // #1, attached to the global module
+int g(); // #2, attached to the global module
+
+//--- M.cpp
+module;
+#include "decls.h"
+export module M;
+export using ::f; // OK, does not declare an entity, exports #1
+#if TEST_INTERFACE
+// error: matches #2, but attached to M
+int g(); // expected-error {{declaration of 'g' in module M follows declaration in the global module}}
+// expected-note@decls.h:2 {{previous declaration is here}}
+#endif
+export int h(); // #3
+export int k(); // #4
+
+//--- useM.cpp
+import M;
+// error: matches #3
+static int h(); // expected-error {{static declaration of 'h' follows non-static declaration}}
+// expected-n...@m.cpp:10 {{previous declaration is here}}
+
+// error: matches #4
+int k(); // expected-error {{declaration of 'k' in the global module follows declaration in module M}}
+// expected-n...@m.cpp:11 {{previous declaration is here}}
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6400,6 +6400,17 @@
     return;
   }
 
+  // Functions with internal linkage are only viable in the same module unit.
+  if (auto *MF = Function->getOwningModule()) {
+    if (Function->getFormalLinkage() <= Linkage::InternalLinkage &&
+        getLangOpts().CPlusPlusModules &&
+        MF->getTopLevelModule() != getCurrentModule()->getTopLevelModule()) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_module_mismatched;
+      return;
+    }
+  }
+
   if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
       !Function->getAttr<TargetAttr>()->isDefaultVersion()) {
     Candidate.Viable = false;
Index: clang/lib/Sema/SemaLookup.cpp
===================================================================
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -3827,6 +3827,12 @@
     //        associated classes are visible within their respective
     //        namespaces even if they are not visible during an ordinary
     //        lookup (11.4).
+    //
+    // C++20 [basic.lookup.argdep] p4.3
+    //     -- are exported, are attached to a named module M, do not appear
+    //        in the translation unit containing the point of the lookup, and
+    //        have the same innermost enclosing non-inline namespace scope as
+    //        a declaration of an associated entity attached to M.
     DeclContext::lookup_result R = NS->lookup(Name);
     for (auto *D : R) {
       auto *Underlying = D;
@@ -3847,6 +3853,30 @@
           if (isVisible(D)) {
             Visible = true;
             break;
+          } else if (getLangOpts().CPlusPlusModules &&
+                     D->isInExportDeclContext()) {
+            // C++20 [basic.lookup.argdep] p4.3 .. are exported
+            Module *FM = D->getOwningModule();
+            // .. are attached to a named module M, do not appear in the
+            // translation unit containing the point of the lookup..
+            if (FM->isModulePurview() &&
+                (ModuleScopes.empty() || FM != ModuleScopes.back().Module)) {
+              for (auto *E : AssociatedClasses) {
+                // and have the same innermost enclosing non-inline namespace
+                // scope as a declaration of an associated entity attached to M
+                if (!E->hasOwningModule() || E->getOwningModule() != FM)
+                  continue;
+                // TODO: maybe this could be cached when generating the
+                // associated namespaces / entities.
+                DeclContext *Ctx = E->getDeclContext();
+                while (!Ctx->isFileContext() || Ctx->isInlineNamespace())
+                  Ctx = Ctx->getParent();
+                if (Ctx == NS)
+                  Visible = true;
+              }
+              if (Visible)
+                break;
+            }
           }
         } else if (D->getFriendObjectKind()) {
           auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext());
Index: clang/include/clang/Sema/Overload.h
===================================================================
--- clang/include/clang/Sema/Overload.h
+++ clang/include/clang/Sema/Overload.h
@@ -795,6 +795,10 @@
     /// This candidate was not viable because its associated constraints were
     /// not satisfied.
     ovl_fail_constraints_not_satisfied,
+
+    /// This candidate was not viable because it has internal linkage and is
+    /// from a different module unit than the use.
+    ovl_fail_module_mismatched,
   };
 
   /// A list of implicit conversion sequences for the arguments of an
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to