iains created this revision.
Herald added a project: All.
iains added reviewers: urnathan, ChuanqiXu.
iains added a subscriber: clang-modules.
iains published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This is an implementation of the first part of P1815 
<https://reviews.llvm.org/P1815> (and includes the testcase for
[basic.def.odr]/ p10).

If a function is in a different modular TU, and has internal-linkage, we 
invalidate its
entry in an overload set.

In [basic.lookup.argdep] p5 ex 2, we now correctly reject the use of `R::g` in 
the attempted
instantiation of 'apply' in TU #3.

Note that clang (and GCC) also rejects `f(x)` in the same TU, where the example 
currently
states it should be OK.  A clarification question has been sent to core about 
this.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129174

Files:
  clang/include/clang/Sema/Overload.h
  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'}}
+
+  // Not OK, R::f from interface of M is reachable, but not visible to lookup.
+  f(x); // expected-error {{use of undeclared identifier 'f'}}
+
+  // error: S::f in module M not considered even though S is an associated
+  // namespace
+  f(x, S::Z()); // expected-error {{use of undeclared identifier 'f'}}
+
+  // 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,16 @@
     return;
   }
 
+  // Functions with internal linkage are only viable in the same module.
+  if (auto *MF = Function->getOwningModule()) {
+    if (Function->getFormalLinkage() <= Linkage::InternalLinkage &&
+        getLangOpts().CPlusPlus20 && MF != getCurrentModule()) {
+      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/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 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