[Verifier] Improve error for cross-module refs
[oota-llvm.git] / unittests / CodeGen / DIEHashTest.cpp
1 //===- llvm/unittest/DebugInfo/DWARFFormValueTest.cpp ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/CodeGen/DIE.h"
11 #include "../lib/CodeGen/AsmPrinter/DIEHash.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/CodeGen/DwarfStringPoolEntry.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Dwarf.h"
16 #include "llvm/Support/Format.h"
17 #include "gtest/gtest.h"
18
19 using namespace llvm;
20
21 namespace {
22
23 // Test fixture
24 class DIEHashTest : public testing::Test {
25 public:
26   BumpPtrAllocator Alloc;
27
28 private:
29   StringMap<DwarfStringPoolEntry> Pool;
30
31 public:
32   DIEString getString(StringRef S) {
33     DwarfStringPoolEntry Entry = {nullptr, 1, 1};
34     return DIEString(
35         DwarfStringPoolEntryRef(*Pool.insert(std::make_pair(S, Entry)).first));
36   }
37 };
38
39 TEST_F(DIEHashTest, Data1) {
40   DIEHash Hash;
41   DIE &Die = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
42   DIEInteger Size(4);
43   Die.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Size);
44   uint64_t MD5Res = Hash.computeTypeSignature(Die);
45   ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res);
46 }
47
48 // struct {};
49 TEST_F(DIEHashTest, TrivialType) {
50   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
51   DIEInteger One(1);
52   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
53
54   // Line and file number are ignored.
55   Unnamed.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
56   Unnamed.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
57   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
58
59   // The exact same hash GCC produces for this DIE.
60   ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res);
61 }
62
63 // struct foo { };
64 TEST_F(DIEHashTest, NamedType) {
65   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
66   DIEInteger One(1);
67   DIEString FooStr = getString("foo");
68   Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
69   Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
70
71   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
72
73   // The exact same hash GCC produces for this DIE.
74   ASSERT_EQ(0xd566dbd2ca5265ffULL, MD5Res);
75 }
76
77 // namespace space { struct foo { }; }
78 TEST_F(DIEHashTest, NamespacedType) {
79   DIE &CU = *DIE::get(Alloc, dwarf::DW_TAG_compile_unit);
80
81   auto Space = DIE::get(Alloc, dwarf::DW_TAG_namespace);
82   DIEInteger One(1);
83   DIEString SpaceStr = getString("space");
84   Space->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, SpaceStr);
85   // DW_AT_declaration is ignored.
86   Space->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
87                   One);
88   // sibling?
89
90   auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
91   DIEString FooStr = getString("foo");
92   Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
93   Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
94
95   DIE &N = *Foo;
96   Space->addChild(std::move(Foo));
97   CU.addChild(std::move(Space));
98
99   uint64_t MD5Res = DIEHash().computeTypeSignature(N);
100
101   // The exact same hash GCC produces for this DIE.
102   ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
103 }
104
105 // struct { int member; };
106 TEST_F(DIEHashTest, TypeWithMember) {
107   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
108   DIEInteger Four(4);
109   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
110
111   DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
112   DIEString IntStr = getString("int");
113   Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
114   Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
115   DIEInteger Five(5);
116   Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
117
118   DIEEntry IntRef(Int);
119
120   auto Member = DIE::get(Alloc, dwarf::DW_TAG_member);
121   DIEString MemberStr = getString("member");
122   Member->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemberStr);
123   DIEInteger Zero(0);
124   Member->addValue(Alloc, dwarf::DW_AT_data_member_location,
125                    dwarf::DW_FORM_data1, Zero);
126   Member->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
127
128   Unnamed.addChild(std::move(Member));
129
130   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
131
132   ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
133 }
134
135 // struct foo { int mem1, mem2; };
136 TEST_F(DIEHashTest, ReusedType) {
137   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
138   DIEInteger Eight(8);
139   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
140
141   DIEInteger Four(4);
142   DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
143   DIEString IntStr = getString("int");
144   Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
145   Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
146   DIEInteger Five(5);
147   Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
148
149   DIEEntry IntRef(Int);
150
151   auto Mem1 = DIE::get(Alloc, dwarf::DW_TAG_member);
152   DIEString Mem1Str = getString("mem1");
153   Mem1->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem1Str);
154   DIEInteger Zero(0);
155   Mem1->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
156                  Zero);
157   Mem1->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
158
159   Unnamed.addChild(std::move(Mem1));
160
161   auto Mem2 = DIE::get(Alloc, dwarf::DW_TAG_member);
162   DIEString Mem2Str = getString("mem2");
163   Mem2->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem2Str);
164   Mem2->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
165                  Four);
166   Mem2->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
167
168   Unnamed.addChild(std::move(Mem2));
169
170   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
171
172   ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
173 }
174
175 // struct foo { static foo f; };
176 TEST_F(DIEHashTest, RecursiveType) {
177   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
178   DIEInteger One(1);
179   Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
180   DIEString FooStr = getString("foo");
181   Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
182
183   auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
184   DIEString MemStr = getString("mem");
185   Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
186   DIEEntry FooRef(Foo);
187   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
188   // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
189
190   Foo.addChild(std::move(Mem));
191
192   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
193
194   ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res);
195 }
196
197 // struct foo { foo *mem; };
198 TEST_F(DIEHashTest, Pointer) {
199   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
200   DIEInteger Eight(8);
201   Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
202   DIEString FooStr = getString("foo");
203   Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
204
205   auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
206   DIEString MemStr = getString("mem");
207   Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
208   DIEInteger Zero(0);
209   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
210                 Zero);
211
212   DIE &FooPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
213   FooPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
214   DIEEntry FooRef(Foo);
215   FooPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
216
217   DIEEntry FooPtrRef(FooPtr);
218   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooPtrRef);
219
220   Foo.addChild(std::move(Mem));
221
222   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
223
224   ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res);
225 }
226
227 // struct foo { foo &mem; };
228 TEST_F(DIEHashTest, Reference) {
229   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
230   DIEInteger Eight(8);
231   Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
232   DIEString FooStr = getString("foo");
233   Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
234
235   auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
236   DIEString MemStr = getString("mem");
237   Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
238   DIEInteger Zero(0);
239   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
240                 Zero);
241
242   DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_reference_type);
243   FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
244   DIEEntry FooEntry(Foo);
245   FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
246
247   DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
248   DIEEntry FooRefRef(FooRef);
249   FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
250                        FooRefRef);
251
252   DIEEntry FooRefConstRef(FooRefConst);
253   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
254
255   Foo.addChild(std::move(Mem));
256
257   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
258
259   ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res);
260 }
261
262 // struct foo { foo &&mem; };
263 TEST_F(DIEHashTest, RValueReference) {
264   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
265   DIEInteger Eight(8);
266   Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
267   DIEString FooStr = getString("foo");
268   Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
269
270   auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
271   DIEString MemStr = getString("mem");
272   Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
273   DIEInteger Zero(0);
274   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
275                 Zero);
276
277   DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_rvalue_reference_type);
278   FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
279   DIEEntry FooEntry(Foo);
280   FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
281
282   DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
283   DIEEntry FooRefRef(FooRef);
284   FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
285                        FooRefRef);
286
287   DIEEntry FooRefConstRef(FooRefConst);
288   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
289
290   Foo.addChild(std::move(Mem));
291
292   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
293
294   ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
295 }
296
297 // struct foo { foo foo::*mem; };
298 TEST_F(DIEHashTest, PtrToMember) {
299   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
300   DIEInteger Eight(8);
301   Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
302   DIEString FooStr = getString("foo");
303   Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
304
305   auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
306   DIEString MemStr = getString("mem");
307   Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
308   DIEInteger Zero(0);
309   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
310                 Zero);
311
312   DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
313   DIEEntry FooEntry(Foo);
314   PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
315   PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
316                        FooEntry);
317
318   DIEEntry PtrToFooMemRef(PtrToFooMem);
319   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PtrToFooMemRef);
320
321   Foo.addChild(std::move(Mem));
322
323   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
324
325   ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
326 }
327
328 // Check that the hash for a pointer-to-member matches regardless of whether the
329 // pointed-to type is a declaration or a definition.
330 //
331 //   struct bar; // { };
332 //   struct foo { bar foo::*mem; };
333 TEST_F(DIEHashTest, PtrToMemberDeclDefMatch) {
334   DIEInteger Zero(0);
335   DIEInteger One(1);
336   DIEInteger Eight(8);
337   DIEString FooStr = getString("foo");
338   DIEString BarStr = getString("bar");
339   DIEString MemStr = getString("mem");
340   uint64_t MD5ResDecl;
341   {
342     DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
343     Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
344     Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
345                  One);
346
347     DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
348     Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
349     Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
350
351     auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
352     Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
353     Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
354                   dwarf::DW_FORM_data1, Zero);
355
356     DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
357     DIEEntry BarEntry(Bar);
358     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
359                          BarEntry);
360     DIEEntry FooEntry(Foo);
361     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
362                          dwarf::DW_FORM_ref4, FooEntry);
363
364     DIEEntry PtrToFooMemRef(PtrToFooMem);
365     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
366                   PtrToFooMemRef);
367
368     Foo.addChild(std::move(Mem));
369
370     MD5ResDecl = DIEHash().computeTypeSignature(Foo);
371   }
372   uint64_t MD5ResDef;
373   {
374     DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
375     Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
376     Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
377
378     DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
379     Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
380     Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
381
382     auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
383     Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
384     Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
385                   dwarf::DW_FORM_data1, Zero);
386
387     DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
388     DIEEntry BarEntry(Bar);
389     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
390                          BarEntry);
391     DIEEntry FooEntry(Foo);
392     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
393                          dwarf::DW_FORM_ref4, FooEntry);
394
395     DIEEntry PtrToFooMemRef(PtrToFooMem);
396     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
397                   PtrToFooMemRef);
398
399     Foo.addChild(std::move(Mem));
400
401     MD5ResDef = DIEHash().computeTypeSignature(Foo);
402   }
403   ASSERT_EQ(MD5ResDef, MD5ResDecl);
404 }
405
406 // Check that the hash for a pointer-to-member matches regardless of whether the
407 // pointed-to type is a declaration or a definition.
408 //
409 //   struct bar; // { };
410 //   struct foo { bar bar::*mem; };
411 TEST_F(DIEHashTest, PtrToMemberDeclDefMisMatch) {
412   DIEInteger Zero(0);
413   DIEInteger One(1);
414   DIEInteger Eight(8);
415   DIEString FooStr = getString("foo");
416   DIEString BarStr = getString("bar");
417   DIEString MemStr = getString("mem");
418   uint64_t MD5ResDecl;
419   {
420     DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
421     Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
422     Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
423                  One);
424
425     DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
426     Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
427     Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
428
429     auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
430     Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
431     Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
432                   dwarf::DW_FORM_data1, Zero);
433
434     DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
435     DIEEntry BarEntry(Bar);
436     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
437                          BarEntry);
438     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
439                          dwarf::DW_FORM_ref4, BarEntry);
440
441     DIEEntry PtrToFooMemRef(PtrToFooMem);
442     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
443                   PtrToFooMemRef);
444
445     Foo.addChild(std::move(Mem));
446
447     MD5ResDecl = DIEHash().computeTypeSignature(Foo);
448   }
449   uint64_t MD5ResDef;
450   {
451     DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
452     Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
453     Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
454
455     DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
456     Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
457     Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
458
459     auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
460     Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
461     Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
462                   dwarf::DW_FORM_data1, Zero);
463
464     DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
465     DIEEntry BarEntry(Bar);
466     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
467                          BarEntry);
468     PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
469                          dwarf::DW_FORM_ref4, BarEntry);
470
471     DIEEntry PtrToFooMemRef(PtrToFooMem);
472     Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
473                   PtrToFooMemRef);
474
475     Foo.addChild(std::move(Mem));
476
477     MD5ResDef = DIEHash().computeTypeSignature(Foo);
478   }
479   // FIXME: This seems to be a bug in the DWARF type hashing specification that
480   // only uses the brief name hashing for types referenced via DW_AT_type. In
481   // this case the type is referenced via DW_AT_containing_type and full hashing
482   // causes a hash to differ when the containing type is a declaration in one TU
483   // and a definition in another.
484   ASSERT_NE(MD5ResDef, MD5ResDecl);
485 }
486
487 // struct { } a;
488 // struct foo { decltype(a) mem; };
489 TEST_F(DIEHashTest, RefUnnamedType) {
490   DIEInteger Zero(0);
491   DIEInteger One(1);
492   DIEInteger Eight(8);
493   DIEString FooStr = getString("foo");
494   DIEString MemStr = getString("mem");
495
496   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
497   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
498
499   DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
500   Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
501   Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
502
503   auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
504   Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
505   Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
506                 Zero);
507
508   DIE &UnnamedPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
509   UnnamedPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
510                       Eight);
511   DIEEntry UnnamedRef(Unnamed);
512   UnnamedPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
513                       UnnamedRef);
514
515   DIEEntry UnnamedPtrRef(UnnamedPtr);
516   Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, UnnamedPtrRef);
517
518   Foo.addChild(std::move(Mem));
519
520   uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
521
522   ASSERT_EQ(0x954e026f01c02529ULL, MD5Res);
523 }
524
525 // struct { struct foo { }; };
526 TEST_F(DIEHashTest, NestedType) {
527   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
528   DIEInteger One(1);
529   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
530
531   auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
532   DIEString FooStr = getString("foo");
533   Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
534   Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
535
536   Unnamed.addChild(std::move(Foo));
537
538   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
539
540   // The exact same hash GCC produces for this DIE.
541   ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res);
542 }
543
544 // struct { static void func(); };
545 TEST_F(DIEHashTest, MemberFunc) {
546   DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
547   DIEInteger One(1);
548   Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
549
550   auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
551   DIEString FuncStr = getString("func");
552   Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
553
554   Unnamed.addChild(std::move(Func));
555
556   uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
557
558   // The exact same hash GCC produces for this DIE.
559   ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res);
560 }
561
562 // struct A {
563 //   static void func();
564 // };
565 TEST_F(DIEHashTest, MemberFuncFlag) {
566   DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
567   DIEInteger One(1);
568   DIEString AStr = getString("A");
569   A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
570   A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
571   A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
572   A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
573
574   auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
575   DIEString FuncStr = getString("func");
576   DIEString FuncLinkage = getString("_ZN1A4funcEv");
577   DIEInteger Two(2);
578   Func->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
579                  One);
580   Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
581   Func->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
582   Func->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
583   Func->addValue(Alloc, dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
584                  FuncLinkage);
585   Func->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
586                  One);
587
588   A.addChild(std::move(Func));
589
590   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
591
592   // The exact same hash GCC produces for this DIE.
593   ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res);
594 }
595
596 // Derived from:
597 // struct A {
598 //   const static int PI = -3;
599 // };
600 // A a;
601 TEST_F(DIEHashTest, MemberSdata) {
602   DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
603   DIEInteger One(1);
604   DIEString AStr = getString("A");
605   A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
606   A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
607   A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
608   A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
609
610   DIEInteger Four(4);
611   DIEInteger Five(5);
612   DIEString FStr = getString("int");
613   DIE &IntTyDIE = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
614   IntTyDIE.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
615   IntTyDIE.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
616   IntTyDIE.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
617
618   DIEEntry IntTy(IntTyDIE);
619   auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
620   PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntTy);
621
622   DIEEntry PITy(*PITyDIE);
623   auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
624   DIEString PIStr = getString("PI");
625   DIEInteger Two(2);
626   DIEInteger NegThree(-3);
627   PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
628   PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
629   PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
630   PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
631   PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
632   PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
633                One);
634   PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, NegThree);
635
636   A.addChild(std::move(PI));
637
638   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
639   ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res);
640 }
641
642 // Derived from:
643 // struct A {
644 //   const static float PI = 3.14;
645 // };
646 // A a;
647 TEST_F(DIEHashTest, MemberBlock) {
648   DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
649   DIEInteger One(1);
650   DIEString AStr = getString("A");
651   A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
652   A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
653   A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
654   A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
655
656   DIEInteger Four(4);
657   DIEString FStr = getString("float");
658   auto FloatTyDIE = DIE::get(Alloc, dwarf::DW_TAG_base_type);
659   FloatTyDIE->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
660                        Four);
661   FloatTyDIE->addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
662                        Four);
663   FloatTyDIE->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
664   DIEEntry FloatTy(*FloatTyDIE);
665   auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
666   PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FloatTy);
667
668   DIEEntry PITy(*PITyDIE);
669   auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
670   DIEString PIStr = getString("PI");
671   DIEInteger Two(2);
672   PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
673   PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
674   PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
675   PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
676   PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
677   PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
678                One);
679
680   DIEBlock PIBlock;
681   DIEInteger Blk1(0xc3);
682   DIEInteger Blk2(0xf5);
683   DIEInteger Blk3(0x48);
684   DIEInteger Blk4(0x40);
685
686   PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk1);
687   PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk2);
688   PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk3);
689   PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk4);
690
691   PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_block1,
692                &PIBlock);
693
694   A.addChild(std::move(PI));
695
696   uint64_t MD5Res = DIEHash().computeTypeSignature(A);
697   ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res);
698 }
699 }