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