1 // clang-format off 2 // REQUIRES: lld, x86 3 4 // Test that we can display function signatures with class types. 5 // RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t.obj -- %s 6 // RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb 7 // RUN: %lldb -f %t.exe -s \ 8 // RUN: %p/Inputs/function-types-classes.lldbinit | FileCheck %s 9 10 // This is just some unimportant helpers needed so that we can get reference and 11 // rvalue-reference types into return values. 12 template<typename T> 13 struct MakeResult { 14 static T result() { 15 return T{}; 16 } 17 }; 18 19 template<typename T> 20 struct MakeResult<T&> { 21 static T& result() { 22 static T t; 23 return t; 24 } 25 }; 26 27 template<typename T> 28 struct MakeResult<T&&> { 29 static T&& result() { 30 static T t; 31 return static_cast<T&&>(t); 32 } 33 }; 34 35 36 template<typename R> 37 R nullary() { return MakeResult<R>::result(); } 38 39 template<typename R, typename A, typename B> 40 R three(A a, B b) { return MakeResult<R>::result(); } 41 42 template<typename R, typename A, typename B, typename C> 43 R four(A a, B b, C c) { return MakeResult<R>::result(); } 44 45 struct S {}; 46 class C {}; 47 union U {}; 48 enum E {}; 49 50 namespace A { 51 namespace B { 52 // NS::NS 53 struct S { }; 54 } 55 56 struct C { 57 // NS::Struct 58 struct S {}; 59 }; 60 } 61 62 struct B { 63 struct A { 64 // Struct::Struct 65 struct S {}; 66 }; 67 }; 68 69 // clang (incorrectly) doesn't emit debug information for outer classes 70 // unless they are instantiated. They should also be emitted if there 71 // is an inner class which is instantiated. 72 A::C ForceInstantiateAC; 73 B ForceInstantiateB; 74 B::A ForceInstantiateBA; 75 76 template<typename T> 77 struct TC {}; 78 79 // const and volatile modifiers 80 auto a = &four<S, C*, U&, E&&>; 81 // CHECK: (S (*)(C *, U &, E &&)) a = {{.*}} 82 auto b = &four<E, const S*, const C&, const U&&>; 83 // CHECK: (E (*)(const S *, const C &, const U &&)) b = {{.*}} 84 auto c = &four<U, volatile E*, volatile S&, volatile C&&>; 85 // CHECK: (U (*)(volatile E *, volatile S &, volatile C &&)) c = {{.*}} 86 auto d = &four<C, const volatile U*, const volatile E&, const volatile S&&>; 87 // CHECK: (C (*)(const volatile U *, const volatile E &, const volatile S &&)) d = {{.*}} 88 89 // classes nested in namespaces and inner classes 90 91 auto e = &three<A::B::S*, B::A::S*, A::C::S&>; 92 // CHECK: (A::B::S *(*)(B::A::S *, A::C::S &)) e = {{.*}} 93 auto f = &three<A::C::S&, A::B::S*, B::A::S*>; 94 // CHECK: (A::C::S &(*)(A::B::S *, B::A::S *)) f = {{.*}} 95 auto g = &three<B::A::S*, A::C::S&, A::B::S*>; 96 // CHECK: (B::A::S *(*)(A::C::S &, A::B::S *)) g = {{.*}} 97 98 // parameter types that are themselves template instantiations. 99 auto h = &four<TC<void>, TC<int>, TC<TC<int>>, TC<A::B::S>>; 100 // CHECK: (TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)) h = {{.*}} 101 102 auto i = &nullary<A::B::S>; 103 // CHECK: (A::B::S (*)()) i = {{.*}} 104 105 106 // Make sure we can handle types that don't have complete debug info. 107 struct Incomplete; 108 auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>; 109 // CHECK: (Incomplete *(*)(Incomplete **, const Incomplete *)) incomplete = {{.*}} 110 111 // CHECK: TranslationUnitDecl {{.*}} 112 // CHECK: |-CXXRecordDecl {{.*}} class C 113 // CHECK: |-CXXRecordDecl {{.*}} union U 114 // CHECK: |-EnumDecl {{.*}} E 115 // CHECK: |-CXXRecordDecl {{.*}} struct S 116 // CHECK: |-VarDecl {{.*}} a 'S (*)(C *, U &, E &&)' 117 // CHECK: |-VarDecl {{.*}} b 'E (*)(const S *, const C &, const U &&)' 118 // CHECK: |-VarDecl {{.*}} c 'U (*)(volatile E *, volatile S &, volatile C &&)' 119 // CHECK: |-VarDecl {{.*}} d 'C (*)(const volatile U *, const volatile E &, const volatile S &&)' 120 // CHECK: |-CXXRecordDecl {{.*}} struct B 121 // CHECK: | `-CXXRecordDecl {{.*}} struct A 122 // CHECK: | `-CXXRecordDecl {{.*}} struct S 123 // CHECK: |-NamespaceDecl {{.*}} A 124 // CHECK: | |-CXXRecordDecl {{.*}} struct C 125 // CHECK: | | `-CXXRecordDecl {{.*}} struct S 126 // CHECK: | `-NamespaceDecl {{.*}} B 127 // CHECK: | `-CXXRecordDecl {{.*}} struct S 128 // CHECK: |-VarDecl {{.*}} e 'A::B::S *(*)(B::A::S *, A::C::S &)' 129 // CHECK: |-VarDecl {{.*}} f 'A::C::S &(*)(A::B::S *, B::A::S *)' 130 // CHECK: |-VarDecl {{.*}} g 'B::A::S *(*)(A::C::S &, A::B::S *)' 131 // CHECK: |-CXXRecordDecl {{.*}} struct TC<int> 132 // CHECK: |-CXXRecordDecl {{.*}} struct TC<TC<int>> 133 // CHECK: |-CXXRecordDecl {{.*}} struct TC<A::B::S> 134 // CHECK: |-CXXRecordDecl {{.*}} struct TC<void> 135 // CHECK: |-VarDecl {{.*}} h 'TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)' 136 // CHECK: |-VarDecl {{.*}} i 'A::B::S (*)()' 137 // CHECK: |-CXXRecordDecl {{.*}} struct Incomplete 138 // CHECK: `-VarDecl {{.*}} incomplete 'Incomplete *(*)(Incomplete **, const Incomplete *)' 139 140 int main(int argc, char **argv) { 141 return 0; 142 } 143