// clang-format off // REQUIRES: lld, x86 // Test various interesting cases for AST reconstruction. // RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 \ // RUN: -Xclang -fkeep-static-consts -c /Fo%t.obj -- %s // RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb // RUN: %lldb -f %t.exe -s \ // RUN: %p/Inputs/nested-types.lldbinit 2>&1 | FileCheck %s struct S { struct NestedStruct { int A = 0; int B = 1; }; enum class NestedEnum { EnumValue1 = 0, EnumValue2 = 1, }; int C = 2; int D = 3; using VoidPtrT = void *; VoidPtrT DD = nullptr; }; struct T { using NestedTypedef = int; using NestedTypedef2 = S; struct NestedStruct { int E = 4; int F = 5; }; using NestedStructAlias = NestedStruct; using NST = S::NestedStruct; NestedTypedef NT = 4; using U = struct { int G = 6; int H = 7; }; }; template class U { public: // See llvm.org/pr39607. clang-cl currently doesn't emit an important debug // info record for nested template instantiations, so we can't reconstruct // a proper DeclContext hierarchy for these. As such, U::V will show up // in the global namespace. template struct V { Param I = 8; Param J = 9; using W = T::NestedTypedef; using X = U; }; struct W { Param M = 12; Param N = 13; }; Param K = 10; Param L = 11; using Y = V; using Z = V; }; constexpr S GlobalA; constexpr S::NestedStruct GlobalB; constexpr T GlobalC; constexpr T::NestedStruct GlobalD; constexpr T::U GlobalE; constexpr U GlobalF; constexpr U::V GlobalG; constexpr U::W GlobalH; constexpr S::NestedEnum GlobalEnum = S::NestedEnum::EnumValue1; int main(int argc, char **argv) { return 0; } // CHECK: (lldb) target variable -T GlobalA // CHECK: (const S) GlobalA = { // CHECK: (int) C = 2 // CHECK: (int) D = 3 // CHECK: (void *) DD = 0x00000000 // CHECK: } // CHECK: (lldb) target variable -T GlobalB // CHECK: (const S::NestedStruct) GlobalB = { // CHECK: (int) A = 0 // CHECK: (int) B = 1 // CHECK: } // CHECK: (lldb) target variable -T GlobalC // CHECK: (const T) GlobalC = { // CHECK: (int) NT = 4 // CHECK: } // CHECK: (lldb) target variable -T GlobalD // CHECK: (const T::NestedStruct) GlobalD = { // CHECK: (int) E = 4 // CHECK: (int) F = 5 // CHECK: } // CHECK: (lldb) target variable -T GlobalE // CHECK: (const T::U) GlobalE = { // CHECK: (int) G = 6 // CHECK: (int) H = 7 // CHECK: } // CHECK: (lldb) target variable -T GlobalF // CHECK: (const U) GlobalF = { // CHECK: (int) K = 10 // CHECK: (int) L = 11 // CHECK: } // CHECK: (lldb) target variable -T GlobalG // CHECK: (const U::V) GlobalG = { // CHECK: (int) I = 8 // CHECK: (int) J = 9 // CHECK: } // CHECK: (lldb) target variable -T GlobalEnum // CHECK: (const S::NestedEnum) GlobalEnum = EnumValue1 // CHECK: (lldb) target modules dump ast // CHECK: Dumping clang ast for 1 modules. // CHECK: TranslationUnitDecl {{.*}} // CHECK: |-CXXRecordDecl {{.*}} struct S definition // CHECK: | |-FieldDecl {{.*}} C 'int' // CHECK: | |-FieldDecl {{.*}} D 'int' // CHECK: | |-FieldDecl {{.*}} DD 'void *' // CHECK: | |-CXXRecordDecl {{.*}} struct NestedStruct definition // CHECK: | | |-FieldDecl {{.*}} A 'int' // CHECK: | | `-FieldDecl {{.*}} B 'int' // CHECK: | `-EnumDecl {{.*}} NestedEnum // CHECK: | |-EnumConstantDecl {{.*}} EnumValue1 'S::NestedEnum' // CHECK: | `-EnumConstantDecl {{.*}} EnumValue2 'S::NestedEnum' // CHECK: |-CXXRecordDecl {{.*}} struct T definition // CHECK: | |-FieldDecl {{.*}} NT 'int' // CHECK: | |-CXXRecordDecl {{.*}} struct NestedStruct definition // CHECK: | | |-FieldDecl {{.*}} E 'int' // CHECK: | | `-FieldDecl {{.*}} F 'int' // CHECK: | `-CXXRecordDecl {{.*}} struct U definition // CHECK: | |-FieldDecl {{.*}} G 'int' // CHECK: | `-FieldDecl {{.*}} H 'int' // CHECK: |-CXXRecordDecl {{.*}} class U definition // CHECK: | |-FieldDecl {{.*}} K 'int' // CHECK: | |-FieldDecl {{.*}} L 'int' // CHECK: | `-CXXRecordDecl {{.*}} struct W definition // CHECK: | |-FieldDecl {{.*}} M 'int' // CHECK: | `-FieldDecl {{.*}} N 'int' // CHECK: |-CXXRecordDecl {{.*}} struct U::V definition // CHECK: | |-FieldDecl {{.*}} I 'int' // CHECK: | `-FieldDecl {{.*}} J 'int'