https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/143029

>From be47b607dca53dce1904cdf1a6316f97454ede7a Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Wed, 4 Jun 2025 15:55:51 -0700
Subject: [PATCH 1/2] [CIR] Add decl case for template specialization

This change adds the switch case to allow template specialization to
pass through emitTopLevelDecl without issuing an error.
---
 clang/include/clang/CIR/MissingFeatures.h     |  1 +
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        |  7 +-
 .../CIR/CodeGen/template-specialization.cpp   | 88 +++++++++++++++++++
 3 files changed, 95 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/CodeGen/template-specialization.cpp

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 7f20424e9b675..f1e0c15d41f64 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -217,6 +217,7 @@ struct MissingFeatures {
   static bool peepholeProtection() { return false; }
   static bool instrumentation() { return false; }
   static bool cleanupAfterErrorDiags() { return false; }
+  static bool cxxRecordStaticMembers() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 87e364197ce7e..e3caa7bee4d1c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -1139,7 +1139,6 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
   case Decl::Typedef:
   case Decl::TypeAlias: // using foo = bar; [C++11]
   case Decl::Record:
-  case Decl::CXXRecord:
     assert(!cir::MissingFeatures::generateDebugInfo());
     break;
 
@@ -1148,6 +1147,12 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
   case Decl::Namespace:
     emitDeclContext(Decl::castToDeclContext(decl));
     break;
+
+  case Decl::ClassTemplateSpecialization:
+  case Decl::CXXRecord:
+    assert(!cir::MissingFeatures::generateDebugInfo());
+    assert(!cir::MissingFeatures::cxxRecordStaticMembers());
+    break;
   }
 }
 
diff --git a/clang/test/CIR/CodeGen/template-specialization.cpp 
b/clang/test/CIR/CodeGen/template-specialization.cpp
new file mode 100644
index 0000000000000..f15a1cba55e0e
--- /dev/null
+++ b/clang/test/CIR/CodeGen/template-specialization.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+template<class T>
+class X {
+public:
+  int f() { return 0; }
+};
+
+template<> class X<int> {
+public:
+  int f() { return 1; }
+};
+
+// TODO: This will get dropped when we are deferring functions
+// The speecialization is instantiated first
+// CIR: cir.func{{.*}} @_ZN1XIiE1fEv
+// CIR:   cir.const #cir.int<1>
+
+// LLVM: define{{.*}} i32 @_ZN1XIiE1fEv
+// LLVM:   store i32 1
+
+void test_double() {
+  X<double> d;
+  d.f();
+}
+
+// CIR: cir.func{{.*}} @_ZN1XIdE1fEv
+// CIR:   cir.const #cir.int<0>
+//
+// CIR: cir.func{{.*}} @_Z11test_doublev()
+// CIR:   cir.call @_ZN1XIdE1fEv
+
+// LLVM: define{{.*}} i32 @_ZN1XIdE1fEv
+// LLVM:   store i32 0
+//
+// LLVM: define{{.*}} void @_Z11test_doublev()
+// LLVM:   call i32 @_ZN1XIdE1fEv
+
+// OGCG: define{{.*}} void @_Z11test_doublev()
+// OGCG:   call{{.*}} i32 @_ZN1XIdE1fEv
+//
+// OGCG: define{{.*}} i32 @_ZN1XIdE1fEv
+// OGCG:   ret i32 0
+
+void test_int() {
+  X<int> n;
+  n.f();
+}
+
+// CIR: cir.func{{.*}} @_Z8test_intv()
+// CIR:   cir.call @_ZN1XIiE1fEv
+
+// LLVM: define{{.*}} void @_Z8test_intv()
+// LLVM:   call i32 @_ZN1XIiE1fEv
+
+// OGCG: define{{.*}} void @_Z8test_intv()
+// OGCG:   call{{.*}} i32 @_ZN1XIiE1fEv
+//
+// OGCG: define{{.*}} i32 @_ZN1XIiE1fEv
+// OGCG:   ret i32 1
+
+void test_short() {
+  X<short> s;
+  s.f();
+}
+
+// CIR: cir.func{{.*}} @_ZN1XIsE1fEv
+// CIR:   cir.const #cir.int<0>
+//
+// CIR: cir.func{{.*}} @_Z10test_shortv()
+// CIR:   cir.call @_ZN1XIsE1fEv
+
+// LLVM: define{{.*}} i32 @_ZN1XIsE1fEv
+// LLVM: store i32 0
+//
+// LLVM: define{{.*}} void @_Z10test_shortv()
+// LLVM:   call i32 @_ZN1XIsE1fEv
+
+// OGCG: define{{.*}} void @_Z10test_shortv()
+// OGCG:   call{{.*}} i32 @_ZN1XIsE1fEv
+//
+// OGCG: define{{.*}} i32 @_ZN1XIsE1fEv
+// OGCG:   ret i32 0

>From 34ea2d6dd39701f75be0b9a33e3b6cd79ed3f88a Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Thu, 5 Jun 2025 14:18:05 -0700
Subject: [PATCH 2/2] Add partial template specialization test

---
 .../CIR/CodeGen/template-specialization.cpp   | 31 ++++++++++++++-----
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/clang/test/CIR/CodeGen/template-specialization.cpp 
b/clang/test/CIR/CodeGen/template-specialization.cpp
index f15a1cba55e0e..5151f8ce15424 100644
--- a/clang/test/CIR/CodeGen/template-specialization.cpp
+++ b/clang/test/CIR/CodeGen/template-specialization.cpp
@@ -5,6 +5,23 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
 // RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
 
+template<typename T, typename U>
+class Templ {};
+
+template<typename T>
+class Templ<T, int>{};
+
+Templ<int, int> t;
+
+// CIR: !rec_Templ3Cint2C_int3E = !cir.record<class "Templ<int, int>" padded 
{!u8i}>
+// CIR: cir.global external @t = #cir.zero : !rec_Templ3Cint2C_int3E
+
+// LLVM: %"class.Templ<int, int>" = type { i8 }
+// LLVM: @t = global %"class.Templ<int, int>" zeroinitializer
+
+// OGCG: %class.Templ = type { i8 }
+// OGCG: @t = global %class.Templ zeroinitializer
+
 template<class T>
 class X {
 public:
@@ -16,14 +33,6 @@ template<> class X<int> {
   int f() { return 1; }
 };
 
-// TODO: This will get dropped when we are deferring functions
-// The speecialization is instantiated first
-// CIR: cir.func{{.*}} @_ZN1XIiE1fEv
-// CIR:   cir.const #cir.int<1>
-
-// LLVM: define{{.*}} i32 @_ZN1XIiE1fEv
-// LLVM:   store i32 1
-
 void test_double() {
   X<double> d;
   d.f();
@@ -52,9 +61,15 @@ void test_int() {
   n.f();
 }
 
+// CIR: cir.func{{.*}} @_ZN1XIiE1fEv
+// CIR:   cir.const #cir.int<1>
+//
 // CIR: cir.func{{.*}} @_Z8test_intv()
 // CIR:   cir.call @_ZN1XIiE1fEv
 
+// LLVM: define{{.*}} i32 @_ZN1XIiE1fEv
+// LLVM:   store i32 1
+//
 // LLVM: define{{.*}} void @_Z8test_intv()
 // LLVM:   call i32 @_ZN1XIiE1fEv
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to