[clang] b22be34 - [CIR] Print the initial value of globals with a ctor region (#229565)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 7 22:57:47 PDT 2026
Author: David Rivera
Date: 2026-10-08T01:57:37-04:00
New Revision: b22be3443558a3834e1d7d444c02e2f32bad2ef2
URL: https://github.com/llvm/llvm-project/commit/b22be3443558a3834e1d7d444c02e2f32bad2ef2
DIFF: https://github.com/llvm/llvm-project/commit/b22be3443558a3834e1d7d444c02e2f32bad2ef2.diff
LOG: [CIR] Print the initial value of globals with a ctor region (#229565)
Globals were not printing their initializer when a ctor region existed
for the op. So round tripping the serialized op before running
LoweringPrepareo on a .cir module was throwing this error from the
verifier:
```sh
error: 'cir.global' op symbol declaration cannot have public visibility
```
The global lost its initial value on the round trip. Once
LoweringPrepare moved the ctor region out, had no initial value and no
regions, so it looked like a public declaration.
The initial value is now printed before the ctor region, the same way
the dtor region already works:
```mlir
cir.global external @s = #cir.zero : !rec_S ctor { ... }
```
The old `= ctor : type { ... }` form no longer parses, and the verifier
requires an initial value on any global with a ctor region.
Claude assisted with this patch.
Added:
Modified:
clang/lib/CIR/Dialect/IR/CIRDialect.cpp
clang/test/CIR/CodeGen/builtin-call.cpp
clang/test/CIR/CodeGen/global-constant-storage.cpp
clang/test/CIR/CodeGen/global-init-order.cpp
clang/test/CIR/CodeGen/global-init.cpp
clang/test/CIR/CodeGen/global-temp-dtor.cpp
clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
clang/test/CIR/CodeGen/global-tls-simple-init.cpp
clang/test/CIR/CodeGen/global-tls-templates.cpp
clang/test/CIR/CodeGen/pointer-to-data-member.cpp
clang/test/CIR/CodeGen/pointer-to-member-func.cpp
clang/test/CIR/CodeGen/unions-with-zero-init.cpp
clang/test/CIR/CodeGenCXX/global-refs.cpp
clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
clang/test/CIR/CodeGenCXX/typeid.cpp
clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
clang/test/CIR/IR/global-init.cir
clang/test/CIR/IR/invalid-global.cir
clang/test/CIR/IR/invalid-static-local.cir
clang/unittests/CIR/ControlFlowTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index a97606a5a9bd7..2c5b785d5fc34 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2371,6 +2371,12 @@ mlir::LogicalResult cir::GlobalOp::verify() {
return failure();
}
+ // The initial value can't be recomputed from the type once the ctor is
+ // lowered (e.g. a null member pointer becomes -1 after CXXABILowering).
+ if (!getCtorRegion().empty() && !getInitialValue().has_value())
+ return emitOpError(
+ "cannot have a constructor region without an initial value");
+
std::optional<DynamicInitInfoAttr> info = getDynamicInitInfo();
if ((getDynamicInitGuard().has_value()) && (!info || info->getLocal()) &&
@@ -2519,17 +2525,14 @@ static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op,
}
p << "= ";
+ if (initAttr)
+ printConstant(p, initAttr);
+
if (!ctorRegion.empty()) {
- p << "ctor ";
- printType();
- p << " ";
+ p << " ctor ";
p.printRegion(ctorRegion,
/*printEntryBlockArgs=*/false,
/*printBlockTerminators=*/false);
- } else {
- // This also prints the type...
- if (initAttr)
- printConstant(p, initAttr);
}
if (!dtorRegion.empty()) {
@@ -2552,26 +2555,24 @@ static ParseResult parseGlobalOpTypeAndInitialValue(OpAsmParser &parser,
if (parser.parseColonType(opTy))
return failure();
} else {
- // Parse contructor, example:
- // cir.global @rgb = ctor : type { ... }
+ // Parse constant with initializer, examples:
+ // cir.global @y = 3.400000e+00 : f32
+ // cir.global @rgb = #cir.const_array<[...] : !cir.array<i8 x 3>>
+ if (parseConstantValue(parser, initialValueAttr).failed())
+ return failure();
+
+ assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
+ "Non-typed attrs shouldn't appear here.");
+ opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
+
+ // Parse constructor, example:
+ // cir.global @rgb = #cir.zero : type ctor { ... }
if (!parser.parseOptionalKeyword("ctor")) {
- if (parser.parseColonType(opTy))
- return failure();
auto parseLoc = parser.getCurrentLocation();
if (parser.parseRegion(ctorRegion, /*arguments=*/{}, /*argTypes=*/{}))
return failure();
if (ensureRegionTerm(parser, ctorRegion, parseLoc).failed())
return failure();
- } else {
- // Parse constant with initializer, examples:
- // cir.global @y = 3.400000e+00 : f32
- // cir.global @rgb = #cir.const_array<[...] : !cir.array<i8 x 3>>
- if (parseConstantValue(parser, initialValueAttr).failed())
- return failure();
-
- assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
- "Non-typed attrs shouldn't appear here.");
- opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
}
// Parse destructor, example:
diff --git a/clang/test/CIR/CodeGen/builtin-call.cpp b/clang/test/CIR/CodeGen/builtin-call.cpp
index 5d84d0e762223..e647852521b41 100644
--- a/clang/test/CIR/CodeGen/builtin-call.cpp
+++ b/clang/test/CIR/CodeGen/builtin-call.cpp
@@ -14,7 +14,7 @@ const double parsed = strtod(str, nullptr);
// LLVM: @_ZL6parsed = internal global double 0.000000e+00, align 8
// LLVM: @v = global ptr null, align 8
-// CIR-BEFORE-LPP: cir.global "private" internal dso_local @_ZL6parsed = ctor : !cir.double {
+// CIR-BEFORE-LPP: cir.global "private" internal dso_local @_ZL6parsed = #cir.fp<0.000000e+00> : !cir.double ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global @_ZL6parsed : !cir.ptr<!cir.double>
// CIR-BEFORE-LPP: %[[GET_BUILTIN:.*]] = cir.get_global @strtod : !cir.ptr<!cir.func<(!cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>) -> !cir.double>>
// CIR-BEFORE-LPP: %[[GET_STR:.*]] = cir.get_global @str : !cir.ptr<!cir.ptr<!s8i>>
@@ -50,7 +50,7 @@ void *memcpy(void *a, const void *b, size_t c) {
}
const void* v = memcpy(nullptr, nullptr, 1);
-// CIR-BEFORE-LPP: cir.global external @v = ctor : !cir.ptr<!void> {
+// CIR-BEFORE-LPP: cir.global external @v = #cir.ptr<null> : !cir.ptr<!void> ctor {
// CIR-BEFORE-LPP: %[[GET_V:.*]] = cir.get_global @v : !cir.ptr<!cir.ptr<!void>>
// CIR-BEFORE-LPP: %[[NULL1:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
// CIR-BEFORE-LPP: %[[NULL2:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void>
diff --git a/clang/test/CIR/CodeGen/global-constant-storage.cpp b/clang/test/CIR/CodeGen/global-constant-storage.cpp
index 64b75c69f2971..e9ae3151401dd 100644
--- a/clang/test/CIR/CodeGen/global-constant-storage.cpp
+++ b/clang/test/CIR/CodeGen/global-constant-storage.cpp
@@ -52,27 +52,27 @@ const C c;
// CIR checks before LoweringPrepare transformation - globals have ctor regions
// Test case 'a' - before LoweringPrepare
-// CIR-BEFORE-LPP: cir.global external @a = ctor : !rec_A {
+// CIR-BEFORE-LPP: cir.global external @a = #cir.zero : !rec_A ctor {
// CIR-BEFORE-LPP: %[[OBJ:.*]] = cir.get_global @a : !cir.ptr<!rec_A>
// CIR-BEFORE-LPP: cir.call @_ZN1AC1Ev(%[[OBJ]]) : (!cir.ptr<!rec_A> {{.*}}) -> ()
// CIR-BEFORE-LPP: %[[OBJ2:.*]] = cir.get_global @a : !cir.ptr<!rec_A>
// CIR-BEFORE-LPP: }
// Test case 'a2' - before LoweringPrepare
-// CIR-BEFORE-LPP: cir.global external @a2 = ctor : !rec_A2 {
+// CIR-BEFORE-LPP: cir.global external @a2 = #cir.zero : !rec_A2 ctor {
// CIR-BEFORE-LPP: %[[OBJ:.*]] = cir.get_global @a2 : !cir.ptr<!rec_A2>
// CIR-BEFORE-LPP: cir.call @_ZN2A2C1Ev(%[[OBJ]]) : (!cir.ptr<!rec_A2> {{.*}}) -> ()
// CIR-BEFORE-LPP: %[[OBJ2:.*]] = cir.get_global @a2 : !cir.ptr<!rec_A2>
// CIR-BEFORE-LPP: }
// Test case 'b' - before LoweringPrepare
-// CIR-BEFORE-LPP: cir.global external @b = ctor : !rec_B {
+// CIR-BEFORE-LPP: cir.global external @b = #cir.zero : !rec_B ctor {
// CIR-BEFORE-LPP: %[[OBJ:.*]] = cir.get_global @b : !cir.ptr<!rec_B>
// CIR-BEFORE-LPP: cir.call @_ZN1BC1Ev(%[[OBJ]]) : (!cir.ptr<!rec_B> {{.*}}) -> ()
// CIR-BEFORE-LPP: }
// Test case 'c' - before LoweringPrepare (internal linkage)
-// CIR-BEFORE-LPP: cir.global {{.*}} internal {{.*}} @_ZL1c = ctor : !rec_C {
+// CIR-BEFORE-LPP: cir.global {{.*}} internal {{.*}} @_ZL1c = #cir.zero : !rec_C ctor {
// CIR-BEFORE-LPP: %[[OBJ:.*]] = cir.get_global @_ZL1c : !cir.ptr<!rec_C>
// CIR-BEFORE-LPP: cir.call @_ZN1CC1Ev(%[[OBJ]]) : (!cir.ptr<!rec_C> {{.*}}) -> ()
// CIR-BEFORE-LPP: %[[OBJ2:.*]] = cir.get_global @_ZL1c : !cir.ptr<!rec_C>
diff --git a/clang/test/CIR/CodeGen/global-init-order.cpp b/clang/test/CIR/CodeGen/global-init-order.cpp
index 41ab8f21abafc..7e2c1251e1360 100644
--- a/clang/test/CIR/CodeGen/global-init-order.cpp
+++ b/clang/test/CIR/CodeGen/global-init-order.cpp
@@ -21,11 +21,11 @@ NeedsCtor Holder::second;
NeedsCtor Holder::first;
// CIR-BEFORE-LPP: cir.global external @p = #cir.global_view<@_ZN6Holder5firstE> : !cir.ptr<!rec_NeedsCtor>
-// CIR-BEFORE-LPP: cir.global external @_ZN6Holder6secondE = ctor : !rec_NeedsCtor {
+// CIR-BEFORE-LPP: cir.global external @_ZN6Holder6secondE = #cir.zero : !rec_NeedsCtor ctor {
// CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @_ZN6Holder6secondE : !cir.ptr<!rec_NeedsCtor>
// CIR-BEFORE-LPP: cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]])
// CIR-BEFORE-LPP: }
-// CIR-BEFORE-LPP: cir.global external @_ZN6Holder5firstE = ctor : !rec_NeedsCtor {
+// CIR-BEFORE-LPP: cir.global external @_ZN6Holder5firstE = #cir.zero : !rec_NeedsCtor ctor {
// CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @_ZN6Holder5firstE : !cir.ptr<!rec_NeedsCtor>
// CIR-BEFORE-LPP: cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]])
// CIR-BEFORE-LPP: }
diff --git a/clang/test/CIR/CodeGen/global-init.cpp b/clang/test/CIR/CodeGen/global-init.cpp
index 7d54e911829b2..6696e73f5b1f5 100644
--- a/clang/test/CIR/CodeGen/global-init.cpp
+++ b/clang/test/CIR/CodeGen/global-init.cpp
@@ -37,7 +37,7 @@ struct NeedsCtor {
NeedsCtor needsCtor;
-// CIR-BEFORE-LPP: cir.global external @needsCtor = ctor : !rec_NeedsCtor {
+// CIR-BEFORE-LPP: cir.global external @needsCtor = #cir.zero : !rec_NeedsCtor ctor {
// CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor>
// CIR-BEFORE-LPP: cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]]) : (!cir.ptr<!rec_NeedsCtor> {{.*}}) -> ()
@@ -85,7 +85,7 @@ struct NeedsCtorDtor {
NeedsCtorDtor needsCtorDtor;
-// CIR-BEFORE-LPP: cir.global external @needsCtorDtor = ctor : !rec_NeedsCtorDtor {
+// CIR-BEFORE-LPP: cir.global external @needsCtorDtor = #cir.zero : !rec_NeedsCtorDtor ctor {
// CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @needsCtorDtor : !cir.ptr<!rec_NeedsCtorDtor>
// CIR-BEFORE-LPP: cir.call @_ZN13NeedsCtorDtorC1Ev(%[[THIS]]) : (!cir.ptr<!rec_NeedsCtorDtor> {{.*}}) -> ()
// CIR-BEFORE-LPP: } dtor {
@@ -115,7 +115,7 @@ float num;
float _Complex a = {num, num};
// CIR-BEFORE-LPP: cir.global external @num = #cir.fp<0.000000e+00> : !cir.float
-// CIR-BEFORE-LPP: cir.global external @a = ctor : !cir.complex<!cir.float> {
+// CIR-BEFORE-LPP: cir.global external @a = #cir.zero : !cir.complex<!cir.float> ctor {
// CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @a : !cir.ptr<!cir.complex<!cir.float>>
// CIR-BEFORE-LPP: %[[NUM:.*]] = cir.get_global @num : !cir.ptr<!cir.float>
// CIR-BEFORE-LPP: %[[REAL:.*]] = cir.load{{.*}} %[[NUM]] : !cir.ptr<!cir.float>, !cir.float
@@ -152,7 +152,7 @@ float _Complex a = {num, num};
float fp;
int i = (int)fp;
-// CIR-BEFORE-LPP: cir.global external @i = ctor : !s32i {
+// CIR-BEFORE-LPP: cir.global external @i = #cir.int<0> : !s32i ctor {
// CIR-BEFORE-LPP: %[[I:.*]] = cir.get_global @i : !cir.ptr<!s32i>
// CIR-BEFORE-LPP: %[[FP:.*]] = cir.get_global @fp : !cir.ptr<!cir.float>
// CIR-BEFORE-LPP: %[[FP_VAL:.*]] = cir.load{{.*}} %[[FP]] : !cir.ptr<!cir.float>, !cir.float
@@ -271,7 +271,7 @@ ArrayDtor arrDtor[16];
int globalInt;
double &&globalDoubleRef = static_cast<double &&>(globalInt);
// CIR-BEFORE-LPP: cir.global external @globalInt = #cir.int<0> : !s32i
-// CIR-BEFORE-LPP: cir.global external @globalDoubleRef = ctor : !cir.ptr<!cir.double> {
+// CIR-BEFORE-LPP: cir.global external @globalDoubleRef = #cir.ptr<null> : !cir.ptr<!cir.double> ctor {
// CIR-BEFORE-LPP: %[[GET_SELF:.*]] = cir.get_global @globalDoubleRef : !cir.ptr<!cir.ptr<!cir.double>>
// CIR-BEFORE-LPP: %[[GET_BACKING_VAR:.*]] = cir.get_global @_ZGR15globalDoubleRef_ : !cir.ptr<!cir.double>
// CIR-BEFORE-LPP: %[[GET_INT_VAR:.*]] = cir.get_global @globalInt : !cir.ptr<!s32i>
diff --git a/clang/test/CIR/CodeGen/global-temp-dtor.cpp b/clang/test/CIR/CodeGen/global-temp-dtor.cpp
index e34bb8b009aeb..7c267ffd0558e 100644
--- a/clang/test/CIR/CodeGen/global-temp-dtor.cpp
+++ b/clang/test/CIR/CodeGen/global-temp-dtor.cpp
@@ -24,7 +24,7 @@ typedef NonTrivial NonTrivialArr[2];
const NonTrivialArr &static_arr_ref = NonTrivialArr{};
thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{};
-// CIR-BEFORE: cir.global external @static_ref = ctor : !cir.ptr<!rec_NonTrivial> {
+// CIR-BEFORE: cir.global external @static_ref = #cir.ptr<null> : !cir.ptr<!rec_NonTrivial> ctor {
// CIR-BEFORE: %[[STATIC_REF:.*]] = cir.get_global @static_ref
// CIR-BEFORE: %[[REF_TEMP:.*]] = cir.get_global @_ZGR10static_ref_
// CIR-BEFORE: cir.call @_ZN10NonTrivialC1Ev(%[[REF_TEMP]])
@@ -47,7 +47,7 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{};
// CIR: cir.call @__cxa_atexit
// CIR: cir.global "private" internal @_ZGR10static_ref_ = #cir.zero : !rec_NonTrivial
-// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = ctor : !cir.ptr<!rec_NonTrivial> {
+// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = #cir.ptr<null> : !cir.ptr<!rec_NonTrivial> ctor {
// CIR-BEFORE: %[[THREAD_REF:.*]] = cir.get_global thread_local @thread_ref
// CIR-BEFORE: %[[REF_TEMP:.*]] = cir.get_global @_ZGR10thread_ref_
// CIR-BEFORE: cir.call @_ZN10NonTrivialC1Ev(%[[REF_TEMP]])
@@ -70,7 +70,7 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{};
// CIR: cir.call @__cxa_thread_atexit
// CIR: cir.global "private" internal tls_model = tls_dyn @_ZGR10thread_ref_ = #cir.zero : !rec_NonTrivial
-// CIR-BEFORE: cir.global external @static_arr_ref = ctor : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> {
+// CIR-BEFORE: cir.global external @static_arr_ref = #cir.ptr<null> : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> ctor {
// CIR-BEFORE: %[[ARRAY_INIT_TEMP:.*]] = cir.alloca {{.*}}"arrayinit.temp"
// CIR-BEFORE: %[[STATIC_ARR_REF:.*]] = cir.get_global @static_arr_ref
// CIR-BEFORE: %[[STATIC_ARR_REF_TEMP:.*]] = cir.get_global @_ZGR14static_arr_ref_
@@ -108,7 +108,7 @@ thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{};
// CIR: cir.call @__cxa_atexit
// CIR: cir.global "private" internal @_ZGR14static_arr_ref_ = #cir.zero : !cir.array<!rec_NonTrivial x 2>
-// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = ctor : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> {
+// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = #cir.ptr<null> : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> ctor {
// CIR-BEFORE: %[[ARRAY_INIT_TEMP:.*]] = cir.alloca {{.*}}"arrayinit.temp"
// CIR-BEFORE: %[[THREAD_ARR_REF:.*]] = cir.get_global thread_local @thread_arr_ref
// CIR-BEFORE: %[[THREAD_ARR_REF_TEMP:.*]] = cir.get_global @_ZGR14thread_arr_ref_
@@ -273,7 +273,7 @@ struct OwnsTemp {
};
OwnsTemp owns_temp{ExtendedTemp()};
-// CIR-BEFORE: cir.global external @owns_temp = ctor : !rec_OwnsTemp {
+// CIR-BEFORE: cir.global external @owns_temp = #cir.zero : !rec_OwnsTemp ctor {
// CIR-BEFORE: } dtor {
// CIR-BEFORE-NEXT: %[[OWNER:.*]] = cir.get_global @owns_temp
// CIR-BEFORE-NEXT: cir.call @_ZN8OwnsTempD1Ev(%[[OWNER]])
diff --git a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
index 4c23dedee6d38..0a0cc48035b0e 100644
--- a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
@@ -122,7 +122,7 @@ thread_local CtorDtor tls_cd = 5;
// LLVM-BOTH: ret void
thread_local CtorDtor tls_cd_dyn = get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = ctor : !rec_CtorDtor {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = #cir.zero : !rec_CtorDtor ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor>
// CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef})
// CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) : (!cir.ptr<!rec_CtorDtor>
@@ -155,7 +155,7 @@ thread_local CtorDtor tls_cd_dyn = get_i();
// LLVM-BOTH: ret void
thread_local CtorDtor &tls_cd_ref = tls_cd_dyn;
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = ctor : !cir.ptr<!rec_CtorDtor> {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = #cir.ptr<null> : !cir.ptr<!rec_CtorDtor> ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>>
// CIR-BEFORE-LPP: %[[CALL:.*]] = cir.get_global thread_local @tls_cd_dyn : !cir.ptr<!rec_CtorDtor>
// CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !cir.ptr<!rec_CtorDtor>, !cir.ptr<!cir.ptr<!rec_CtorDtor>>
@@ -182,7 +182,7 @@ thread_local CtorDtor &tls_cd_ref = tls_cd_dyn;
// OGCG: }
thread_local CtorDtor tls_cd_dyn_not_used = get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = ctor : !rec_CtorDtor {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used = #cir.zero : !rec_CtorDtor ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor>
// CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef})
// CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]])
diff --git a/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp b/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
index 08d3a2d9ed4f3..c6442a0e3cc59 100644
--- a/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
@@ -12,7 +12,7 @@ thread_local int d = f();
// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn @a = #cir.int<5> : !s32i
// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn @b = #cir.int<5> : !s32i
// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW1c", "_ZTH1c"> @c = #cir.int<5> : !s32i
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW1d", "_ZTH1d"> @d = ctor
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW1d", "_ZTH1d"> @d = #cir.int<0> : !s32i ctor
// CIR-DAG: cir.global external tls_model = tls_dyn @a = #cir.int<5> : !s32i
// CIR-DAG: cir.global external tls_model = tls_dyn @b = #cir.int<5> : !s32i
diff --git a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
index 049e8fd9f16d7..af6c9fe8695dd 100644
--- a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
@@ -144,7 +144,7 @@ thread_local int tls_int = 5;
// CIR: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW7tls_int", "_ZTH7tls_int"> @tls_int = #cir.int<5> : !s32i
thread_local int tls_int_dyn = get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = ctor : !s32i {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = #cir.int<0> : !s32i ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_dyn : !cir.ptr<!s32i>
// CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef})
// CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !s32i, !cir.ptr<!s32i>
@@ -164,7 +164,7 @@ thread_local int tls_int_dyn = get_i();
// LLVM-BOTH: ret void
thread_local int &tls_int_ref = tls_int_dyn;
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = ctor : !cir.ptr<!s32i> {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = #cir.ptr<null> : !cir.ptr<!s32i> ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_ref : !cir.ptr<!cir.ptr<!s32i>>
// CIR-BEFORE-LPP: %[[GET_OTHER:.*]] = cir.get_global thread_local @tls_int_dyn : !cir.ptr<!s32i>
// CIR-BEFORE-LPP: cir.store {{.*}}%[[GET_OTHER]], %[[GET_GLOB]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
@@ -189,7 +189,7 @@ thread_local int &tls_int_ref = tls_int_dyn;
// OGCG: ret ptr %[[GET_GLOB]]
thread_local int tls_int_self_init = tls_int_self_init + get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = ctor : !s32i {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = #cir.int<0> : !s32i ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @tls_int_self_init : !cir.ptr<!s32i>
// CIR-BEFORE-LPP: %[[GET_SELF:.*]] = cir.get_global thread_local @tls_int_self_init : !cir.ptr<!s32i>
// CIR-BEFORE-LPP: %[[LOAD_SELF:.*]] = cir.load {{.*}}%[[GET_SELF]] : !cir.ptr<!s32i>, !s32i
@@ -227,7 +227,7 @@ extern thread_local int definitely_inited = 5;
// CIR: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW17definitely_inited", "_ZTH17definitely_inited"> @definitely_inited = #cir.int<5> : !s32i
extern thread_local int definitely_inited_dyn = get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> @definitely_inited_dyn = ctor : !s32i {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> @definitely_inited_dyn = #cir.int<0> : !s32i ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @definitely_inited_dyn : !cir.ptr<!s32i>
// CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef})
// CIR-BEFORE-LPP: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !s32i, !cir.ptr<!s32i>
diff --git a/clang/test/CIR/CodeGen/global-tls-templates.cpp b/clang/test/CIR/CodeGen/global-tls-templates.cpp
index 8c896a4acf0af..1022d296b0b79 100644
--- a/clang/test/CIR/CodeGen/global-tls-templates.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-templates.cpp
@@ -13,13 +13,13 @@ struct CtorDtor {
template<typename T>
thread_local T tls_templ = {get_i()};
-// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_model = tls_dyn tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> dynamic_init_guard<"_ZGV9tls_templIiE"> @_Z9tls_templIiE = ctor : !s32i {
+// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_model = tls_dyn tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> dynamic_init_guard<"_ZGV9tls_templIiE"> @_Z9tls_templIiE = #cir.int<0> : !s32i ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @_Z9tls_templIiE : !cir.ptr<!s32i>
// CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef})
// CIR-BEFORE-LPP: cir.store{{.*}} %[[CALL]], %[[GET_GLOB]] : !s32i, !cir.ptr<!s32i>
// CIR-BEFORE-LPP: }
//
-// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_model = tls_dyn tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", "_ZGV9tls_templI8CtorDtorE"> dynamic_init_guard<"_ZGV9tls_templI8CtorDtorE"> @_Z9tls_templI8CtorDtorE = ctor : !rec_CtorDtor {
+// CIR-BEFORE-LPP-LABEL: cir.global linkonce_odr comdat tls_model = tls_dyn tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", "_ZGV9tls_templI8CtorDtorE"> dynamic_init_guard<"_ZGV9tls_templI8CtorDtorE"> @_Z9tls_templI8CtorDtorE = #cir.zero : !rec_CtorDtor ctor {
// CIR-BEFORE-LPP: %[[GET_GLOB:.*]] = cir.get_global thread_local @_Z9tls_templI8CtorDtorE : !cir.ptr<!rec_CtorDtor>
// CIR-BEFORE-LPP: %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i {llvm.noundef})
// CIR-BEFORE-LPP: cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) : (!cir.ptr<!rec_CtorDtor>
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
index 46b3cb88fd1a4..f8e06fdf69a2d 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
@@ -30,7 +30,7 @@ auto test1() -> int Point::* {
int Point::*pt_member_nested_region = test1();
-// CIR-BEFORE: cir.global external @pt_member_nested_region = ctor : !cir.data_member<!s32i in !rec_Point> {
+// CIR-BEFORE: cir.global external @pt_member_nested_region = #cir.data_member<null> : !cir.data_member<!s32i in !rec_Point> ctor {
// CIR-BEFORE: %[[MEMBER_PTR_ADDR:.*]] = cir.get_global @pt_member_nested_region : !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
// CIR-BEFORE: %[[MEMBER_PTR:.*]] = cir.call @_Z5test1v() : () -> !cir.data_member<!s32i in !rec_Point>
// CIR-BEFORE: cir.store{{.*}} %[[MEMBER_PTR]], %[[MEMBER_PTR_ADDR]] : !cir.data_member<!s32i in !rec_Point>, !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
diff --git a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
index afe853c3423a9..65494afa5fd23 100644
--- a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
@@ -52,7 +52,7 @@ void (Foo::*m2_ptr)(int) = &Foo::m2;
// Self-referencing PMF causes a null method.
long (Foo::*pmf1)(int) = pmf1;
-// CIR-BEFORE: @pmf1 = ctor : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i) -> !s64i> in !rec_Foo> {
+// CIR-BEFORE: @pmf1 = #cir.method<null> : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i) -> !s64i> in !rec_Foo> ctor {
// CIR-AFTER: cir.global external @pmf1 = #cir.const_record<{#cir.int<0> : !s64i, #cir.int<0> : !s64i}>
// LLVM: @pmf1 = global { i64, i64 } zeroinitializer, align 8
// OGCG: @pmf1 = global { i64, i64 } zeroinitializer, align 8
diff --git a/clang/test/CIR/CodeGen/unions-with-zero-init.cpp b/clang/test/CIR/CodeGen/unions-with-zero-init.cpp
index ebddb95c545eb..2b84c18925dae 100644
--- a/clang/test/CIR/CodeGen/unions-with-zero-init.cpp
+++ b/clang/test/CIR/CodeGen/unions-with-zero-init.cpp
@@ -66,7 +66,7 @@ auto use() {
}
union outer_aggregate{int S::*m; int i; } outer_a1 = { p };
-// CIR-BEFORE-LABEL: cir.global external @outer_a1 = ctor : !rec_outer_aggregate {
+// CIR-BEFORE-LABEL: cir.global external @outer_a1 = #cir.const_record<{#cir.data_member<null> : !cir.data_member<!s32i in !rec_S>}> : !rec_outer_aggregate ctor {
// CIR-BEFORE: %[[GET_GLOB:.*]] = cir.get_global @outer_a1 : !cir.ptr<!rec_outer_aggregate>
// CIR-BEFORE: %[[GET_MEM:.*]] = cir.get_member %[[GET_GLOB]][0] {name = "m"} : !cir.ptr<!rec_outer_aggregate> -> !cir.ptr<!cir.data_member<!s32i in !rec_S>>
// CIR-BEFORE: %[[GET_P:.*]] = cir.get_global @p : !cir.ptr<!cir.data_member<!s32i in !rec_S>>
diff --git a/clang/test/CIR/CodeGenCXX/global-refs.cpp b/clang/test/CIR/CodeGenCXX/global-refs.cpp
index 7843fad4de638..98a2e85e71ca0 100644
--- a/clang/test/CIR/CodeGenCXX/global-refs.cpp
+++ b/clang/test/CIR/CodeGenCXX/global-refs.cpp
@@ -51,7 +51,7 @@ const DefCtor &constDefCtorRef{};
// LLVM: @constDefCtorRef = constant ptr @_ZGR15constDefCtorRef_, align 8
WithCtor withCtor{};
-// CIR-BEFORE: cir.global external @withCtor = ctor : !rec_WithCtor {
+// CIR-BEFORE: cir.global external @withCtor = #cir.zero : !rec_WithCtor ctor {
// CIR-BEFORE-NEXT: %[[GET_GLOB:.*]] = cir.get_global @withCtor : !cir.ptr<!rec_WithCtor>
// CIR-BEFORE-NEXT: cir.call @_ZN8WithCtorC1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_WithCtor>{{.*}}) -> ()
// CIR-BEFORE-NEXT: } align(1) ast(#cir.var.decl.ast)
@@ -68,7 +68,7 @@ WithCtor &withCtorRef = withCtor;
// LLVM: @withCtorRef = constant ptr @withCtor, align 8
const WithCtor &constWithCtorRef{};
-// CIR-BEFORE: cir.global external @constWithCtorRef = ctor : !cir.ptr<!rec_WithCtor> {
+// CIR-BEFORE: cir.global external @constWithCtorRef = #cir.ptr<null> : !cir.ptr<!rec_WithCtor> ctor {
// CIR-BEFORE-NEXT: %[[GET_GLOB:.*]] = cir.get_global @constWithCtorRef : !cir.ptr<!cir.ptr<!rec_WithCtor>>
// CIR-BEFORE-NEXT: %[[GET_GLOB_OBJ:.*]] = cir.get_global @_ZGR16constWithCtorRef_ : !cir.ptr<!rec_WithCtor>
// CIR-BEFORE-NEXT: cir.call @_ZN8WithCtorC1Ev(%[[GET_GLOB_OBJ]]) : (!cir.ptr<!rec_WithCtor>{{.*}}) -> ()
@@ -85,7 +85,7 @@ const WithCtor &constWithCtorRef{};
// LLVM: @constWithCtorRef = global ptr null, align 8
const WithCtor &constWithCtorRef2{5};
-// CIR-BEFORE: cir.global external @constWithCtorRef2 = ctor : !cir.ptr<!rec_WithCtor> {
+// CIR-BEFORE: cir.global external @constWithCtorRef2 = #cir.ptr<null> : !cir.ptr<!rec_WithCtor> ctor {
// CIR-BEFORE-NEXT: %[[GET_GLOB:.*]] = cir.get_global @constWithCtorRef2 : !cir.ptr<!cir.ptr<!rec_WithCtor>>
// CIR-BEFORE-NEXT: %[[GET_GLOB_OBJ:.*]] = cir.get_global @_ZGR17constWithCtorRef2_ : !cir.ptr<!rec_WithCtor>
// CIR-BEFORE-NEXT: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
@@ -104,7 +104,7 @@ const WithCtor &constWithCtorRef2{5};
// LLVM: @constWithCtorRef2 = global ptr null, align 8
WithCtorDtor withCtorDtor{};
-// CIR-BEFORE: cir.global external @withCtorDtor = ctor : !rec_WithCtorDtor {
+// CIR-BEFORE: cir.global external @withCtorDtor = #cir.zero : !rec_WithCtorDtor ctor {
// CIR-BEFORE-NEXT: %[[GET_GLOB:.*]] = cir.get_global @withCtorDtor : !cir.ptr<!rec_WithCtorDtor>
// CIR-BEFORE-NEXT: cir.call @_ZN12WithCtorDtorC1Ev(%[[GET_GLOB]]) : (!cir.ptr<!rec_WithCtorDtor>{{.*}}) -> ()
// CIR-BEFORE-NEXT: } dtor {
diff --git a/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp b/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
index 60aeff885b3af..75e303a3b15ba 100644
--- a/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
+++ b/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
@@ -38,16 +38,16 @@ A C::a = A();
// Static inside of C.
-// CIR-BEFORE-LPP: cir.global external @_ZN1C1aE = ctor : !rec_A {
+// CIR-BEFORE-LPP: cir.global external @_ZN1C1aE = #cir.zero : !rec_A ctor {
// CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast)
-// CIR-BEFORE-LPP: cir.global external @c = ctor : !rec_C {
+// CIR-BEFORE-LPP: cir.global external @c = #cir.zero : !rec_C ctor {
// CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast)
-// CIR-BEFORE-LPP: cir.global external @a1 = ctor : !rec_A1 {
+// CIR-BEFORE-LPP: cir.global external @a1 = #cir.zero : !rec_A1 ctor {
// CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast) init_priority(300)
-// CIR-BEFORE-LPP: cir.global external @a = ctor : !rec_A {
+// CIR-BEFORE-LPP: cir.global external @a = #cir.zero : !rec_A ctor {
// CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast) init_priority(300)
-// CIR-BEFORE-LPP: cir.global external @b = ctor : !rec_B {
+// CIR-BEFORE-LPP: cir.global external @b = #cir.zero : !rec_B ctor {
// CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast) init_priority(200)
// CIR: cir.global_ctors = [#cir.global_ctor<"_GLOBAL__I_000200", 200>, #cir.global_ctor<"_GLOBAL__I_000300", 300>, #cir.global_ctor<"_GLOBAL__sub_I_[[FILENAME:.*]]", 65535>]
diff --git a/clang/test/CIR/CodeGenCXX/typeid.cpp b/clang/test/CIR/CodeGenCXX/typeid.cpp
index a4608bf6a0205..ec1c0e4f81cd0 100644
--- a/clang/test/CIR/CodeGenCXX/typeid.cpp
+++ b/clang/test/CIR/CodeGenCXX/typeid.cpp
@@ -34,7 +34,7 @@ extern A &a;
// CIR-AFTER: cir.global external @_ZN5Test14a_tiE = #cir.ptr<null> : !cir.ptr<!rec_std3A3Atype_info>
-// CIR-BEFORE: cir.global external @_ZN5Test14a_tiE = ctor : !cir.ptr<!rec_std3A3Atype_info> {
+// CIR-BEFORE: cir.global external @_ZN5Test14a_tiE = #cir.ptr<null> : !cir.ptr<!rec_std3A3Atype_info> ctor {
// CIR-AFTER: cir.func{{.*}}@__cxx_global_var_init() {
//
// CIR-NEXT: %[[GET_GLOB_ATI:.*]] = cir.get_global @_ZN5Test14a_tiE : !cir.ptr<!cir.ptr<!rec_std3A3Atype_info>>
diff --git a/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp b/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
index 22508f0ed5c0c..03491faadfe1f 100644
--- a/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
+++ b/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
@@ -42,7 +42,7 @@ Inherits I2 {{1,2,3},{1.1, 2.2, 3.3}, 4, 5, 6};
// OGCG: @I2 = global { i32, i32, i32, float, float, float, i32, i32, i32 } { i32 1, i32 2, i32 3, float {{.*}}, float {{.*}}, float {{.*}}, i32 4, i32 5, i32 6 }, align 4
VirtualInherits VI;
-// CIR-BEFORE: cir.global external @VI = ctor : !rec_VirtualInherits {
+// CIR-BEFORE: cir.global external @VI = #cir.zero : !rec_VirtualInherits ctor {
// CIR-BEFORE: %[[GET_GLOB:.*]] = cir.get_global @VI : !cir.ptr<!rec_VirtualInherits>
// CIR-BEFORE: cir.call @_ZN15VirtualInheritsC1Ev(%[[GET_GLOB]]) nothrow : (!cir.ptr<!rec_VirtualInherits> {llvm.align = 8 : i64, llvm.dereferenceable = 20 : i64, llvm.nonnull, llvm.noundef}) -> ()
// CIR-BEFORE: } align(8) ast(#cir.var.decl.ast)
diff --git a/clang/test/CIR/IR/global-init.cir b/clang/test/CIR/IR/global-init.cir
index 3e0387ed52594..f73362e3b9ee8 100644
--- a/clang/test/CIR/IR/global-init.cir
+++ b/clang/test/CIR/IR/global-init.cir
@@ -1,6 +1,7 @@
// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
!u8i = !cir.int<u, 8>
+!s64i = !cir.int<s, 64>
!rec_NeedsCtor = !cir.struct<"NeedsCtor" {pad !u8i}>
!rec_NeedsDtor = !cir.struct<"NeedsDtor" {pad !u8i}>
@@ -8,11 +9,11 @@
module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
cir.func private @_ZN9NeedsCtorC1Ev(!cir.ptr<!rec_NeedsCtor>)
- cir.global external @needsCtor = ctor : !rec_NeedsCtor {
+ cir.global external @needsCtor = #cir.zero : !rec_NeedsCtor ctor {
%0 = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor>
cir.call @_ZN9NeedsCtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtor>) -> ()
}
- // CHECK: cir.global external @needsCtor = ctor : !rec_NeedsCtor {
+ // CHECK: cir.global external @needsCtor = #cir.zero : !rec_NeedsCtor ctor {
// CHECK: %0 = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor>
// CHECK: cir.call @_ZN9NeedsCtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtor>) -> ()
// CHECK: }
@@ -29,7 +30,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
cir.func private @_ZN13NeedsCtorDtorC1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
cir.func private @_ZN13NeedsCtorDtorD1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
- cir.global external dso_local @needsCtorDtor = ctor : !rec_NeedsCtorDtor {
+ cir.global external dso_local @needsCtorDtor = #cir.zero : !rec_NeedsCtorDtor ctor {
%0 = cir.get_global @needsCtorDtor : !cir.ptr<!rec_NeedsCtorDtor>
cir.call @_ZN13NeedsCtorDtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtorDtor>) -> ()
} dtor {
@@ -38,11 +39,25 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
}
// CHECK: cir.func private @_ZN13NeedsCtorDtorC1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
// CHECK: cir.func private @_ZN13NeedsCtorDtorD1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
- // CHECK: cir.global external dso_local @needsCtorDtor = ctor : !rec_NeedsCtorDtor {
+ // CHECK: cir.global external dso_local @needsCtorDtor = #cir.zero : !rec_NeedsCtorDtor ctor {
// CHECK: %0 = cir.get_global @needsCtorDtor : !cir.ptr<!rec_NeedsCtorDtor>
// CHECK: cir.call @_ZN13NeedsCtorDtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtorDtor>) -> ()
// CHECK: } dtor {
// CHECK: %0 = cir.get_global @needsCtorDtor : !cir.ptr<!rec_NeedsCtorDtor>
// CHECK: cir.call @_ZN13NeedsCtorDtorD1Ev(%0) : (!cir.ptr<!rec_NeedsCtorDtor>) -> ()
// CHECK: }
+
+ // The initial value is kept alongside the ctor even when it is not zero,
+ // e.g. a null data member pointer after CXX ABI lowering.
+ cir.func private @_Z9getMemberv() -> !s64i
+ cir.global external @memberPtr = #cir.int<-1> : !s64i ctor {
+ %0 = cir.get_global @memberPtr : !cir.ptr<!s64i>
+ %1 = cir.call @_Z9getMemberv() : () -> !s64i
+ cir.store %1, %0 : !s64i, !cir.ptr<!s64i>
+ }
+ // CHECK: cir.global external @memberPtr = #cir.int<-1> : !s64i ctor {
+ // CHECK: %0 = cir.get_global @memberPtr : !cir.ptr<!s64i>
+ // CHECK: %1 = cir.call @_Z9getMemberv() : () -> !s64i
+ // CHECK: cir.store %1, %0 : !s64i, !cir.ptr<!s64i>
+ // CHECK: }
}
diff --git a/clang/test/CIR/IR/invalid-global.cir b/clang/test/CIR/IR/invalid-global.cir
index dda5de7af9560..620cdbabb2c24 100644
--- a/clang/test/CIR/IR/invalid-global.cir
+++ b/clang/test/CIR/IR/invalid-global.cir
@@ -20,7 +20,7 @@ module {
cir.global external @target = #cir.int<42> : !s32i
// expected-error @below {{global alias shall not have an initializer or constructor/destructor regions}}
-cir.global external @bad_alias_with_ctor alias(@target) = ctor : !s32i {
+cir.global external @bad_alias_with_ctor alias(@target) = #cir.int<0> : !s32i ctor {
cir.yield
}
@@ -60,3 +60,18 @@ module {
cir.global external comdat(1) @bad_comdat = #cir.int<42> : !s32i
}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module {
+
+// The custom syntax always carries an initial value, so use the generic form.
+// expected-error @below {{cannot have a constructor region without an initial value}}
+"cir.global"() <{global_visibility = 0 : i32, linkage = #cir.linkage<external>, sym_name = "ctor_without_init", sym_type = !s32i}> ({
+ cir.yield
+}, {
+}) : () -> ()
+
+}
diff --git a/clang/test/CIR/IR/invalid-static-local.cir b/clang/test/CIR/IR/invalid-static-local.cir
index 31a7b1178d92e..6c3a73cb7984e 100644
--- a/clang/test/CIR/IR/invalid-static-local.cir
+++ b/clang/test/CIR/IR/invalid-static-local.cir
@@ -67,7 +67,7 @@ module {
cir.global "private" internal dynamic_init_guard<"_ZGVZ1fvE1y"> @_ZZ1fvE1y : !s32i
dynamic_init_info<local = true, tls = none, is_inline = false, tsk = undeclared>
-cir.global "private" internal @_AnotherGlobal = ctor : !s32i {
+cir.global "private" internal @_AnotherGlobal = #cir.int<0> : !s32i ctor {
// expected-error @below {{'cir.local_init' op expects ancestor op 'cir.func'}}
cir.local_init static_local @_ZZ1fvE1y ctor {
cir.yield
diff --git a/clang/unittests/CIR/ControlFlowTest.cpp b/clang/unittests/CIR/ControlFlowTest.cpp
index 47312d5e8843a..51b22c620c0a1 100644
--- a/clang/unittests/CIR/ControlFlowTest.cpp
+++ b/clang/unittests/CIR/ControlFlowTest.cpp
@@ -543,7 +543,7 @@ TEST_F(CIRControlFlowTest, CleanupScopeOp) {
TEST_F(CIRControlFlowTest, GlobalOpWithCtorAndDtor) {
OwningOpRef<ModuleOp> module = parse(R"CIR(
!s32i = !cir.int<s, 32>
- cir.global external @g = ctor : !s32i {
+ cir.global external @g = #cir.int<0> : !s32i ctor {
cir.yield
} dtor {
cir.yield
More information about the cfe-commits
mailing list