Skip to content

Commit 2028eb8

Browse files
committed
[CIR][CIRGen][TBAA] Add support for enum
1 parent 2ab0704 commit 2028eb8

File tree

4 files changed

+187
-12
lines changed

4 files changed

+187
-12
lines changed

clang/include/clang/CIR/MissingFeatures.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct MissingFeatures {
6060
static bool tbaa() { return false; }
6161
static bool tbaaStruct() { return false; }
6262
static bool tbaaTagForStruct() { return false; }
63-
static bool tbaaTagForEnum() { return false; }
63+
static bool tbaaTagForEnum() { return true; }
6464
static bool tbaaTagForBitInt() { return false; }
6565
static bool tbaaVTablePtr() { return false; }
6666
static bool tbaaIncompleteType() { return false; }

clang/lib/CIR/CodeGen/CIRGenTBAA.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,23 @@ cir::TBAAAttr CIRGenTBAA::getTypeInfoHelper(clang::QualType qty) {
174174
// Enum types are distinct types. In C++ they have "underlying types",
175175
// however they aren't related for TBAA.
176176
if (const EnumType *ety = dyn_cast<EnumType>(ty)) {
177-
assert(!cir::MissingFeatures::tbaaTagForEnum());
178-
return tbaa_NYI(mlirContext);
177+
assert(cir::MissingFeatures::tbaaTagForEnum());
178+
if (!features.CPlusPlus)
179+
return getTypeInfo(ety->getDecl()->getIntegerType());
180+
181+
// In C++ mode, types have linkage, so we can rely on the ODR and
182+
// on their mangled names, if they're external.
183+
// TODO: Is there a way to get a program-wide unique name for a
184+
// decl with local linkage or no linkage?
185+
if (!ety->getDecl()->isExternallyVisible())
186+
return getChar();
187+
188+
SmallString<256> outName;
189+
llvm::raw_svector_ostream out(outName);
190+
types.getCXXABI().getMangleContext().mangleCanonicalTypeName(
191+
QualType(ety, 0), out);
192+
return cir::TBAAScalarAttr::get(mlirContext, outName,
193+
types.convertType(qty));
179194
}
180195
if (const auto *eit = dyn_cast<BitIntType>(ty)) {
181196
assert(!cir::MissingFeatures::tbaaTagForBitInt());

clang/test/CIR/CodeGen/tbaa-enum.c

+12-9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// CIR: #tbaa[[CHAR:.*]] = #cir.tbaa_omnipotent_char
1515
// CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar<id = "int", type = !s32i>
1616
// CIR: #tbaa[[LONG_LONG:.*]] = #cir.tbaa_scalar<id = "long long", type = !s64i>
17+
// CIR: #tbaa[[LONG:.*]] = #cir.tbaa_scalar<id = "long", type = !s64i>
1718
// CIR: #tbaa[[SHORT:.*]] = #cir.tbaa_scalar<id = "short", type = !s16i>
1819

1920
typedef unsigned char uint8_t;
@@ -54,14 +55,14 @@ uint32_t g0(EnumAuto32 *E, uint32_t *val) {
5455
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !s32i
5556
// CIR: %[[U_C0:.*]] = cir.cast(integral, %[[C0]] : !s32i), !u32i
5657
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u32i>>, !cir.ptr<!u32i>
57-
// CIR: cir.store %[[U_C0]], %[[E_PTR]] : !u32i, !cir.ptr<!u32i> tbaa(#tbaa[[NYI]])
58+
// CIR: cir.store %[[U_C0]], %[[E_PTR]] : !u32i, !cir.ptr<!u32i> tbaa(#tbaa[[INT]])
5859
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u32i>>, !cir.ptr<!u32i>
5960
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u32i>, !u32i tbaa(#tbaa[[INT]])
6061
// CIR: cir.store %[[RET]], %{{.*}} : !u32i, !cir.ptr<!u32i>
6162

6263
// LLVM-LABEL: define{{.*}} i32 @g0(
6364
// LLVM: store i32 5, ptr %{{.*}}, align 4, !tbaa [[TAG_i32:!.*]]
64-
// LLVM: store i32 0, ptr %{{.*}}, align 4
65+
// LLVM: store i32 0, ptr %{{.*}}, align 4, !tbaa [[TAG_i32]]
6566
// LLVM: load i32, ptr %{{.*}}, align 4, !tbaa [[TAG_i32]]
6667
*val = 5;
6768
*E = RED_AUTO_32;
@@ -76,14 +77,14 @@ uint64_t g1(EnumAuto64 *E, uint64_t *val) {
7677
// CIR: cir.store %[[U_C5]], %[[VAL_PTR]] : !u64i, !cir.ptr<!u64i> tbaa(#tbaa[[LONG_LONG]])
7778
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !u64i
7879
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
79-
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u64i, !cir.ptr<!u64i> tbaa(#tbaa[[NYI]])
80+
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u64i, !cir.ptr<!u64i> tbaa(#tbaa[[LONG]])
8081
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
8182
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u64i>, !u64i tbaa(#tbaa[[LONG_LONG]])
8283
// CIR: cir.store %[[RET]], %{{.*}} : !u64i, !cir.ptr<!u64i>
8384

8485
// LLVM-LABEL: define{{.*}} i64 @g1(
8586
// LLVM: store i64 5, ptr %{{.*}}, align 8, !tbaa [[TAG_i64:!.*]]
86-
// LLVM: store i64 0, ptr %{{.*}}, align 8
87+
// LLVM: store i64 0, ptr %{{.*}}, align 8, !tbaa [[TAG_long:!.*]]
8788
// LLVM: load i64, ptr %{{.*}}, align 8, !tbaa [[TAG_i64]]
8889
*val = 5;
8990
*E = RED_AUTO_64;
@@ -98,14 +99,14 @@ uint16_t g2(Enum16 *E, uint16_t *val) {
9899
// CIR: cir.store %[[U_C5]], %[[VAL_PTR]] : !u16i, !cir.ptr<!u16i> tbaa(#tbaa[[SHORT]])
99100
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !u16i
100101
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u16i>>, !cir.ptr<!u16i>
101-
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u16i, !cir.ptr<!u16i> tbaa(#tbaa[[NYI]])
102+
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u16i, !cir.ptr<!u16i> tbaa(#tbaa[[SHORT]])
102103
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u16i>>, !cir.ptr<!u16i>
103104
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u16i>, !u16i tbaa(#tbaa[[SHORT]])
104105
// CIR: cir.store %[[RET]], %{{.*}} : !u16i, !cir.ptr<!u16i>
105106

106107
// LLVM-LABEL: define{{.*}} i16 @g2(
107108
// LLVM: store i16 5, ptr %{{.*}}, align 2, !tbaa [[TAG_i16:!.*]]
108-
// LLVM: store i16 0, ptr %{{.*}}, align 2
109+
// LLVM: store i16 0, ptr %{{.*}}, align 2, !tbaa [[TAG_i16]]
109110
// LLVM: load i16, ptr %{{.*}}, align 2, !tbaa [[TAG_i16]]
110111
*val = 5;
111112
*E = RED_16;
@@ -120,15 +121,15 @@ uint8_t g3(Enum8 *E, uint8_t *val) {
120121
// CIR: cir.store %[[U_C5]], %[[VAL_PTR]] : !u8i, !cir.ptr<!u8i> tbaa(#tbaa[[CHAR]])
121122
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !u8i
122123
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
123-
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u8i, !cir.ptr<!u8i> tbaa(#tbaa[[NYI]])
124+
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u8i, !cir.ptr<!u8i> tbaa(#tbaa[[CHAR]])
124125
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
125126
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u8i>, !u8i tbaa(#tbaa[[CHAR]])
126127
// CIR: cir.store %[[RET]], %{{.*}} : !u8i, !cir.ptr<!u8i>
127128

128129

129130
// LLVM-LABEL: define{{.*}} i8 @g3(
130131
// LLVM: store i8 5, ptr %{{.*}}, align 1, !tbaa [[TAG_i8:!.*]]
131-
// LLVM: store i8 0, ptr %{{.*}}, align 1
132+
// LLVM: store i8 0, ptr %{{.*}}, align 1, !tbaa [[TAG_i8]]
132133
// LLVM: load i8, ptr %{{.*}}, align 1, !tbaa [[TAG_i8]]
133134
*val = 5;
134135
*E = RED_8;
@@ -141,6 +142,8 @@ uint8_t g3(Enum8 *E, uint8_t *val) {
141142
// LLVM: [[TAG_c_tbaa]] = !{!"Simple C/C++ TBAA"}
142143
// LLVM: [[TAG_i64]] = !{[[TYPE_i64:!.*]], [[TYPE_i64]], i64 0}
143144
// LLVM: [[TYPE_i64]] = !{!"long long", [[TYPE_char]],
145+
// LLVM: [[TAG_long]] = !{[[TYPE_long:!.*]], [[TYPE_long]], i64 0}
146+
// LLVM: [[TYPE_long]] = !{!"long", [[TYPE_char]], i64 0}
144147
// LLVM: [[TAG_i16]] = !{[[TYPE_i16:!.*]], [[TYPE_i16]], i64 0}
145148
// LLVM: [[TYPE_i16]] = !{!"short", [[TYPE_char]],
146-
// LLVM: [[TAG_i8]] = !{[[TYPE_i8:!.*]], [[TYPE_char]], i64 0}
149+
// LLVM: [[TAG_i8]] = !{[[TYPE_i8:!.*]], [[TYPE_char]], i64 0}

clang/test/CIR/CodeGen/tbaa-enum.cpp

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// This is inspired from clang/test/CodeGen/tbaa.c, with both CIR and LLVM checks.
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -O1
3+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
4+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes
5+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
6+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O1 -disable-llvm-passes -relaxed-aliasing
7+
// RUN: FileCheck --check-prefix=NO-TBAA --input-file=%t.ll %s
8+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -O0 -disable-llvm-passes
9+
// RUN: FileCheck --check-prefix=NO-TBAA --input-file=%t.ll %s
10+
11+
// NO-TBAA-NOT: !tbaa
12+
13+
// CIR: #tbaa[[NYI:.*]] = #cir.tbaa
14+
// CIR: #tbaa[[CHAR:.*]] = #cir.tbaa_omnipotent_char
15+
// CIR: #tbaa[[INT:.*]] = #cir.tbaa_scalar<id = "int", type = !s32i>
16+
// CIR: #tbaa[[EnumAuto32:.*]] = #cir.tbaa_scalar<id = "_ZTS10EnumAuto32", type = !u32i>
17+
// CIR: #tbaa[[LONG_LONG:.*]] = #cir.tbaa_scalar<id = "long long", type = !s64i>
18+
// CIR: #tbaa[[EnumAuto64:.*]] = #cir.tbaa_scalar<id = "_ZTS10EnumAuto64", type = !u64i>
19+
// CIR: #tbaa[[SHORT:.*]] = #cir.tbaa_scalar<id = "short", type = !s16i>
20+
// CIR: #tbaa[[Enum16:.*]] = #cir.tbaa_scalar<id = "_ZTS6Enum16", type = !u16i>
21+
// CIR: #tbaa[[Enum8:.*]] = #cir.tbaa_scalar<id = "_ZTS5Enum8", type = !u8i>
22+
23+
24+
typedef unsigned char uint8_t;
25+
typedef unsigned short uint16_t;
26+
typedef unsigned int uint32_t;
27+
typedef unsigned long long uint64_t;
28+
29+
typedef enum {
30+
RED_AUTO_32,
31+
GREEN_AUTO_32,
32+
BLUE_AUTO_32
33+
} EnumAuto32;
34+
35+
typedef enum {
36+
RED_AUTO_64,
37+
GREEN_AUTO_64,
38+
BLUE_AUTO_64 = 0x100000000ull
39+
} EnumAuto64;
40+
41+
typedef enum : uint16_t {
42+
RED_16,
43+
GREEN_16,
44+
BLUE_16
45+
} Enum16;
46+
47+
typedef enum : uint8_t {
48+
RED_8,
49+
GREEN_8,
50+
BLUE_8
51+
} Enum8;
52+
53+
uint32_t g0(EnumAuto32 *E, uint32_t *val) {
54+
// CIR-LABEL: cir.func @_Z2g0
55+
// CIR: %[[C5:.*]] = cir.const #cir.int<5> : !s32i
56+
// CIR: %[[U_C5:.*]] = cir.cast(integral, %[[C5]] : !s32i), !u32i
57+
// CIR: %[[VAL_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u32i>>, !cir.ptr<!u32i>
58+
// CIR: cir.store %[[U_C5]], %[[VAL_PTR]] : !u32i, !cir.ptr<!u32i> tbaa(#tbaa[[INT]])
59+
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !u32i
60+
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u32i>>, !cir.ptr<!u32i>
61+
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u32i, !cir.ptr<!u32i> tbaa(#tbaa[[EnumAuto32]])
62+
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u32i>>, !cir.ptr<!u32i>
63+
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u32i>, !u32i tbaa(#tbaa[[INT]])
64+
// CIR: cir.store %[[RET]], %{{.*}} : !u32i, !cir.ptr<!u32i>
65+
66+
// LLVM-LABEL: define{{.*}} i32 @_Z2g0
67+
// LLVM: store i32 5, ptr %{{.*}}, align 4, !tbaa [[TAG_i32:!.*]]
68+
// LLVM: store i32 0, ptr %{{.*}}, align 4, !tbaa [[TAG_EnumAuto32:!.*]]
69+
// LLVM: load i32, ptr %{{.*}}, align 4, !tbaa [[TAG_i32]]
70+
*val = 5;
71+
*E = RED_AUTO_32;
72+
return *val;
73+
}
74+
75+
uint64_t g1(EnumAuto64 *E, uint64_t *val) {
76+
// CIR-LABEL: cir.func @_Z2g1
77+
// CIR: %[[C5:.*]] = cir.const #cir.int<5> : !s32i
78+
// CIR: %[[U_C5:.*]] = cir.cast(integral, %[[C5]] : !s32i), !u64i
79+
// CIR: %[[VAL_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
80+
// CIR: cir.store %[[U_C5]], %[[VAL_PTR]] : !u64i, !cir.ptr<!u64i> tbaa(#tbaa[[LONG_LONG]])
81+
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !u64i
82+
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
83+
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u64i, !cir.ptr<!u64i> tbaa(#tbaa[[EnumAuto64]])
84+
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u64i>>, !cir.ptr<!u64i>
85+
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u64i>, !u64i tbaa(#tbaa[[LONG_LONG]])
86+
// CIR: cir.store %[[RET]], %{{.*}} : !u64i, !cir.ptr<!u64i>
87+
88+
// LLVM-LABEL: define{{.*}} i64 @_Z2g1
89+
// LLVM: store i64 5, ptr %{{.*}}, align 8, !tbaa [[TAG_i64:!.*]]
90+
// LLVM: store i64 0, ptr %{{.*}}, align 8, !tbaa [[TAG_EnumAuto64:!.*]]
91+
// LLVM: load i64, ptr %{{.*}}, align 8, !tbaa [[TAG_i64]]
92+
*val = 5;
93+
*E = RED_AUTO_64;
94+
return *val;
95+
}
96+
97+
uint16_t g2(Enum16 *E, uint16_t *val) {
98+
// CIR-LABEL: cir.func @_Z2g2
99+
// CIR: %[[C5:.*]] = cir.const #cir.int<5> : !s32i
100+
// CIR: %[[U_C5:.*]] = cir.cast(integral, %[[C5]] : !s32i), !u16i
101+
// CIR: %[[VAL_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u16i>>, !cir.ptr<!u16i>
102+
// CIR: cir.store %[[U_C5]], %[[VAL_PTR]] : !u16i, !cir.ptr<!u16i> tbaa(#tbaa[[SHORT]])
103+
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !u16i
104+
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u16i>>, !cir.ptr<!u16i>
105+
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u16i, !cir.ptr<!u16i> tbaa(#tbaa[[Enum16]])
106+
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u16i>>, !cir.ptr<!u16i>
107+
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u16i>, !u16i tbaa(#tbaa[[SHORT]])
108+
// CIR: cir.store %[[RET]], %{{.*}} : !u16i, !cir.ptr<!u16i>
109+
110+
// LLVM-LABEL: define{{.*}} i16 @_Z2g2
111+
// LLVM: store i16 5, ptr %{{.*}}, align 2, !tbaa [[TAG_i16:!.*]]
112+
// LLVM: store i16 0, ptr %{{.*}}, align 2, !tbaa [[TAG_Enum16:!.*]]
113+
// LLVM: load i16, ptr %{{.*}}, align 2, !tbaa [[TAG_i16]]
114+
*val = 5;
115+
*E = RED_16;
116+
return *val;
117+
}
118+
119+
uint8_t g3(Enum8 *E, uint8_t *val) {
120+
// CIR-LABEL: cir.func @_Z2g3
121+
// CIR: %[[C5:.*]] = cir.const #cir.int<5> : !s32i
122+
// CIR: %[[U_C5:.*]] = cir.cast(integral, %[[C5]] : !s32i), !u8i
123+
// CIR: %[[VAL_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
124+
// CIR: cir.store %[[U_C5]], %[[VAL_PTR]] : !u8i, !cir.ptr<!u8i> tbaa(#tbaa[[CHAR]])
125+
// CIR: %[[C0:.*]] = cir.const #cir.int<0> : !u8i
126+
// CIR: %[[E_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
127+
// CIR: cir.store %[[C0]], %[[E_PTR]] : !u8i, !cir.ptr<!u8i> tbaa(#tbaa[[Enum8]])
128+
// CIR: %[[RET_PTR:.*]] = cir.load deref %{{.*}} : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
129+
// CIR: %[[RET:.*]] = cir.load %[[RET_PTR]] : !cir.ptr<!u8i>, !u8i tbaa(#tbaa[[CHAR]])
130+
// CIR: cir.store %[[RET]], %{{.*}} : !u8i, !cir.ptr<!u8i>
131+
132+
133+
// LLVM-LABEL: define{{.*}} i8 @_Z2g3
134+
// LLVM: store i8 5, ptr %{{.*}}, align 1, !tbaa [[TAG_i8:!.*]]
135+
// LLVM: store i8 0, ptr %{{.*}}, align 1, !tbaa [[TAG_Enum8:!.*]]
136+
// LLVM: load i8, ptr %{{.*}}, align 1, !tbaa [[TAG_i8]]
137+
*val = 5;
138+
*E = RED_8;
139+
return *val;
140+
}
141+
142+
// LLVM: [[TAG_i32]] = !{[[TYPE_i32:!.*]], [[TYPE_i32]], i64 0}
143+
// LLVM: [[TYPE_i32]] = !{!"int", [[TYPE_char:!.*]],
144+
// LLVM: [[TYPE_char]] = !{!"omnipotent char", [[TAG_c_tbaa:!.*]],
145+
// LLVM: [[TAG_c_tbaa]] = !{!"Simple C/C++ TBAA"}
146+
// LLVM: [[TAG_EnumAuto32]] = !{[[TYPE_EnumAuto32:!.*]], [[TYPE_EnumAuto32]], i64 0}
147+
// LLVM: [[TYPE_EnumAuto32]] = !{!"_ZTS10EnumAuto32", [[TYPE_char]],
148+
// LLVM: [[TAG_i64]] = !{[[TYPE_i64:!.*]], [[TYPE_i64]], i64 0}
149+
// LLVM: [[TYPE_i64]] = !{!"long long", [[TYPE_char]],
150+
// LLVM: [[TAG_EnumAuto64]] = !{[[TYPE_EnumAuto64:!.*]], [[TYPE_EnumAuto64]], i64 0}
151+
// LLVM: [[TYPE_EnumAuto64]] = !{!"_ZTS10EnumAuto64", [[TYPE_char]],
152+
// LLVM: [[TAG_i16]] = !{[[TYPE_i16:!.*]], [[TYPE_i16]], i64 0}
153+
// LLVM: [[TYPE_i16]] = !{!"short", [[TYPE_char]],
154+
// LLVM: [[TAG_Enum16]] = !{[[TYPE_Enum16:!.*]], [[TYPE_Enum16]], i64 0}
155+
// LLVM: [[TYPE_Enum16]] = !{!"_ZTS6Enum16", [[TYPE_char]],
156+
// LLVM: [[TAG_Enum8]] = !{[[TYPE_Enum8:!.*]], [[TYPE_Enum8]], i64 0}
157+
// LLVM: [[TYPE_Enum8]] = !{!"_ZTS5Enum8", [[TYPE_char]],

0 commit comments

Comments
 (0)