| /* Compile with: |
| clang -g -c odr-uniquing.cpp -o odr-uniquing/1.o |
| cp odr-uniquing/1.o odr-uniquing/2.o |
| The aim of these test is to check that all the 'type types' that |
| should be uniqued through the ODR really are. |
| |
| The resulting object file is linked against itself using a fake |
| debug map. The end result is: |
| - with ODR uniquing: all types (expect for the union for now) in |
| the second CU should point back to the types of the first CU. |
| - without ODR uniquing: all types are re-emited in the second CU |
| */ |
| |
| // RUN: dsymutil -f -oso-prepend-path=%p/../Inputs/odr-uniquing -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -v -debug-info - | FileCheck -check-prefix=ODR -check-prefix=CHECK %s |
| // RUN: dsymutil -f -oso-prepend-path=%p/../Inputs/odr-uniquing -y %p/dummy-debug-map.map -no-odr -o - | llvm-dwarfdump -v -debug-info - | FileCheck -check-prefix=NOODR -check-prefix=CHECK %s |
| |
| // The first compile unit contains all the types: |
| // CHECK: TAG_compile_unit |
| // CHECK-NOT: DW_TAG |
| // CHECK: AT_name{{.*}}"odr-uniquing.cpp" |
| |
| struct S { |
| struct Nested {}; |
| }; |
| |
| // CHECK: 0x[[S:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type |
| // CHECK-NEXT: DW_AT_name{{.*}}"S" |
| // CHECK-NOT: NULL |
| // CHECK: 0x[[NESTED:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type |
| // CHECK-NOT: DW_TAG |
| // CHECK: DW_AT_name{{.*}}"Nested" |
| // CHECK: NULL |
| |
| namespace N { |
| class C {}; |
| } |
| |
| // CHECK: DW_TAG_namespace |
| // CHECK-NEXT: DW_AT_name{{.*}}"N" |
| // CHECK-NOT: NULL |
| // CHECK: 0x[[NC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type |
| // CHECK-NEXT: DW_AT_name{{.*}}"C" |
| // CHECK: NULL |
| |
| union U { |
| class C {} C; |
| struct S {} S; |
| }; |
| |
| // CHECK: 0x[[U:[0-9a-f]*]]:{{.*}}DW_TAG_union_type |
| // CHECK-NEXT: DW_AT_name{{.*}}"U" |
| // CHECK-NOT: NULL |
| // CHECK: 0x[[UC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type |
| // CHECK-NOT: NULL |
| // CHECK: 0x[[US:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type |
| // CHECK: NULL |
| |
| typedef S AliasForS; |
| |
| // CHECK: 0x[[ALIASFORS:[0-9a-f]*]]:{{.*}}DW_TAG_typedef |
| // CHECK-NEXT: DW_AT_type{{.*}}[[S]] |
| // CHECK-NEXT: DW_AT_name{{.*}}"AliasForS" |
| |
| namespace { |
| class AnonC {}; |
| } |
| |
| // CHECK: DW_TAG_namespace |
| // CHECK-NOT: {{DW_AT_name|NULL|DW_TAG}} |
| // CHECK: 0x[[ANONC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type |
| // CHECK-NEXT: DW_AT_name{{.*}}"AnonC" |
| |
| // This function is only here to hold objects that refer to the above types. |
| void foo() { |
| AliasForS s; |
| S::Nested n; |
| N::C nc; |
| AnonC ac; |
| U u; |
| } |
| |
| // The second CU contents depend on wether we disabled ODR uniquing or |
| // not. |
| |
| // CHECK: TAG_compile_unit |
| // CHECK-NOT: DW_TAG |
| // CHECK: AT_name{{.*}}"odr-uniquing.cpp" |
| |
| // The union itself is not uniqued for now (for dsymutil-compatibility), |
| // but the types defined inside it should be. |
| // ODR: DW_TAG_union_type |
| // ODR-NEXT: DW_AT_name{{.*}}"U" |
| // ODR: DW_TAG_member |
| // ODR-NEXT: DW_AT_name{{.*}}"C" |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_type{{.*}}[[UC]] |
| // ODR: DW_TAG_member |
| // ODR-NEXT: DW_AT_name{{.*}}"S" |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_type{{.*}}[[US]] |
| |
| // Check that the variables point to the right type |
| // ODR: DW_TAG_subprogram |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_name{{.*}}"foo" |
| // ODR-NOT: NULL |
| // ODR: DW_TAG_variable |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_name{{.*}}"s" |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_type{{.*}}[[ALIASFORS]] |
| // ODR: DW_AT_name{{.*}}"n" |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_type{{.*}}[[NESTED]] |
| // ODR: DW_TAG_variable |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_name{{.*}}"nc" |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_type{{.*}}[[NC]] |
| // ODR: DW_TAG_variable |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_name{{.*}}"ac" |
| // ODR-NOT: DW_TAG |
| // ODR: DW_AT_type{{.*}}[[ANONC]] |
| |
| // With no ODR uniquing, we should get copies of all the types: |
| |
| // This is "struct S" |
| // NOODR: 0x[[DUP_S:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type |
| // NOODR-NEXT: DW_AT_name{{.*}}"S" |
| // NOODR-NOT: NULL |
| // NOODR: 0x[[DUP_NESTED:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_name{{.*}}"Nested" |
| |
| // This is "class N::C" |
| // NOODR: DW_TAG_namespace |
| // NOODR-NEXT: DW_AT_name{{.*}}"N" |
| // NOODR: 0x[[DUP_NC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type |
| // NOODR-NEXT: DW_AT_name{{.*}}"C" |
| |
| // This is "union U" |
| // NOODR: 0x[[DUP_U:[0-9a-f]*]]:{{.*}}DW_TAG_union_type |
| // NOODR-NEXT: DW_AT_name{{.*}}"U" |
| // NOODR-NOT: NULL |
| // NOODR: 0x[[DUP_UC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type |
| // NOODR-NOT: NULL |
| // NOODR: 0x[[DUP_US:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type |
| // NOODR: NULL |
| |
| // Check that the variables point to the right type |
| // NOODR: DW_TAG_subprogram |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_name{{.*}}"foo" |
| // NOODR-NOT: NULL |
| // NOODR: DW_TAG_variable |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_name{{.*}}"s" |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_type{{.*}}0x[[DUP_ALIASFORS:[0-9a-f]*]] |
| // NOODR: DW_TAG_variable |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_name{{.*}}"n" |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_type{{.*}}[[DUP_NESTED]] |
| // NOODR: DW_TAG_variable |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_name{{.*}}"nc" |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_type{{.*}}[[DUP_NC]] |
| // NOODR: DW_TAG_variable |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_name{{.*}}"ac" |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_type{{.*}}0x[[DUP_ANONC:[0-9a-f]*]] |
| |
| // This is "AliasForS" |
| // NOODR: 0x[[DUP_ALIASFORS]]:{{.*}}DW_TAG_typedef |
| // NOODR-NOT: DW_TAG |
| // NOODR: DW_AT_name{{.*}}"AliasForS" |
| |
| // This is "(anonymous namespace)::AnonC" |
| // NOODR: DW_TAG_namespace |
| // NOODR-NOT: {{DW_AT_name|NULL|DW_TAG}} |
| // NOODR: 0x[[DUP_ANONC]]:{{.*}}DW_TAG_class_type |
| // NOODR-NEXT: DW_AT_name{{.*}}"AnonC" |
| |