Author: adams381
Date: 2026-05-14T10:40:21-05:00
New Revision: cc4efa3992b11d85a7a57f58fc88a2bbde91a8b8

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

LOG: [CIR] Lower static locals in C++ ctor and dtor bodies (#197089)

Static locals declared inside a C++ constructor or destructor body were
hitting `errorNYI("C++ constructors static var context")` (and the dtor
variant) in `CIRGenModule::getOrCreateStaticVarDecl`, even though the
rest of the static-local plumbing was already in place. The fix is to
mirror what classic CodeGen does at `CGDecl.cpp:328-334` — pick
`GlobalDecl(cd, Ctor_Base)` for ctors and `GlobalDecl(dd, Dtor_Base)`
for dtors instead of erroring.

Hit this trying to compile a couple of SPEC CPU 2026 benchmarks with
`-fclangir`: `flightdm` has a `static constexpr std::array` inside
`FGCondition::FGCondition`, and `gmsh` has a similar shape in
`MetaEl.cpp`. The minimum repro is the obvious one:

```c++
struct Foo { Foo() { static int x = 42; (void)x; } };
Foo f;
```

The new test cross-checks against OGCG so we catch any drift — both
backends emit `@_ZZN4CtorC1EvE1x = linkonce_odr global i32 42, comdat,
align 4` and the dtor analogue.

Both CIR test suites pass cleanly (`check-clang-cir-codegen` and
`check-clang-cir`).

Added: 
    clang/test/CIR/CodeGen/static-local-in-ctor.cpp

Modified: 
    clang/lib/CIR/CodeGen/CIRGenDecl.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp 
b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 2bf90e99eb7d3..c2a0dd80407ca 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -487,10 +487,10 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &d,
   }
 
   GlobalDecl gd;
-  if (isa<CXXConstructorDecl>(dc))
-    errorNYI(d.getSourceRange(), "C++ constructors static var context");
-  else if (isa<CXXDestructorDecl>(dc))
-    errorNYI(d.getSourceRange(), "C++ destructors static var context");
+  if (const auto *cd = dyn_cast<CXXConstructorDecl>(dc))
+    gd = GlobalDecl(cd, Ctor_Base);
+  else if (const auto *dd = dyn_cast<CXXDestructorDecl>(dc))
+    gd = GlobalDecl(dd, Dtor_Base);
   else if (const auto *fd = dyn_cast<FunctionDecl>(dc))
     gd = GlobalDecl(fd);
   else {

diff  --git a/clang/test/CIR/CodeGen/static-local-in-ctor.cpp 
b/clang/test/CIR/CodeGen/static-local-in-ctor.cpp
new file mode 100644
index 0000000000000..6056d3a2cbfe1
--- /dev/null
+++ b/clang/test/CIR/CodeGen/static-local-in-ctor.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s 
-o %t.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+
+struct Ctor {
+  Ctor() {
+    static int x = 42;
+    (void)x;
+  }
+};
+
+struct Dtor {
+  ~Dtor() {
+    static int y = 7;
+    (void)y;
+  }
+};
+
+void use() { Ctor c; Dtor d; }
+
+
+// Static local inside the constructor body.
+
+// CIR-DAG: cir.global linkonce_odr comdat @_ZZN4CtorC1EvE1x = #cir.int<42> : 
!s32i {alignment = 4 : i64}
+// LLVM-DAG: @_ZZN4CtorC1EvE1x = linkonce_odr global i32 42, comdat, align 4
+
+
+// Static local inside the destructor body.
+
+// CIR-DAG: cir.global linkonce_odr comdat @_ZZN4DtorD1EvE1y = #cir.int<7> : 
!s32i {alignment = 4 : i64}
+// LLVM-DAG: @_ZZN4DtorD1EvE1y = linkonce_odr global i32 7, comdat, align 4
+
+
+// The static local is loaded by cir.get_global inside the base-subobject
+// constructor / destructor body (Itanium ABI emits both C1/C2 and D1/D2;
+// both reference the same static).
+
+// CIR: cir.func{{.*}}@_ZN4CtorC2Ev
+// CIR:   cir.get_global @_ZZN4CtorC1EvE1x : !cir.ptr<!s32i>
+
+// CIR: cir.func{{.*}}@_ZN4DtorD2Ev
+// CIR:   cir.get_global @_ZZN4DtorD1EvE1y : !cir.ptr<!s32i>


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to