+/* Compile with:
+ clang -g -c odr-uniquing.cpp -o odr-uniquing/1.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: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/odr-uniquing -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -debug-dump=info - | FileCheck -check-prefix=ODR -check-prefix=CHECK %s
+// RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/odr-uniquing -y %p/dummy-debug-map.map -no-odr -o - | llvm-dwarfdump -debug-dump=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"
+