/* Compile with: for FILE in `seq 3`; do clang -g -c X86/odr-fwd-declaration2.cpp -DFILE$FILE -o Inputs/odr-fwd-declaration2/$FILE.o done */ // RUN: dsymutil -f -oso-prepend-path=%p/../Inputs/odr-fwd-declaration2 -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -v -debug-info - | FileCheck %s #ifdef FILE1 # 1 "Header.h" 1 struct A { struct B; B *bPtr; B &bRef; int B::*bPtrToField; }; # 3 "Source1.cpp" 2 void foo() { A *ptr1 = 0; } // First we confirm that bPtr, bRef and bPtrToField reference the forward // declaration of the struct B. // // CHECK: DW_TAG_member // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "bPtr" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[PTR1:[a-f0-9]*]] // // CHECK: [[STRUCT1:[a-f0-9]*]]:{{.*}}TAG_structure_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "B" // CHECK-NOT: AT_byte_size // CHECK: DW_AT_declaration // // CHECK: DW_TAG_member // CHECK: AT_name{{.*}} "bRef" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[REF1:[a-f0-9]*]] // // CHECK: TAG_member // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "bPtrToField" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[PTRTOMEMBER1:[a-f0-9]*]] // // CHECK: [[PTR1]]:{{.*}}TAG_pointer_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT1]] // // CHECK: [[REF1]]:{{.*}}TAG_reference_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT1]] // // CHECK: [[PTRTOMEMBER1]]:{{.*}}TAG_ptr_to_member_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_containing_type{{.*}}0x{{0*}}[[STRUCT1]] #elif defined(FILE2) # 1 "Header.h" 1 struct A { struct B; B *bPtr; B &bRef; int B::*bPtrToField; }; # 3 "Source2.cpp" 2 struct A::B { int x; }; void bar() { A *ptr2 = 0; } // Next we confirm that bPtr, bRef and bPtrToField reference the definition of // B, rather than its declaration. // // CHECK: [[STRUCTA:[a-f0-9]*]]:{{.*}}TAG_structure_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "A" // CHECK-NOT: AT_byte_size // CHECK: DW_AT_byte_size // // CHECK: DW_TAG_member // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "bPtr" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[PTR2:[a-f0-9]*]] // // CHECK: [[STRUCT2:[a-f0-9]*]]:{{.*}}TAG_structure_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "B" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: DW_AT_byte_size // // CHECK: DW_TAG_member // CHECK: AT_name{{.*}} "bRef" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[REF2:[a-f0-9]*]] // // CHECK: TAG_member // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "bPtrToField" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[PTRTOMEMBER2:[a-f0-9]*]] // // CHECK: [[PTR2]]:{{.*}}TAG_pointer_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT2]] // // CHECK: [[REF2]]:{{.*}}TAG_reference_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT2]] // // CHECK: [[PTRTOMEMBER2]]:{{.*}}TAG_ptr_to_member_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_containing_type{{.*}}0x{{0*}}[[STRUCT2:[a-f0-9]*]] #elif defined(FILE3) # 1 "Header.h" 1 struct A { struct B; B *bPtr; B &bRef; int B::*bPtrToField; }; # 3 "Source2.cpp" 2 struct A::B { int x; }; void bar() { A *ptr2 = 0; } // Finally we confirm that uniquing isn't broken by checking that further // references to 'struct A' point to its now complete definition. // // CHECK: TAG_variable // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_name{{.*}} "ptr2" // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[PTR3:[a-f0-9]*]] // // CHECK: [[PTR3]]:{{.*}}TAG_pointer_type // CHECK-NOT: {{DW_TAG|NULL}} // CHECK: AT_type{{.*}}0x{{0*}}[[STRUCTA]] #else #error "You must define which file you generate" #endif