| // clang-format off |
| // REQUIRES: lld |
| |
| // Test that we can display function signatures with class types. |
| // RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s |
| // RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \ |
| // RUN: %p/Inputs/function-types-classes.lldbinit | FileCheck %s |
| |
| // This is just some unimportant helpers needed so that we can get reference and |
| // rvalue-reference types into return values. |
| template<typename T> |
| struct MakeResult { |
| static T result() { |
| return T{}; |
| } |
| }; |
| |
| template<typename T> |
| struct MakeResult<T&> { |
| static T& result() { |
| static T t; |
| return t; |
| } |
| }; |
| |
| template<typename T> |
| struct MakeResult<T&&> { |
| static T&& result() { |
| static T t; |
| return static_cast<T&&>(t); |
| } |
| }; |
| |
| |
| template<typename R> |
| R nullary() { return MakeResult<R>::result(); } |
| |
| template<typename R, typename A, typename B> |
| R three(A a, B b) { return MakeResult<R>::result(); } |
| |
| template<typename R, typename A, typename B, typename C> |
| R four(A a, B b, C c) { return MakeResult<R>::result(); } |
| |
| struct S {}; |
| class C {}; |
| union U {}; |
| enum E {}; |
| |
| namespace A { |
| namespace B { |
| // NS::NS |
| struct S { }; |
| } |
| |
| struct C { |
| // NS::Struct |
| struct S {}; |
| }; |
| } |
| |
| struct B { |
| struct A { |
| // Struct::Struct |
| struct S {}; |
| }; |
| }; |
| |
| // clang (incorrectly) doesn't emit debug information for outer classes |
| // unless they are instantiated. They should also be emitted if there |
| // is an inner class which is instantiated. |
| A::C ForceInstantiateAC; |
| B ForceInstantiateB; |
| B::A ForceInstantiateBA; |
| |
| template<typename T> |
| struct TC {}; |
| |
| // const and volatile modifiers |
| auto a = &four<S, C*, U&, E&&>; |
| // CHECK: (S (*)(C *, U &, E &&)) a = {{.*}} |
| auto b = &four<E, const S*, const C&, const U&&>; |
| // CHECK: (E (*)(const S *, const C &, const U &&)) b = {{.*}} |
| auto c = &four<U, volatile E*, volatile S&, volatile C&&>; |
| // CHECK: (U (*)(volatile E *, volatile S &, volatile C &&)) c = {{.*}} |
| auto d = &four<C, const volatile U*, const volatile E&, const volatile S&&>; |
| // CHECK: (C (*)(const volatile U *, const volatile E &, const volatile S &&)) d = {{.*}} |
| |
| // classes nested in namespaces and inner classes |
| |
| auto e = &three<A::B::S*, B::A::S*, A::C::S&>; |
| // CHECK: (A::B::S *(*)(B::A::S *, A::C::S &)) e = {{.*}} |
| auto f = &three<A::C::S&, A::B::S*, B::A::S*>; |
| // CHECK: (A::C::S &(*)(A::B::S *, B::A::S *)) f = {{.*}} |
| auto g = &three<B::A::S*, A::C::S&, A::B::S*>; |
| // CHECK: (B::A::S *(*)(A::C::S &, A::B::S *)) g = {{.*}} |
| |
| // parameter types that are themselves template instantiations. |
| auto h = &four<TC<void>, TC<int>, TC<TC<int>>, TC<A::B::S>>; |
| // CHECK: (TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)) h = {{.*}} |
| |
| auto i = &nullary<A::B::S>; |
| // CHECK: (A::B::S (*)()) i = {{.*}} |
| |
| |
| // Make sure we can handle types that don't have complete debug info. |
| struct Incomplete; |
| auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>; |
| // CHECK: (Incomplete *(*)(Incomplete **, const Incomplete *)) incomplete = {{.*}} |
| |
| // CHECK: TranslationUnitDecl {{.*}} |
| // CHECK: |-CXXRecordDecl {{.*}} class C |
| // CHECK: |-CXXRecordDecl {{.*}} union U |
| // CHECK: |-EnumDecl {{.*}} E |
| // CHECK: |-CXXRecordDecl {{.*}} struct S |
| // CHECK: |-VarDecl {{.*}} a 'S (*)(C *, U &, E &&)'
|
| // CHECK: |-VarDecl {{.*}} b 'E (*)(const S *, const C &, const U &&)'
|
| // CHECK: |-VarDecl {{.*}} c 'U (*)(volatile E *, volatile S &, volatile C &&)'
|
| // CHECK: |-VarDecl {{.*}} d 'C (*)(const volatile U *, const volatile E &, const volatile S &&)' |
| // CHECK: |-CXXRecordDecl {{.*}} struct B |
| // CHECK: | `-CXXRecordDecl {{.*}} struct A |
| // CHECK: | `-CXXRecordDecl {{.*}} struct S |
| // CHECK: |-NamespaceDecl {{.*}} A |
| // CHECK: | |-CXXRecordDecl {{.*}} struct C |
| // CHECK: | | `-CXXRecordDecl {{.*}} struct S |
| // CHECK: | `-NamespaceDecl {{.*}} B |
| // CHECK: | `-CXXRecordDecl {{.*}} struct S |
| // CHECK: |-VarDecl {{.*}} e 'A::B::S *(*)(B::A::S *, A::C::S &)'
|
| // CHECK: |-VarDecl {{.*}} f 'A::C::S &(*)(A::B::S *, B::A::S *)'
|
| // CHECK: |-VarDecl {{.*}} g 'B::A::S *(*)(A::C::S &, A::B::S *)' |
| // CHECK: |-CXXRecordDecl {{.*}} struct TC<int> |
| // CHECK: |-CXXRecordDecl {{.*}} struct TC<TC<int>> |
| // CHECK: |-CXXRecordDecl {{.*}} struct TC<A::B::S> |
| // CHECK: |-CXXRecordDecl {{.*}} struct TC<void> |
| // CHECK: |-VarDecl {{.*}} h 'TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)'
|
| // CHECK: |-VarDecl {{.*}} i 'A::B::S (*)()' |
| // CHECK: |-CXXRecordDecl {{.*}} struct Incomplete |
| // CHECK: `-VarDecl {{.*}} incomplete 'Incomplete *(*)(Incomplete **, const Incomplete *)' |
| |
| int main(int argc, char **argv) { |
| return 0; |
| } |