[clang] 15ddc09 - [C++20] [Modules] Handle linkage properly for specializations when overloading

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 26 03:31:05 PDT 2022


Author: Chuanqi Xu
Date: 2022-07-26T18:30:48+08:00
New Revision: 15ddc09ef9b05ffd5398165049b5202264fa203a

URL: https://github.com/llvm/llvm-project/commit/15ddc09ef9b05ffd5398165049b5202264fa203a
DIFF: https://github.com/llvm/llvm-project/commit/15ddc09ef9b05ffd5398165049b5202264fa203a.diff

LOG: [C++20] [Modules] Handle linkage properly for specializations when overloading

Currently, the semantics of linkage in clang is slightly
different from the semantics in C++ spec. In C++ spec, only names
have linkage. So that all entities of the same should share
one linkage. But in clang, different entities of the same could
have different linkage.

It would break a use case where the template have external linkage and
its specialization have internal linkage due to its type argument is
internal linkage. The root cause is that the semantics of internal
linkage in clang is a mixed form of internal linkage and TU-local in
C++ spec. It is hard to solve the root problem and I tried to add a
workaround inplace.

Added: 
    clang/test/Modules/instantiation-argdep-lookup.cppm

Modified: 
    clang/lib/Sema/SemaOverload.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 65dae00345f6d..7207ce7c4d21e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6403,11 +6403,21 @@ void Sema::AddOverloadCandidate(
   // Functions with internal linkage are only viable in the same module unit.
   if (auto *MF = Function->getOwningModule()) {
     if (getLangOpts().CPlusPlusModules && !MF->isModuleMapModule() &&
-        Function->getFormalLinkage() <= Linkage::InternalLinkage &&
         !isModuleUnitOfCurrentTU(MF)) {
-      Candidate.Viable = false;
-      Candidate.FailureKind = ovl_fail_module_mismatched;
-      return;
+      /// FIXME: Currently, the semantics of linkage in clang is slightly
+      /// 
diff erent from the semantics in C++ spec. In C++ spec, only names
+      /// have linkage. So that all entities of the same should share one
+      /// linkage. But in clang, 
diff erent entities of the same could have
+      /// 
diff erent linkage.
+      NamedDecl *ND = Function;
+      if (auto *SpecInfo = Function->getTemplateSpecializationInfo())
+        ND = SpecInfo->getTemplate();
+      
+      if (ND->getFormalLinkage() <= Linkage::InternalLinkage) {
+        Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_module_mismatched;
+        return;
+      }
     }
   }
 

diff  --git a/clang/test/Modules/instantiation-argdep-lookup.cppm b/clang/test/Modules/instantiation-argdep-lookup.cppm
new file mode 100644
index 0000000000000..fc9009a5bc13d
--- /dev/null
+++ b/clang/test/Modules/instantiation-argdep-lookup.cppm
@@ -0,0 +1,42 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+//
+//--- foo.h
+
+namespace ns {
+struct A {};
+
+template<typename Func>
+constexpr bool __call_is_nt(A)
+{
+    return true;
+}
+ns::A make();
+
+template <typename T>
+bool foo(T t) {
+    auto func = [](){};
+    return __call_is_nt<decltype(func)>(t);
+}
+}
+
+//--- A.cppm
+module;
+#include "foo.h"
+export module A;
+export namespace ns {
+    using ns::foo;
+    using ns::make;
+}
+
+//--- Use.cpp
+// expected-no-diagnostics
+import A;
+void test() {
+    auto a = ns::make();
+    ns::foo(a);
+}


        


More information about the cfe-commits mailing list