1//===- unittests/IR/MetadataTest.cpp - Metadata unit tests ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/IR/Metadata.h"
10#include "llvm/ADT/DenseMap.h"
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/IR/Constants.h"
13#include "llvm/IR/DIBuilder.h"
14#include "llvm/IR/DebugInfo.h"
15#include "llvm/IR/DebugInfoMetadata.h"
16#include "llvm/IR/Function.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/LLVMContext.h"
19#include "llvm/IR/Module.h"
20#include "llvm/IR/ModuleSlotTracker.h"
21#include "llvm/IR/Type.h"
22#include "llvm/IR/Verifier.h"
23#include "llvm/Support/raw_ostream.h"
24#include "gtest/gtest.h"
25#include <optional>
26using namespace llvm;
27
28namespace {
29
30TEST(ContextAndReplaceableUsesTest, FromContext) {
31 LLVMContext Context;
32 ContextAndReplaceableUses CRU(Context);
33 EXPECT_EQ(&Context, &CRU.getContext());
34 EXPECT_FALSE(CRU.hasReplaceableUses());
35 EXPECT_FALSE(CRU.getReplaceableUses());
36}
37
38TEST(ContextAndReplaceableUsesTest, FromReplaceableUses) {
39 LLVMContext Context;
40 ContextAndReplaceableUses CRU(std::make_unique<ReplaceableMetadataImpl>(args&: Context));
41 EXPECT_EQ(&Context, &CRU.getContext());
42 EXPECT_TRUE(CRU.hasReplaceableUses());
43 EXPECT_TRUE(CRU.getReplaceableUses());
44}
45
46TEST(ContextAndReplaceableUsesTest, makeReplaceable) {
47 LLVMContext Context;
48 ContextAndReplaceableUses CRU(Context);
49 CRU.makeReplaceable(ReplaceableUses: std::make_unique<ReplaceableMetadataImpl>(args&: Context));
50 EXPECT_EQ(&Context, &CRU.getContext());
51 EXPECT_TRUE(CRU.hasReplaceableUses());
52 EXPECT_TRUE(CRU.getReplaceableUses());
53}
54
55TEST(ContextAndReplaceableUsesTest, takeReplaceableUses) {
56 LLVMContext Context;
57 auto ReplaceableUses = std::make_unique<ReplaceableMetadataImpl>(args&: Context);
58 auto *Ptr = ReplaceableUses.get();
59 ContextAndReplaceableUses CRU(std::move(ReplaceableUses));
60 ReplaceableUses = CRU.takeReplaceableUses();
61 EXPECT_EQ(&Context, &CRU.getContext());
62 EXPECT_FALSE(CRU.hasReplaceableUses());
63 EXPECT_FALSE(CRU.getReplaceableUses());
64 EXPECT_EQ(Ptr, ReplaceableUses.get());
65}
66
67class MetadataTest : public testing::Test {
68public:
69 MetadataTest() : M("test", Context), Counter(0) {}
70
71protected:
72 LLVMContext Context;
73 Module M;
74 int Counter;
75
76 MDNode *getNode() { return MDNode::get(Context, MDs: std::nullopt); }
77 MDNode *getNode(Metadata *MD) { return MDNode::get(Context, MDs: MD); }
78 MDNode *getNode(Metadata *MD1, Metadata *MD2) {
79 Metadata *MDs[] = {MD1, MD2};
80 return MDNode::get(Context, MDs);
81 }
82
83 MDTuple *getTuple() { return MDTuple::getDistinct(Context, MDs: std::nullopt); }
84 DISubroutineType *getSubroutineType() {
85 return DISubroutineType::getDistinct(Context, Flags: DINode::FlagZero, CC: 0,
86 TypeArray: getNode(MD: nullptr));
87 }
88 DISubprogram *getSubprogram() {
89 return DISubprogram::getDistinct(
90 Context, Scope: nullptr, Name: "", LinkageName: "", File: nullptr, Line: 0, Type: nullptr, ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0,
91 Flags: DINode::FlagZero, SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
92 }
93 DIFile *getFile() {
94 return DIFile::getDistinct(Context, Filename: "file.c", Directory: "/path/to/dir");
95 }
96 DICompileUnit *getUnit() {
97 return DICompileUnit::getDistinct(
98 Context, SourceLanguage: 1, File: getFile(), Producer: "clang", IsOptimized: false, Flags: "-g", RuntimeVersion: 2, SplitDebugFilename: "",
99 EmissionKind: DICompileUnit::FullDebug, EnumTypes: getTuple(), RetainedTypes: getTuple(), GlobalVariables: getTuple(),
100 ImportedEntities: getTuple(), Macros: getTuple(), DWOId: 0, SplitDebugInlining: true, DebugInfoForProfiling: false,
101 NameTableKind: DICompileUnit::DebugNameTableKind::Default, RangesBaseAddress: false, SysRoot: "/", SDK: "");
102 }
103 DIType *getBasicType(StringRef Name) {
104 return DIBasicType::get(Context, Tag: dwarf::DW_TAG_unspecified_type, Name);
105 }
106 DIType *getDerivedType() {
107 return DIDerivedType::getDistinct(
108 Context, Tag: dwarf::DW_TAG_pointer_type, Name: "", File: nullptr, Line: 0, Scope: nullptr,
109 BaseType: getBasicType(Name: "basictype"), SizeInBits: 1, AlignInBits: 2, OffsetInBits: 0, DWARFAddressSpace: std::nullopt, PtrAuthData: {}, Flags: DINode::FlagZero);
110 }
111 Constant *getConstant() {
112 return ConstantInt::get(Ty: Type::getInt32Ty(C&: Context), V: Counter++);
113 }
114 ConstantAsMetadata *getConstantAsMetadata() {
115 return ConstantAsMetadata::get(C: getConstant());
116 }
117 DIType *getCompositeType() {
118 return DICompositeType::getDistinct(
119 Context, Tag: dwarf::DW_TAG_structure_type, Name: "", File: nullptr, Line: 0, Scope: nullptr, BaseType: nullptr,
120 SizeInBits: 32, AlignInBits: 32, OffsetInBits: 0, Flags: DINode::FlagZero, Elements: nullptr, RuntimeLang: 0, VTableHolder: nullptr, TemplateParams: nullptr, Identifier: "");
121 }
122 Function *getFunction(StringRef Name) {
123 return Function::Create(
124 Ty: FunctionType::get(Result: Type::getVoidTy(C&: Context), Params: std::nullopt, isVarArg: false),
125 Linkage: Function::ExternalLinkage, N: Name, M);
126 }
127};
128typedef MetadataTest MDStringTest;
129
130// Test that construction of MDString with different value produces different
131// MDString objects, even with the same string pointer and nulls in the string.
132TEST_F(MDStringTest, CreateDifferent) {
133 char x[3] = { 'f', 0, 'A' };
134 MDString *s1 = MDString::get(Context, Str: StringRef(&x[0], 3));
135 x[2] = 'B';
136 MDString *s2 = MDString::get(Context, Str: StringRef(&x[0], 3));
137 EXPECT_NE(s1, s2);
138}
139
140// Test that creation of MDStrings with the same string contents produces the
141// same MDString object, even with different pointers.
142TEST_F(MDStringTest, CreateSame) {
143 char x[4] = { 'a', 'b', 'c', 'X' };
144 char y[4] = { 'a', 'b', 'c', 'Y' };
145
146 MDString *s1 = MDString::get(Context, Str: StringRef(&x[0], 3));
147 MDString *s2 = MDString::get(Context, Str: StringRef(&y[0], 3));
148 EXPECT_EQ(s1, s2);
149}
150
151// Test that MDString prints out the string we fed it.
152TEST_F(MDStringTest, PrintingSimple) {
153 char str[14] = "testing 1 2 3";
154 MDString *s = MDString::get(Context, Str: StringRef(&str[0], 13));
155 strncpy(dest: str, src: "aaaaaaaaaaaaa", n: 14);
156
157 std::string Str;
158 raw_string_ostream oss(Str);
159 s->print(OS&: oss);
160 EXPECT_STREQ("!\"testing 1 2 3\"", oss.str().c_str());
161}
162
163// Test printing of MDString with non-printable characters.
164TEST_F(MDStringTest, PrintingComplex) {
165 char str[5] = {0, '\n', '"', '\\', (char)-1};
166 MDString *s = MDString::get(Context, Str: StringRef(str+0, 5));
167 std::string Str;
168 raw_string_ostream oss(Str);
169 s->print(OS&: oss);
170 EXPECT_STREQ("!\"\\00\\0A\\22\\\\\\FF\"", oss.str().c_str());
171}
172
173typedef MetadataTest MDNodeTest;
174
175// Test the two constructors, and containing other Constants.
176TEST_F(MDNodeTest, Simple) {
177 char x[3] = { 'a', 'b', 'c' };
178 char y[3] = { '1', '2', '3' };
179
180 MDString *s1 = MDString::get(Context, Str: StringRef(&x[0], 3));
181 MDString *s2 = MDString::get(Context, Str: StringRef(&y[0], 3));
182 ConstantAsMetadata *CI =
183 ConstantAsMetadata::get(C: ConstantInt::get(Context, V: APInt(8, 0)));
184
185 std::vector<Metadata *> V;
186 V.push_back(x: s1);
187 V.push_back(x: CI);
188 V.push_back(x: s2);
189
190 MDNode *n1 = MDNode::get(Context, MDs: V);
191 Metadata *const c1 = n1;
192 MDNode *n2 = MDNode::get(Context, MDs: c1);
193 Metadata *const c2 = n2;
194 MDNode *n3 = MDNode::get(Context, MDs: V);
195 MDNode *n4 = MDNode::getIfExists(Context, MDs: V);
196 MDNode *n5 = MDNode::getIfExists(Context, MDs: c1);
197 MDNode *n6 = MDNode::getIfExists(Context, MDs: c2);
198 EXPECT_NE(n1, n2);
199 EXPECT_EQ(n1, n3);
200 EXPECT_EQ(n4, n1);
201 EXPECT_EQ(n5, n2);
202 EXPECT_EQ(n6, (Metadata *)nullptr);
203
204 EXPECT_EQ(3u, n1->getNumOperands());
205 EXPECT_EQ(s1, n1->getOperand(0));
206 EXPECT_EQ(CI, n1->getOperand(1));
207 EXPECT_EQ(s2, n1->getOperand(2));
208
209 EXPECT_EQ(1u, n2->getNumOperands());
210 EXPECT_EQ(n1, n2->getOperand(0));
211}
212
213TEST_F(MDNodeTest, Delete) {
214 Constant *C = ConstantInt::get(Ty: Type::getInt32Ty(C&: Context), V: 1);
215 Instruction *I = new BitCastInst(C, Type::getInt32Ty(C&: Context));
216
217 Metadata *const V = LocalAsMetadata::get(Local: I);
218 MDNode *n = MDNode::get(Context, MDs: V);
219 TrackingMDRef wvh(n);
220
221 EXPECT_EQ(n, wvh);
222
223 I->deleteValue();
224}
225
226TEST_F(MDNodeTest, SelfReference) {
227 // !0 = !{!0}
228 // !1 = !{!0}
229 {
230 auto Temp = MDNode::getTemporary(Context, MDs: std::nullopt);
231 Metadata *Args[] = {Temp.get()};
232 MDNode *Self = MDNode::get(Context, MDs: Args);
233 Self->replaceOperandWith(I: 0, New: Self);
234 ASSERT_EQ(Self, Self->getOperand(0));
235
236 // Self-references should be distinct, so MDNode::get() should grab a
237 // uniqued node that references Self, not Self.
238 Args[0] = Self;
239 MDNode *Ref1 = MDNode::get(Context, MDs: Args);
240 MDNode *Ref2 = MDNode::get(Context, MDs: Args);
241 EXPECT_NE(Self, Ref1);
242 EXPECT_EQ(Ref1, Ref2);
243 }
244
245 // !0 = !{!0, !{}}
246 // !1 = !{!0, !{}}
247 {
248 auto Temp = MDNode::getTemporary(Context, MDs: std::nullopt);
249 Metadata *Args[] = {Temp.get(), MDNode::get(Context, MDs: std::nullopt)};
250 MDNode *Self = MDNode::get(Context, MDs: Args);
251 Self->replaceOperandWith(I: 0, New: Self);
252 ASSERT_EQ(Self, Self->getOperand(0));
253
254 // Self-references should be distinct, so MDNode::get() should grab a
255 // uniqued node that references Self, not Self itself.
256 Args[0] = Self;
257 MDNode *Ref1 = MDNode::get(Context, MDs: Args);
258 MDNode *Ref2 = MDNode::get(Context, MDs: Args);
259 EXPECT_NE(Self, Ref1);
260 EXPECT_EQ(Ref1, Ref2);
261 }
262}
263
264TEST_F(MDNodeTest, Print) {
265 Constant *C = ConstantInt::get(Ty: Type::getInt32Ty(C&: Context), V: 7);
266 MDString *S = MDString::get(Context, Str: "foo");
267 MDNode *N0 = getNode();
268 MDNode *N1 = getNode(MD: N0);
269 MDNode *N2 = getNode(MD1: N0, MD2: N1);
270
271 Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2};
272 MDNode *N = MDNode::get(Context, MDs: Args);
273
274 std::string Expected;
275 {
276 raw_string_ostream OS(Expected);
277 OS << "<" << (void *)N << "> = !{";
278 C->printAsOperand(O&: OS);
279 OS << ", ";
280 S->printAsOperand(OS);
281 OS << ", null";
282 MDNode *Nodes[] = {N0, N1, N2};
283 for (auto *Node : Nodes)
284 OS << ", <" << (void *)Node << ">";
285 OS << "}";
286 }
287
288 std::string Actual;
289 {
290 raw_string_ostream OS(Actual);
291 N->print(OS);
292 }
293
294 EXPECT_EQ(Expected, Actual);
295}
296
297#define EXPECT_PRINTER_EQ(EXPECTED, PRINT) \
298 do { \
299 std::string Actual_; \
300 raw_string_ostream OS(Actual_); \
301 PRINT; \
302 OS.flush(); \
303 std::string Expected_(EXPECTED); \
304 EXPECT_EQ(Expected_, Actual_); \
305 } while (false)
306
307TEST_F(MDNodeTest, PrintTemporary) {
308 MDNode *Arg = getNode();
309 TempMDNode Temp = MDNode::getTemporary(Context, MDs: Arg);
310 MDNode *N = getNode(MD: Temp.get());
311 Module M("test", Context);
312 NamedMDNode *NMD = M.getOrInsertNamedMetadata(Name: "named");
313 NMD->addOperand(M: N);
314
315 EXPECT_PRINTER_EQ("!0 = !{!1}", N->print(OS, &M));
316 EXPECT_PRINTER_EQ("!1 = <temporary!> !{!2}", Temp->print(OS, &M));
317 EXPECT_PRINTER_EQ("!2 = !{}", Arg->print(OS, &M));
318
319 // Cleanup.
320 Temp->replaceAllUsesWith(MD: Arg);
321}
322
323TEST_F(MDNodeTest, PrintFromModule) {
324 Constant *C = ConstantInt::get(Ty: Type::getInt32Ty(C&: Context), V: 7);
325 MDString *S = MDString::get(Context, Str: "foo");
326 MDNode *N0 = getNode();
327 MDNode *N1 = getNode(MD: N0);
328 MDNode *N2 = getNode(MD1: N0, MD2: N1);
329
330 Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2};
331 MDNode *N = MDNode::get(Context, MDs: Args);
332 Module M("test", Context);
333 NamedMDNode *NMD = M.getOrInsertNamedMetadata(Name: "named");
334 NMD->addOperand(M: N);
335
336 std::string Expected;
337 {
338 raw_string_ostream OS(Expected);
339 OS << "!0 = !{";
340 C->printAsOperand(O&: OS);
341 OS << ", ";
342 S->printAsOperand(OS);
343 OS << ", null, !1, !2, !3}";
344 }
345
346 EXPECT_PRINTER_EQ(Expected, N->print(OS, &M));
347}
348
349TEST_F(MDNodeTest, PrintFromFunction) {
350 Module M("test", Context);
351 auto *FTy = FunctionType::get(Result: Type::getVoidTy(C&: Context), isVarArg: false);
352 auto *F0 = Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F0", M: &M);
353 auto *F1 = Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F1", M: &M);
354 auto *BB0 = BasicBlock::Create(Context, Name: "entry", Parent: F0);
355 auto *BB1 = BasicBlock::Create(Context, Name: "entry", Parent: F1);
356 auto *R0 = ReturnInst::Create(C&: Context, InsertAtEnd: BB0);
357 auto *R1 = ReturnInst::Create(C&: Context, InsertAtEnd: BB1);
358 auto *N0 = MDNode::getDistinct(Context, MDs: std::nullopt);
359 auto *N1 = MDNode::getDistinct(Context, MDs: std::nullopt);
360 R0->setMetadata(Kind: "md", Node: N0);
361 R1->setMetadata(Kind: "md", Node: N1);
362
363 EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, &M));
364 EXPECT_PRINTER_EQ("!1 = distinct !{}", N1->print(OS, &M));
365
366 ModuleSlotTracker MST(&M);
367 EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, MST));
368 EXPECT_PRINTER_EQ("!1 = distinct !{}", N1->print(OS, MST));
369}
370
371TEST_F(MDNodeTest, PrintFromMetadataAsValue) {
372 Module M("test", Context);
373
374 auto *Intrinsic =
375 Function::Create(Ty: FunctionType::get(Result: Type::getVoidTy(C&: Context),
376 Params: Type::getMetadataTy(C&: Context), isVarArg: false),
377 Linkage: GlobalValue::ExternalLinkage, N: "llvm.intrinsic", M: &M);
378
379 auto *FTy = FunctionType::get(Result: Type::getVoidTy(C&: Context), isVarArg: false);
380 auto *F0 = Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F0", M: &M);
381 auto *F1 = Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F1", M: &M);
382 auto *BB0 = BasicBlock::Create(Context, Name: "entry", Parent: F0);
383 auto *BB1 = BasicBlock::Create(Context, Name: "entry", Parent: F1);
384 auto *N0 = MDNode::getDistinct(Context, MDs: std::nullopt);
385 auto *N1 = MDNode::getDistinct(Context, MDs: std::nullopt);
386 auto *MAV0 = MetadataAsValue::get(Context, MD: N0);
387 auto *MAV1 = MetadataAsValue::get(Context, MD: N1);
388 CallInst::Create(Func: Intrinsic, Args: MAV0, NameStr: "", InsertAtEnd: BB0);
389 CallInst::Create(Func: Intrinsic, Args: MAV1, NameStr: "", InsertAtEnd: BB1);
390
391 EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS));
392 EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS));
393 EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false));
394 EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false));
395 EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true));
396 EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true));
397
398 ModuleSlotTracker MST(&M);
399 EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS, MST));
400 EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS, MST));
401 EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false, MST));
402 EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false, MST));
403 EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true, MST));
404 EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true, MST));
405}
406
407TEST_F(MDNodeTest, PrintWithDroppedCallOperand) {
408 Module M("test", Context);
409
410 auto *FTy = FunctionType::get(Result: Type::getVoidTy(C&: Context), isVarArg: false);
411 auto *F0 = Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F0", M: &M);
412 auto *F1 = Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F1", M: &M);
413 auto *BB0 = BasicBlock::Create(Context, Name: "entry", Parent: F0);
414
415 CallInst *CI0 = CallInst::Create(Func: F1, NameStr: "", InsertAtEnd: BB0);
416 CI0->dropAllReferences();
417
418 auto *R0 = ReturnInst::Create(C&: Context, InsertAtEnd: BB0);
419 auto *N0 = MDNode::getDistinct(Context, MDs: std::nullopt);
420 R0->setMetadata(Kind: "md", Node: N0);
421
422 // Printing the metadata node would previously result in a failed assertion
423 // due to the call instruction's dropped function operand.
424 ModuleSlotTracker MST(&M);
425 EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, MST));
426}
427
428TEST_F(MDNodeTest, PrintTree) {
429 DILocalScope *Scope = getSubprogram();
430 DIFile *File = getFile();
431 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
432 {
433 DIType *Type = getDerivedType();
434 auto *Var = DILocalVariable::get(Context, Scope, Name: "foo", File,
435 /*LineNo=*/Line: 8, Type, /*ArgNo=*/Arg: 2, Flags,
436 /*Align=*/AlignInBits: 8, Annotations: nullptr);
437 std::string Expected;
438 {
439 raw_string_ostream SS(Expected);
440 Var->print(OS&: SS);
441 // indent level 1
442 Scope->print(OS&: (SS << "\n").indent(NumSpaces: 2));
443 File->print(OS&: (SS << "\n").indent(NumSpaces: 2));
444 Type->print(OS&: (SS << "\n").indent(NumSpaces: 2));
445 // indent level 2
446 auto *BaseType = cast<DIDerivedType>(Val: Type)->getBaseType();
447 BaseType->print(OS&: (SS << "\n").indent(NumSpaces: 4));
448 }
449
450 EXPECT_PRINTER_EQ(Expected, Var->printTree(OS));
451 }
452
453 {
454 // Test if printTree works correctly when there is
455 // a cycle in the MDNode and its dependencies.
456 //
457 // We're trying to create type like this:
458 // struct LinkedList {
459 // LinkedList *Head;
460 // };
461 auto *StructTy = cast<DICompositeType>(Val: getCompositeType());
462 DIType *PointerTy = DIDerivedType::getDistinct(
463 Context, Tag: dwarf::DW_TAG_pointer_type, Name: "", File: nullptr, Line: 0, Scope: nullptr, BaseType: StructTy,
464 SizeInBits: 1, AlignInBits: 2, OffsetInBits: 0, DWARFAddressSpace: std::nullopt, PtrAuthData: {}, Flags: DINode::FlagZero);
465 StructTy->replaceElements(Elements: MDTuple::get(Context, MDs: PointerTy));
466
467 auto *Var = DILocalVariable::get(Context, Scope, Name: "foo", File,
468 /*LineNo=*/Line: 8, Type: StructTy, /*ArgNo=*/Arg: 2, Flags,
469 /*Align=*/AlignInBits: 8, Annotations: nullptr);
470 std::string Expected;
471 {
472 raw_string_ostream SS(Expected);
473 Var->print(OS&: SS);
474 // indent level 1
475 Scope->print(OS&: (SS << "\n").indent(NumSpaces: 2));
476 File->print(OS&: (SS << "\n").indent(NumSpaces: 2));
477 StructTy->print(OS&: (SS << "\n").indent(NumSpaces: 2));
478 // indent level 2
479 StructTy->getRawElements()->print(OS&: (SS << "\n").indent(NumSpaces: 4));
480 // indent level 3
481 auto Elements = StructTy->getElements();
482 Elements[0]->print(OS&: (SS << "\n").indent(NumSpaces: 6));
483 }
484
485 EXPECT_PRINTER_EQ(Expected, Var->printTree(OS));
486 }
487}
488#undef EXPECT_PRINTER_EQ
489
490TEST_F(MDNodeTest, NullOperand) {
491 // metadata !{}
492 MDNode *Empty = MDNode::get(Context, MDs: std::nullopt);
493
494 // metadata !{metadata !{}}
495 Metadata *Ops[] = {Empty};
496 MDNode *N = MDNode::get(Context, MDs: Ops);
497 ASSERT_EQ(Empty, N->getOperand(0));
498
499 // metadata !{metadata !{}} => metadata !{null}
500 N->replaceOperandWith(I: 0, New: nullptr);
501 ASSERT_EQ(nullptr, N->getOperand(0));
502
503 // metadata !{null}
504 Ops[0] = nullptr;
505 MDNode *NullOp = MDNode::get(Context, MDs: Ops);
506 ASSERT_EQ(nullptr, NullOp->getOperand(0));
507 EXPECT_EQ(N, NullOp);
508}
509
510TEST_F(MDNodeTest, DistinctOnUniquingCollision) {
511 // !{}
512 MDNode *Empty = MDNode::get(Context, MDs: std::nullopt);
513 ASSERT_TRUE(Empty->isResolved());
514 EXPECT_FALSE(Empty->isDistinct());
515
516 // !{!{}}
517 Metadata *Wrapped1Ops[] = {Empty};
518 MDNode *Wrapped1 = MDNode::get(Context, MDs: Wrapped1Ops);
519 ASSERT_EQ(Empty, Wrapped1->getOperand(0));
520 ASSERT_TRUE(Wrapped1->isResolved());
521 EXPECT_FALSE(Wrapped1->isDistinct());
522
523 // !{!{!{}}}
524 Metadata *Wrapped2Ops[] = {Wrapped1};
525 MDNode *Wrapped2 = MDNode::get(Context, MDs: Wrapped2Ops);
526 ASSERT_EQ(Wrapped1, Wrapped2->getOperand(0));
527 ASSERT_TRUE(Wrapped2->isResolved());
528 EXPECT_FALSE(Wrapped2->isDistinct());
529
530 // !{!{!{}}} => !{!{}}
531 Wrapped2->replaceOperandWith(I: 0, New: Empty);
532 ASSERT_EQ(Empty, Wrapped2->getOperand(0));
533 EXPECT_TRUE(Wrapped2->isDistinct());
534 EXPECT_FALSE(Wrapped1->isDistinct());
535}
536
537TEST_F(MDNodeTest, UniquedOnDeletedOperand) {
538 // temp !{}
539 TempMDTuple T = MDTuple::getTemporary(Context, MDs: std::nullopt);
540
541 // !{temp !{}}
542 Metadata *Ops[] = {T.get()};
543 MDTuple *N = MDTuple::get(Context, MDs: Ops);
544
545 // !{temp !{}} => !{null}
546 T.reset();
547 ASSERT_TRUE(N->isUniqued());
548 Metadata *NullOps[] = {nullptr};
549 ASSERT_EQ(N, MDTuple::get(Context, NullOps));
550}
551
552TEST_F(MDNodeTest, DistinctOnDeletedValueOperand) {
553 // i1* @GV
554 Type *Ty = PointerType::getUnqual(C&: Context);
555 std::unique_ptr<GlobalVariable> GV(
556 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
557 ConstantAsMetadata *Op = ConstantAsMetadata::get(C: GV.get());
558
559 // !{i1* @GV}
560 Metadata *Ops[] = {Op};
561 MDTuple *N = MDTuple::get(Context, MDs: Ops);
562
563 // !{i1* @GV} => !{null}
564 GV.reset();
565 ASSERT_TRUE(N->isDistinct());
566 ASSERT_EQ(nullptr, N->getOperand(0));
567 Metadata *NullOps[] = {nullptr};
568 ASSERT_NE(N, MDTuple::get(Context, NullOps));
569}
570
571TEST_F(MDNodeTest, getDistinct) {
572 // !{}
573 MDNode *Empty = MDNode::get(Context, MDs: std::nullopt);
574 ASSERT_TRUE(Empty->isResolved());
575 ASSERT_FALSE(Empty->isDistinct());
576 ASSERT_EQ(Empty, MDNode::get(Context, std::nullopt));
577
578 // distinct !{}
579 MDNode *Distinct1 = MDNode::getDistinct(Context, MDs: std::nullopt);
580 MDNode *Distinct2 = MDNode::getDistinct(Context, MDs: std::nullopt);
581 EXPECT_TRUE(Distinct1->isResolved());
582 EXPECT_TRUE(Distinct2->isDistinct());
583 EXPECT_NE(Empty, Distinct1);
584 EXPECT_NE(Empty, Distinct2);
585 EXPECT_NE(Distinct1, Distinct2);
586
587 // !{}
588 ASSERT_EQ(Empty, MDNode::get(Context, std::nullopt));
589}
590
591TEST_F(MDNodeTest, isUniqued) {
592 MDNode *U = MDTuple::get(Context, MDs: std::nullopt);
593 MDNode *D = MDTuple::getDistinct(Context, MDs: std::nullopt);
594 auto T = MDTuple::getTemporary(Context, MDs: std::nullopt);
595 EXPECT_TRUE(U->isUniqued());
596 EXPECT_FALSE(D->isUniqued());
597 EXPECT_FALSE(T->isUniqued());
598}
599
600TEST_F(MDNodeTest, isDistinct) {
601 MDNode *U = MDTuple::get(Context, MDs: std::nullopt);
602 MDNode *D = MDTuple::getDistinct(Context, MDs: std::nullopt);
603 auto T = MDTuple::getTemporary(Context, MDs: std::nullopt);
604 EXPECT_FALSE(U->isDistinct());
605 EXPECT_TRUE(D->isDistinct());
606 EXPECT_FALSE(T->isDistinct());
607}
608
609TEST_F(MDNodeTest, isTemporary) {
610 MDNode *U = MDTuple::get(Context, MDs: std::nullopt);
611 MDNode *D = MDTuple::getDistinct(Context, MDs: std::nullopt);
612 auto T = MDTuple::getTemporary(Context, MDs: std::nullopt);
613 EXPECT_FALSE(U->isTemporary());
614 EXPECT_FALSE(D->isTemporary());
615 EXPECT_TRUE(T->isTemporary());
616}
617
618TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) {
619 // temporary !{}
620 auto Temp = MDTuple::getTemporary(Context, MDs: std::nullopt);
621 ASSERT_FALSE(Temp->isResolved());
622
623 // distinct !{temporary !{}}
624 Metadata *Ops[] = {Temp.get()};
625 MDNode *Distinct = MDNode::getDistinct(Context, MDs: Ops);
626 EXPECT_TRUE(Distinct->isResolved());
627 EXPECT_EQ(Temp.get(), Distinct->getOperand(0));
628
629 // temporary !{} => !{}
630 MDNode *Empty = MDNode::get(Context, MDs: std::nullopt);
631 Temp->replaceAllUsesWith(MD: Empty);
632 EXPECT_EQ(Empty, Distinct->getOperand(0));
633}
634
635TEST_F(MDNodeTest, handleChangedOperandRecursion) {
636 // !0 = !{}
637 MDNode *N0 = MDNode::get(Context, MDs: std::nullopt);
638
639 // !1 = !{!3, null}
640 auto Temp3 = MDTuple::getTemporary(Context, MDs: std::nullopt);
641 Metadata *Ops1[] = {Temp3.get(), nullptr};
642 MDNode *N1 = MDNode::get(Context, MDs: Ops1);
643
644 // !2 = !{!3, !0}
645 Metadata *Ops2[] = {Temp3.get(), N0};
646 MDNode *N2 = MDNode::get(Context, MDs: Ops2);
647
648 // !3 = !{!2}
649 Metadata *Ops3[] = {N2};
650 MDNode *N3 = MDNode::get(Context, MDs: Ops3);
651 Temp3->replaceAllUsesWith(MD: N3);
652
653 // !4 = !{!1}
654 Metadata *Ops4[] = {N1};
655 MDNode *N4 = MDNode::get(Context, MDs: Ops4);
656
657 // Confirm that the cycle prevented RAUW from getting dropped.
658 EXPECT_TRUE(N0->isResolved());
659 EXPECT_FALSE(N1->isResolved());
660 EXPECT_FALSE(N2->isResolved());
661 EXPECT_FALSE(N3->isResolved());
662 EXPECT_FALSE(N4->isResolved());
663
664 // Create a couple of distinct nodes to observe what's going on.
665 //
666 // !5 = distinct !{!2}
667 // !6 = distinct !{!3}
668 Metadata *Ops5[] = {N2};
669 MDNode *N5 = MDNode::getDistinct(Context, MDs: Ops5);
670 Metadata *Ops6[] = {N3};
671 MDNode *N6 = MDNode::getDistinct(Context, MDs: Ops6);
672
673 // Mutate !2 to look like !1, causing a uniquing collision (and an RAUW).
674 // This will ripple up, with !3 colliding with !4, and RAUWing. Since !2
675 // references !3, this can cause a re-entry of handleChangedOperand() when !3
676 // is not ready for it.
677 //
678 // !2->replaceOperandWith(1, nullptr)
679 // !2: !{!3, !0} => !{!3, null}
680 // !2->replaceAllUsesWith(!1)
681 // !3: !{!2] => !{!1}
682 // !3->replaceAllUsesWith(!4)
683 N2->replaceOperandWith(I: 1, New: nullptr);
684
685 // If all has gone well, N2 and N3 will have been RAUW'ed and deleted from
686 // under us. Just check that the other nodes are sane.
687 //
688 // !1 = !{!4, null}
689 // !4 = !{!1}
690 // !5 = distinct !{!1}
691 // !6 = distinct !{!4}
692 EXPECT_EQ(N4, N1->getOperand(0));
693 EXPECT_EQ(N1, N4->getOperand(0));
694 EXPECT_EQ(N1, N5->getOperand(0));
695 EXPECT_EQ(N4, N6->getOperand(0));
696}
697
698TEST_F(MDNodeTest, replaceResolvedOperand) {
699 // Check code for replacing one resolved operand with another. If doing this
700 // directly (via replaceOperandWith()) becomes illegal, change the operand to
701 // a global value that gets RAUW'ed.
702 //
703 // Use a temporary node to keep N from being resolved.
704 auto Temp = MDTuple::getTemporary(Context, MDs: std::nullopt);
705 Metadata *Ops[] = {nullptr, Temp.get()};
706
707 MDNode *Empty = MDTuple::get(Context, MDs: ArrayRef<Metadata *>());
708 MDNode *N = MDTuple::get(Context, MDs: Ops);
709 EXPECT_EQ(nullptr, N->getOperand(0));
710 ASSERT_FALSE(N->isResolved());
711
712 // Check code for replacing resolved nodes.
713 N->replaceOperandWith(I: 0, New: Empty);
714 EXPECT_EQ(Empty, N->getOperand(0));
715
716 // Check code for adding another unresolved operand.
717 N->replaceOperandWith(I: 0, New: Temp.get());
718 EXPECT_EQ(Temp.get(), N->getOperand(0));
719
720 // Remove the references to Temp; required for teardown.
721 Temp->replaceAllUsesWith(MD: nullptr);
722}
723
724TEST_F(MDNodeTest, replaceWithUniqued) {
725 auto *Empty = MDTuple::get(Context, MDs: std::nullopt);
726 MDTuple *FirstUniqued;
727 {
728 Metadata *Ops[] = {Empty};
729 auto Temp = MDTuple::getTemporary(Context, MDs: Ops);
730 EXPECT_TRUE(Temp->isTemporary());
731
732 // Don't expect a collision.
733 auto *Current = Temp.get();
734 FirstUniqued = MDNode::replaceWithUniqued(N: std::move(Temp));
735 EXPECT_TRUE(FirstUniqued->isUniqued());
736 EXPECT_TRUE(FirstUniqued->isResolved());
737 EXPECT_EQ(Current, FirstUniqued);
738 }
739 {
740 Metadata *Ops[] = {Empty};
741 auto Temp = MDTuple::getTemporary(Context, MDs: Ops);
742 EXPECT_TRUE(Temp->isTemporary());
743
744 // Should collide with Uniqued above this time.
745 auto *Uniqued = MDNode::replaceWithUniqued(N: std::move(Temp));
746 EXPECT_TRUE(Uniqued->isUniqued());
747 EXPECT_TRUE(Uniqued->isResolved());
748 EXPECT_EQ(FirstUniqued, Uniqued);
749 }
750 {
751 auto Unresolved = MDTuple::getTemporary(Context, MDs: std::nullopt);
752 Metadata *Ops[] = {Unresolved.get()};
753 auto Temp = MDTuple::getTemporary(Context, MDs: Ops);
754 EXPECT_TRUE(Temp->isTemporary());
755
756 // Shouldn't be resolved.
757 auto *Uniqued = MDNode::replaceWithUniqued(N: std::move(Temp));
758 EXPECT_TRUE(Uniqued->isUniqued());
759 EXPECT_FALSE(Uniqued->isResolved());
760
761 // Should be a different node.
762 EXPECT_NE(FirstUniqued, Uniqued);
763
764 // Should resolve when we update its node (note: be careful to avoid a
765 // collision with any other nodes above).
766 Uniqued->replaceOperandWith(I: 0, New: nullptr);
767 EXPECT_TRUE(Uniqued->isResolved());
768 }
769}
770
771TEST_F(MDNodeTest, replaceWithUniquedResolvingOperand) {
772 // temp !{}
773 MDTuple *Op = MDTuple::getTemporary(Context, MDs: std::nullopt).release();
774 EXPECT_FALSE(Op->isResolved());
775
776 // temp !{temp !{}}
777 Metadata *Ops[] = {Op};
778 MDTuple *N = MDTuple::getTemporary(Context, MDs: Ops).release();
779 EXPECT_FALSE(N->isResolved());
780
781 // temp !{temp !{}} => !{temp !{}}
782 ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));
783 EXPECT_FALSE(N->isResolved());
784
785 // !{temp !{}} => !{!{}}
786 ASSERT_EQ(Op, MDNode::replaceWithUniqued(TempMDTuple(Op)));
787 EXPECT_TRUE(Op->isResolved());
788 EXPECT_TRUE(N->isResolved());
789}
790
791TEST_F(MDNodeTest, replaceWithUniquedDeletedOperand) {
792 // i1* @GV
793 Type *Ty = PointerType::getUnqual(C&: Context);
794 std::unique_ptr<GlobalVariable> GV(
795 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
796 ConstantAsMetadata *Op = ConstantAsMetadata::get(C: GV.get());
797
798 // temp !{i1* @GV}
799 Metadata *Ops[] = {Op};
800 MDTuple *N = MDTuple::getTemporary(Context, MDs: Ops).release();
801
802 // temp !{i1* @GV} => !{i1* @GV}
803 ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));
804 ASSERT_TRUE(N->isUniqued());
805
806 // !{i1* @GV} => !{null}
807 GV.reset();
808 ASSERT_TRUE(N->isDistinct());
809 ASSERT_EQ(nullptr, N->getOperand(0));
810 Metadata *NullOps[] = {nullptr};
811 ASSERT_NE(N, MDTuple::get(Context, NullOps));
812}
813
814TEST_F(MDNodeTest, replaceWithUniquedChangedOperand) {
815 // i1* @GV
816 Type *Ty = PointerType::getUnqual(C&: Context);
817 std::unique_ptr<GlobalVariable> GV(
818 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
819 ConstantAsMetadata *Op = ConstantAsMetadata::get(C: GV.get());
820
821 // temp !{i1* @GV}
822 Metadata *Ops[] = {Op};
823 MDTuple *N = MDTuple::getTemporary(Context, MDs: Ops).release();
824
825 // temp !{i1* @GV} => !{i1* @GV}
826 ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));
827 ASSERT_TRUE(N->isUniqued());
828
829 // !{i1* @GV} => !{i1* @GV2}
830 std::unique_ptr<GlobalVariable> GV2(
831 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
832 GV->replaceAllUsesWith(V: GV2.get());
833 ASSERT_TRUE(N->isUniqued());
834 Metadata *NullOps[] = {ConstantAsMetadata::get(C: GV2.get())};
835 ASSERT_EQ(N, MDTuple::get(Context, NullOps));
836}
837
838TEST_F(MDNodeTest, replaceWithDistinct) {
839 {
840 auto *Empty = MDTuple::get(Context, MDs: std::nullopt);
841 Metadata *Ops[] = {Empty};
842 auto Temp = MDTuple::getTemporary(Context, MDs: Ops);
843 EXPECT_TRUE(Temp->isTemporary());
844
845 // Don't expect a collision.
846 auto *Current = Temp.get();
847 auto *Distinct = MDNode::replaceWithDistinct(N: std::move(Temp));
848 EXPECT_TRUE(Distinct->isDistinct());
849 EXPECT_TRUE(Distinct->isResolved());
850 EXPECT_EQ(Current, Distinct);
851 }
852 {
853 auto Unresolved = MDTuple::getTemporary(Context, MDs: std::nullopt);
854 Metadata *Ops[] = {Unresolved.get()};
855 auto Temp = MDTuple::getTemporary(Context, MDs: Ops);
856 EXPECT_TRUE(Temp->isTemporary());
857
858 // Don't expect a collision.
859 auto *Current = Temp.get();
860 auto *Distinct = MDNode::replaceWithDistinct(N: std::move(Temp));
861 EXPECT_TRUE(Distinct->isDistinct());
862 EXPECT_TRUE(Distinct->isResolved());
863 EXPECT_EQ(Current, Distinct);
864
865 // Cleanup; required for teardown.
866 Unresolved->replaceAllUsesWith(MD: nullptr);
867 }
868}
869
870TEST_F(MDNodeTest, replaceWithPermanent) {
871 Metadata *Ops[] = {nullptr};
872 auto Temp = MDTuple::getTemporary(Context, MDs: Ops);
873 auto *T = Temp.get();
874
875 // U is a normal, uniqued node that references T.
876 auto *U = MDTuple::get(Context, MDs: T);
877 EXPECT_TRUE(U->isUniqued());
878
879 // Make Temp self-referencing.
880 Temp->replaceOperandWith(I: 0, New: T);
881
882 // Try to uniquify Temp. This should, despite the name in the API, give a
883 // 'distinct' node, since self-references aren't allowed to be uniqued.
884 //
885 // Since it's distinct, N should have the same address as when it was a
886 // temporary (i.e., be equal to T not U).
887 auto *N = MDNode::replaceWithPermanent(N: std::move(Temp));
888 EXPECT_EQ(N, T);
889 EXPECT_TRUE(N->isDistinct());
890
891 // U should be the canonical unique node with N as the argument.
892 EXPECT_EQ(U, MDTuple::get(Context, N));
893 EXPECT_TRUE(U->isUniqued());
894
895 // This temporary should collide with U when replaced, but it should still be
896 // uniqued.
897 EXPECT_EQ(U, MDNode::replaceWithPermanent(MDTuple::getTemporary(Context, N)));
898 EXPECT_TRUE(U->isUniqued());
899
900 // This temporary should become a new uniqued node.
901 auto Temp2 = MDTuple::getTemporary(Context, MDs: U);
902 auto *V = Temp2.get();
903 EXPECT_EQ(V, MDNode::replaceWithPermanent(std::move(Temp2)));
904 EXPECT_TRUE(V->isUniqued());
905 EXPECT_EQ(U, V->getOperand(0));
906}
907
908TEST_F(MDNodeTest, deleteTemporaryWithTrackingRef) {
909 TrackingMDRef Ref;
910 EXPECT_EQ(nullptr, Ref.get());
911 {
912 auto Temp = MDTuple::getTemporary(Context, MDs: std::nullopt);
913 Ref.reset(MD: Temp.get());
914 EXPECT_EQ(Temp.get(), Ref.get());
915 }
916 EXPECT_EQ(nullptr, Ref.get());
917}
918
919typedef MetadataTest DILocationTest;
920
921TEST_F(DILocationTest, Merge) {
922 DISubprogram *N = getSubprogram();
923 DIScope *S = DILexicalBlock::get(Context, Scope: N, File: getFile(), Line: 3, Column: 4);
924
925 {
926 // Identical.
927 auto *A = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
928 auto *B = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
929 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
930 EXPECT_EQ(2u, M->getLine());
931 EXPECT_EQ(7u, M->getColumn());
932 EXPECT_EQ(N, M->getScope());
933 }
934
935 {
936 // Identical, different scopes.
937 auto *A = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
938 auto *B = DILocation::get(Context, Line: 2, Column: 7, Scope: S);
939 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
940 EXPECT_EQ(2u, M->getLine());
941 EXPECT_EQ(7u, M->getColumn());
942 EXPECT_EQ(N, M->getScope());
943 }
944
945 {
946 // Same line, different column.
947 auto *A = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
948 auto *B = DILocation::get(Context, Line: 2, Column: 10, Scope: S);
949 auto *M0 = DILocation::getMergedLocation(LocA: A, LocB: B);
950 auto *M1 = DILocation::getMergedLocation(LocA: B, LocB: A);
951 for (auto *M : {M0, M1}) {
952 EXPECT_EQ(2u, M->getLine());
953 EXPECT_EQ(0u, M->getColumn());
954 EXPECT_EQ(N, M->getScope());
955 }
956 }
957
958 {
959 // Different lines, same scopes.
960 auto *A = DILocation::get(Context, Line: 1, Column: 6, Scope: N);
961 auto *B = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
962 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
963 EXPECT_EQ(0u, M->getLine());
964 EXPECT_EQ(0u, M->getColumn());
965 EXPECT_EQ(N, M->getScope());
966 }
967
968 {
969 // Twisty locations, all different, same function.
970 auto *A = DILocation::get(Context, Line: 1, Column: 6, Scope: N);
971 auto *B = DILocation::get(Context, Line: 2, Column: 7, Scope: S);
972 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
973 EXPECT_EQ(0u, M->getLine());
974 EXPECT_EQ(0u, M->getColumn());
975 EXPECT_EQ(N, M->getScope());
976 }
977
978 {
979 // Different function, same inlined-at.
980 auto *F = getFile();
981 auto *SP1 = DISubprogram::getDistinct(Context, Scope: F, Name: "a", LinkageName: "a", File: F, Line: 0, Type: nullptr,
982 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
983 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
984 auto *SP2 = DISubprogram::getDistinct(Context, Scope: F, Name: "b", LinkageName: "b", File: F, Line: 0, Type: nullptr,
985 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
986 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
987
988 auto *I = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
989 auto *A = DILocation::get(Context, Line: 1, Column: 6, Scope: SP1, InlinedAt: I);
990 auto *B = DILocation::get(Context, Line: 3, Column: 8, Scope: SP2, InlinedAt: I);
991 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
992 EXPECT_EQ(2u, M->getLine());
993 EXPECT_EQ(7u, M->getColumn());
994 EXPECT_EQ(N, M->getScope());
995 EXPECT_EQ(nullptr, M->getInlinedAt());
996 }
997
998 {
999 // Different function, inlined-at same line, but different column.
1000 auto *F = getFile();
1001 auto *SP1 = DISubprogram::getDistinct(Context, Scope: F, Name: "a", LinkageName: "a", File: F, Line: 0, Type: nullptr,
1002 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1003 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1004 auto *SP2 = DISubprogram::getDistinct(Context, Scope: F, Name: "b", LinkageName: "b", File: F, Line: 0, Type: nullptr,
1005 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1006 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1007
1008 auto *IA = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
1009 auto *IB = DILocation::get(Context, Line: 2, Column: 8, Scope: N);
1010 auto *A = DILocation::get(Context, Line: 1, Column: 6, Scope: SP1, InlinedAt: IA);
1011 auto *B = DILocation::get(Context, Line: 3, Column: 8, Scope: SP2, InlinedAt: IB);
1012 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
1013 EXPECT_EQ(2u, M->getLine());
1014 EXPECT_EQ(0u, M->getColumn());
1015 EXPECT_EQ(N, M->getScope());
1016 EXPECT_EQ(nullptr, M->getInlinedAt());
1017 }
1018
1019 {
1020 // Completely different.
1021 auto *I = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
1022 auto *A = DILocation::get(Context, Line: 1, Column: 6, Scope: S, InlinedAt: I);
1023 auto *B = DILocation::get(Context, Line: 2, Column: 7, Scope: getSubprogram());
1024 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
1025 EXPECT_EQ(0u, M->getLine());
1026 EXPECT_EQ(0u, M->getColumn());
1027 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1028 EXPECT_EQ(S, M->getScope());
1029 EXPECT_EQ(nullptr, M->getInlinedAt());
1030 }
1031
1032 // Two locations, same line/column different file, inlined at the same place.
1033 {
1034 auto *FA = getFile();
1035 auto *FB = getFile();
1036 auto *FI = getFile();
1037
1038 auto *SPA = DISubprogram::getDistinct(Context, Scope: FA, Name: "a", LinkageName: "a", File: FA, Line: 0, Type: nullptr,
1039 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1040 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1041
1042 auto *SPB = DISubprogram::getDistinct(Context, Scope: FB, Name: "b", LinkageName: "b", File: FB, Line: 0, Type: nullptr,
1043 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1044 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1045
1046 auto *SPI = DISubprogram::getDistinct(Context, Scope: FI, Name: "i", LinkageName: "i", File: FI, Line: 0, Type: nullptr,
1047 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1048 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1049
1050 auto *I = DILocation::get(Context, Line: 3, Column: 8, Scope: SPI);
1051 auto *A = DILocation::get(Context, Line: 2, Column: 7, Scope: SPA, InlinedAt: I);
1052 auto *B = DILocation::get(Context, Line: 2, Column: 7, Scope: SPB, InlinedAt: I);
1053 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
1054 EXPECT_EQ(3u, M->getLine());
1055 EXPECT_EQ(8u, M->getColumn());
1056 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1057 EXPECT_EQ(SPI, M->getScope());
1058 EXPECT_EQ(nullptr, M->getInlinedAt());
1059 }
1060
1061 // Two locations, same line/column different file, one location with 2 scopes,
1062 // inlined at the same place.
1063 {
1064 auto *FA = getFile();
1065 auto *FB = getFile();
1066 auto *FI = getFile();
1067
1068 auto *SPA = DISubprogram::getDistinct(Context, Scope: FA, Name: "a", LinkageName: "a", File: FA, Line: 0, Type: nullptr,
1069 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1070 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1071
1072 auto *SPB = DISubprogram::getDistinct(Context, Scope: FB, Name: "b", LinkageName: "b", File: FB, Line: 0, Type: nullptr,
1073 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1074 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1075
1076 auto *SPI = DISubprogram::getDistinct(Context, Scope: FI, Name: "i", LinkageName: "i", File: FI, Line: 0, Type: nullptr,
1077 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1078 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1079
1080 auto *SPAScope = DILexicalBlock::getDistinct(Context, Scope: SPA, File: FA, Line: 4, Column: 9);
1081
1082 auto *I = DILocation::get(Context, Line: 3, Column: 8, Scope: SPI);
1083 auto *A = DILocation::get(Context, Line: 2, Column: 7, Scope: SPAScope, InlinedAt: I);
1084 auto *B = DILocation::get(Context, Line: 2, Column: 7, Scope: SPB, InlinedAt: I);
1085 auto *M = DILocation::getMergedLocation(LocA: A, LocB: B);
1086 EXPECT_EQ(3u, M->getLine());
1087 EXPECT_EQ(8u, M->getColumn());
1088 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1089 EXPECT_EQ(SPI, M->getScope());
1090 EXPECT_EQ(nullptr, M->getInlinedAt());
1091 }
1092
1093 // Merge a location in C, which is inlined-at in B that is inlined in A,
1094 // with a location in A that has the same scope, line and column as B's
1095 // inlined-at location.
1096 {
1097 auto *FA = getFile();
1098 auto *FB = getFile();
1099 auto *FC = getFile();
1100
1101 auto *SPA = DISubprogram::getDistinct(Context, Scope: FA, Name: "a", LinkageName: "a", File: FA, Line: 0, Type: nullptr,
1102 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1103 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1104
1105 auto *SPB = DISubprogram::getDistinct(Context, Scope: FB, Name: "b", LinkageName: "b", File: FB, Line: 0, Type: nullptr,
1106 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1107 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1108
1109 auto *SPC = DISubprogram::getDistinct(Context, Scope: FC, Name: "c", LinkageName: "c", File: FC, Line: 0, Type: nullptr,
1110 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1111 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1112
1113 auto *A = DILocation::get(Context, Line: 3, Column: 2, Scope: SPA);
1114 auto *B = DILocation::get(Context, Line: 2, Column: 4, Scope: SPB, InlinedAt: A);
1115 auto *C = DILocation::get(Context, Line: 13, Column: 2, Scope: SPC, InlinedAt: B);
1116 auto *M = DILocation::getMergedLocation(LocA: A, LocB: C);
1117 EXPECT_EQ(3u, M->getLine());
1118 EXPECT_EQ(2u, M->getColumn());
1119 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1120 EXPECT_EQ(SPA, M->getScope());
1121 EXPECT_EQ(nullptr, M->getInlinedAt());
1122 }
1123
1124 // Two inlined locations with the same scope, line and column
1125 // in the same inlined-at function at different line and column.
1126 {
1127 auto *FA = getFile();
1128 auto *FB = getFile();
1129 auto *FC = getFile();
1130
1131 auto *SPA = DISubprogram::getDistinct(Context, Scope: FA, Name: "a", LinkageName: "a", File: FA, Line: 0, Type: nullptr,
1132 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1133 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1134
1135 auto *SPB = DISubprogram::getDistinct(Context, Scope: FB, Name: "b", LinkageName: "b", File: FB, Line: 0, Type: nullptr,
1136 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1137 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1138
1139 auto *SPC = DISubprogram::getDistinct(Context, Scope: FC, Name: "c", LinkageName: "c", File: FC, Line: 0, Type: nullptr,
1140 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1141 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1142
1143 auto *A = DILocation::get(Context, Line: 10, Column: 20, Scope: SPA);
1144 auto *B1 = DILocation::get(Context, Line: 3, Column: 2, Scope: SPB, InlinedAt: A);
1145 auto *B2 = DILocation::get(Context, Line: 4, Column: 5, Scope: SPB, InlinedAt: A);
1146 auto *C1 = DILocation::get(Context, Line: 2, Column: 4, Scope: SPC, InlinedAt: B1);
1147 auto *C2 = DILocation::get(Context, Line: 2, Column: 4, Scope: SPC, InlinedAt: B2);
1148
1149 auto *M = DILocation::getMergedLocation(LocA: C1, LocB: C2);
1150 EXPECT_EQ(2u, M->getLine());
1151 EXPECT_EQ(4u, M->getColumn());
1152 EXPECT_EQ(SPC, M->getScope());
1153 ASSERT_NE(nullptr, M->getInlinedAt());
1154
1155 auto *I1 = M->getInlinedAt();
1156 EXPECT_EQ(0u, I1->getLine());
1157 EXPECT_EQ(0u, I1->getColumn());
1158 EXPECT_EQ(SPB, I1->getScope());
1159 EXPECT_EQ(A, I1->getInlinedAt());
1160 }
1161
1162 // Two locations, different line/column and scope in the same subprogram,
1163 // inlined at the same place. This should result in a 0:0 location with
1164 // the nearest common scope in the inlined function.
1165 {
1166 auto *FA = getFile();
1167 auto *FI = getFile();
1168
1169 auto *SPA = DISubprogram::getDistinct(Context, Scope: FA, Name: "a", LinkageName: "a", File: FA, Line: 0, Type: nullptr,
1170 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1171 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1172
1173 auto *SPI = DISubprogram::getDistinct(Context, Scope: FI, Name: "i", LinkageName: "i", File: FI, Line: 0, Type: nullptr,
1174 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1175 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1176
1177 // Nearest common scope for the two locations in a.
1178 auto *SPAScope1 = DILexicalBlock::getDistinct(Context, Scope: SPA, File: FA, Line: 4, Column: 9);
1179
1180 // Scope for the first location in a.
1181 auto *SPAScope2 =
1182 DILexicalBlock::getDistinct(Context, Scope: SPAScope1, File: FA, Line: 10, Column: 12);
1183
1184 // Scope for the second location in a.
1185 auto *SPAScope3 =
1186 DILexicalBlock::getDistinct(Context, Scope: SPAScope1, File: FA, Line: 20, Column: 8);
1187 auto *SPAScope4 =
1188 DILexicalBlock::getDistinct(Context, Scope: SPAScope3, File: FA, Line: 21, Column: 12);
1189
1190 auto *I = DILocation::get(Context, Line: 3, Column: 8, Scope: SPI);
1191 auto *A1 = DILocation::get(Context, Line: 12, Column: 7, Scope: SPAScope2, InlinedAt: I);
1192 auto *A2 = DILocation::get(Context, Line: 21, Column: 15, Scope: SPAScope4, InlinedAt: I);
1193 auto *M = DILocation::getMergedLocation(LocA: A1, LocB: A2);
1194 EXPECT_EQ(0u, M->getLine());
1195 EXPECT_EQ(0u, M->getColumn());
1196 EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
1197 EXPECT_EQ(SPAScope1, M->getScope());
1198 EXPECT_EQ(I, M->getInlinedAt());
1199 }
1200
1201 // Regression test to catch a case where an iterator was invalidated due to
1202 // handling the chain of inlined-at locations after the nearest common
1203 // location for the two arguments were found.
1204 {
1205 auto *FA = getFile();
1206 auto *FB = getFile();
1207 auto *FI = getFile();
1208
1209 auto *SPA = DISubprogram::getDistinct(Context, Scope: FA, Name: "a", LinkageName: "a", File: FA, Line: 0, Type: nullptr,
1210 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1211 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1212
1213 auto *SPB = DISubprogram::getDistinct(Context, Scope: FB, Name: "b", LinkageName: "b", File: FB, Line: 0, Type: nullptr,
1214 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1215 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1216
1217 auto *SPI = DISubprogram::getDistinct(Context, Scope: FI, Name: "i", LinkageName: "i", File: FI, Line: 0, Type: nullptr,
1218 ScopeLine: 0, ContainingType: nullptr, VirtualIndex: 0, ThisAdjustment: 0, Flags: DINode::FlagZero,
1219 SPFlags: DISubprogram::SPFlagZero, Unit: nullptr);
1220
1221 auto *SPAScope1 = DILexicalBlock::getDistinct(Context, Scope: SPA, File: FA, Line: 4, Column: 9);
1222 auto *SPAScope2 = DILexicalBlock::getDistinct(Context, Scope: SPA, File: FA, Line: 8, Column: 3);
1223
1224 DILocation *InlinedAt = nullptr;
1225
1226 // Create a chain of inlined-at locations.
1227 for (int i = 0; i < 256; i++) {
1228 InlinedAt = DILocation::get(Context, Line: 3 + i, Column: 8 + i, Scope: SPI, InlinedAt);
1229 }
1230
1231 auto *A1 = DILocation::get(Context, Line: 5, Column: 9, Scope: SPAScope1, InlinedAt);
1232 auto *A2 = DILocation::get(Context, Line: 9, Column: 8, Scope: SPAScope2, InlinedAt);
1233 auto *B = DILocation::get(Context, Line: 10, Column: 3, Scope: SPB, InlinedAt: A1);
1234 auto *M1 = DILocation::getMergedLocation(LocA: B, LocB: A2);
1235 EXPECT_EQ(0u, M1->getLine());
1236 EXPECT_EQ(0u, M1->getColumn());
1237 EXPECT_TRUE(isa<DILocalScope>(M1->getScope()));
1238 EXPECT_EQ(SPA, M1->getScope());
1239 EXPECT_EQ(InlinedAt, M1->getInlinedAt());
1240
1241 // Test the other argument order for good measure.
1242 auto *M2 = DILocation::getMergedLocation(LocA: A2, LocB: B);
1243 EXPECT_EQ(M1, M2);
1244 }
1245}
1246
1247TEST_F(DILocationTest, getDistinct) {
1248 MDNode *N = getSubprogram();
1249 DILocation *L0 = DILocation::getDistinct(Context, Line: 2, Column: 7, Scope: N);
1250 EXPECT_TRUE(L0->isDistinct());
1251 DILocation *L1 = DILocation::get(Context, Line: 2, Column: 7, Scope: N);
1252 EXPECT_FALSE(L1->isDistinct());
1253 EXPECT_EQ(L1, DILocation::get(Context, 2, 7, N));
1254}
1255
1256TEST_F(DILocationTest, getTemporary) {
1257 MDNode *N = MDNode::get(Context, MDs: std::nullopt);
1258 auto L = DILocation::getTemporary(Context, Line: 2, Column: 7, Scope: N);
1259 EXPECT_TRUE(L->isTemporary());
1260 EXPECT_FALSE(L->isResolved());
1261}
1262
1263TEST_F(DILocationTest, cloneTemporary) {
1264 MDNode *N = MDNode::get(Context, MDs: std::nullopt);
1265 auto L = DILocation::getTemporary(Context, Line: 2, Column: 7, Scope: N);
1266 EXPECT_TRUE(L->isTemporary());
1267 auto L2 = L->clone();
1268 EXPECT_TRUE(L2->isTemporary());
1269}
1270
1271TEST_F(DILocationTest, discriminatorEncoding) {
1272 EXPECT_EQ(0U, *DILocation::encodeDiscriminator(0, 0, 0));
1273
1274 // Encode base discriminator as a component: lsb is 0, then the value.
1275 // The other components are all absent, so we leave all the other bits 0.
1276 EXPECT_EQ(2U, *DILocation::encodeDiscriminator(1, 0, 0));
1277
1278 // Base discriminator component is empty, so lsb is 1. Next component is not
1279 // empty, so its lsb is 0, then its value (1). Next component is empty.
1280 // So the bit pattern is 101.
1281 EXPECT_EQ(5U, *DILocation::encodeDiscriminator(0, 1, 0));
1282
1283 // First 2 components are empty, so the bit pattern is 11. Then the
1284 // next component - ending up with 1011.
1285 EXPECT_EQ(0xbU, *DILocation::encodeDiscriminator(0, 0, 1));
1286
1287 // The bit pattern for the first 2 components is 11. The next bit is 0,
1288 // because the last component is not empty. We have 29 bits usable for
1289 // encoding, but we cap it at 12 bits uniformously for all components. We
1290 // encode the last component over 14 bits.
1291 EXPECT_EQ(0xfffbU, *DILocation::encodeDiscriminator(0, 0, 0xfff));
1292
1293 EXPECT_EQ(0x102U, *DILocation::encodeDiscriminator(1, 1, 0));
1294
1295 EXPECT_EQ(0x13eU, *DILocation::encodeDiscriminator(0x1f, 1, 0));
1296
1297 EXPECT_EQ(0x87feU, *DILocation::encodeDiscriminator(0x1ff, 1, 0));
1298
1299 EXPECT_EQ(0x1f3eU, *DILocation::encodeDiscriminator(0x1f, 0x1f, 0));
1300
1301 EXPECT_EQ(0x3ff3eU, *DILocation::encodeDiscriminator(0x1f, 0x1ff, 0));
1302
1303 EXPECT_EQ(0x1ff87feU, *DILocation::encodeDiscriminator(0x1ff, 0x1ff, 0));
1304
1305 EXPECT_EQ(0xfff9f3eU, *DILocation::encodeDiscriminator(0x1f, 0x1f, 0xfff));
1306
1307 EXPECT_EQ(0xffc3ff3eU, *DILocation::encodeDiscriminator(0x1f, 0x1ff, 0x1ff));
1308
1309 EXPECT_EQ(0xffcf87feU, *DILocation::encodeDiscriminator(0x1ff, 0x1f, 0x1ff));
1310
1311 EXPECT_EQ(0xe1ff87feU, *DILocation::encodeDiscriminator(0x1ff, 0x1ff, 7));
1312}
1313
1314TEST_F(DILocationTest, discriminatorEncodingNegativeTests) {
1315 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0, 0, 0x1000));
1316 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0x1000, 0, 0));
1317 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0, 0x1000, 0));
1318 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0, 0, 0x1000));
1319 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(0x1ff, 0x1ff, 8));
1320 EXPECT_EQ(std::nullopt, DILocation::encodeDiscriminator(
1321 std::numeric_limits<uint32_t>::max(),
1322 std::numeric_limits<uint32_t>::max(), 0));
1323}
1324
1325TEST_F(DILocationTest, discriminatorSpecialCases) {
1326 // We don't test getCopyIdentifier here because the only way
1327 // to set it is by constructing an encoded discriminator using
1328 // encodeDiscriminator, which is already tested.
1329 auto L1 = DILocation::get(Context, Line: 1, Column: 2, Scope: getSubprogram());
1330 EXPECT_EQ(0U, L1->getBaseDiscriminator());
1331 EXPECT_EQ(1U, L1->getDuplicationFactor());
1332
1333 EXPECT_EQ(L1, *L1->cloneWithBaseDiscriminator(0));
1334 EXPECT_EQ(L1, *L1->cloneByMultiplyingDuplicationFactor(0));
1335 EXPECT_EQ(L1, *L1->cloneByMultiplyingDuplicationFactor(1));
1336
1337 auto L2 = *L1->cloneWithBaseDiscriminator(D: 1);
1338 EXPECT_EQ(0U, L1->getBaseDiscriminator());
1339 EXPECT_EQ(1U, L1->getDuplicationFactor());
1340
1341 EXPECT_EQ(1U, L2->getBaseDiscriminator());
1342 EXPECT_EQ(1U, L2->getDuplicationFactor());
1343
1344 auto L3 = *L2->cloneByMultiplyingDuplicationFactor(DF: 2);
1345 EXPECT_EQ(1U, L3->getBaseDiscriminator());
1346 EXPECT_EQ(2U, L3->getDuplicationFactor());
1347
1348 EXPECT_EQ(L2, *L2->cloneByMultiplyingDuplicationFactor(1));
1349
1350 auto L4 = *L3->cloneByMultiplyingDuplicationFactor(DF: 4);
1351 EXPECT_EQ(1U, L4->getBaseDiscriminator());
1352 EXPECT_EQ(8U, L4->getDuplicationFactor());
1353
1354 auto L5 = *L4->cloneWithBaseDiscriminator(D: 2);
1355 EXPECT_EQ(2U, L5->getBaseDiscriminator());
1356 EXPECT_EQ(8U, L5->getDuplicationFactor());
1357
1358 // Check extreme cases
1359 auto L6 = *L1->cloneWithBaseDiscriminator(D: 0xfff);
1360 EXPECT_EQ(0xfffU, L6->getBaseDiscriminator());
1361 EXPECT_EQ(0xfffU, (*L6->cloneByMultiplyingDuplicationFactor(0xfff))
1362 ->getDuplicationFactor());
1363
1364 // Check we return std::nullopt for unencodable cases.
1365 EXPECT_EQ(std::nullopt, L4->cloneWithBaseDiscriminator(0x1000));
1366 EXPECT_EQ(std::nullopt, L4->cloneByMultiplyingDuplicationFactor(0x1000));
1367}
1368
1369
1370typedef MetadataTest GenericDINodeTest;
1371
1372TEST_F(GenericDINodeTest, get) {
1373 StringRef Header = "header";
1374 auto *Empty = MDNode::get(Context, MDs: std::nullopt);
1375 Metadata *Ops1[] = {Empty};
1376 auto *N = GenericDINode::get(Context, Tag: 15, Header, DwarfOps: Ops1);
1377 EXPECT_EQ(15u, N->getTag());
1378 EXPECT_EQ(2u, N->getNumOperands());
1379 EXPECT_EQ(Header, N->getHeader());
1380 EXPECT_EQ(MDString::get(Context, Header), N->getOperand(0));
1381 EXPECT_EQ(1u, N->getNumDwarfOperands());
1382 EXPECT_EQ(Empty, N->getDwarfOperand(0));
1383 EXPECT_EQ(Empty, N->getOperand(1));
1384 ASSERT_TRUE(N->isUniqued());
1385
1386 EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops1));
1387
1388 N->replaceOperandWith(I: 1, New: nullptr);
1389 EXPECT_EQ(15u, N->getTag());
1390 EXPECT_EQ(Header, N->getHeader());
1391 EXPECT_EQ(nullptr, N->getDwarfOperand(0));
1392 ASSERT_TRUE(N->isUniqued());
1393
1394 Metadata *Ops2[] = {nullptr};
1395 EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops2));
1396
1397 N->replaceDwarfOperandWith(I: 0, New: Empty);
1398 EXPECT_EQ(15u, N->getTag());
1399 EXPECT_EQ(Header, N->getHeader());
1400 EXPECT_EQ(Empty, N->getDwarfOperand(0));
1401 ASSERT_TRUE(N->isUniqued());
1402 EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops1));
1403
1404 TempGenericDINode Temp = N->clone();
1405 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
1406}
1407
1408TEST_F(GenericDINodeTest, getEmptyHeader) {
1409 // Canonicalize !"" to null.
1410 auto *N = GenericDINode::get(Context, Tag: 15, Header: StringRef(), DwarfOps: std::nullopt);
1411 EXPECT_EQ(StringRef(), N->getHeader());
1412 EXPECT_EQ(nullptr, N->getOperand(0));
1413}
1414
1415typedef MetadataTest DISubrangeTest;
1416
1417TEST_F(DISubrangeTest, get) {
1418 auto *N = DISubrange::get(Context, Count: 5, LowerBound: 7);
1419 auto Count = N->getCount();
1420 auto Lower = N->getLowerBound();
1421 EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());
1422 ASSERT_TRUE(Count);
1423 ASSERT_TRUE(isa<ConstantInt *>(Count));
1424 EXPECT_EQ(5, cast<ConstantInt *>(Count)->getSExtValue());
1425 EXPECT_EQ(7, cast<ConstantInt *>(Lower)->getSExtValue());
1426 EXPECT_EQ(N, DISubrange::get(Context, 5, 7));
1427 EXPECT_EQ(DISubrange::get(Context, 5, 0), DISubrange::get(Context, 5));
1428
1429 TempDISubrange Temp = N->clone();
1430 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
1431}
1432
1433TEST_F(DISubrangeTest, getEmptyArray) {
1434 auto *N = DISubrange::get(Context, Count: -1, LowerBound: 0);
1435 auto Count = N->getCount();
1436 auto Lower = N->getLowerBound();
1437 EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());
1438 ASSERT_TRUE(Count);
1439 ASSERT_TRUE(isa<ConstantInt *>(Count));
1440 EXPECT_EQ(-1, cast<ConstantInt *>(Count)->getSExtValue());
1441 EXPECT_EQ(0, cast<ConstantInt *>(Lower)->getSExtValue());
1442 EXPECT_EQ(N, DISubrange::get(Context, -1, 0));
1443}
1444
1445TEST_F(DISubrangeTest, getVariableCount) {
1446 DILocalScope *Scope = getSubprogram();
1447 DIFile *File = getFile();
1448 DIType *Type = getDerivedType();
1449 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
1450 auto *VlaExpr = DILocalVariable::get(Context, Scope, Name: "vla_expr", File, Line: 8,
1451 Type, Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1452
1453 auto *N = DISubrange::get(Context, CountNode: VlaExpr, LowerBound: 0);
1454 auto Count = N->getCount();
1455 auto Lower = N->getLowerBound();
1456 ASSERT_TRUE(Count);
1457 ASSERT_TRUE(isa<DIVariable *>(Count));
1458 EXPECT_EQ(VlaExpr, cast<DIVariable *>(Count));
1459 ASSERT_TRUE(isa<DIVariable>(N->getRawCountNode()));
1460 EXPECT_EQ(0, cast<ConstantInt *>(Lower)->getSExtValue());
1461 EXPECT_EQ("vla_expr", cast<DIVariable *>(Count)->getName());
1462 EXPECT_EQ(N, DISubrange::get(Context, VlaExpr, 0));
1463}
1464
1465TEST_F(DISubrangeTest, fortranAllocatableInt) {
1466 DILocalScope *Scope = getSubprogram();
1467 DIFile *File = getFile();
1468 DIType *Type = getDerivedType();
1469 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
1470 auto *LI = ConstantAsMetadata::get(
1471 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: -10));
1472 auto *UI = ConstantAsMetadata::get(
1473 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: 10));
1474 auto *SI = ConstantAsMetadata::get(
1475 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: 4));
1476 auto *UIother = ConstantAsMetadata::get(
1477 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: 20));
1478 auto *UVother = DILocalVariable::get(Context, Scope, Name: "ubother", File, Line: 8, Type,
1479 Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1480 auto *UEother = DIExpression::get(Context, Elements: {5, 6});
1481 auto *LIZero = ConstantAsMetadata::get(
1482 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: 0));
1483 auto *UIZero = ConstantAsMetadata::get(
1484 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: 0));
1485
1486 auto *N = DISubrange::get(Context, CountNode: nullptr, LowerBound: LI, UpperBound: UI, Stride: SI);
1487
1488 auto Lower = N->getLowerBound();
1489 ASSERT_TRUE(Lower);
1490 ASSERT_TRUE(isa<ConstantInt *>(Lower));
1491 EXPECT_EQ(cast<ConstantInt>(LI->getValue()), cast<ConstantInt *>(Lower));
1492
1493 auto Upper = N->getUpperBound();
1494 ASSERT_TRUE(Upper);
1495 ASSERT_TRUE(isa<ConstantInt *>(Upper));
1496 EXPECT_EQ(cast<ConstantInt>(UI->getValue()), cast<ConstantInt *>(Upper));
1497
1498 auto Stride = N->getStride();
1499 ASSERT_TRUE(Stride);
1500 ASSERT_TRUE(isa<ConstantInt *>(Stride));
1501 EXPECT_EQ(cast<ConstantInt>(SI->getValue()), cast<ConstantInt *>(Stride));
1502
1503 EXPECT_EQ(N, DISubrange::get(Context, nullptr, LI, UI, SI));
1504
1505 EXPECT_NE(N, DISubrange::get(Context, nullptr, LI, UIother, SI));
1506 EXPECT_NE(N, DISubrange::get(Context, nullptr, LI, UEother, SI));
1507 EXPECT_NE(N, DISubrange::get(Context, nullptr, LI, UVother, SI));
1508
1509 auto *NZeroLower = DISubrange::get(Context, CountNode: nullptr, LowerBound: LIZero, UpperBound: UI, Stride: SI);
1510 EXPECT_NE(NZeroLower, DISubrange::get(Context, nullptr, nullptr, UI, SI));
1511
1512 auto *NZeroUpper = DISubrange::get(Context, CountNode: nullptr, LowerBound: LI, UpperBound: UIZero, Stride: SI);
1513 EXPECT_NE(NZeroUpper, DISubrange::get(Context, nullptr, LI, nullptr, SI));
1514}
1515
1516TEST_F(DISubrangeTest, fortranAllocatableVar) {
1517 DILocalScope *Scope = getSubprogram();
1518 DIFile *File = getFile();
1519 DIType *Type = getDerivedType();
1520 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
1521 auto *LV =
1522 DILocalVariable::get(Context, Scope, Name: "lb", File, Line: 8, Type, Arg: 2, Flags, AlignInBits: 8,
1523 Annotations: nullptr);
1524 auto *UV =
1525 DILocalVariable::get(Context, Scope, Name: "ub", File, Line: 8, Type, Arg: 2, Flags, AlignInBits: 8,
1526 Annotations: nullptr);
1527 auto *SV =
1528 DILocalVariable::get(Context, Scope, Name: "st", File, Line: 8, Type, Arg: 2, Flags, AlignInBits: 8,
1529 Annotations: nullptr);
1530 auto *SVother = DILocalVariable::get(Context, Scope, Name: "stother", File, Line: 8, Type,
1531 Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1532 auto *SIother = ConstantAsMetadata::get(
1533 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: 20));
1534 auto *SEother = DIExpression::get(Context, Elements: {5, 6});
1535
1536 auto *N = DISubrange::get(Context, CountNode: nullptr, LowerBound: LV, UpperBound: UV, Stride: SV);
1537
1538 auto Lower = N->getLowerBound();
1539 ASSERT_TRUE(Lower);
1540 ASSERT_TRUE(isa<DIVariable *>(Lower));
1541 EXPECT_EQ(LV, cast<DIVariable *>(Lower));
1542
1543 auto Upper = N->getUpperBound();
1544 ASSERT_TRUE(Upper);
1545 ASSERT_TRUE(isa<DIVariable *>(Upper));
1546 EXPECT_EQ(UV, cast<DIVariable *>(Upper));
1547
1548 auto Stride = N->getStride();
1549 ASSERT_TRUE(Stride);
1550 ASSERT_TRUE(isa<DIVariable *>(Stride));
1551 EXPECT_EQ(SV, cast<DIVariable *>(Stride));
1552
1553 EXPECT_EQ(N, DISubrange::get(Context, nullptr, LV, UV, SV));
1554
1555 EXPECT_NE(N, DISubrange::get(Context, nullptr, LV, UV, SVother));
1556 EXPECT_NE(N, DISubrange::get(Context, nullptr, LV, UV, SEother));
1557 EXPECT_NE(N, DISubrange::get(Context, nullptr, LV, UV, SIother));
1558}
1559
1560TEST_F(DISubrangeTest, fortranAllocatableExpr) {
1561 DILocalScope *Scope = getSubprogram();
1562 DIFile *File = getFile();
1563 DIType *Type = getDerivedType();
1564 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
1565 auto *LE = DIExpression::get(Context, Elements: {1, 2});
1566 auto *UE = DIExpression::get(Context, Elements: {2, 3});
1567 auto *SE = DIExpression::get(Context, Elements: {3, 4});
1568 auto *LEother = DIExpression::get(Context, Elements: {5, 6});
1569 auto *LIother = ConstantAsMetadata::get(
1570 C: ConstantInt::getSigned(Ty: Type::getInt64Ty(C&: Context), V: 20));
1571 auto *LVother = DILocalVariable::get(Context, Scope, Name: "lbother", File, Line: 8, Type,
1572 Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1573
1574 auto *N = DISubrange::get(Context, CountNode: nullptr, LowerBound: LE, UpperBound: UE, Stride: SE);
1575
1576 auto Lower = N->getLowerBound();
1577 ASSERT_TRUE(Lower);
1578 ASSERT_TRUE(isa<DIExpression *>(Lower));
1579 EXPECT_EQ(LE, cast<DIExpression *>(Lower));
1580
1581 auto Upper = N->getUpperBound();
1582 ASSERT_TRUE(Upper);
1583 ASSERT_TRUE(isa<DIExpression *>(Upper));
1584 EXPECT_EQ(UE, cast<DIExpression *>(Upper));
1585
1586 auto Stride = N->getStride();
1587 ASSERT_TRUE(Stride);
1588 ASSERT_TRUE(isa<DIExpression *>(Stride));
1589 EXPECT_EQ(SE, cast<DIExpression *>(Stride));
1590
1591 EXPECT_EQ(N, DISubrange::get(Context, nullptr, LE, UE, SE));
1592
1593 EXPECT_NE(N, DISubrange::get(Context, nullptr, LEother, UE, SE));
1594 EXPECT_NE(N, DISubrange::get(Context, nullptr, LIother, UE, SE));
1595 EXPECT_NE(N, DISubrange::get(Context, nullptr, LVother, UE, SE));
1596}
1597
1598typedef MetadataTest DIGenericSubrangeTest;
1599
1600TEST_F(DIGenericSubrangeTest, fortranAssumedRankInt) {
1601 DILocalScope *Scope = getSubprogram();
1602 DIFile *File = getFile();
1603 DIType *Type = getDerivedType();
1604 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
1605 auto *LI = DIExpression::get(
1606 Context, Elements: {dwarf::DW_OP_consts, static_cast<uint64_t>(-10)});
1607 auto *UI = DIExpression::get(Context, Elements: {dwarf::DW_OP_consts, 10});
1608 auto *SI = DIExpression::get(Context, Elements: {dwarf::DW_OP_consts, 4});
1609 auto *UIother = DIExpression::get(Context, Elements: {dwarf::DW_OP_consts, 20});
1610 auto *UVother = DILocalVariable::get(Context, Scope, Name: "ubother", File, Line: 8, Type,
1611 Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1612 auto *UEother = DIExpression::get(Context, Elements: {5, 6});
1613 auto *LIZero = DIExpression::get(Context, Elements: {dwarf::DW_OP_consts, 0});
1614 auto *UIZero = DIExpression::get(Context, Elements: {dwarf::DW_OP_consts, 0});
1615
1616 auto *N = DIGenericSubrange::get(Context, CountNode: nullptr, LowerBound: LI, UpperBound: UI, Stride: SI);
1617
1618 auto Lower = N->getLowerBound();
1619 ASSERT_TRUE(Lower);
1620 ASSERT_TRUE(isa<DIExpression *>(Lower));
1621 EXPECT_EQ(dyn_cast_or_null<DIExpression>(LI), cast<DIExpression *>(Lower));
1622
1623 auto Upper = N->getUpperBound();
1624 ASSERT_TRUE(Upper);
1625 ASSERT_TRUE(isa<DIExpression *>(Upper));
1626 EXPECT_EQ(dyn_cast_or_null<DIExpression>(UI), cast<DIExpression *>(Upper));
1627
1628 auto Stride = N->getStride();
1629 ASSERT_TRUE(Stride);
1630 ASSERT_TRUE(isa<DIExpression *>(Stride));
1631 EXPECT_EQ(dyn_cast_or_null<DIExpression>(SI), cast<DIExpression *>(Stride));
1632
1633 EXPECT_EQ(N, DIGenericSubrange::get(Context, nullptr, LI, UI, SI));
1634
1635 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LI, UIother, SI));
1636 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LI, UEother, SI));
1637 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LI, UVother, SI));
1638
1639 auto *NZeroLower = DIGenericSubrange::get(Context, CountNode: nullptr, LowerBound: LIZero, UpperBound: UI, Stride: SI);
1640 EXPECT_NE(NZeroLower,
1641 DIGenericSubrange::get(Context, nullptr, nullptr, UI, SI));
1642
1643 auto *NZeroUpper = DIGenericSubrange::get(Context, CountNode: nullptr, LowerBound: LI, UpperBound: UIZero, Stride: SI);
1644 EXPECT_NE(NZeroUpper,
1645 DIGenericSubrange::get(Context, nullptr, LI, nullptr, SI));
1646}
1647
1648TEST_F(DIGenericSubrangeTest, fortranAssumedRankVar) {
1649 DILocalScope *Scope = getSubprogram();
1650 DIFile *File = getFile();
1651 DIType *Type = getDerivedType();
1652 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
1653 auto *LV =
1654 DILocalVariable::get(Context, Scope, Name: "lb", File, Line: 8, Type, Arg: 2, Flags, AlignInBits: 8,
1655 Annotations: nullptr);
1656 auto *UV =
1657 DILocalVariable::get(Context, Scope, Name: "ub", File, Line: 8, Type, Arg: 2, Flags, AlignInBits: 8,
1658 Annotations: nullptr);
1659 auto *SV =
1660 DILocalVariable::get(Context, Scope, Name: "st", File, Line: 8, Type, Arg: 2, Flags, AlignInBits: 8,
1661 Annotations: nullptr);
1662 auto *SVother = DILocalVariable::get(Context, Scope, Name: "stother", File, Line: 8, Type,
1663 Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1664 auto *SIother = DIExpression::get(
1665 Context, Elements: {dwarf::DW_OP_consts, static_cast<uint64_t>(-1)});
1666 auto *SEother = DIExpression::get(Context, Elements: {5, 6});
1667
1668 auto *N = DIGenericSubrange::get(Context, CountNode: nullptr, LowerBound: LV, UpperBound: UV, Stride: SV);
1669
1670 auto Lower = N->getLowerBound();
1671 ASSERT_TRUE(Lower);
1672 ASSERT_TRUE(isa<DIVariable *>(Lower));
1673 EXPECT_EQ(LV, cast<DIVariable *>(Lower));
1674
1675 auto Upper = N->getUpperBound();
1676 ASSERT_TRUE(Upper);
1677 ASSERT_TRUE(isa<DIVariable *>(Upper));
1678 EXPECT_EQ(UV, cast<DIVariable *>(Upper));
1679
1680 auto Stride = N->getStride();
1681 ASSERT_TRUE(Stride);
1682 ASSERT_TRUE(isa<DIVariable *>(Stride));
1683 EXPECT_EQ(SV, cast<DIVariable *>(Stride));
1684
1685 EXPECT_EQ(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SV));
1686
1687 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SVother));
1688 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SEother));
1689 EXPECT_NE(N, DIGenericSubrange::get(Context, nullptr, LV, UV, SIother));
1690}
1691
1692TEST_F(DIGenericSubrangeTest, useDIBuilder) {
1693 DILocalScope *Scope = getSubprogram();
1694 DIFile *File = getFile();
1695 DIType *Type = getDerivedType();
1696 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
1697 auto *LV =
1698 DILocalVariable::get(Context, Scope, Name: "lb", File, Line: 8, Type, Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1699 auto *UE = DIExpression::get(Context, Elements: {2, 3});
1700 auto *SE = DIExpression::get(Context, Elements: {3, 4});
1701
1702 auto *LVother = DILocalVariable::get(Context, Scope, Name: "lbother", File, Line: 8, Type,
1703 Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
1704 auto *LIother = DIExpression::get(
1705 Context, Elements: {dwarf::DW_OP_consts, static_cast<uint64_t>(-1)});
1706
1707 Module M("M", Context);
1708 DIBuilder DIB(M);
1709
1710 auto *N = DIB.getOrCreateGenericSubrange(
1711 Count: DIGenericSubrange::BoundType(nullptr), LowerBound: DIGenericSubrange::BoundType(LV),
1712 UpperBound: DIGenericSubrange::BoundType(UE), Stride: DIGenericSubrange::BoundType(SE));
1713
1714 auto Lower = N->getLowerBound();
1715 ASSERT_TRUE(Lower);
1716 ASSERT_TRUE(isa<DIVariable *>(Lower));
1717 EXPECT_EQ(LV, cast<DIVariable *>(Lower));
1718
1719 auto Upper = N->getUpperBound();
1720 ASSERT_TRUE(Upper);
1721 ASSERT_TRUE(isa<DIExpression *>(Upper));
1722 EXPECT_EQ(UE, cast<DIExpression *>(Upper));
1723
1724 auto Stride = N->getStride();
1725 ASSERT_TRUE(Stride);
1726 ASSERT_TRUE(isa<DIExpression *>(Stride));
1727 EXPECT_EQ(SE, cast<DIExpression *>(Stride));
1728
1729 EXPECT_EQ(
1730 N, DIB.getOrCreateGenericSubrange(DIGenericSubrange::BoundType(nullptr),
1731 DIGenericSubrange::BoundType(LV),
1732 DIGenericSubrange::BoundType(UE),
1733 DIGenericSubrange::BoundType(SE)));
1734
1735 EXPECT_NE(
1736 N, DIB.getOrCreateGenericSubrange(DIGenericSubrange::BoundType(nullptr),
1737 DIGenericSubrange::BoundType(LVother),
1738 DIGenericSubrange::BoundType(UE),
1739 DIGenericSubrange::BoundType(SE)));
1740 EXPECT_NE(
1741 N, DIB.getOrCreateGenericSubrange(DIGenericSubrange::BoundType(nullptr),
1742 DIGenericSubrange::BoundType(LIother),
1743 DIGenericSubrange::BoundType(UE),
1744 DIGenericSubrange::BoundType(SE)));
1745}
1746typedef MetadataTest DIEnumeratorTest;
1747
1748TEST_F(DIEnumeratorTest, get) {
1749 auto *N = DIEnumerator::get(Context, Value: 7, IsUnsigned: false, Name: "name");
1750 EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag());
1751 EXPECT_EQ(7, N->getValue().getSExtValue());
1752 EXPECT_FALSE(N->isUnsigned());
1753 EXPECT_EQ("name", N->getName());
1754 EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name"));
1755
1756 EXPECT_NE(N, DIEnumerator::get(Context, 7, true, "name"));
1757 EXPECT_NE(N, DIEnumerator::get(Context, 8, false, "name"));
1758 EXPECT_NE(N, DIEnumerator::get(Context, 7, false, "nam"));
1759
1760 TempDIEnumerator Temp = N->clone();
1761 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
1762}
1763
1764TEST_F(DIEnumeratorTest, getWithLargeValues) {
1765 auto *N = DIEnumerator::get(Context, Value: APInt::getMaxValue(numBits: 128), IsUnsigned: false, Name: "val");
1766 EXPECT_EQ(128U, N->getValue().popcount());
1767 EXPECT_EQ(N,
1768 DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val"));
1769 EXPECT_NE(N,
1770 DIEnumerator::get(Context, APInt::getMinValue(128), false, "val"));
1771}
1772
1773typedef MetadataTest DIBasicTypeTest;
1774
1775TEST_F(DIBasicTypeTest, get) {
1776 auto *N =
1777 DIBasicType::get(Context, Tag: dwarf::DW_TAG_base_type, Name: "special", SizeInBits: 33, AlignInBits: 26, Encoding: 7,
1778 Flags: DINode::FlagZero);
1779 EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag());
1780 EXPECT_EQ("special", N->getName());
1781 EXPECT_EQ(33u, N->getSizeInBits());
1782 EXPECT_EQ(26u, N->getAlignInBits());
1783 EXPECT_EQ(7u, N->getEncoding());
1784 EXPECT_EQ(0u, N->getLine());
1785 EXPECT_EQ(DINode::FlagZero, N->getFlags());
1786 EXPECT_EQ(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
1787 26, 7, DINode::FlagZero));
1788
1789 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type,
1790 "special", 33, 26, 7, DINode::FlagZero));
1791 EXPECT_NE(N,
1792 DIBasicType::get(Context, dwarf::DW_TAG_base_type, "s", 33, 26, 7,
1793 DINode::FlagZero));
1794 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 32,
1795 26, 7, DINode::FlagZero));
1796 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
1797 25, 7, DINode::FlagZero));
1798 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
1799 26, 6, DINode::FlagZero));
1800 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
1801 26, 7, DINode::FlagBigEndian));
1802 EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
1803 26, 7, DINode::FlagLittleEndian));
1804
1805 TempDIBasicType Temp = N->clone();
1806 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
1807}
1808
1809TEST_F(DIBasicTypeTest, getWithLargeValues) {
1810 auto *N = DIBasicType::get(Context, Tag: dwarf::DW_TAG_base_type, Name: "special",
1811 UINT64_MAX, UINT32_MAX - 1, Encoding: 7, Flags: DINode::FlagZero);
1812 EXPECT_EQ(UINT64_MAX, N->getSizeInBits());
1813 EXPECT_EQ(UINT32_MAX - 1, N->getAlignInBits());
1814}
1815
1816TEST_F(DIBasicTypeTest, getUnspecified) {
1817 auto *N =
1818 DIBasicType::get(Context, Tag: dwarf::DW_TAG_unspecified_type, Name: "unspecified");
1819 EXPECT_EQ(dwarf::DW_TAG_unspecified_type, N->getTag());
1820 EXPECT_EQ("unspecified", N->getName());
1821 EXPECT_EQ(0u, N->getSizeInBits());
1822 EXPECT_EQ(0u, N->getAlignInBits());
1823 EXPECT_EQ(0u, N->getEncoding());
1824 EXPECT_EQ(0u, N->getLine());
1825 EXPECT_EQ(DINode::FlagZero, N->getFlags());
1826}
1827
1828typedef MetadataTest DITypeTest;
1829
1830TEST_F(DITypeTest, clone) {
1831 // Check that DIType has a specialized clone that returns TempDIType.
1832 DIType *N = DIBasicType::get(Context, Tag: dwarf::DW_TAG_base_type, Name: "int", SizeInBits: 32, AlignInBits: 32,
1833 Encoding: dwarf::DW_ATE_signed, Flags: DINode::FlagZero);
1834
1835 TempDIType Temp = N->clone();
1836 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
1837}
1838
1839TEST_F(DITypeTest, cloneWithFlags) {
1840 // void (void)
1841 Metadata *TypesOps[] = {nullptr};
1842 Metadata *Types = MDTuple::get(Context, MDs: TypesOps);
1843
1844 DIType *D =
1845 DISubroutineType::getDistinct(Context, Flags: DINode::FlagZero, CC: 0, TypeArray: Types);
1846 EXPECT_EQ(DINode::FlagZero, D->getFlags());
1847 TempDIType D2 = D->cloneWithFlags(NewFlags: DINode::FlagRValueReference);
1848 EXPECT_EQ(DINode::FlagRValueReference, D2->getFlags());
1849 EXPECT_EQ(DINode::FlagZero, D->getFlags());
1850
1851 TempDIType T =
1852 DISubroutineType::getTemporary(Context, Flags: DINode::FlagZero, CC: 0, TypeArray: Types);
1853 EXPECT_EQ(DINode::FlagZero, T->getFlags());
1854 TempDIType T2 = T->cloneWithFlags(NewFlags: DINode::FlagRValueReference);
1855 EXPECT_EQ(DINode::FlagRValueReference, T2->getFlags());
1856 EXPECT_EQ(DINode::FlagZero, T->getFlags());
1857}
1858
1859typedef MetadataTest DIDerivedTypeTest;
1860
1861TEST_F(DIDerivedTypeTest, get) {
1862 DIFile *File = getFile();
1863 DIScope *Scope = getSubprogram();
1864 DIType *BaseType = getBasicType(Name: "basic");
1865 MDTuple *ExtraData = getTuple();
1866 unsigned DWARFAddressSpace = 8;
1867 DIDerivedType::PtrAuthData PtrAuthData(1, false, 1234, true, true);
1868 DIDerivedType::PtrAuthData PtrAuthData2(1, false, 1234, true, false);
1869 DINode::DIFlags Flags5 = static_cast<DINode::DIFlags>(5);
1870 DINode::DIFlags Flags4 = static_cast<DINode::DIFlags>(4);
1871
1872 auto *N = DIDerivedType::get(
1873 Context, Tag: dwarf::DW_TAG_pointer_type, Name: "something", File, Line: 1, Scope,
1874 BaseType, SizeInBits: 2, AlignInBits: 3, OffsetInBits: 4, DWARFAddressSpace, PtrAuthData: std::nullopt, Flags: Flags5, ExtraData);
1875 auto *N1 = DIDerivedType::get(Context, Tag: dwarf::DW_TAG_LLVM_ptrauth_type, Name: "",
1876 File, Line: 1, Scope, BaseType: N, SizeInBits: 2, AlignInBits: 3, OffsetInBits: 4, DWARFAddressSpace,
1877 PtrAuthData, Flags: Flags5, ExtraData);
1878 EXPECT_EQ(dwarf::DW_TAG_pointer_type, N->getTag());
1879 EXPECT_EQ("something", N->getName());
1880 EXPECT_EQ(File, N->getFile());
1881 EXPECT_EQ(1u, N->getLine());
1882 EXPECT_EQ(Scope, N->getScope());
1883 EXPECT_EQ(BaseType, N->getBaseType());
1884 EXPECT_EQ(2u, N->getSizeInBits());
1885 EXPECT_EQ(3u, N->getAlignInBits());
1886 EXPECT_EQ(4u, N->getOffsetInBits());
1887 EXPECT_EQ(DWARFAddressSpace, *N->getDWARFAddressSpace());
1888 EXPECT_EQ(std::nullopt, N->getPtrAuthData());
1889 EXPECT_EQ(PtrAuthData, N1->getPtrAuthData());
1890 EXPECT_NE(PtrAuthData2, N1->getPtrAuthData());
1891 EXPECT_EQ(5u, N->getFlags());
1892 EXPECT_EQ(ExtraData, N->getExtraData());
1893 EXPECT_EQ(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1894 "something", File, 1, Scope, BaseType, 2, 3,
1895 4, DWARFAddressSpace, std::nullopt, Flags5,
1896 ExtraData));
1897
1898 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_reference_type,
1899 "something", File, 1, Scope, BaseType, 2, 3,
1900 4, DWARFAddressSpace, std::nullopt, Flags5,
1901 ExtraData));
1902 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "else",
1903 File, 1, Scope, BaseType, 2, 3, 4,
1904 DWARFAddressSpace, std::nullopt, Flags5,
1905 ExtraData));
1906 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1907 "something", getFile(), 1, Scope, BaseType, 2,
1908 3, 4, DWARFAddressSpace, std::nullopt, Flags5,
1909 ExtraData));
1910 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1911 "something", File, 2, Scope, BaseType, 2, 3,
1912 4, DWARFAddressSpace, std::nullopt, Flags5,
1913 ExtraData));
1914 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1915 "something", File, 1, getSubprogram(),
1916 BaseType, 2, 3, 4, DWARFAddressSpace,
1917 std::nullopt, Flags5, ExtraData));
1918 EXPECT_NE(N, DIDerivedType::get(
1919 Context, dwarf::DW_TAG_pointer_type, "something", File, 1,
1920 Scope, getBasicType("basic2"), 2, 3, 4, DWARFAddressSpace,
1921 std::nullopt, Flags5, ExtraData));
1922 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1923 "something", File, 1, Scope, BaseType, 3, 3,
1924 4, DWARFAddressSpace, std::nullopt, Flags5,
1925 ExtraData));
1926 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1927 "something", File, 1, Scope, BaseType, 2, 2,
1928 4, DWARFAddressSpace, std::nullopt, Flags5,
1929 ExtraData));
1930 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1931 "something", File, 1, Scope, BaseType, 2, 3,
1932 5, DWARFAddressSpace, std::nullopt, Flags5,
1933 ExtraData));
1934 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1935 "something", File, 1, Scope, BaseType, 2, 3,
1936 4, DWARFAddressSpace + 1, std::nullopt,
1937 Flags5, ExtraData));
1938 EXPECT_NE(N1,
1939 DIDerivedType::get(Context, dwarf::DW_TAG_LLVM_ptrauth_type, "",
1940 File, 1, Scope, N, 2, 3, 4, DWARFAddressSpace,
1941 std::nullopt, Flags5, ExtraData));
1942 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1943 "something", File, 1, Scope, BaseType, 2, 3,
1944 4, DWARFAddressSpace, std::nullopt, Flags4,
1945 ExtraData));
1946 EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
1947 "something", File, 1, Scope, BaseType, 2, 3,
1948 4, DWARFAddressSpace, std::nullopt, Flags5,
1949 getTuple()));
1950
1951 TempDIDerivedType Temp = N->clone();
1952 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
1953 TempDIDerivedType Temp1 = N1->clone();
1954 EXPECT_EQ(N1, MDNode::replaceWithUniqued(std::move(Temp1)));
1955}
1956
1957TEST_F(DIDerivedTypeTest, getWithLargeValues) {
1958 DIFile *File = getFile();
1959 DIScope *Scope = getSubprogram();
1960 DIType *BaseType = getBasicType(Name: "basic");
1961 MDTuple *ExtraData = getTuple();
1962 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
1963
1964 auto *N = DIDerivedType::get(Context, Tag: dwarf::DW_TAG_pointer_type, Name: "something",
1965 File, Line: 1, Scope, BaseType, UINT64_MAX,
1966 UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3,
1967 PtrAuthData: std::nullopt, Flags, ExtraData);
1968 EXPECT_EQ(UINT64_MAX, N->getSizeInBits());
1969 EXPECT_EQ(UINT32_MAX - 1, N->getAlignInBits());
1970 EXPECT_EQ(UINT64_MAX - 2, N->getOffsetInBits());
1971 EXPECT_EQ(UINT32_MAX - 3, *N->getDWARFAddressSpace());
1972
1973 auto *N1 = DIDerivedType::get(
1974 Context, Tag: dwarf::DW_TAG_LLVM_ptrauth_type, Name: "", File, Line: 1, Scope, BaseType: N,
1975 UINT64_MAX, UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3,
1976 PtrAuthData: DIDerivedType::PtrAuthData(7, true, 0xffff, true, false), Flags,
1977 ExtraData);
1978 EXPECT_EQ(7U, N1->getPtrAuthData()->key());
1979 EXPECT_EQ(true, N1->getPtrAuthData()->isAddressDiscriminated());
1980 EXPECT_EQ(0xffffU, N1->getPtrAuthData()->extraDiscriminator());
1981}
1982
1983typedef MetadataTest DICompositeTypeTest;
1984
1985TEST_F(DICompositeTypeTest, get) {
1986 unsigned Tag = dwarf::DW_TAG_structure_type;
1987 StringRef Name = "some name";
1988 DIFile *File = getFile();
1989 unsigned Line = 1;
1990 DIScope *Scope = getSubprogram();
1991 DIType *BaseType = getCompositeType();
1992 uint64_t SizeInBits = 2;
1993 uint32_t AlignInBits = 3;
1994 uint64_t OffsetInBits = 4;
1995 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
1996 MDTuple *Elements = getTuple();
1997 unsigned RuntimeLang = 6;
1998 DIType *VTableHolder = getCompositeType();
1999 MDTuple *TemplateParams = getTuple();
2000 StringRef Identifier = "some id";
2001
2002 auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2003 BaseType, SizeInBits, AlignInBits,
2004 OffsetInBits, Flags, Elements, RuntimeLang,
2005 VTableHolder, TemplateParams, Identifier);
2006 EXPECT_EQ(Tag, N->getTag());
2007 EXPECT_EQ(Name, N->getName());
2008 EXPECT_EQ(File, N->getFile());
2009 EXPECT_EQ(Line, N->getLine());
2010 EXPECT_EQ(Scope, N->getScope());
2011 EXPECT_EQ(BaseType, N->getBaseType());
2012 EXPECT_EQ(SizeInBits, N->getSizeInBits());
2013 EXPECT_EQ(AlignInBits, N->getAlignInBits());
2014 EXPECT_EQ(OffsetInBits, N->getOffsetInBits());
2015 EXPECT_EQ(Flags, N->getFlags());
2016 EXPECT_EQ(Elements, N->getElements().get());
2017 EXPECT_EQ(RuntimeLang, N->getRuntimeLang());
2018 EXPECT_EQ(VTableHolder, N->getVTableHolder());
2019 EXPECT_EQ(TemplateParams, N->getTemplateParams().get());
2020 EXPECT_EQ(Identifier, N->getIdentifier());
2021
2022 EXPECT_EQ(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2023 BaseType, SizeInBits, AlignInBits,
2024 OffsetInBits, Flags, Elements, RuntimeLang,
2025 VTableHolder, TemplateParams, Identifier));
2026
2027 EXPECT_NE(N, DICompositeType::get(Context, Tag + 1, Name, File, Line, Scope,
2028 BaseType, SizeInBits, AlignInBits,
2029 OffsetInBits, Flags, Elements, RuntimeLang,
2030 VTableHolder, TemplateParams, Identifier));
2031 EXPECT_NE(N, DICompositeType::get(Context, Tag, "abc", File, Line, Scope,
2032 BaseType, SizeInBits, AlignInBits,
2033 OffsetInBits, Flags, Elements, RuntimeLang,
2034 VTableHolder, TemplateParams, Identifier));
2035 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, getFile(), Line, Scope,
2036 BaseType, SizeInBits, AlignInBits,
2037 OffsetInBits, Flags, Elements, RuntimeLang,
2038 VTableHolder, TemplateParams, Identifier));
2039 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line + 1, Scope,
2040 BaseType, SizeInBits, AlignInBits,
2041 OffsetInBits, Flags, Elements, RuntimeLang,
2042 VTableHolder, TemplateParams, Identifier));
2043 EXPECT_NE(N, DICompositeType::get(
2044 Context, Tag, Name, File, Line, getSubprogram(), BaseType,
2045 SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
2046 RuntimeLang, VTableHolder, TemplateParams, Identifier));
2047 EXPECT_NE(N, DICompositeType::get(
2048 Context, Tag, Name, File, Line, Scope, getBasicType("other"),
2049 SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
2050 RuntimeLang, VTableHolder, TemplateParams, Identifier));
2051 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2052 BaseType, SizeInBits + 1, AlignInBits,
2053 OffsetInBits, Flags, Elements, RuntimeLang,
2054 VTableHolder, TemplateParams, Identifier));
2055 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2056 BaseType, SizeInBits, AlignInBits + 1,
2057 OffsetInBits, Flags, Elements, RuntimeLang,
2058 VTableHolder, TemplateParams, Identifier));
2059 EXPECT_NE(N, DICompositeType::get(
2060 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
2061 AlignInBits, OffsetInBits + 1, Flags, Elements, RuntimeLang,
2062 VTableHolder, TemplateParams, Identifier));
2063 DINode::DIFlags FlagsPOne = static_cast<DINode::DIFlags>(Flags + 1);
2064 EXPECT_NE(N, DICompositeType::get(
2065 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
2066 AlignInBits, OffsetInBits, FlagsPOne, Elements, RuntimeLang,
2067 VTableHolder, TemplateParams, Identifier));
2068 EXPECT_NE(N, DICompositeType::get(
2069 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
2070 AlignInBits, OffsetInBits, Flags, getTuple(), RuntimeLang,
2071 VTableHolder, TemplateParams, Identifier));
2072 EXPECT_NE(N, DICompositeType::get(
2073 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
2074 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1,
2075 VTableHolder, TemplateParams, Identifier));
2076 EXPECT_NE(N, DICompositeType::get(
2077 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
2078 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
2079 getCompositeType(), TemplateParams, Identifier));
2080 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2081 BaseType, SizeInBits, AlignInBits,
2082 OffsetInBits, Flags, Elements, RuntimeLang,
2083 VTableHolder, getTuple(), Identifier));
2084 EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2085 BaseType, SizeInBits, AlignInBits,
2086 OffsetInBits, Flags, Elements, RuntimeLang,
2087 VTableHolder, TemplateParams, "other"));
2088
2089 // Be sure that missing identifiers get null pointers.
2090 EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2091 BaseType, SizeInBits, AlignInBits,
2092 OffsetInBits, Flags, Elements, RuntimeLang,
2093 VTableHolder, TemplateParams, "")
2094 ->getRawIdentifier());
2095 EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2096 BaseType, SizeInBits, AlignInBits,
2097 OffsetInBits, Flags, Elements, RuntimeLang,
2098 VTableHolder, TemplateParams)
2099 ->getRawIdentifier());
2100
2101 TempDICompositeType Temp = N->clone();
2102 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2103}
2104
2105TEST_F(DICompositeTypeTest, getWithLargeValues) {
2106 unsigned Tag = dwarf::DW_TAG_structure_type;
2107 StringRef Name = "some name";
2108 DIFile *File = getFile();
2109 unsigned Line = 1;
2110 DIScope *Scope = getSubprogram();
2111 DIType *BaseType = getCompositeType();
2112 uint64_t SizeInBits = UINT64_MAX;
2113 uint32_t AlignInBits = UINT32_MAX - 1;
2114 uint64_t OffsetInBits = UINT64_MAX - 2;
2115 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
2116 MDTuple *Elements = getTuple();
2117 unsigned RuntimeLang = 6;
2118 DIType *VTableHolder = getCompositeType();
2119 MDTuple *TemplateParams = getTuple();
2120 StringRef Identifier = "some id";
2121
2122 auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,
2123 BaseType, SizeInBits, AlignInBits,
2124 OffsetInBits, Flags, Elements, RuntimeLang,
2125 VTableHolder, TemplateParams, Identifier);
2126 EXPECT_EQ(SizeInBits, N->getSizeInBits());
2127 EXPECT_EQ(AlignInBits, N->getAlignInBits());
2128 EXPECT_EQ(OffsetInBits, N->getOffsetInBits());
2129}
2130
2131TEST_F(DICompositeTypeTest, replaceOperands) {
2132 unsigned Tag = dwarf::DW_TAG_structure_type;
2133 StringRef Name = "some name";
2134 DIFile *File = getFile();
2135 unsigned Line = 1;
2136 DIScope *Scope = getSubprogram();
2137 DIType *BaseType = getCompositeType();
2138 uint64_t SizeInBits = 2;
2139 uint32_t AlignInBits = 3;
2140 uint64_t OffsetInBits = 4;
2141 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
2142 unsigned RuntimeLang = 6;
2143 StringRef Identifier = "some id";
2144
2145 auto *N = DICompositeType::get(
2146 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2147 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier);
2148
2149 auto *Elements = MDTuple::getDistinct(Context, MDs: std::nullopt);
2150 EXPECT_EQ(nullptr, N->getElements().get());
2151 N->replaceElements(Elements);
2152 EXPECT_EQ(Elements, N->getElements().get());
2153 N->replaceElements(Elements: nullptr);
2154 EXPECT_EQ(nullptr, N->getElements().get());
2155
2156 DIType *VTableHolder = getCompositeType();
2157 EXPECT_EQ(nullptr, N->getVTableHolder());
2158 N->replaceVTableHolder(VTableHolder);
2159 EXPECT_EQ(VTableHolder, N->getVTableHolder());
2160 // As an extension, the containing type can be anything. This is
2161 // used by Rust to associate vtables with their concrete type.
2162 DIType *BasicType = getBasicType(Name: "basic");
2163 N->replaceVTableHolder(VTableHolder: BasicType);
2164 EXPECT_EQ(BasicType, N->getVTableHolder());
2165 N->replaceVTableHolder(VTableHolder: nullptr);
2166 EXPECT_EQ(nullptr, N->getVTableHolder());
2167
2168 auto *TemplateParams = MDTuple::getDistinct(Context, MDs: std::nullopt);
2169 EXPECT_EQ(nullptr, N->getTemplateParams().get());
2170 N->replaceTemplateParams(TemplateParams);
2171 EXPECT_EQ(TemplateParams, N->getTemplateParams().get());
2172 N->replaceTemplateParams(TemplateParams: nullptr);
2173 EXPECT_EQ(nullptr, N->getTemplateParams().get());
2174}
2175
2176TEST_F(DICompositeTypeTest, variant_part) {
2177 unsigned Tag = dwarf::DW_TAG_variant_part;
2178 StringRef Name = "some name";
2179 DIFile *File = getFile();
2180 unsigned Line = 1;
2181 DIScope *Scope = getSubprogram();
2182 DIType *BaseType = getCompositeType();
2183 uint64_t SizeInBits = 2;
2184 uint32_t AlignInBits = 3;
2185 uint64_t OffsetInBits = 4;
2186 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
2187 unsigned RuntimeLang = 6;
2188 StringRef Identifier = "some id";
2189 DIDerivedType *Discriminator = cast<DIDerivedType>(Val: getDerivedType());
2190 DIDerivedType *Discriminator2 = cast<DIDerivedType>(Val: getDerivedType());
2191
2192 EXPECT_NE(Discriminator, Discriminator2);
2193
2194 auto *N = DICompositeType::get(
2195 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2196 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2197 Discriminator);
2198
2199 // Test the hashing.
2200 auto *Same = DICompositeType::get(
2201 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2202 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2203 Discriminator);
2204 auto *Other = DICompositeType::get(
2205 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2206 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2207 Discriminator: Discriminator2);
2208 auto *NoDisc = DICompositeType::get(
2209 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2210 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2211 Discriminator: nullptr);
2212
2213 EXPECT_EQ(N, Same);
2214 EXPECT_NE(Same, Other);
2215 EXPECT_NE(Same, NoDisc);
2216 EXPECT_NE(Other, NoDisc);
2217
2218 EXPECT_EQ(N->getDiscriminator(), Discriminator);
2219}
2220
2221TEST_F(DICompositeTypeTest, dynamicArray) {
2222 unsigned Tag = dwarf::DW_TAG_array_type;
2223 StringRef Name = "some name";
2224 DIFile *File = getFile();
2225 unsigned Line = 1;
2226 DILocalScope *Scope = getSubprogram();
2227 DIType *BaseType = getCompositeType();
2228 uint64_t SizeInBits = 32;
2229 uint32_t AlignInBits = 32;
2230 uint64_t OffsetInBits = 4;
2231 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(3);
2232 unsigned RuntimeLang = 6;
2233 StringRef Identifier = "some id";
2234 DIType *Type = getDerivedType();
2235 Metadata *DlVar1 = DILocalVariable::get(Context, Scope, Name: "dl_var1", File, Line: 8,
2236 Type, Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
2237 Metadata *DlVar2 = DILocalVariable::get(Context, Scope, Name: "dl_var2", File, Line: 8,
2238 Type, Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
2239 uint64_t Elements1[] = {dwarf::DW_OP_push_object_address, dwarf::DW_OP_deref};
2240 Metadata *DataLocation1 = DIExpression::get(Context, Elements: Elements1);
2241
2242 uint64_t Elements2[] = {dwarf::DW_OP_constu, 0};
2243 Metadata *DataLocation2 = DIExpression::get(Context, Elements: Elements2);
2244
2245 uint64_t Elements3[] = {dwarf::DW_OP_constu, 3};
2246 Metadata *Rank1 = DIExpression::get(Context, Elements: Elements3);
2247
2248 uint64_t Elements4[] = {dwarf::DW_OP_constu, 4};
2249 Metadata *Rank2 = DIExpression::get(Context, Elements: Elements4);
2250
2251 ConstantInt *RankInt1 = ConstantInt::get(Context, V: APInt(7, 0));
2252 ConstantAsMetadata *RankConst1 = ConstantAsMetadata::get(C: RankInt1);
2253 ConstantInt *RankInt2 = ConstantInt::get(Context, V: APInt(6, 0));
2254 ConstantAsMetadata *RankConst2 = ConstantAsMetadata::get(C: RankInt2);
2255 auto *N1 = DICompositeType::get(
2256 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2257 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2258 Discriminator: nullptr, DataLocation: DlVar1);
2259
2260 auto *Same1 = DICompositeType::get(
2261 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2262 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2263 Discriminator: nullptr, DataLocation: DlVar1);
2264
2265 auto *Other1 = DICompositeType::get(
2266 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2267 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2268 Discriminator: nullptr, DataLocation: DlVar2);
2269
2270 EXPECT_EQ(N1, Same1);
2271 EXPECT_NE(Same1, Other1);
2272 EXPECT_EQ(N1->getDataLocation(), DlVar1);
2273
2274 auto *N2 = DICompositeType::get(
2275 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2276 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2277 Discriminator: nullptr, DataLocation: DataLocation1);
2278
2279 auto *Same2 = DICompositeType::get(
2280 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2281 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2282 Discriminator: nullptr, DataLocation: DataLocation1);
2283
2284 auto *Other2 = DICompositeType::get(
2285 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2286 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2287 Discriminator: nullptr, DataLocation: DataLocation2);
2288
2289 EXPECT_EQ(N2, Same2);
2290 EXPECT_NE(Same2, Other2);
2291 EXPECT_EQ(N2->getDataLocationExp(), DataLocation1);
2292
2293 auto *N3 = DICompositeType::get(
2294 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2295 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2296 Discriminator: nullptr, DataLocation: DataLocation1, Associated: nullptr, Allocated: nullptr, Rank: Rank1);
2297
2298 auto *Same3 = DICompositeType::get(
2299 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2300 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2301 Discriminator: nullptr, DataLocation: DataLocation1, Associated: nullptr, Allocated: nullptr, Rank: Rank1);
2302
2303 auto *Other3 = DICompositeType::get(
2304 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2305 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2306 Discriminator: nullptr, DataLocation: DataLocation1, Associated: nullptr, Allocated: nullptr, Rank: Rank2);
2307
2308 EXPECT_EQ(N3, Same3);
2309 EXPECT_NE(Same3, Other3);
2310 EXPECT_EQ(N3->getRankExp(), Rank1);
2311
2312 auto *N4 = DICompositeType::get(
2313 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2314 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2315 Discriminator: nullptr, DataLocation: DataLocation1, Associated: nullptr, Allocated: nullptr, Rank: RankConst1);
2316
2317 auto *Same4 = DICompositeType::get(
2318 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2319 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2320 Discriminator: nullptr, DataLocation: DataLocation1, Associated: nullptr, Allocated: nullptr, Rank: RankConst1);
2321
2322 auto *Other4 = DICompositeType::get(
2323 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
2324 OffsetInBits, Flags, Elements: nullptr, RuntimeLang, VTableHolder: nullptr, TemplateParams: nullptr, Identifier,
2325 Discriminator: nullptr, DataLocation: DataLocation1, Associated: nullptr, Allocated: nullptr, Rank: RankConst2);
2326
2327 EXPECT_EQ(N4, Same4);
2328 EXPECT_NE(Same4, Other4);
2329 EXPECT_EQ(N4->getRankConst(), RankInt1);
2330}
2331
2332typedef MetadataTest DISubroutineTypeTest;
2333
2334TEST_F(DISubroutineTypeTest, get) {
2335 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(1);
2336 DINode::DIFlags FlagsPOne = static_cast<DINode::DIFlags>(Flags + 1);
2337 MDTuple *TypeArray = getTuple();
2338
2339 auto *N = DISubroutineType::get(Context, Flags, CC: 0, TypeArray);
2340 EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag());
2341 EXPECT_EQ(Flags, N->getFlags());
2342 EXPECT_EQ(TypeArray, N->getTypeArray().get());
2343 EXPECT_EQ(N, DISubroutineType::get(Context, Flags, 0, TypeArray));
2344
2345 EXPECT_NE(N, DISubroutineType::get(Context, FlagsPOne, 0, TypeArray));
2346 EXPECT_NE(N, DISubroutineType::get(Context, Flags, 0, getTuple()));
2347
2348 // Test the hashing of calling conventions.
2349 auto *Fast = DISubroutineType::get(
2350 Context, Flags, CC: dwarf::DW_CC_BORLAND_msfastcall, TypeArray);
2351 auto *Std = DISubroutineType::get(Context, Flags,
2352 CC: dwarf::DW_CC_BORLAND_stdcall, TypeArray);
2353 EXPECT_EQ(Fast,
2354 DISubroutineType::get(Context, Flags,
2355 dwarf::DW_CC_BORLAND_msfastcall, TypeArray));
2356 EXPECT_EQ(Std, DISubroutineType::get(
2357 Context, Flags, dwarf::DW_CC_BORLAND_stdcall, TypeArray));
2358
2359 EXPECT_NE(N, Fast);
2360 EXPECT_NE(N, Std);
2361 EXPECT_NE(Fast, Std);
2362
2363 TempDISubroutineType Temp = N->clone();
2364 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2365
2366 // Test always-empty operands.
2367 EXPECT_EQ(nullptr, N->getScope());
2368 EXPECT_EQ(nullptr, N->getFile());
2369 EXPECT_EQ("", N->getName());
2370}
2371
2372typedef MetadataTest DIFileTest;
2373
2374TEST_F(DIFileTest, get) {
2375 StringRef Filename = "file";
2376 StringRef Directory = "dir";
2377 DIFile::ChecksumKind CSKind = DIFile::ChecksumKind::CSK_MD5;
2378 StringRef ChecksumString = "000102030405060708090a0b0c0d0e0f";
2379 DIFile::ChecksumInfo<StringRef> Checksum(CSKind, ChecksumString);
2380 StringRef Source = "source";
2381 auto *N = DIFile::get(Context, Filename, Directory, CS: Checksum, Source);
2382
2383 EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag());
2384 EXPECT_EQ(Filename, N->getFilename());
2385 EXPECT_EQ(Directory, N->getDirectory());
2386 EXPECT_EQ(Checksum, N->getChecksum());
2387 EXPECT_EQ(Source, N->getSource());
2388 EXPECT_EQ(N, DIFile::get(Context, Filename, Directory, Checksum, Source));
2389
2390 EXPECT_NE(N, DIFile::get(Context, "other", Directory, Checksum, Source));
2391 EXPECT_NE(N, DIFile::get(Context, Filename, "other", Checksum, Source));
2392 DIFile::ChecksumInfo<StringRef> OtherChecksum(DIFile::ChecksumKind::CSK_SHA1, ChecksumString);
2393 EXPECT_NE(
2394 N, DIFile::get(Context, Filename, Directory, OtherChecksum));
2395 StringRef OtherSource = "other";
2396 EXPECT_NE(N, DIFile::get(Context, Filename, Directory, Checksum, OtherSource));
2397 EXPECT_NE(N, DIFile::get(Context, Filename, Directory, Checksum));
2398 EXPECT_NE(N, DIFile::get(Context, Filename, Directory));
2399
2400 TempDIFile Temp = N->clone();
2401 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2402}
2403
2404TEST_F(DIFileTest, EmptySource) {
2405 DIFile *N = DIFile::get(Context, Filename: "file", Directory: "dir");
2406 EXPECT_EQ(std::nullopt, N->getSource());
2407
2408 std::optional<DIFile::ChecksumInfo<StringRef>> Checksum;
2409 std::optional<StringRef> Source;
2410 N = DIFile::get(Context, Filename: "file", Directory: "dir", CS: Checksum, Source);
2411 EXPECT_EQ(Source, N->getSource());
2412
2413 Source = "";
2414 N = DIFile::get(Context, Filename: "file", Directory: "dir", CS: Checksum, Source);
2415 EXPECT_EQ(Source, N->getSource());
2416}
2417
2418TEST_F(DIFileTest, ScopeGetFile) {
2419 // Ensure that DIScope::getFile() returns itself.
2420 DIScope *N = DIFile::get(Context, Filename: "file", Directory: "dir");
2421 EXPECT_EQ(N, N->getFile());
2422}
2423
2424typedef MetadataTest DICompileUnitTest;
2425
2426TEST_F(DICompileUnitTest, get) {
2427 unsigned SourceLanguage = 1;
2428 DIFile *File = getFile();
2429 StringRef Producer = "some producer";
2430 bool IsOptimized = false;
2431 StringRef Flags = "flag after flag";
2432 unsigned RuntimeVersion = 2;
2433 StringRef SplitDebugFilename = "another/file";
2434 auto EmissionKind = DICompileUnit::FullDebug;
2435 MDTuple *EnumTypes = getTuple();
2436 MDTuple *RetainedTypes = getTuple();
2437 MDTuple *GlobalVariables = getTuple();
2438 MDTuple *ImportedEntities = getTuple();
2439 uint64_t DWOId = 0x10000000c0ffee;
2440 MDTuple *Macros = getTuple();
2441 StringRef SysRoot = "/";
2442 StringRef SDK = "MacOSX.sdk";
2443 auto *N = DICompileUnit::getDistinct(
2444 Context, SourceLanguage, File, Producer, IsOptimized, Flags,
2445 RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
2446 RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining: true,
2447 DebugInfoForProfiling: false, NameTableKind: DICompileUnit::DebugNameTableKind::Default, RangesBaseAddress: false, SysRoot, SDK);
2448
2449 EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag());
2450 EXPECT_EQ(SourceLanguage, N->getSourceLanguage());
2451 EXPECT_EQ(File, N->getFile());
2452 EXPECT_EQ(Producer, N->getProducer());
2453 EXPECT_EQ(IsOptimized, N->isOptimized());
2454 EXPECT_EQ(Flags, N->getFlags());
2455 EXPECT_EQ(RuntimeVersion, N->getRuntimeVersion());
2456 EXPECT_EQ(SplitDebugFilename, N->getSplitDebugFilename());
2457 EXPECT_EQ(EmissionKind, N->getEmissionKind());
2458 EXPECT_EQ(EnumTypes, N->getEnumTypes().get());
2459 EXPECT_EQ(RetainedTypes, N->getRetainedTypes().get());
2460 EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());
2461 EXPECT_EQ(ImportedEntities, N->getImportedEntities().get());
2462 EXPECT_EQ(Macros, N->getMacros().get());
2463 EXPECT_EQ(DWOId, N->getDWOId());
2464 EXPECT_EQ(SysRoot, N->getSysRoot());
2465 EXPECT_EQ(SDK, N->getSDK());
2466
2467 TempDICompileUnit Temp = N->clone();
2468 EXPECT_EQ(dwarf::DW_TAG_compile_unit, Temp->getTag());
2469 EXPECT_EQ(SourceLanguage, Temp->getSourceLanguage());
2470 EXPECT_EQ(File, Temp->getFile());
2471 EXPECT_EQ(Producer, Temp->getProducer());
2472 EXPECT_EQ(IsOptimized, Temp->isOptimized());
2473 EXPECT_EQ(Flags, Temp->getFlags());
2474 EXPECT_EQ(RuntimeVersion, Temp->getRuntimeVersion());
2475 EXPECT_EQ(SplitDebugFilename, Temp->getSplitDebugFilename());
2476 EXPECT_EQ(EmissionKind, Temp->getEmissionKind());
2477 EXPECT_EQ(EnumTypes, Temp->getEnumTypes().get());
2478 EXPECT_EQ(RetainedTypes, Temp->getRetainedTypes().get());
2479 EXPECT_EQ(GlobalVariables, Temp->getGlobalVariables().get());
2480 EXPECT_EQ(ImportedEntities, Temp->getImportedEntities().get());
2481 EXPECT_EQ(Macros, Temp->getMacros().get());
2482 EXPECT_EQ(SysRoot, Temp->getSysRoot());
2483 EXPECT_EQ(SDK, Temp->getSDK());
2484
2485 auto *TempAddress = Temp.get();
2486 auto *Clone = MDNode::replaceWithPermanent(N: std::move(Temp));
2487 EXPECT_TRUE(Clone->isDistinct());
2488 EXPECT_EQ(TempAddress, Clone);
2489}
2490
2491TEST_F(DICompileUnitTest, replaceArrays) {
2492 unsigned SourceLanguage = 1;
2493 DIFile *File = getFile();
2494 StringRef Producer = "some producer";
2495 bool IsOptimized = false;
2496 StringRef Flags = "flag after flag";
2497 unsigned RuntimeVersion = 2;
2498 StringRef SplitDebugFilename = "another/file";
2499 auto EmissionKind = DICompileUnit::FullDebug;
2500 MDTuple *EnumTypes = MDTuple::getDistinct(Context, MDs: std::nullopt);
2501 MDTuple *RetainedTypes = MDTuple::getDistinct(Context, MDs: std::nullopt);
2502 MDTuple *ImportedEntities = MDTuple::getDistinct(Context, MDs: std::nullopt);
2503 uint64_t DWOId = 0xc0ffee;
2504 StringRef SysRoot = "/";
2505 StringRef SDK = "MacOSX.sdk";
2506 auto *N = DICompileUnit::getDistinct(
2507 Context, SourceLanguage, File, Producer, IsOptimized, Flags,
2508 RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
2509 RetainedTypes, GlobalVariables: nullptr, ImportedEntities, Macros: nullptr, DWOId, SplitDebugInlining: true, DebugInfoForProfiling: false,
2510 NameTableKind: DICompileUnit::DebugNameTableKind::Default, RangesBaseAddress: false, SysRoot, SDK);
2511
2512 auto *GlobalVariables = MDTuple::getDistinct(Context, MDs: std::nullopt);
2513 EXPECT_EQ(nullptr, N->getGlobalVariables().get());
2514 N->replaceGlobalVariables(N: GlobalVariables);
2515 EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());
2516 N->replaceGlobalVariables(N: nullptr);
2517 EXPECT_EQ(nullptr, N->getGlobalVariables().get());
2518
2519 auto *Macros = MDTuple::getDistinct(Context, MDs: std::nullopt);
2520 EXPECT_EQ(nullptr, N->getMacros().get());
2521 N->replaceMacros(N: Macros);
2522 EXPECT_EQ(Macros, N->getMacros().get());
2523 N->replaceMacros(N: nullptr);
2524 EXPECT_EQ(nullptr, N->getMacros().get());
2525}
2526
2527typedef MetadataTest DISubprogramTest;
2528
2529TEST_F(DISubprogramTest, get) {
2530 DIScope *Scope = getCompositeType();
2531 StringRef Name = "name";
2532 StringRef LinkageName = "linkage";
2533 DIFile *File = getFile();
2534 unsigned Line = 2;
2535 DISubroutineType *Type = getSubroutineType();
2536 bool IsLocalToUnit = false;
2537 bool IsDefinition = true;
2538 unsigned ScopeLine = 3;
2539 DIType *ContainingType = getCompositeType();
2540 unsigned Virtuality = 2;
2541 unsigned VirtualIndex = 5;
2542 int ThisAdjustment = -3;
2543 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(6);
2544 bool IsOptimized = false;
2545 MDTuple *TemplateParams = getTuple();
2546 DISubprogram *Declaration = getSubprogram();
2547 MDTuple *RetainedNodes = getTuple();
2548 MDTuple *ThrownTypes = getTuple();
2549 MDTuple *Annotations = getTuple();
2550 StringRef TargetFuncName = "target";
2551 DICompileUnit *Unit = getUnit();
2552 DISubprogram::DISPFlags SPFlags =
2553 static_cast<DISubprogram::DISPFlags>(Virtuality);
2554 assert(!IsLocalToUnit && IsDefinition && !IsOptimized &&
2555 "bools and SPFlags have to match");
2556 SPFlags |= DISubprogram::SPFlagDefinition;
2557
2558 auto *N = DISubprogram::get(
2559 Context, Scope, Name, LinkageName, File, Line, Type, ScopeLine,
2560 ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit,
2561 TemplateParams, Declaration, RetainedNodes, ThrownTypes, Annotations,
2562 TargetFuncName);
2563
2564 EXPECT_EQ(dwarf::DW_TAG_subprogram, N->getTag());
2565 EXPECT_EQ(Scope, N->getScope());
2566 EXPECT_EQ(Name, N->getName());
2567 EXPECT_EQ(LinkageName, N->getLinkageName());
2568 EXPECT_EQ(File, N->getFile());
2569 EXPECT_EQ(Line, N->getLine());
2570 EXPECT_EQ(Type, N->getType());
2571 EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());
2572 EXPECT_EQ(IsDefinition, N->isDefinition());
2573 EXPECT_EQ(ScopeLine, N->getScopeLine());
2574 EXPECT_EQ(ContainingType, N->getContainingType());
2575 EXPECT_EQ(Virtuality, N->getVirtuality());
2576 EXPECT_EQ(VirtualIndex, N->getVirtualIndex());
2577 EXPECT_EQ(ThisAdjustment, N->getThisAdjustment());
2578 EXPECT_EQ(Flags, N->getFlags());
2579 EXPECT_EQ(IsOptimized, N->isOptimized());
2580 EXPECT_EQ(Unit, N->getUnit());
2581 EXPECT_EQ(TemplateParams, N->getTemplateParams().get());
2582 EXPECT_EQ(Declaration, N->getDeclaration());
2583 EXPECT_EQ(RetainedNodes, N->getRetainedNodes().get());
2584 EXPECT_EQ(ThrownTypes, N->getThrownTypes().get());
2585 EXPECT_EQ(Annotations, N->getAnnotations().get());
2586 EXPECT_EQ(TargetFuncName, N->getTargetFuncName());
2587 EXPECT_EQ(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2588 Type, ScopeLine, ContainingType, VirtualIndex,
2589 ThisAdjustment, Flags, SPFlags, Unit,
2590 TemplateParams, Declaration, RetainedNodes,
2591 ThrownTypes, Annotations, TargetFuncName));
2592
2593 EXPECT_NE(N, DISubprogram::get(Context, getCompositeType(), Name, LinkageName,
2594 File, Line, Type, ScopeLine, ContainingType,
2595 VirtualIndex, ThisAdjustment, Flags, SPFlags,
2596 Unit, TemplateParams, Declaration,
2597 RetainedNodes, ThrownTypes, Annotations,
2598 TargetFuncName));
2599 EXPECT_NE(N, DISubprogram::get(Context, Scope, "other", LinkageName, File,
2600 Line, Type, ScopeLine, ContainingType,
2601 VirtualIndex, ThisAdjustment, Flags, SPFlags,
2602 Unit, TemplateParams, Declaration,
2603 RetainedNodes, ThrownTypes, Annotations,
2604 TargetFuncName));
2605 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, "other", File, Line,
2606 Type, ScopeLine, ContainingType, VirtualIndex,
2607 ThisAdjustment, Flags, SPFlags, Unit,
2608 TemplateParams, Declaration, RetainedNodes,
2609 ThrownTypes, Annotations, TargetFuncName));
2610 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, getFile(),
2611 Line, Type, ScopeLine, ContainingType,
2612 VirtualIndex, ThisAdjustment, Flags, SPFlags,
2613 Unit, TemplateParams, Declaration,
2614 RetainedNodes, ThrownTypes, Annotations,
2615 TargetFuncName));
2616 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File,
2617 Line + 1, Type, ScopeLine, ContainingType,
2618 VirtualIndex, ThisAdjustment, Flags, SPFlags,
2619 Unit, TemplateParams, Declaration,
2620 RetainedNodes, ThrownTypes, Annotations,
2621 TargetFuncName));
2622 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2623 getSubroutineType(), ScopeLine, ContainingType,
2624 VirtualIndex, ThisAdjustment, Flags, SPFlags,
2625 Unit, TemplateParams, Declaration,
2626 RetainedNodes, ThrownTypes, Annotations,
2627 TargetFuncName));
2628 EXPECT_NE(N, DISubprogram::get(
2629 Context, Scope, Name, LinkageName, File, Line, Type,
2630 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,
2631 Flags, SPFlags ^ DISubprogram::SPFlagLocalToUnit, Unit,
2632 TemplateParams, Declaration, RetainedNodes, ThrownTypes,
2633 Annotations, TargetFuncName));
2634 EXPECT_NE(N, DISubprogram::get(
2635 Context, Scope, Name, LinkageName, File, Line, Type,
2636 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,
2637 Flags, SPFlags ^ DISubprogram::SPFlagDefinition, Unit,
2638 TemplateParams, Declaration, RetainedNodes, ThrownTypes,
2639 Annotations, TargetFuncName));
2640 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2641 Type, ScopeLine + 1, ContainingType,
2642 VirtualIndex, ThisAdjustment, Flags, SPFlags,
2643 Unit, TemplateParams, Declaration,
2644 RetainedNodes, ThrownTypes, Annotations,
2645 TargetFuncName));
2646 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2647 Type, ScopeLine, getCompositeType(),
2648 VirtualIndex, ThisAdjustment, Flags, SPFlags,
2649 Unit, TemplateParams, Declaration,
2650 RetainedNodes, ThrownTypes, Annotations,
2651 TargetFuncName));
2652 EXPECT_NE(N, DISubprogram::get(
2653 Context, Scope, Name, LinkageName, File, Line, Type,
2654 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,
2655 Flags, SPFlags ^ DISubprogram::SPFlagVirtual, Unit,
2656 TemplateParams, Declaration, RetainedNodes, ThrownTypes,
2657 Annotations, TargetFuncName));
2658 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2659 Type, ScopeLine, ContainingType,
2660 VirtualIndex + 1, ThisAdjustment, Flags,
2661 SPFlags, Unit, TemplateParams, Declaration,
2662 RetainedNodes, ThrownTypes, Annotations,
2663 TargetFuncName));
2664 EXPECT_NE(N, DISubprogram::get(
2665 Context, Scope, Name, LinkageName, File, Line, Type,
2666 ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,
2667 Flags, SPFlags ^ DISubprogram::SPFlagOptimized, Unit,
2668 TemplateParams, Declaration, RetainedNodes, ThrownTypes,
2669 Annotations, TargetFuncName));
2670 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2671 Type, ScopeLine, ContainingType, VirtualIndex,
2672 ThisAdjustment, Flags, SPFlags, nullptr,
2673 TemplateParams, Declaration, RetainedNodes,
2674 ThrownTypes, Annotations, TargetFuncName));
2675 EXPECT_NE(N,
2676 DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2677 Type, ScopeLine, ContainingType, VirtualIndex,
2678 ThisAdjustment, Flags, SPFlags, Unit, getTuple(),
2679 Declaration, RetainedNodes, ThrownTypes,
2680 Annotations, TargetFuncName));
2681 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2682 Type, ScopeLine, ContainingType, VirtualIndex,
2683 ThisAdjustment, Flags, SPFlags, Unit,
2684 TemplateParams, getSubprogram(), RetainedNodes,
2685 ThrownTypes, Annotations, TargetFuncName));
2686 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2687 Type, ScopeLine, ContainingType, VirtualIndex,
2688 ThisAdjustment, Flags, SPFlags, Unit,
2689 TemplateParams, Declaration, getTuple(),
2690 ThrownTypes, Annotations, TargetFuncName));
2691 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2692 Type, ScopeLine, ContainingType, VirtualIndex,
2693 ThisAdjustment, Flags, SPFlags, Unit,
2694 TemplateParams, Declaration, RetainedNodes,
2695 getTuple(), Annotations, TargetFuncName));
2696 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2697 Type, ScopeLine, ContainingType, VirtualIndex,
2698 ThisAdjustment, Flags, SPFlags, Unit,
2699 TemplateParams, Declaration, RetainedNodes,
2700 ThrownTypes, getTuple(), TargetFuncName));
2701 EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
2702 Type, ScopeLine, ContainingType, VirtualIndex,
2703 ThisAdjustment, Flags, SPFlags, Unit,
2704 TemplateParams, Declaration, RetainedNodes,
2705 ThrownTypes, Annotations, "other"));
2706
2707 TempDISubprogram Temp = N->clone();
2708 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2709}
2710
2711typedef MetadataTest DILexicalBlockTest;
2712
2713TEST_F(DILexicalBlockTest, get) {
2714 DILocalScope *Scope = getSubprogram();
2715 DIFile *File = getFile();
2716 unsigned Line = 5;
2717 unsigned Column = 8;
2718
2719 auto *N = DILexicalBlock::get(Context, Scope, File, Line, Column);
2720
2721 EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());
2722 EXPECT_EQ(Scope, N->getScope());
2723 EXPECT_EQ(File, N->getFile());
2724 EXPECT_EQ(Line, N->getLine());
2725 EXPECT_EQ(Column, N->getColumn());
2726 EXPECT_EQ(N, DILexicalBlock::get(Context, Scope, File, Line, Column));
2727
2728 EXPECT_NE(N,
2729 DILexicalBlock::get(Context, getSubprogram(), File, Line, Column));
2730 EXPECT_NE(N, DILexicalBlock::get(Context, Scope, getFile(), Line, Column));
2731 EXPECT_NE(N, DILexicalBlock::get(Context, Scope, File, Line + 1, Column));
2732 EXPECT_NE(N, DILexicalBlock::get(Context, Scope, File, Line, Column + 1));
2733
2734 TempDILexicalBlock Temp = N->clone();
2735 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2736}
2737
2738TEST_F(DILexicalBlockTest, Overflow) {
2739 DISubprogram *SP = getSubprogram();
2740 DIFile *F = getFile();
2741 {
2742 auto *LB = DILexicalBlock::get(Context, Scope: SP, File: F, Line: 2, Column: 7);
2743 EXPECT_EQ(2u, LB->getLine());
2744 EXPECT_EQ(7u, LB->getColumn());
2745 }
2746 unsigned U16 = 1u << 16;
2747 {
2748 auto *LB = DILexicalBlock::get(Context, Scope: SP, File: F, UINT32_MAX, Column: U16 - 1);
2749 EXPECT_EQ(UINT32_MAX, LB->getLine());
2750 EXPECT_EQ(U16 - 1, LB->getColumn());
2751 }
2752 {
2753 auto *LB = DILexicalBlock::get(Context, Scope: SP, File: F, UINT32_MAX, Column: U16);
2754 EXPECT_EQ(UINT32_MAX, LB->getLine());
2755 EXPECT_EQ(0u, LB->getColumn());
2756 }
2757 {
2758 auto *LB = DILexicalBlock::get(Context, Scope: SP, File: F, UINT32_MAX, Column: U16 + 1);
2759 EXPECT_EQ(UINT32_MAX, LB->getLine());
2760 EXPECT_EQ(0u, LB->getColumn());
2761 }
2762}
2763
2764typedef MetadataTest DILexicalBlockFileTest;
2765
2766TEST_F(DILexicalBlockFileTest, get) {
2767 DILocalScope *Scope = getSubprogram();
2768 DIFile *File = getFile();
2769 unsigned Discriminator = 5;
2770
2771 auto *N = DILexicalBlockFile::get(Context, Scope, File, Discriminator);
2772
2773 EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());
2774 EXPECT_EQ(Scope, N->getScope());
2775 EXPECT_EQ(File, N->getFile());
2776 EXPECT_EQ(Discriminator, N->getDiscriminator());
2777 EXPECT_EQ(N, DILexicalBlockFile::get(Context, Scope, File, Discriminator));
2778
2779 EXPECT_NE(N, DILexicalBlockFile::get(Context, getSubprogram(), File,
2780 Discriminator));
2781 EXPECT_NE(N,
2782 DILexicalBlockFile::get(Context, Scope, getFile(), Discriminator));
2783 EXPECT_NE(N,
2784 DILexicalBlockFile::get(Context, Scope, File, Discriminator + 1));
2785
2786 TempDILexicalBlockFile Temp = N->clone();
2787 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2788}
2789
2790typedef MetadataTest DINamespaceTest;
2791
2792TEST_F(DINamespaceTest, get) {
2793 DIScope *Scope = getFile();
2794 StringRef Name = "namespace";
2795 bool ExportSymbols = true;
2796
2797 auto *N = DINamespace::get(Context, Scope, Name, ExportSymbols);
2798
2799 EXPECT_EQ(dwarf::DW_TAG_namespace, N->getTag());
2800 EXPECT_EQ(Scope, N->getScope());
2801 EXPECT_EQ(Name, N->getName());
2802 EXPECT_EQ(N, DINamespace::get(Context, Scope, Name, ExportSymbols));
2803 EXPECT_NE(N, DINamespace::get(Context, getFile(), Name, ExportSymbols));
2804 EXPECT_NE(N, DINamespace::get(Context, Scope, "other", ExportSymbols));
2805 EXPECT_NE(N, DINamespace::get(Context, Scope, Name, !ExportSymbols));
2806
2807 TempDINamespace Temp = N->clone();
2808 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2809}
2810
2811typedef MetadataTest DIModuleTest;
2812
2813TEST_F(DIModuleTest, get) {
2814 DIFile *File = getFile();
2815 DIScope *Scope = getFile();
2816 StringRef Name = "module";
2817 StringRef ConfigMacro = "-DNDEBUG";
2818 StringRef Includes = "-I.";
2819 StringRef APINotes = "/tmp/m.apinotes";
2820 unsigned LineNo = 4;
2821 bool IsDecl = true;
2822
2823 auto *N = DIModule::get(Context, File, Scope, Name, ConfigurationMacros: ConfigMacro, IncludePath: Includes,
2824 APINotesFile: APINotes, LineNo, IsDecl);
2825
2826 EXPECT_EQ(dwarf::DW_TAG_module, N->getTag());
2827 EXPECT_EQ(File, N->getFile());
2828 EXPECT_EQ(Scope, N->getScope());
2829 EXPECT_EQ(Name, N->getName());
2830 EXPECT_EQ(ConfigMacro, N->getConfigurationMacros());
2831 EXPECT_EQ(Includes, N->getIncludePath());
2832 EXPECT_EQ(APINotes, N->getAPINotesFile());
2833 EXPECT_EQ(LineNo, N->getLineNo());
2834 EXPECT_EQ(IsDecl, N->getIsDecl());
2835 EXPECT_EQ(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,
2836 APINotes, LineNo, IsDecl));
2837 EXPECT_NE(N, DIModule::get(Context, getFile(), getFile(), Name, ConfigMacro,
2838 Includes, APINotes, LineNo, IsDecl));
2839 EXPECT_NE(N, DIModule::get(Context, File, Scope, "other", ConfigMacro,
2840 Includes, APINotes, LineNo, IsDecl));
2841 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, "other", Includes,
2842 APINotes, LineNo, IsDecl));
2843 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, "other",
2844 APINotes, LineNo, IsDecl));
2845 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,
2846 "other", LineNo, IsDecl));
2847 EXPECT_NE(N, DIModule::get(Context, getFile(), Scope, Name, ConfigMacro,
2848 Includes, APINotes, LineNo, IsDecl));
2849 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,
2850 APINotes, 5, IsDecl));
2851 EXPECT_NE(N, DIModule::get(Context, File, Scope, Name, ConfigMacro, Includes,
2852 APINotes, LineNo, false));
2853
2854 TempDIModule Temp = N->clone();
2855 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2856}
2857
2858typedef MetadataTest DITemplateTypeParameterTest;
2859
2860TEST_F(DITemplateTypeParameterTest, get) {
2861 StringRef Name = "template";
2862 DIType *Type = getBasicType(Name: "basic");
2863 bool defaulted = false;
2864
2865 auto *N = DITemplateTypeParameter::get(Context, Name, Type, IsDefault: defaulted);
2866
2867 EXPECT_EQ(dwarf::DW_TAG_template_type_parameter, N->getTag());
2868 EXPECT_EQ(Name, N->getName());
2869 EXPECT_EQ(Type, N->getType());
2870 EXPECT_EQ(N, DITemplateTypeParameter::get(Context, Name, Type, defaulted));
2871
2872 EXPECT_NE(N, DITemplateTypeParameter::get(Context, "other", Type, defaulted));
2873 EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name,
2874 getBasicType("other"), defaulted));
2875 EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name, Type, true));
2876
2877 TempDITemplateTypeParameter Temp = N->clone();
2878 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2879}
2880
2881typedef MetadataTest DITemplateValueParameterTest;
2882
2883TEST_F(DITemplateValueParameterTest, get) {
2884 unsigned Tag = dwarf::DW_TAG_template_value_parameter;
2885 StringRef Name = "template";
2886 DIType *Type = getBasicType(Name: "basic");
2887 bool defaulted = false;
2888 Metadata *Value = getConstantAsMetadata();
2889
2890 auto *N =
2891 DITemplateValueParameter::get(Context, Tag, Name, Type, IsDefault: defaulted, Value);
2892 EXPECT_EQ(Tag, N->getTag());
2893 EXPECT_EQ(Name, N->getName());
2894 EXPECT_EQ(Type, N->getType());
2895 EXPECT_EQ(Value, N->getValue());
2896 EXPECT_EQ(N, DITemplateValueParameter::get(Context, Tag, Name, Type,
2897 defaulted, Value));
2898
2899 EXPECT_NE(N, DITemplateValueParameter::get(
2900 Context, dwarf::DW_TAG_GNU_template_template_param, Name,
2901 Type, defaulted, Value));
2902 EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, "other", Type,
2903 defaulted, Value));
2904 EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name,
2905 getBasicType("other"), defaulted,
2906 Value));
2907 EXPECT_NE(N,
2908 DITemplateValueParameter::get(Context, Tag, Name, Type, defaulted,
2909 getConstantAsMetadata()));
2910 EXPECT_NE(
2911 N, DITemplateValueParameter::get(Context, Tag, Name, Type, true, Value));
2912
2913 TempDITemplateValueParameter Temp = N->clone();
2914 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
2915}
2916
2917typedef MetadataTest DIGlobalVariableTest;
2918
2919TEST_F(DIGlobalVariableTest, get) {
2920 DIScope *Scope = getSubprogram();
2921 StringRef Name = "name";
2922 StringRef LinkageName = "linkage";
2923 DIFile *File = getFile();
2924 unsigned Line = 5;
2925 DIType *Type = getDerivedType();
2926 bool IsLocalToUnit = false;
2927 bool IsDefinition = true;
2928 MDTuple *templateParams = getTuple();
2929 DIDerivedType *StaticDataMemberDeclaration =
2930 cast<DIDerivedType>(Val: getDerivedType());
2931
2932 uint32_t AlignInBits = 8;
2933
2934 auto *N = DIGlobalVariable::get(
2935 Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
2936 IsDefinition, StaticDataMemberDeclaration, TemplateParams: templateParams, AlignInBits,
2937 Annotations: nullptr);
2938
2939 EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag());
2940 EXPECT_EQ(Scope, N->getScope());
2941 EXPECT_EQ(Name, N->getName());
2942 EXPECT_EQ(LinkageName, N->getLinkageName());
2943 EXPECT_EQ(File, N->getFile());
2944 EXPECT_EQ(Line, N->getLine());
2945 EXPECT_EQ(Type, N->getType());
2946 EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());
2947 EXPECT_EQ(IsDefinition, N->isDefinition());
2948 EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration());
2949 EXPECT_EQ(templateParams, N->getTemplateParams());
2950 EXPECT_EQ(AlignInBits, N->getAlignInBits());
2951 EXPECT_EQ(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2952 Line, Type, IsLocalToUnit, IsDefinition,
2953 StaticDataMemberDeclaration,
2954 templateParams, AlignInBits, nullptr));
2955
2956 EXPECT_NE(N, DIGlobalVariable::get(
2957 Context, getSubprogram(), Name, LinkageName, File, Line,
2958 Type, IsLocalToUnit, IsDefinition,
2959 StaticDataMemberDeclaration, templateParams, AlignInBits,
2960 nullptr));
2961 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, "other", LinkageName, File,
2962 Line, Type, IsLocalToUnit, IsDefinition,
2963 StaticDataMemberDeclaration,
2964 templateParams, AlignInBits, nullptr));
2965 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, "other", File, Line,
2966 Type, IsLocalToUnit, IsDefinition,
2967 StaticDataMemberDeclaration,
2968 templateParams, AlignInBits, nullptr));
2969 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName,
2970 getFile(), Line, Type, IsLocalToUnit,
2971 IsDefinition, StaticDataMemberDeclaration,
2972 templateParams, AlignInBits, nullptr));
2973 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2974 Line + 1, Type, IsLocalToUnit,
2975 IsDefinition, StaticDataMemberDeclaration,
2976 templateParams, AlignInBits, nullptr));
2977 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2978 Line, getDerivedType(), IsLocalToUnit,
2979 IsDefinition, StaticDataMemberDeclaration,
2980 templateParams, AlignInBits, nullptr));
2981 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2982 Line, Type, !IsLocalToUnit, IsDefinition,
2983 StaticDataMemberDeclaration,
2984 templateParams, AlignInBits, nullptr));
2985 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2986 Line, Type, IsLocalToUnit, !IsDefinition,
2987 StaticDataMemberDeclaration,
2988 templateParams, AlignInBits, nullptr));
2989 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2990 Line, Type, IsLocalToUnit, IsDefinition,
2991 cast<DIDerivedType>(getDerivedType()),
2992 templateParams, AlignInBits, nullptr));
2993 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2994 Line, Type, IsLocalToUnit, IsDefinition,
2995 StaticDataMemberDeclaration, nullptr,
2996 AlignInBits, nullptr));
2997 EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
2998 Line, Type, IsLocalToUnit, IsDefinition,
2999 StaticDataMemberDeclaration,
3000 templateParams, (AlignInBits << 1),
3001 nullptr));
3002
3003 TempDIGlobalVariable Temp = N->clone();
3004 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
3005}
3006
3007typedef MetadataTest DIGlobalVariableExpressionTest;
3008
3009TEST_F(DIGlobalVariableExpressionTest, get) {
3010 DIScope *Scope = getSubprogram();
3011 StringRef Name = "name";
3012 StringRef LinkageName = "linkage";
3013 DIFile *File = getFile();
3014 unsigned Line = 5;
3015 DIType *Type = getDerivedType();
3016 bool IsLocalToUnit = false;
3017 bool IsDefinition = true;
3018 MDTuple *templateParams = getTuple();
3019 auto *Expr = DIExpression::get(Context, Elements: {1, 2});
3020 auto *Expr2 = DIExpression::get(Context, Elements: {1, 2, 3});
3021 DIDerivedType *StaticDataMemberDeclaration =
3022 cast<DIDerivedType>(Val: getDerivedType());
3023 uint32_t AlignInBits = 8;
3024
3025 auto *Var = DIGlobalVariable::get(
3026 Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
3027 IsDefinition, StaticDataMemberDeclaration, TemplateParams: templateParams, AlignInBits,
3028 Annotations: nullptr);
3029 auto *Var2 = DIGlobalVariable::get(
3030 Context, Scope, Name: "other", LinkageName, File, Line, Type, IsLocalToUnit,
3031 IsDefinition, StaticDataMemberDeclaration, TemplateParams: templateParams, AlignInBits,
3032 Annotations: nullptr);
3033 auto *N = DIGlobalVariableExpression::get(Context, Variable: Var, Expression: Expr);
3034
3035 EXPECT_EQ(Var, N->getVariable());
3036 EXPECT_EQ(Expr, N->getExpression());
3037 EXPECT_EQ(N, DIGlobalVariableExpression::get(Context, Var, Expr));
3038 EXPECT_NE(N, DIGlobalVariableExpression::get(Context, Var2, Expr));
3039 EXPECT_NE(N, DIGlobalVariableExpression::get(Context, Var, Expr2));
3040
3041 TempDIGlobalVariableExpression Temp = N->clone();
3042 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
3043}
3044
3045typedef MetadataTest DILocalVariableTest;
3046
3047TEST_F(DILocalVariableTest, get) {
3048 DILocalScope *Scope = getSubprogram();
3049 StringRef Name = "name";
3050 DIFile *File = getFile();
3051 unsigned Line = 5;
3052 DIType *Type = getDerivedType();
3053 unsigned Arg = 6;
3054 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
3055 uint32_t AlignInBits = 8;
3056
3057 auto *N =
3058 DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg, Flags,
3059 AlignInBits, Annotations: nullptr);
3060 EXPECT_TRUE(N->isParameter());
3061 EXPECT_EQ(Scope, N->getScope());
3062 EXPECT_EQ(Name, N->getName());
3063 EXPECT_EQ(File, N->getFile());
3064 EXPECT_EQ(Line, N->getLine());
3065 EXPECT_EQ(Type, N->getType());
3066 EXPECT_EQ(Arg, N->getArg());
3067 EXPECT_EQ(Flags, N->getFlags());
3068 EXPECT_EQ(AlignInBits, N->getAlignInBits());
3069 EXPECT_EQ(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg,
3070 Flags, AlignInBits, nullptr));
3071
3072 EXPECT_FALSE(
3073 DILocalVariable::get(Context, Scope, Name, File, Line, Type, 0, Flags,
3074 AlignInBits, nullptr)->isParameter());
3075 EXPECT_NE(N, DILocalVariable::get(Context, getSubprogram(), Name, File, Line,
3076 Type, Arg, Flags, AlignInBits, nullptr));
3077 EXPECT_NE(N, DILocalVariable::get(Context, Scope, "other", File, Line, Type,
3078 Arg, Flags, AlignInBits, nullptr));
3079 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, getFile(), Line, Type,
3080 Arg, Flags, AlignInBits, nullptr));
3081 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line + 1, Type,
3082 Arg, Flags, AlignInBits, nullptr));
3083 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line,
3084 getDerivedType(), Arg, Flags, AlignInBits,
3085 nullptr));
3086 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type,
3087 Arg + 1, Flags, AlignInBits, nullptr));
3088 EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type,
3089 Arg, Flags, (AlignInBits << 1), nullptr));
3090
3091 TempDILocalVariable Temp = N->clone();
3092 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
3093}
3094
3095TEST_F(DILocalVariableTest, getArg256) {
3096 EXPECT_EQ(255u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
3097 0, nullptr, 255, DINode::FlagZero, 0,
3098 nullptr)
3099 ->getArg());
3100 EXPECT_EQ(256u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
3101 0, nullptr, 256, DINode::FlagZero, 0,
3102 nullptr)
3103 ->getArg());
3104 EXPECT_EQ(257u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
3105 0, nullptr, 257, DINode::FlagZero, 0,
3106 nullptr)
3107 ->getArg());
3108 unsigned Max = UINT16_MAX;
3109 EXPECT_EQ(Max, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
3110 0, nullptr, Max, DINode::FlagZero, 0,
3111 nullptr)
3112 ->getArg());
3113}
3114
3115typedef MetadataTest DIExpressionTest;
3116
3117TEST_F(DIExpressionTest, get) {
3118 uint64_t Elements[] = {2, 6, 9, 78, 0};
3119 auto *N = DIExpression::get(Context, Elements);
3120 EXPECT_EQ(ArrayRef(Elements), N->getElements());
3121 EXPECT_EQ(N, DIExpression::get(Context, Elements));
3122
3123 EXPECT_EQ(5u, N->getNumElements());
3124 EXPECT_EQ(2u, N->getElement(0));
3125 EXPECT_EQ(6u, N->getElement(1));
3126 EXPECT_EQ(9u, N->getElement(2));
3127 EXPECT_EQ(78u, N->getElement(3));
3128 EXPECT_EQ(0u, N->getElement(4));
3129
3130 TempDIExpression Temp = N->clone();
3131 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
3132
3133 // Test DIExpression::prepend().
3134 uint64_t Elts0[] = {dwarf::DW_OP_LLVM_fragment, 0, 32};
3135 auto *N0 = DIExpression::get(Context, Elements: Elts0);
3136 uint8_t DIExprFlags = DIExpression::ApplyOffset;
3137 DIExprFlags |= DIExpression::DerefBefore;
3138 DIExprFlags |= DIExpression::DerefAfter;
3139 DIExprFlags |= DIExpression::StackValue;
3140 auto *N0WithPrependedOps = DIExpression::prepend(Expr: N0, Flags: DIExprFlags, Offset: 64);
3141 uint64_t Elts1[] = {dwarf::DW_OP_deref,
3142 dwarf::DW_OP_plus_uconst, 64,
3143 dwarf::DW_OP_deref,
3144 dwarf::DW_OP_stack_value,
3145 dwarf::DW_OP_LLVM_fragment, 0, 32};
3146 auto *N1 = DIExpression::get(Context, Elements: Elts1);
3147 EXPECT_EQ(N0WithPrependedOps, N1);
3148
3149 // Test DIExpression::append().
3150 uint64_t Elts2[] = {dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 64,
3151 dwarf::DW_OP_deref, dwarf::DW_OP_stack_value};
3152 auto *N2 = DIExpression::append(Expr: N0, Ops: Elts2);
3153 EXPECT_EQ(N0WithPrependedOps, N2);
3154}
3155
3156TEST_F(DIExpressionTest, isValid) {
3157#define EXPECT_VALID(...) \
3158 do { \
3159 uint64_t Elements[] = {__VA_ARGS__}; \
3160 EXPECT_TRUE(DIExpression::get(Context, Elements)->isValid()); \
3161 } while (false)
3162#define EXPECT_INVALID(...) \
3163 do { \
3164 uint64_t Elements[] = {__VA_ARGS__}; \
3165 EXPECT_FALSE(DIExpression::get(Context, Elements)->isValid()); \
3166 } while (false)
3167
3168 // Empty expression should be valid.
3169 EXPECT_TRUE(DIExpression::get(Context, std::nullopt)->isValid());
3170
3171 // Valid constructions.
3172 EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6);
3173 EXPECT_VALID(dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus);
3174 EXPECT_VALID(dwarf::DW_OP_deref);
3175 EXPECT_VALID(dwarf::DW_OP_LLVM_fragment, 3, 7);
3176 EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref);
3177 EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6);
3178 EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_LLVM_fragment, 3, 7);
3179 EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6,
3180 dwarf::DW_OP_LLVM_fragment, 3, 7);
3181 EXPECT_VALID(dwarf::DW_OP_LLVM_entry_value, 1);
3182 EXPECT_VALID(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_entry_value, 1);
3183
3184 // Invalid constructions.
3185 EXPECT_INVALID(~0u);
3186 EXPECT_INVALID(dwarf::DW_OP_plus, 0);
3187 EXPECT_INVALID(dwarf::DW_OP_plus_uconst);
3188 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment);
3189 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3);
3190 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus_uconst, 3);
3191 EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_deref);
3192 EXPECT_INVALID(dwarf::DW_OP_LLVM_entry_value, 2);
3193 EXPECT_INVALID(dwarf::DW_OP_plus_uconst, 5, dwarf::DW_OP_LLVM_entry_value, 1);
3194 EXPECT_INVALID(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 5,
3195 dwarf::DW_OP_LLVM_entry_value, 1);
3196 EXPECT_INVALID(dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_LLVM_entry_value, 1);
3197
3198#undef EXPECT_VALID
3199#undef EXPECT_INVALID
3200}
3201
3202TEST_F(DIExpressionTest, createFragmentExpression) {
3203#define EXPECT_VALID_FRAGMENT(Offset, Size, ...) \
3204 do { \
3205 uint64_t Elements[] = {__VA_ARGS__}; \
3206 DIExpression *Expression = DIExpression::get(Context, Elements); \
3207 EXPECT_TRUE( \
3208 DIExpression::createFragmentExpression(Expression, Offset, Size) \
3209 .has_value()); \
3210 } while (false)
3211#define EXPECT_INVALID_FRAGMENT(Offset, Size, ...) \
3212 do { \
3213 uint64_t Elements[] = {__VA_ARGS__}; \
3214 DIExpression *Expression = DIExpression::get(Context, Elements); \
3215 EXPECT_FALSE( \
3216 DIExpression::createFragmentExpression(Expression, Offset, Size) \
3217 .has_value()); \
3218 } while (false)
3219
3220 // createFragmentExpression adds correct ops.
3221 std::optional<DIExpression*> R = DIExpression::createFragmentExpression(
3222 Expr: DIExpression::get(Context, Elements: {}), OffsetInBits: 0, SizeInBits: 32);
3223 EXPECT_EQ(R.has_value(), true);
3224 EXPECT_EQ(3u, (*R)->getNumElements());
3225 EXPECT_EQ(dwarf::DW_OP_LLVM_fragment, (*R)->getElement(0));
3226 EXPECT_EQ(0u, (*R)->getElement(1));
3227 EXPECT_EQ(32u, (*R)->getElement(2));
3228
3229 // Valid fragment expressions.
3230 EXPECT_VALID_FRAGMENT(0, 32, {});
3231 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_deref);
3232 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_LLVM_fragment, 0, 32);
3233 EXPECT_VALID_FRAGMENT(16, 16, dwarf::DW_OP_LLVM_fragment, 0, 32);
3234
3235 // Invalid fragment expressions (incompatible ops).
3236 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus,
3237 dwarf::DW_OP_stack_value);
3238 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 14, dwarf::DW_OP_minus,
3239 dwarf::DW_OP_stack_value);
3240 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 16, dwarf::DW_OP_shr,
3241 dwarf::DW_OP_stack_value);
3242 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 16, dwarf::DW_OP_shl,
3243 dwarf::DW_OP_stack_value);
3244 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 16, dwarf::DW_OP_shra,
3245 dwarf::DW_OP_stack_value);
3246 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,
3247 dwarf::DW_OP_stack_value);
3248
3249 // Fragments can be created for expressions using DW_OP_plus to compute an
3250 // address.
3251 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus);
3252 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref);
3253 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref,
3254 dwarf::DW_OP_stack_value);
3255
3256 // Check the other deref operations work in the same way.
3257 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,
3258 dwarf::DW_OP_deref_size, 1);
3259 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,
3260 dwarf::DW_OP_deref_type, 1, 1);
3261 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,
3262 dwarf::DW_OP_xderef);
3263 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,
3264 dwarf::DW_OP_xderef_size, 1);
3265 EXPECT_VALID_FRAGMENT(0, 32, dwarf::DW_OP_plus_uconst, 6,
3266 dwarf::DW_OP_xderef_type, 1, 1);
3267
3268 // Fragments cannot be created for expressions using DW_OP_plus to compute an
3269 // implicit value (check that this correctly fails even though there is a
3270 // deref in the expression).
3271 EXPECT_INVALID_FRAGMENT(0, 32, dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst,
3272 2, dwarf::DW_OP_stack_value);
3273
3274#undef EXPECT_VALID_FRAGMENT
3275#undef EXPECT_INVALID_FRAGMENT
3276}
3277
3278TEST_F(DIExpressionTest, convertToUndefExpression) {
3279#define EXPECT_UNDEF_OPS_EQUAL(TestExpr, Expected) \
3280 do { \
3281 const DIExpression *Undef = \
3282 DIExpression::convertToUndefExpression(TestExpr); \
3283 EXPECT_EQ(Undef, Expected); \
3284 } while (false)
3285#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})
3286
3287 // Expressions which are single-location and non-complex should be unchanged.
3288 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(), GET_EXPR());
3289 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_fragment, 0, 32),
3290 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 0, 32));
3291
3292 // Variadic expressions should become single-location.
3293 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0), GET_EXPR());
3294 EXPECT_UNDEF_OPS_EQUAL(
3295 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_fragment, 32, 32),
3296 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 32, 32));
3297 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,
3298 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul),
3299 GET_EXPR());
3300 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,
3301 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul,
3302 dwarf::DW_OP_LLVM_fragment, 64, 32),
3303 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 64, 32));
3304
3305 // Any stack-computing ops should be removed.
3306 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_plus_uconst, 8), GET_EXPR());
3307 EXPECT_UNDEF_OPS_EQUAL(
3308 GET_EXPR(dwarf::DW_OP_plus_uconst, 8, dwarf::DW_OP_LLVM_fragment, 0, 16),
3309 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 0, 16));
3310 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 24, dwarf::DW_OP_shra),
3311 GET_EXPR());
3312 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 24, dwarf::DW_OP_shra,
3313 dwarf::DW_OP_LLVM_fragment, 8, 16),
3314 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 8, 16));
3315 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_deref), GET_EXPR());
3316 EXPECT_UNDEF_OPS_EQUAL(
3317 GET_EXPR(dwarf::DW_OP_deref, dwarf::DW_OP_LLVM_fragment, 16, 16),
3318 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 16, 16));
3319 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 4, dwarf::DW_OP_minus),
3320 GET_EXPR());
3321 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_constu, 4, dwarf::DW_OP_minus,
3322 dwarf::DW_OP_LLVM_fragment, 24, 16),
3323 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 24, 16));
3324
3325 // Stack-value operators are also not preserved.
3326 EXPECT_UNDEF_OPS_EQUAL(
3327 GET_EXPR(dwarf::DW_OP_plus_uconst, 8, dwarf::DW_OP_stack_value),
3328 GET_EXPR());
3329 EXPECT_UNDEF_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_plus_uconst, 8,
3330 dwarf::DW_OP_stack_value,
3331 dwarf::DW_OP_LLVM_fragment, 32, 16),
3332 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 32, 16));
3333
3334#undef EXPECT_UNDEF_OPS_EQUAL
3335#undef GET_EXPR
3336}
3337
3338TEST_F(DIExpressionTest, convertToVariadicExpression) {
3339#define EXPECT_CONVERT_IS_NOOP(TestExpr) \
3340 do { \
3341 const DIExpression *Variadic = \
3342 DIExpression::convertToVariadicExpression(TestExpr); \
3343 EXPECT_EQ(Variadic, TestExpr); \
3344 } while (false)
3345#define EXPECT_VARIADIC_OPS_EQUAL(TestExpr, Expected) \
3346 do { \
3347 const DIExpression *Variadic = \
3348 DIExpression::convertToVariadicExpression(TestExpr); \
3349 EXPECT_EQ(Variadic, Expected); \
3350 } while (false)
3351#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})
3352
3353 // Expressions which are already variadic should be unaffected.
3354 EXPECT_CONVERT_IS_NOOP(
3355 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value));
3356 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,
3357 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_plus,
3358 dwarf::DW_OP_stack_value));
3359 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_constu, 5, dwarf::DW_OP_LLVM_arg,
3360 0, dwarf::DW_OP_plus,
3361 dwarf::DW_OP_stack_value));
3362 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,
3363 dwarf::DW_OP_stack_value,
3364 dwarf::DW_OP_LLVM_fragment, 0, 32));
3365
3366 // Other expressions should receive a leading `LLVM_arg 0`.
3367 EXPECT_VARIADIC_OPS_EQUAL(GET_EXPR(), GET_EXPR(dwarf::DW_OP_LLVM_arg, 0));
3368 EXPECT_VARIADIC_OPS_EQUAL(
3369 GET_EXPR(dwarf::DW_OP_plus_uconst, 4),
3370 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4));
3371 EXPECT_VARIADIC_OPS_EQUAL(
3372 GET_EXPR(dwarf::DW_OP_plus_uconst, 4, dwarf::DW_OP_stack_value),
3373 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4,
3374 dwarf::DW_OP_stack_value));
3375 EXPECT_VARIADIC_OPS_EQUAL(
3376 GET_EXPR(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_stack_value,
3377 dwarf::DW_OP_LLVM_fragment, 32, 32),
3378 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 6,
3379 dwarf::DW_OP_stack_value, dwarf::DW_OP_LLVM_fragment, 32, 32));
3380 EXPECT_VARIADIC_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_plus_uconst, 14,
3381 dwarf::DW_OP_LLVM_fragment, 32, 32),
3382 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,
3383 dwarf::DW_OP_plus_uconst, 14,
3384 dwarf::DW_OP_LLVM_fragment, 32, 32));
3385
3386#undef EXPECT_CONVERT_IS_NOOP
3387#undef EXPECT_VARIADIC_OPS_EQUAL
3388#undef GET_EXPR
3389}
3390
3391TEST_F(DIExpressionTest, convertToNonVariadicExpression) {
3392#define EXPECT_CONVERT_IS_NOOP(TestExpr) \
3393 do { \
3394 std::optional<const DIExpression *> NonVariadic = \
3395 DIExpression::convertToNonVariadicExpression(TestExpr); \
3396 EXPECT_TRUE(NonVariadic.has_value()); \
3397 EXPECT_EQ(*NonVariadic, TestExpr); \
3398 } while (false)
3399#define EXPECT_NON_VARIADIC_OPS_EQUAL(TestExpr, Expected) \
3400 do { \
3401 std::optional<const DIExpression *> NonVariadic = \
3402 DIExpression::convertToNonVariadicExpression(TestExpr); \
3403 EXPECT_TRUE(NonVariadic.has_value()); \
3404 EXPECT_EQ(*NonVariadic, Expected); \
3405 } while (false)
3406#define EXPECT_INVALID_CONVERSION(TestExpr) \
3407 do { \
3408 std::optional<const DIExpression *> NonVariadic = \
3409 DIExpression::convertToNonVariadicExpression(TestExpr); \
3410 EXPECT_FALSE(NonVariadic.has_value()); \
3411 } while (false)
3412#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})
3413
3414 // Expressions which are already non-variadic should be unaffected.
3415 EXPECT_CONVERT_IS_NOOP(GET_EXPR());
3416 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_plus_uconst, 4));
3417 EXPECT_CONVERT_IS_NOOP(
3418 GET_EXPR(dwarf::DW_OP_plus_uconst, 4, dwarf::DW_OP_stack_value));
3419 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_plus_uconst, 6,
3420 dwarf::DW_OP_stack_value,
3421 dwarf::DW_OP_LLVM_fragment, 32, 32));
3422 EXPECT_CONVERT_IS_NOOP(GET_EXPR(dwarf::DW_OP_plus_uconst, 14,
3423 dwarf::DW_OP_LLVM_fragment, 32, 32));
3424
3425 // Variadic expressions with a single leading `LLVM_arg 0` and no other
3426 // LLVM_args should have the leading arg removed.
3427 EXPECT_NON_VARIADIC_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0), GET_EXPR());
3428 EXPECT_NON_VARIADIC_OPS_EQUAL(
3429 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value),
3430 GET_EXPR(dwarf::DW_OP_stack_value));
3431 EXPECT_NON_VARIADIC_OPS_EQUAL(
3432 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_fragment, 16, 32),
3433 GET_EXPR(dwarf::DW_OP_LLVM_fragment, 16, 32));
3434 EXPECT_NON_VARIADIC_OPS_EQUAL(
3435 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_stack_value,
3436 dwarf::DW_OP_LLVM_fragment, 24, 32),
3437 GET_EXPR(dwarf::DW_OP_stack_value, dwarf::DW_OP_LLVM_fragment, 24, 32));
3438 EXPECT_NON_VARIADIC_OPS_EQUAL(
3439 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4),
3440 GET_EXPR(dwarf::DW_OP_plus_uconst, 4));
3441 EXPECT_NON_VARIADIC_OPS_EQUAL(
3442 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 4,
3443 dwarf::DW_OP_stack_value),
3444 GET_EXPR(dwarf::DW_OP_plus_uconst, 4, dwarf::DW_OP_stack_value));
3445 EXPECT_NON_VARIADIC_OPS_EQUAL(
3446 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 6,
3447 dwarf::DW_OP_stack_value, dwarf::DW_OP_LLVM_fragment, 32, 32),
3448 GET_EXPR(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_stack_value,
3449 dwarf::DW_OP_LLVM_fragment, 32, 32));
3450 EXPECT_NON_VARIADIC_OPS_EQUAL(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,
3451 dwarf::DW_OP_plus_uconst, 14,
3452 dwarf::DW_OP_LLVM_fragment, 32, 32),
3453 GET_EXPR(dwarf::DW_OP_plus_uconst, 14,
3454 dwarf::DW_OP_LLVM_fragment, 32, 32));
3455
3456 // Variadic expressions that have any LLVM_args other than a leading
3457 // `LLVM_arg 0` cannot be converted and so should return std::nullopt.
3458 EXPECT_INVALID_CONVERSION(GET_EXPR(
3459 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul));
3460 EXPECT_INVALID_CONVERSION(
3461 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 1,
3462 dwarf::DW_OP_plus, dwarf::DW_OP_stack_value));
3463 EXPECT_INVALID_CONVERSION(
3464 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 0,
3465 dwarf::DW_OP_minus, dwarf::DW_OP_stack_value));
3466 EXPECT_INVALID_CONVERSION(GET_EXPR(dwarf::DW_OP_constu, 5,
3467 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_div,
3468 dwarf::DW_OP_stack_value));
3469
3470#undef EXPECT_CONVERT_IS_NOOP
3471#undef EXPECT_NON_VARIADIC_OPS_EQUAL
3472#undef EXPECT_INVALID_CONVERSION
3473#undef GET_EXPR
3474}
3475
3476TEST_F(DIExpressionTest, replaceArg) {
3477#define EXPECT_REPLACE_ARG_EQ(Expr, OldArg, NewArg, ...) \
3478 do { \
3479 uint64_t Elements[] = {__VA_ARGS__}; \
3480 ArrayRef<uint64_t> Expected = Elements; \
3481 DIExpression *Expression = DIExpression::replaceArg(Expr, OldArg, NewArg); \
3482 EXPECT_EQ(Expression->getElements(), Expected); \
3483 } while (false)
3484
3485 auto N = DIExpression::get(
3486 Context, Elements: {dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_LLVM_arg, 1,
3487 dwarf::DW_OP_plus, dwarf::DW_OP_LLVM_arg, 2, dwarf::DW_OP_mul});
3488 EXPECT_REPLACE_ARG_EQ(N, 0, 1, dwarf::DW_OP_LLVM_arg, 0,
3489 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus,
3490 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul);
3491 EXPECT_REPLACE_ARG_EQ(N, 0, 2, dwarf::DW_OP_LLVM_arg, 1,
3492 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus,
3493 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul);
3494 EXPECT_REPLACE_ARG_EQ(N, 2, 0, dwarf::DW_OP_LLVM_arg, 0,
3495 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_plus,
3496 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_mul);
3497 EXPECT_REPLACE_ARG_EQ(N, 2, 1, dwarf::DW_OP_LLVM_arg, 0,
3498 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_plus,
3499 dwarf::DW_OP_LLVM_arg, 1, dwarf::DW_OP_mul);
3500
3501#undef EXPECT_REPLACE_ARG_EQ
3502}
3503
3504TEST_F(DIExpressionTest, isEqualExpression) {
3505#define EXPECT_EQ_DEBUG_VALUE(ExprA, DirectA, ExprB, DirectB) \
3506 EXPECT_TRUE(DIExpression::isEqualExpression(ExprA, DirectA, ExprB, DirectB))
3507#define EXPECT_NE_DEBUG_VALUE(ExprA, DirectA, ExprB, DirectB) \
3508 EXPECT_FALSE(DIExpression::isEqualExpression(ExprA, DirectA, ExprB, DirectB))
3509#define GET_EXPR(...) DIExpression::get(Context, {__VA_ARGS__})
3510
3511 EXPECT_EQ_DEBUG_VALUE(GET_EXPR(), false, GET_EXPR(), false);
3512 EXPECT_NE_DEBUG_VALUE(GET_EXPR(), false, GET_EXPR(), true);
3513 EXPECT_EQ_DEBUG_VALUE(
3514 GET_EXPR(dwarf::DW_OP_plus_uconst, 32), true,
3515 GET_EXPR(dwarf::DW_OP_plus_uconst, 32, dwarf::DW_OP_deref), false);
3516 EXPECT_NE_DEBUG_VALUE(
3517 GET_EXPR(dwarf::DW_OP_plus_uconst, 16, dwarf::DW_OP_deref), true,
3518 GET_EXPR(dwarf::DW_OP_plus_uconst, 16, dwarf::DW_OP_deref), false);
3519 EXPECT_EQ_DEBUG_VALUE(
3520 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus_uconst, 5), false,
3521 GET_EXPR(dwarf::DW_OP_plus_uconst, 5), false);
3522 EXPECT_NE_DEBUG_VALUE(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus),
3523 false,
3524 GET_EXPR(dwarf::DW_OP_LLVM_arg, 0,
3525 dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_plus),
3526 false);
3527 EXPECT_NE_DEBUG_VALUE(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_constu,
3528 8, dwarf::DW_OP_minus),
3529 false,
3530 GET_EXPR(dwarf::DW_OP_constu, 8, dwarf::DW_OP_LLVM_arg,
3531 0, dwarf::DW_OP_minus),
3532 false);
3533 // These expressions are actually equivalent, but we do not currently identify
3534 // commutative operations with different operand orders as being equivalent.
3535 EXPECT_NE_DEBUG_VALUE(GET_EXPR(dwarf::DW_OP_LLVM_arg, 0, dwarf::DW_OP_constu,
3536 8, dwarf::DW_OP_plus),
3537 false,
3538 GET_EXPR(dwarf::DW_OP_constu, 8, dwarf::DW_OP_LLVM_arg,
3539 0, dwarf::DW_OP_plus),
3540 false);
3541
3542#undef EXPECT_EQ_DEBUG_VALUE
3543#undef EXPECT_NE_DEBUG_VALUE
3544#undef GET_EXPR
3545}
3546
3547TEST_F(DIExpressionTest, foldConstant) {
3548 const ConstantInt *Int;
3549 const ConstantInt *NewInt;
3550 DIExpression *Expr;
3551 DIExpression *NewExpr;
3552
3553#define EXPECT_FOLD_CONST(StartWidth, StartValue, EndWidth, EndValue, NumElts) \
3554 Int = ConstantInt::get(Context, APInt(StartWidth, StartValue)); \
3555 std::tie(NewExpr, NewInt) = Expr->constantFold(Int); \
3556 ASSERT_EQ(NewInt->getBitWidth(), EndWidth##u); \
3557 EXPECT_EQ(NewInt->getValue(), APInt(EndWidth, EndValue)); \
3558 EXPECT_EQ(NewExpr->getNumElements(), NumElts##u)
3559
3560 // Unfoldable expression should return the original unmodified Int/Expr.
3561 Expr = DIExpression::get(Context, Elements: {dwarf::DW_OP_deref});
3562 EXPECT_FOLD_CONST(32, 117, 32, 117, 1);
3563 EXPECT_EQ(NewExpr, Expr);
3564 EXPECT_EQ(NewInt, Int);
3565 EXPECT_TRUE(NewExpr->startsWithDeref());
3566
3567 // One unsigned bit-width conversion.
3568 Expr = DIExpression::get(
3569 Context, Elements: {dwarf::DW_OP_LLVM_convert, 72, dwarf::DW_ATE_unsigned});
3570 EXPECT_FOLD_CONST(8, 12, 72, 12, 0);
3571
3572 // Two unsigned bit-width conversions (mask truncation).
3573 Expr = DIExpression::get(
3574 Context, Elements: {dwarf::DW_OP_LLVM_convert, 8, dwarf::DW_ATE_unsigned,
3575 dwarf::DW_OP_LLVM_convert, 16, dwarf::DW_ATE_unsigned});
3576 EXPECT_FOLD_CONST(32, -1, 16, 0xff, 0);
3577
3578 // Sign extension.
3579 Expr = DIExpression::get(
3580 Context, Elements: {dwarf::DW_OP_LLVM_convert, 32, dwarf::DW_ATE_signed});
3581 EXPECT_FOLD_CONST(16, -1, 32, -1, 0);
3582
3583 // Get non-foldable operations back in the new Expr.
3584 uint64_t Elements[] = {dwarf::DW_OP_deref, dwarf::DW_OP_stack_value};
3585 ArrayRef<uint64_t> Expected = Elements;
3586 Expr = DIExpression::get(
3587 Context, Elements: {dwarf::DW_OP_LLVM_convert, 32, dwarf::DW_ATE_signed});
3588 Expr = DIExpression::append(Expr, Ops: Expected);
3589 ASSERT_EQ(Expr->getNumElements(), 5u);
3590 EXPECT_FOLD_CONST(16, -1, 32, -1, 2);
3591 EXPECT_EQ(NewExpr->getElements(), Expected);
3592
3593#undef EXPECT_FOLD_CONST
3594}
3595
3596TEST_F(DIExpressionTest, appendToStackAssert) {
3597 DIExpression *Expr = DIExpression::get(Context, Elements: {});
3598
3599 // Verify that the DW_OP_LLVM_convert operands, which have the same values as
3600 // DW_OP_stack_value and DW_OP_LLVM_fragment, do not get interpreted as such
3601 // operations. This previously triggered an assert.
3602 uint64_t FromSize = dwarf::DW_OP_stack_value;
3603 uint64_t ToSize = dwarf::DW_OP_LLVM_fragment;
3604 uint64_t Ops[] = {
3605 dwarf::DW_OP_LLVM_convert, FromSize, dwarf::DW_ATE_signed,
3606 dwarf::DW_OP_LLVM_convert, ToSize, dwarf::DW_ATE_signed,
3607 };
3608 Expr = DIExpression::appendToStack(Expr, Ops);
3609
3610 uint64_t Expected[] = {
3611 dwarf::DW_OP_LLVM_convert, FromSize, dwarf::DW_ATE_signed,
3612 dwarf::DW_OP_LLVM_convert, ToSize, dwarf::DW_ATE_signed,
3613 dwarf::DW_OP_stack_value};
3614 EXPECT_EQ(Expr->getElements(), ArrayRef<uint64_t>(Expected));
3615}
3616
3617typedef MetadataTest DIObjCPropertyTest;
3618
3619TEST_F(DIObjCPropertyTest, get) {
3620 StringRef Name = "name";
3621 DIFile *File = getFile();
3622 unsigned Line = 5;
3623 StringRef GetterName = "getter";
3624 StringRef SetterName = "setter";
3625 unsigned Attributes = 7;
3626 DIType *Type = getBasicType(Name: "basic");
3627
3628 auto *N = DIObjCProperty::get(Context, Name, File, Line, GetterName,
3629 SetterName, Attributes, Type);
3630
3631 EXPECT_EQ(dwarf::DW_TAG_APPLE_property, N->getTag());
3632 EXPECT_EQ(Name, N->getName());
3633 EXPECT_EQ(File, N->getFile());
3634 EXPECT_EQ(Line, N->getLine());
3635 EXPECT_EQ(GetterName, N->getGetterName());
3636 EXPECT_EQ(SetterName, N->getSetterName());
3637 EXPECT_EQ(Attributes, N->getAttributes());
3638 EXPECT_EQ(Type, N->getType());
3639 EXPECT_EQ(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
3640 SetterName, Attributes, Type));
3641
3642 EXPECT_NE(N, DIObjCProperty::get(Context, "other", File, Line, GetterName,
3643 SetterName, Attributes, Type));
3644 EXPECT_NE(N, DIObjCProperty::get(Context, Name, getFile(), Line, GetterName,
3645 SetterName, Attributes, Type));
3646 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line + 1, GetterName,
3647 SetterName, Attributes, Type));
3648 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, "other",
3649 SetterName, Attributes, Type));
3650 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
3651 "other", Attributes, Type));
3652 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
3653 SetterName, Attributes + 1, Type));
3654 EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
3655 SetterName, Attributes,
3656 getBasicType("other")));
3657
3658 TempDIObjCProperty Temp = N->clone();
3659 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
3660}
3661
3662typedef MetadataTest DIImportedEntityTest;
3663
3664TEST_F(DIImportedEntityTest, get) {
3665 unsigned Tag = dwarf::DW_TAG_imported_module;
3666 DIScope *Scope = getSubprogram();
3667 DINode *Entity = getCompositeType();
3668 DIFile *File = getFile();
3669 unsigned Line = 5;
3670 StringRef Name = "name";
3671
3672 auto *N =
3673 DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line, Name);
3674
3675 EXPECT_EQ(Tag, N->getTag());
3676 EXPECT_EQ(Scope, N->getScope());
3677 EXPECT_EQ(Entity, N->getEntity());
3678 EXPECT_EQ(File, N->getFile());
3679 EXPECT_EQ(Line, N->getLine());
3680 EXPECT_EQ(Name, N->getName());
3681 EXPECT_EQ(
3682 N, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line, Name));
3683
3684 EXPECT_NE(N,
3685 DIImportedEntity::get(Context, dwarf::DW_TAG_imported_declaration,
3686 Scope, Entity, File, Line, Name));
3687 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, getSubprogram(), Entity,
3688 File, Line, Name));
3689 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, getCompositeType(),
3690 File, Line, Name));
3691 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, Entity, nullptr, Line,
3692 Name));
3693 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, Entity, File,
3694 Line + 1, Name));
3695 EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,
3696 "other"));
3697
3698 TempDIImportedEntity Temp = N->clone();
3699 EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
3700
3701 MDTuple *Elements1 = getTuple();
3702 MDTuple *Elements2 = getTuple();
3703 auto *Ne = DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,
3704 Name, Elements: Elements1);
3705
3706 EXPECT_EQ(Elements1, Ne->getElements().get());
3707
3708 EXPECT_EQ(Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,
3709 Name, Elements1));
3710 EXPECT_NE(Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,
3711 "ModOther", Elements1));
3712 EXPECT_NE(Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line,
3713 Name, Elements2));
3714 EXPECT_NE(
3715 Ne, DIImportedEntity::get(Context, Tag, Scope, Entity, File, Line, Name));
3716
3717 TempDIImportedEntity Tempe = Ne->clone();
3718 EXPECT_EQ(Ne, MDNode::replaceWithUniqued(std::move(Tempe)));
3719}
3720
3721typedef MetadataTest MetadataAsValueTest;
3722
3723TEST_F(MetadataAsValueTest, MDNode) {
3724 MDNode *N = MDNode::get(Context, MDs: std::nullopt);
3725 auto *V = MetadataAsValue::get(Context, MD: N);
3726 EXPECT_TRUE(V->getType()->isMetadataTy());
3727 EXPECT_EQ(N, V->getMetadata());
3728
3729 auto *V2 = MetadataAsValue::get(Context, MD: N);
3730 EXPECT_EQ(V, V2);
3731}
3732
3733TEST_F(MetadataAsValueTest, MDNodeMDNode) {
3734 MDNode *N = MDNode::get(Context, MDs: std::nullopt);
3735 Metadata *Ops[] = {N};
3736 MDNode *N2 = MDNode::get(Context, MDs: Ops);
3737 auto *V = MetadataAsValue::get(Context, MD: N2);
3738 EXPECT_TRUE(V->getType()->isMetadataTy());
3739 EXPECT_EQ(N2, V->getMetadata());
3740
3741 auto *V2 = MetadataAsValue::get(Context, MD: N2);
3742 EXPECT_EQ(V, V2);
3743
3744 auto *V3 = MetadataAsValue::get(Context, MD: N);
3745 EXPECT_TRUE(V3->getType()->isMetadataTy());
3746 EXPECT_NE(V, V3);
3747 EXPECT_EQ(N, V3->getMetadata());
3748}
3749
3750TEST_F(MetadataAsValueTest, MDNodeConstant) {
3751 auto *C = ConstantInt::getTrue(Context);
3752 auto *MD = ConstantAsMetadata::get(C);
3753 Metadata *Ops[] = {MD};
3754 auto *N = MDNode::get(Context, MDs: Ops);
3755
3756 auto *V = MetadataAsValue::get(Context, MD);
3757 EXPECT_TRUE(V->getType()->isMetadataTy());
3758 EXPECT_EQ(MD, V->getMetadata());
3759
3760 auto *V2 = MetadataAsValue::get(Context, MD: N);
3761 EXPECT_EQ(MD, V2->getMetadata());
3762 EXPECT_EQ(V, V2);
3763}
3764
3765typedef MetadataTest ValueAsMetadataTest;
3766
3767TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) {
3768 Type *Ty = PointerType::getUnqual(C&: Context);
3769 std::unique_ptr<GlobalVariable> GV0(
3770 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
3771 auto *MD = ValueAsMetadata::get(V: GV0.get());
3772 EXPECT_TRUE(MD->getValue() == GV0.get());
3773 ASSERT_TRUE(GV0->use_empty());
3774
3775 std::unique_ptr<GlobalVariable> GV1(
3776 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
3777 GV0->replaceAllUsesWith(V: GV1.get());
3778 EXPECT_TRUE(MD->getValue() == GV1.get());
3779}
3780
3781TEST_F(ValueAsMetadataTest, handleRAUWWithTypeChange) {
3782 // Test that handleRAUW supports type changes.
3783 // This is helpful in cases where poison values are used to encode
3784 // types in metadata, e.g. in type annotations.
3785 // Changing the type stored in metadata requires to change the type of
3786 // the stored poison value.
3787 auto *I32Poison = PoisonValue::get(T: Type::getInt32Ty(C&: Context));
3788 auto *I64Poison = PoisonValue::get(T: Type::getInt64Ty(C&: Context));
3789 auto *MD = ConstantAsMetadata::get(C: I32Poison);
3790
3791 EXPECT_EQ(MD->getValue(), I32Poison);
3792 EXPECT_NE(MD->getValue(), I64Poison);
3793
3794 ValueAsMetadata::handleRAUW(From: I32Poison, To: I64Poison);
3795
3796 EXPECT_NE(MD->getValue(), I32Poison);
3797 EXPECT_EQ(MD->getValue(), I64Poison);
3798}
3799
3800TEST_F(ValueAsMetadataTest, TempTempReplacement) {
3801 // Create a constant.
3802 ConstantAsMetadata *CI =
3803 ConstantAsMetadata::get(C: ConstantInt::get(Context, V: APInt(8, 0)));
3804
3805 auto Temp1 = MDTuple::getTemporary(Context, MDs: std::nullopt);
3806 auto Temp2 = MDTuple::getTemporary(Context, MDs: {CI});
3807 auto *N = MDTuple::get(Context, MDs: {Temp1.get()});
3808
3809 // Test replacing a temporary node with another temporary node.
3810 Temp1->replaceAllUsesWith(MD: Temp2.get());
3811 EXPECT_EQ(N->getOperand(0), Temp2.get());
3812
3813 // Clean up Temp2 for teardown.
3814 Temp2->replaceAllUsesWith(MD: nullptr);
3815}
3816
3817TEST_F(ValueAsMetadataTest, CollidingDoubleUpdates) {
3818 // Create a constant.
3819 ConstantAsMetadata *CI =
3820 ConstantAsMetadata::get(C: ConstantInt::get(Context, V: APInt(8, 0)));
3821
3822 // Create a temporary to prevent nodes from resolving.
3823 auto Temp = MDTuple::getTemporary(Context, MDs: std::nullopt);
3824
3825 // When the first operand of N1 gets reset to nullptr, it'll collide with N2.
3826 Metadata *Ops1[] = {CI, CI, Temp.get()};
3827 Metadata *Ops2[] = {nullptr, CI, Temp.get()};
3828
3829 auto *N1 = MDTuple::get(Context, MDs: Ops1);
3830 auto *N2 = MDTuple::get(Context, MDs: Ops2);
3831 ASSERT_NE(N1, N2);
3832
3833 // Tell metadata that the constant is getting deleted.
3834 //
3835 // After this, N1 will be invalid, so don't touch it.
3836 ValueAsMetadata::handleDeletion(V: CI->getValue());
3837 EXPECT_EQ(nullptr, N2->getOperand(0));
3838 EXPECT_EQ(nullptr, N2->getOperand(1));
3839 EXPECT_EQ(Temp.get(), N2->getOperand(2));
3840
3841 // Clean up Temp for teardown.
3842 Temp->replaceAllUsesWith(MD: nullptr);
3843}
3844
3845typedef MetadataTest DIArgListTest;
3846
3847TEST_F(DIArgListTest, get) {
3848 SmallVector<ValueAsMetadata *, 2> VMs;
3849 VMs.push_back(
3850 Elt: ConstantAsMetadata::get(C: ConstantInt::get(Context, V: APInt(8, 0))));
3851 VMs.push_back(
3852 Elt: ConstantAsMetadata::get(C: ConstantInt::get(Context, V: APInt(2, 0))));
3853 DIArgList *DV0 = DIArgList::get(Context, Args: VMs);
3854 DIArgList *DV1 = DIArgList::get(Context, Args: VMs);
3855 EXPECT_EQ(DV0, DV1);
3856}
3857
3858TEST_F(DIArgListTest, UpdatesOnRAUW) {
3859 Type *Ty = PointerType::getUnqual(C&: Context);
3860 ConstantAsMetadata *CI =
3861 ConstantAsMetadata::get(C: ConstantInt::get(Context, V: APInt(8, 0)));
3862 std::unique_ptr<GlobalVariable> GV0(
3863 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
3864 auto *MD0 = ValueAsMetadata::get(V: GV0.get());
3865
3866 SmallVector<ValueAsMetadata *, 2> VMs;
3867 VMs.push_back(Elt: CI);
3868 VMs.push_back(Elt: MD0);
3869 auto *AL = DIArgList::get(Context, Args: VMs);
3870 EXPECT_EQ(AL->getArgs()[0], CI);
3871 EXPECT_EQ(AL->getArgs()[1], MD0);
3872
3873 std::unique_ptr<GlobalVariable> GV1(
3874 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
3875 auto *MD1 = ValueAsMetadata::get(V: GV1.get());
3876 GV0->replaceAllUsesWith(V: GV1.get());
3877 EXPECT_EQ(AL->getArgs()[0], CI);
3878 EXPECT_EQ(AL->getArgs()[1], MD1);
3879}
3880
3881typedef MetadataTest TrackingMDRefTest;
3882
3883TEST_F(TrackingMDRefTest, UpdatesOnRAUW) {
3884 Type *Ty = PointerType::getUnqual(C&: Context);
3885 std::unique_ptr<GlobalVariable> GV0(
3886 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
3887 TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(V: GV0.get()));
3888 EXPECT_TRUE(MD->getValue() == GV0.get());
3889 ASSERT_TRUE(GV0->use_empty());
3890
3891 std::unique_ptr<GlobalVariable> GV1(
3892 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
3893 GV0->replaceAllUsesWith(V: GV1.get());
3894 EXPECT_TRUE(MD->getValue() == GV1.get());
3895
3896 // Reset it, so we don't inadvertently test deletion.
3897 MD.reset();
3898}
3899
3900TEST_F(TrackingMDRefTest, UpdatesOnDeletion) {
3901 Type *Ty = PointerType::getUnqual(C&: Context);
3902 std::unique_ptr<GlobalVariable> GV(
3903 new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
3904 TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(V: GV.get()));
3905 EXPECT_TRUE(MD->getValue() == GV.get());
3906 ASSERT_TRUE(GV->use_empty());
3907
3908 GV.reset();
3909 EXPECT_TRUE(!MD);
3910}
3911
3912TEST(NamedMDNodeTest, Search) {
3913 LLVMContext Context;
3914 ConstantAsMetadata *C =
3915 ConstantAsMetadata::get(C: ConstantInt::get(Ty: Type::getInt32Ty(C&: Context), V: 1));
3916 ConstantAsMetadata *C2 =
3917 ConstantAsMetadata::get(C: ConstantInt::get(Ty: Type::getInt32Ty(C&: Context), V: 2));
3918
3919 Metadata *const V = C;
3920 Metadata *const V2 = C2;
3921 MDNode *n = MDNode::get(Context, MDs: V);
3922 MDNode *n2 = MDNode::get(Context, MDs: V2);
3923
3924 Module M("MyModule", Context);
3925 const char *Name = "llvm.NMD1";
3926 NamedMDNode *NMD = M.getOrInsertNamedMetadata(Name);
3927 NMD->addOperand(M: n);
3928 NMD->addOperand(M: n2);
3929
3930 std::string Str;
3931 raw_string_ostream oss(Str);
3932 NMD->print(ROS&: oss);
3933 EXPECT_STREQ("!llvm.NMD1 = !{!0, !1}\n",
3934 oss.str().c_str());
3935}
3936
3937typedef MetadataTest FunctionAttachmentTest;
3938TEST_F(FunctionAttachmentTest, setMetadata) {
3939 Function *F = getFunction(Name: "foo");
3940 ASSERT_FALSE(F->hasMetadata());
3941 EXPECT_EQ(nullptr, F->getMetadata(LLVMContext::MD_dbg));
3942 EXPECT_EQ(nullptr, F->getMetadata("dbg"));
3943 EXPECT_EQ(nullptr, F->getMetadata("other"));
3944
3945 DISubprogram *SP1 = getSubprogram();
3946 DISubprogram *SP2 = getSubprogram();
3947 ASSERT_NE(SP1, SP2);
3948
3949 F->setMetadata(Kind: "dbg", Node: SP1);
3950 EXPECT_TRUE(F->hasMetadata());
3951 EXPECT_EQ(SP1, F->getMetadata(LLVMContext::MD_dbg));
3952 EXPECT_EQ(SP1, F->getMetadata("dbg"));
3953 EXPECT_EQ(nullptr, F->getMetadata("other"));
3954
3955 F->setMetadata(KindID: LLVMContext::MD_dbg, Node: SP2);
3956 EXPECT_TRUE(F->hasMetadata());
3957 EXPECT_EQ(SP2, F->getMetadata(LLVMContext::MD_dbg));
3958 EXPECT_EQ(SP2, F->getMetadata("dbg"));
3959 EXPECT_EQ(nullptr, F->getMetadata("other"));
3960
3961 F->setMetadata(Kind: "dbg", Node: nullptr);
3962 EXPECT_FALSE(F->hasMetadata());
3963 EXPECT_EQ(nullptr, F->getMetadata(LLVMContext::MD_dbg));
3964 EXPECT_EQ(nullptr, F->getMetadata("dbg"));
3965 EXPECT_EQ(nullptr, F->getMetadata("other"));
3966
3967 MDTuple *T1 = getTuple();
3968 MDTuple *T2 = getTuple();
3969 ASSERT_NE(T1, T2);
3970
3971 F->setMetadata(Kind: "other1", Node: T1);
3972 F->setMetadata(Kind: "other2", Node: T2);
3973 EXPECT_TRUE(F->hasMetadata());
3974 EXPECT_EQ(T1, F->getMetadata("other1"));
3975 EXPECT_EQ(T2, F->getMetadata("other2"));
3976 EXPECT_EQ(nullptr, F->getMetadata("dbg"));
3977
3978 F->setMetadata(Kind: "other1", Node: T2);
3979 F->setMetadata(Kind: "other2", Node: T1);
3980 EXPECT_EQ(T2, F->getMetadata("other1"));
3981 EXPECT_EQ(T1, F->getMetadata("other2"));
3982
3983 F->setMetadata(Kind: "other1", Node: nullptr);
3984 F->setMetadata(Kind: "other2", Node: nullptr);
3985 EXPECT_FALSE(F->hasMetadata());
3986 EXPECT_EQ(nullptr, F->getMetadata("other1"));
3987 EXPECT_EQ(nullptr, F->getMetadata("other2"));
3988}
3989
3990TEST_F(FunctionAttachmentTest, getAll) {
3991 Function *F = getFunction(Name: "foo");
3992
3993 MDTuple *T1 = getTuple();
3994 MDTuple *T2 = getTuple();
3995 MDTuple *P = getTuple();
3996 DISubprogram *SP = getSubprogram();
3997
3998 F->setMetadata(Kind: "other1", Node: T2);
3999 F->setMetadata(KindID: LLVMContext::MD_dbg, Node: SP);
4000 F->setMetadata(Kind: "other2", Node: T1);
4001 F->setMetadata(KindID: LLVMContext::MD_prof, Node: P);
4002 F->setMetadata(Kind: "other2", Node: T2);
4003 F->setMetadata(Kind: "other1", Node: T1);
4004
4005 SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
4006 F->getAllMetadata(MDs);
4007 ASSERT_EQ(4u, MDs.size());
4008 EXPECT_EQ(LLVMContext::MD_dbg, MDs[0].first);
4009 EXPECT_EQ(LLVMContext::MD_prof, MDs[1].first);
4010 EXPECT_EQ(Context.getMDKindID("other1"), MDs[2].first);
4011 EXPECT_EQ(Context.getMDKindID("other2"), MDs[3].first);
4012 EXPECT_EQ(SP, MDs[0].second);
4013 EXPECT_EQ(P, MDs[1].second);
4014 EXPECT_EQ(T1, MDs[2].second);
4015 EXPECT_EQ(T2, MDs[3].second);
4016}
4017
4018TEST_F(FunctionAttachmentTest, Verifier) {
4019 Function *F = getFunction(Name: "foo");
4020 F->setMetadata(Kind: "attach", Node: getTuple());
4021 F->setIsMaterializable(true);
4022
4023 // Confirm this is materializable.
4024 ASSERT_TRUE(F->isMaterializable());
4025
4026 // Materializable functions cannot have metadata attachments.
4027 EXPECT_TRUE(verifyFunction(*F));
4028
4029 // Function declarations can.
4030 F->setIsMaterializable(false);
4031 EXPECT_FALSE(verifyModule(*F->getParent()));
4032 EXPECT_FALSE(verifyFunction(*F));
4033
4034 // So can definitions.
4035 (void)new UnreachableInst(Context, BasicBlock::Create(Context, Name: "bb", Parent: F));
4036 EXPECT_FALSE(verifyModule(*F->getParent()));
4037 EXPECT_FALSE(verifyFunction(*F));
4038}
4039
4040TEST_F(FunctionAttachmentTest, RealEntryCount) {
4041 Function *F = getFunction(Name: "foo");
4042 EXPECT_FALSE(F->getEntryCount().has_value());
4043 F->setEntryCount(Count: 12304, Type: Function::PCT_Real);
4044 auto Count = F->getEntryCount();
4045 EXPECT_TRUE(Count.has_value());
4046 EXPECT_EQ(12304u, Count->getCount());
4047 EXPECT_EQ(Function::PCT_Real, Count->getType());
4048}
4049
4050TEST_F(FunctionAttachmentTest, SyntheticEntryCount) {
4051 Function *F = getFunction(Name: "bar");
4052 EXPECT_FALSE(F->getEntryCount().has_value());
4053 F->setEntryCount(Count: 123, Type: Function::PCT_Synthetic);
4054 auto Count = F->getEntryCount(AllowSynthetic: true /*allow synthetic*/);
4055 EXPECT_TRUE(Count.has_value());
4056 EXPECT_EQ(123u, Count->getCount());
4057 EXPECT_EQ(Function::PCT_Synthetic, Count->getType());
4058}
4059
4060TEST_F(FunctionAttachmentTest, SubprogramAttachment) {
4061 Function *F = getFunction(Name: "foo");
4062 DISubprogram *SP = getSubprogram();
4063 F->setSubprogram(SP);
4064
4065 // Note that the static_cast confirms that F->getSubprogram() actually
4066 // returns an DISubprogram.
4067 EXPECT_EQ(SP, static_cast<DISubprogram *>(F->getSubprogram()));
4068 EXPECT_EQ(SP, F->getMetadata("dbg"));
4069 EXPECT_EQ(SP, F->getMetadata(LLVMContext::MD_dbg));
4070}
4071
4072typedef MetadataTest DistinctMDOperandPlaceholderTest;
4073TEST_F(DistinctMDOperandPlaceholderTest, getID) {
4074 EXPECT_EQ(7u, DistinctMDOperandPlaceholder(7).getID());
4075}
4076
4077TEST_F(DistinctMDOperandPlaceholderTest, replaceUseWith) {
4078 // Set up some placeholders.
4079 DistinctMDOperandPlaceholder PH0(7);
4080 DistinctMDOperandPlaceholder PH1(3);
4081 DistinctMDOperandPlaceholder PH2(0);
4082 Metadata *Ops[] = {&PH0, &PH1, &PH2};
4083 auto *D = MDTuple::getDistinct(Context, MDs: Ops);
4084 ASSERT_EQ(&PH0, D->getOperand(0));
4085 ASSERT_EQ(&PH1, D->getOperand(1));
4086 ASSERT_EQ(&PH2, D->getOperand(2));
4087
4088 // Replace them.
4089 auto *N0 = MDTuple::get(Context, MDs: std::nullopt);
4090 auto *N1 = MDTuple::get(Context, MDs: N0);
4091 PH0.replaceUseWith(MD: N0);
4092 PH1.replaceUseWith(MD: N1);
4093 PH2.replaceUseWith(MD: nullptr);
4094 EXPECT_EQ(N0, D->getOperand(0));
4095 EXPECT_EQ(N1, D->getOperand(1));
4096 EXPECT_EQ(nullptr, D->getOperand(2));
4097}
4098
4099TEST_F(DistinctMDOperandPlaceholderTest, replaceUseWithNoUser) {
4100 // There is no user, but we can still call replace.
4101 DistinctMDOperandPlaceholder(7).replaceUseWith(
4102 MD: MDTuple::get(Context, MDs: std::nullopt));
4103}
4104
4105// Test various assertions in metadata tracking. Don't run these tests if gtest
4106// will use SEH to recover from them. Two of these tests get halfway through
4107// inserting metadata into DenseMaps for tracking purposes, and then they
4108// assert, and we attempt to destroy an LLVMContext with broken invariants,
4109// leading to infinite loops.
4110#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH)
4111TEST_F(DistinctMDOperandPlaceholderTest, MetadataAsValue) {
4112 // This shouldn't crash.
4113 DistinctMDOperandPlaceholder PH(7);
4114 EXPECT_DEATH(MetadataAsValue::get(Context, &PH),
4115 "Unexpected callback to owner");
4116}
4117
4118TEST_F(DistinctMDOperandPlaceholderTest, UniquedMDNode) {
4119 // This shouldn't crash.
4120 DistinctMDOperandPlaceholder PH(7);
4121 EXPECT_DEATH(MDTuple::get(Context, &PH), "Unexpected callback to owner");
4122}
4123
4124TEST_F(DistinctMDOperandPlaceholderTest, SecondDistinctMDNode) {
4125 // This shouldn't crash.
4126 DistinctMDOperandPlaceholder PH(7);
4127 MDTuple::getDistinct(Context, &PH);
4128 EXPECT_DEATH(MDTuple::getDistinct(Context, &PH),
4129 "Placeholders can only be used once");
4130}
4131
4132TEST_F(DistinctMDOperandPlaceholderTest, TrackingMDRefAndDistinctMDNode) {
4133 // TrackingMDRef doesn't install an owner callback, so it can't be detected
4134 // as an invalid use. However, using a placeholder in a TrackingMDRef *and*
4135 // a distinct node isn't possible and we should assert.
4136 //
4137 // (There's no positive test for using TrackingMDRef because it's not a
4138 // useful thing to do.)
4139 {
4140 DistinctMDOperandPlaceholder PH(7);
4141 MDTuple::getDistinct(Context, &PH);
4142 EXPECT_DEATH(TrackingMDRef Ref(&PH), "Placeholders can only be used once");
4143 }
4144 {
4145 DistinctMDOperandPlaceholder PH(7);
4146 TrackingMDRef Ref(&PH);
4147 EXPECT_DEATH(MDTuple::getDistinct(Context, &PH),
4148 "Placeholders can only be used once");
4149 }
4150}
4151#endif
4152
4153typedef MetadataTest DebugVariableTest;
4154TEST_F(DebugVariableTest, DenseMap) {
4155 DenseMap<DebugVariable, uint64_t> DebugVariableMap;
4156
4157 DILocalScope *Scope = getSubprogram();
4158 DIFile *File = getFile();
4159 DIType *Type = getDerivedType();
4160 DINode::DIFlags Flags = static_cast<DINode::DIFlags>(7);
4161
4162 DILocation *InlinedLoc = DILocation::get(Context, Line: 2, Column: 7, Scope);
4163
4164 DILocalVariable *VarA =
4165 DILocalVariable::get(Context, Scope, Name: "A", File, Line: 5, Type, Arg: 2, Flags, AlignInBits: 8, Annotations: nullptr);
4166 DILocalVariable *VarB =
4167 DILocalVariable::get(Context, Scope, Name: "B", File, Line: 7, Type, Arg: 3, Flags, AlignInBits: 8, Annotations: nullptr);
4168
4169 DebugVariable DebugVariableA(VarA, std::nullopt, nullptr);
4170 DebugVariable DebugVariableInlineA(VarA, std::nullopt, InlinedLoc);
4171 DebugVariable DebugVariableB(VarB, std::nullopt, nullptr);
4172 DebugVariable DebugVariableFragB(VarB, {{16, 16}}, nullptr);
4173
4174 DebugVariableMap.insert(KV: {DebugVariableA, 2});
4175 DebugVariableMap.insert(KV: {DebugVariableInlineA, 3});
4176 DebugVariableMap.insert(KV: {DebugVariableB, 6});
4177 DebugVariableMap.insert(KV: {DebugVariableFragB, 12});
4178
4179 EXPECT_EQ(DebugVariableMap.count(DebugVariableA), 1u);
4180 EXPECT_EQ(DebugVariableMap.count(DebugVariableInlineA), 1u);
4181 EXPECT_EQ(DebugVariableMap.count(DebugVariableB), 1u);
4182 EXPECT_EQ(DebugVariableMap.count(DebugVariableFragB), 1u);
4183
4184 EXPECT_EQ(DebugVariableMap.find(DebugVariableA)->second, 2u);
4185 EXPECT_EQ(DebugVariableMap.find(DebugVariableInlineA)->second, 3u);
4186 EXPECT_EQ(DebugVariableMap.find(DebugVariableB)->second, 6u);
4187 EXPECT_EQ(DebugVariableMap.find(DebugVariableFragB)->second, 12u);
4188}
4189
4190typedef MetadataTest MDTupleAllocationTest;
4191TEST_F(MDTupleAllocationTest, Tracking) {
4192 // Make sure that the move constructor and move assignment op
4193 // for MDOperand correctly adjust tracking information.
4194 auto *Value1 = getConstantAsMetadata();
4195 MDTuple *A = MDTuple::getDistinct(Context, MDs: {Value1, Value1});
4196 EXPECT_EQ(A->getOperand(0), Value1);
4197 EXPECT_EQ(A->getOperand(1), Value1);
4198
4199 MDNode::op_range Ops = A->operands();
4200
4201 MDOperand NewOps1;
4202 // Move assignment operator.
4203 NewOps1 = std::move(*const_cast<MDOperand *>(Ops.begin()));
4204 // Move constructor.
4205 MDOperand NewOps2(std::move(*const_cast<MDOperand *>(Ops.begin() + 1)));
4206
4207 EXPECT_EQ(NewOps1.get(), static_cast<Metadata *>(Value1));
4208 EXPECT_EQ(NewOps2.get(), static_cast<Metadata *>(Value1));
4209
4210 auto *Value2 = getConstantAsMetadata();
4211 Value *V1 = Value1->getValue();
4212 Value *V2 = Value2->getValue();
4213 ValueAsMetadata::handleRAUW(From: V1, To: V2);
4214
4215 EXPECT_EQ(NewOps1.get(), static_cast<Metadata *>(Value2));
4216 EXPECT_EQ(NewOps2.get(), static_cast<Metadata *>(Value2));
4217}
4218
4219TEST_F(MDTupleAllocationTest, Resize) {
4220 MDTuple *A = getTuple();
4221 Metadata *Value1 = getConstantAsMetadata();
4222 Metadata *Value2 = getConstantAsMetadata();
4223 Metadata *Value3 = getConstantAsMetadata();
4224
4225 EXPECT_EQ(A->getNumOperands(), 0u);
4226
4227 // Add a couple of elements to it, which resizes the node.
4228 A->push_back(MD: Value1);
4229 EXPECT_EQ(A->getNumOperands(), 1u);
4230 EXPECT_EQ(A->getOperand(0), Value1);
4231
4232 A->push_back(MD: Value2);
4233 EXPECT_EQ(A->getNumOperands(), 2u);
4234 EXPECT_EQ(A->getOperand(0), Value1);
4235 EXPECT_EQ(A->getOperand(1), Value2);
4236
4237 // Append another element, which should resize the node
4238 // to a "large" node, though not detectable by the user.
4239 A->push_back(MD: Value3);
4240 EXPECT_EQ(A->getNumOperands(), 3u);
4241 EXPECT_EQ(A->getOperand(0), Value1);
4242 EXPECT_EQ(A->getOperand(1), Value2);
4243 EXPECT_EQ(A->getOperand(2), Value3);
4244
4245 // Remove the last element
4246 A->pop_back();
4247 EXPECT_EQ(A->getNumOperands(), 2u);
4248 EXPECT_EQ(A->getOperand(1), Value2);
4249
4250 // Allocate a node with 4 operands.
4251 Metadata *Value4 = getConstantAsMetadata();
4252 Metadata *Value5 = getConstantAsMetadata();
4253
4254 Metadata *Ops[] = {Value1, Value2, Value3, Value4};
4255 MDTuple *B = MDTuple::getDistinct(Context, MDs: Ops);
4256
4257 EXPECT_EQ(B->getNumOperands(), 4u);
4258 B->pop_back();
4259 EXPECT_EQ(B->getNumOperands(), 3u);
4260 B->push_back(MD: Value5);
4261 EXPECT_EQ(B->getNumOperands(), 4u);
4262 EXPECT_EQ(B->getOperand(0), Value1);
4263 EXPECT_EQ(B->getOperand(1), Value2);
4264 EXPECT_EQ(B->getOperand(2), Value3);
4265 EXPECT_EQ(B->getOperand(3), Value5);
4266
4267 // Check that we can resize temporary nodes as well.
4268 auto Temp1 = MDTuple::getTemporary(Context, MDs: std::nullopt);
4269 EXPECT_EQ(Temp1->getNumOperands(), 0u);
4270
4271 Temp1->push_back(MD: Value1);
4272 EXPECT_EQ(Temp1->getNumOperands(), 1u);
4273 EXPECT_EQ(Temp1->getOperand(0), Value1);
4274
4275 for (int i = 0; i < 11; i++)
4276 Temp1->push_back(MD: Value2);
4277 EXPECT_EQ(Temp1->getNumOperands(), 12u);
4278 EXPECT_EQ(Temp1->getOperand(2), Value2);
4279 EXPECT_EQ(Temp1->getOperand(11), Value2);
4280
4281 // Allocate a node that starts off as a large one.
4282 Metadata *OpsLarge[] = {Value1, Value2, Value3, Value4,
4283 Value1, Value2, Value3, Value4,
4284 Value1, Value2, Value3, Value4,
4285 Value1, Value2, Value3, Value4,
4286 Value1, Value2, Value3, Value4};
4287 MDTuple *C = MDTuple::getDistinct(Context, MDs: OpsLarge);
4288 EXPECT_EQ(C->getNumOperands(), 20u);
4289 EXPECT_EQ(C->getOperand(7), Value4);
4290 EXPECT_EQ(C->getOperand(13), Value2);
4291
4292 C->push_back(MD: Value1);
4293 C->push_back(MD: Value2);
4294 EXPECT_EQ(C->getNumOperands(), 22u);
4295 EXPECT_EQ(C->getOperand(21), Value2);
4296 C->pop_back();
4297 EXPECT_EQ(C->getNumOperands(), 21u);
4298 EXPECT_EQ(C->getOperand(20), Value1);
4299}
4300
4301TEST_F(MDTupleAllocationTest, Tracking2) {
4302 // Resize a tuple and check that we can still RAUW one of its operands.
4303 auto *Value1 = getConstantAsMetadata();
4304 MDTuple *A = getTuple();
4305 A->push_back(MD: Value1);
4306 A->push_back(MD: Value1);
4307 A->push_back(MD: Value1); // Causes a resize to large.
4308 EXPECT_EQ(A->getOperand(0), Value1);
4309 EXPECT_EQ(A->getOperand(1), Value1);
4310 EXPECT_EQ(A->getOperand(2), Value1);
4311
4312 auto *Value2 = getConstantAsMetadata();
4313 Value *V1 = Value1->getValue();
4314 Value *V2 = Value2->getValue();
4315 ValueAsMetadata::handleRAUW(From: V1, To: V2);
4316
4317 EXPECT_EQ(A->getOperand(0), Value2);
4318 EXPECT_EQ(A->getOperand(1), Value2);
4319 EXPECT_EQ(A->getOperand(2), Value2);
4320}
4321
4322#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH)
4323typedef MetadataTest MDTupleAllocationDeathTest;
4324TEST_F(MDTupleAllocationDeathTest, ResizeRejected) {
4325 MDTuple *A = MDTuple::get(Context, std::nullopt);
4326 auto *Value1 = getConstantAsMetadata();
4327 EXPECT_DEATH(A->push_back(Value1),
4328 "Resizing is not supported for uniqued nodes");
4329
4330 // Check that a node, which has been allocated as a temporary,
4331 // cannot be resized after it has been uniqued.
4332 auto *Value2 = getConstantAsMetadata();
4333 auto B = MDTuple::getTemporary(Context, {Value2});
4334 B->push_back(Value2);
4335 MDTuple *BUniqued = MDNode::replaceWithUniqued(std::move(B));
4336 EXPECT_EQ(BUniqued->getNumOperands(), 2u);
4337 EXPECT_EQ(BUniqued->getOperand(1), Value2);
4338 EXPECT_DEATH(BUniqued->push_back(Value2),
4339 "Resizing is not supported for uniqued nodes");
4340}
4341#endif
4342
4343} // end namespace
4344

source code of llvm/unittests/IR/MetadataTest.cpp