[Modules] Don't re-generate template specialization in the importer
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>
Tue, 14 Feb 2023 02:27:22 +0000 (10:27 +0800)
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>
Tue, 14 Feb 2023 09:15:33 +0000 (17:15 +0800)
Close https://github.com/llvm/llvm-project/issues/60693.

In this issue, we can find that the importer will try to generate the
template specialization again in the importer, which is not good and
wastes time. This patch tries to address the problem.

clang/include/clang/AST/ASTContext.h
clang/lib/AST/ASTContext.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/test/Modules/pr59780.cppm
clang/test/Modules/pr60693.cppm [new file with mode: 0644]

index 006063e21eb3d23891c6247119c6128f13d0f9b0..0f4decc14579b7e1a207574d0e55328430678d00 100644 (file)
@@ -3043,7 +3043,7 @@ public:
   }
 
   GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const;
-  GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
+  GVALinkage GetGVALinkageForVariable(const VarDecl *VD) const;
 
   /// Determines if the decl can be CodeGen'ed or deserialized from PCH
   /// lazily, only when used; this is only relevant for function or file scoped
index a188837d4144c60a149f77c5a1893156b0fce1ed..a5f7f6a019f87d9d444a3cde4fef8e24f9a70417 100644 (file)
@@ -11764,7 +11764,7 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
   llvm_unreachable("Invalid Linkage!");
 }
 
-GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) const {
   return adjustGVALinkageForExternalDefinitionKind(*this, VD,
            adjustGVALinkageForAttributes(*this, VD,
              basicGVALinkageForVariable(*this, VD)));
index 9e1e58a7fa7e29e40dac6a10bdcf30e22b2487f3..69d192612bccf9fa19bdfabf29872e0dee7afb03 100644 (file)
@@ -1068,7 +1068,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
   if (D->getStorageDuration() == SD_Static) {
     bool ModulesCodegen = false;
     if (Writer.WritingModule &&
-        !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo()) {
+        !D->getDescribedVarTemplate()) {
       // When building a C++20 module interface unit or a partition unit, a
       // strong definition in the module interface is provided by the
       // compilation of that unit, not by its users. (Inline variables are still
@@ -1077,7 +1077,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
           (Writer.WritingModule->isInterfaceOrPartition() ||
            (D->hasAttr<DLLExportAttr>() &&
             Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) &&
-          Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal;
+           Writer.Context->GetGVALinkageForVariable(D) >= GVA_StrongExternal;
     }
     Record.push_back(ModulesCodegen);
     if (ModulesCodegen)
@@ -2550,7 +2550,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
       // compilation of that unit, not by its users. (Inline functions are still
       // emitted in module users.)
       Linkage = Writer->Context->GetGVALinkageForFunction(FD);
-      ModulesCodegen = *Linkage == GVA_StrongExternal;
+      ModulesCodegen = *Linkage >= GVA_StrongExternal;
     }
     if (Writer->Context->getLangOpts().ModulesCodegen ||
         (FD->hasAttr<DLLExportAttr>() &&
index 9578325b976bac6e94330489fdeb8db0bb43d1cb..d4bbd52c13f1a4ad16f093903fcce6f1aa2f51f6 100644 (file)
@@ -33,8 +33,8 @@ struct Y<int> {
 
 int Y<int>::value = 0;
 
-// CHECK-NOT: @_ZW1a1xIiE = {{.*}}available_externally{{.*}}global
-// CHECK-NOT: @_ZNW1a1YIiE5valueE = {{.*}}available_externally{{.*}}global
+// CHECK-NOT: @_ZW1a1xIiE = {{.*}}external{{.*}}global
+// CHECK-NOT: @_ZNW1a1YIiE5valueE = {{.*}}external{{.*}}global
 
 //--- use.cpp
 import a;
@@ -42,5 +42,5 @@ int foo() {
     return x<int> + Y<int>::value;
 }
 
-// CHECK: @_ZW1a1xIiE = {{.*}}available_externally{{.*}}global
-// CHECK: @_ZNW1a1YIiE5valueE = {{.*}}available_externally{{.*}}global
+// CHECK: @_ZW1a1xIiE = {{.*}}external{{.*}}global
+// CHECK: @_ZNW1a1YIiE5valueE = {{.*}}external{{.*}}global
diff --git a/clang/test/Modules/pr60693.cppm b/clang/test/Modules/pr60693.cppm
new file mode 100644 (file)
index 0000000..117a0f2
--- /dev/null
@@ -0,0 +1,54 @@
+// Address: https://github.com/llvm/llvm-project/issues/60693
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm -emit-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=a=%t/a.pcm %t/c.cpp -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
+
+//--- a.cppm
+export module a;
+
+constexpr bool f() {
+       for (unsigned n = 0; n != 10; ++n) {
+       }
+       return true;
+}
+
+export template<typename>
+struct s {
+       static constexpr auto a = f();
+       static constexpr auto b = f();
+       static constexpr auto c = f();
+       static constexpr auto d = f();
+    int foo() {
+        return 43;
+    }
+    int bar() {
+        return 44;
+    }
+};
+
+template struct s<int>;
+template struct s<long>;
+
+//--- c.cpp
+import a;
+
+extern "C" int use() {
+    s<int> _;
+    return _.a + _.b + _.c + _.d;
+}
+
+extern "C" long use2() {
+    s<long> _;
+    return _.foo();
+}
+
+// CHECK: define{{.*}}@use(
+// CHECK-NOT: }
+// CHECK: ret{{.*}} 4
+
+// CHECK: declare{{.*}}@_ZNW1a1sIlE3fooEv
+// CHECK-NOT: _ZNW1a1sIlE3barEv