xref: /llvm-project/clang/test/CodeGenCXX/debug-info-simple-template-names.cpp (revision 1cee3d9db77b2c62a03efe1cce45f627dcbe6457)
1 // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown_unknown -std=c++17 %s -o - -w -debug-info-kind=limited -gsimple-template-names=mangled \
2 // RUN:   | FileCheck %s
3 // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown_unknown -std=c++17 %s -o - -w -debug-info-kind=limited -gsimple-template-names=simple \
4 // RUN:   | FileCheck %s --implicit-check-not=_STN --check-prefix=SIMPLE
5 // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown_unknown -std=c++17 %s -o - -w -debug-info-kind=limited \
6 // RUN:   | FileCheck %s --implicit-check-not=_STN --check-prefix=FULL
7 // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown_unknown -std=c++17 %s -o - -w -debug-info-kind=line-tables-only -gsimple-template-names=mangled -fdebug-info-for-profiling \
8 // RUN:   | FileCheck %s --implicit-check-not=_STN --check-prefix=FULL
9 
10 template <typename... T>
f1()11 void f1() {}
12 template <typename T, T V>
f2()13 void f2() {}
14 template <typename... T>
15 struct t1 {};
16 extern int x;
17 int x;
18 struct t2 {
19   template <typename T = float>
operator t1<int>t220   operator t1<int>() { __builtin_unreachable(); }
21 };
22 template <template <typename...> class T>
f3()23 void f3() {}
24 namespace {
25 enum LocalEnum { LocalEnum1 };
26 }
27 template<typename T, T ... ts>
28 struct t3 { };
29 struct t4 {
30   t3<LocalEnum, LocalEnum1> m1;
31 };
32 
33 t4 v1;
34 enum { UnnamedEnum1 };
35 template<decltype(UnnamedEnum1)>
f4()36 void f4() {
37 }
38 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "t3<(anonymous namespace)::LocalEnum, ((anonymous namespace)::LocalEnum)0>"
f()39 void f() {
40   // Basic examples of simplifiable/rebuildable names
41   f1<>();
42   // CHECK: !DISubprogram(name: "_STN|f1|<>",
43   // SIMPLE: !DISubprogram(name: "f1",
44   // FULL: !DISubprogram(name: "f1<>",
45   f1<int>();
46   // CHECK: !DISubprogram(name: "_STN|f1|<int>",
47   f1<void()>();
48   // CHECK: !DISubprogram(name: "_STN|f1|<void ()>",
49   f2<int, 42>();
50   // CHECK: !DISubprogram(name: "_STN|f2|<int, 42>",
51 
52   // Check that even though the nested name can't be rebuilt, it'll carry its
53   // full name and the outer name can be rebuilt from that.
54   f1<t1<void() noexcept>>();
55   // CHECK: !DISubprogram(name: "_STN|f1|<t1<void () noexcept> >",
56 
57   // Vector array types are encoded in DWARF but the decoding in llvm-dwarfdump
58   // isn't implemented yet.
59   f1<__attribute__((__vector_size__((sizeof(int) * 2)))) int>();
60   // CHECK: !DISubprogram(name: "f1<__attribute__((__vector_size__(2 * sizeof(int)))) int>",
61 
62   // noexcept is part of function types in C++17 onwards, but not encoded in
63   // DWARF
64   f1<void() noexcept>();
65   // CHECK: !DISubprogram(name: "f1<void () noexcept>",
66 
67   // Unnamed entities (lambdas, structs/classes, enums) can't be fully rebuilt
68   // since we don't emit the column number. Also lambdas and unnamed classes are
69   // ambiguous with each other - there's no DWARF that designates a lambda as
70   // anything other than another unnamed class/struct.
71   auto Lambda = [] {};
72   f1<decltype(Lambda)>();
73   // CHECK: !DISubprogram(name: "f1<(lambda at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 2]]:17)>",
74   f1<t1<t1<decltype(Lambda)>>>();
75   // CHECK: !DISubprogram(name: "f1<t1<t1<(lambda at {{.*}}> > >",
76   struct {
77   } unnamed_struct;
78   f1<decltype(unnamed_struct)>();
79   // CHECK: !DISubprogram(name: "f1<(unnamed struct at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 3]]:3)>",
80   f1<void (decltype(unnamed_struct))>();
81   // CHECK: !DISubprogram(name: "f1<void ((unnamed struct at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 5]]:3))>",
82   enum {} unnamed_enum;
83   f1<decltype(unnamed_enum)>();
84   // CHECK: !DISubprogram(name: "f1<(unnamed enum at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 2]]:3)>",
85 
86   // Declarations can't readily be reversed as the value in the DWARF only
87   // contains the address of the value - we'd have to do symbol lookup to find
88   // the name of that value (& rely on it not having been stripped out, etc).
89   f2<int *, &x>();
90   // CHECK: !DISubprogram(name: "f2<int *, &x>",
91 
92   // We could probably handle \/ this case, but since it's a small subset of
93   // pointer typed non-type-template parameters which can't be handled it
94   // doesn't seem high priority.
95   f2<decltype(nullptr), nullptr>();
96   // CHECK: !DISubprogram(name: "f2<std::nullptr_t, nullptr>",
97 
98   // These larger constants are encoded as data blocks which makes them a bit
99   // harder to re-render. I think they might be missing sign information, or at
100   // maybe it's just a question of doing APInt things to render such large
101   // values. Punting on this for now.
102   f2<__int128, ((__int128)9223372036854775807) * 2>();
103   // CHECK: !DISubprogram(name: "f2<__int128, (__int128)18446744073709551614>",
104 
105   t2().operator t1<int>();
106   // FIXME: This should be something like "operator t1<int><float>"
107   // CHECK: !DISubprogram(name: "operator t1<float>",
108 
109   // Function pointer non-type-template parameters currently don't get any DWARF
110   // value (GCC doesn't provide one either) and even if there was a value, if
111   // it's like variable/pointer non-type template parameters, it couldn't be
112   // rebuilt anyway (see the note above for details on that) so we don't have to
113   // worry about seeing conversion operators as parameters to other templates.
114 
115   f3<t1>();
116   // CHECK: !DISubprogram(name: "_STN|f3|<t1>",
117 
118   f1<_BitInt(3)>();
119   // CHECK: !DISubprogram(name: "f1<_BitInt(3)>",
120 
121   f1<const unsigned _BitInt(5)>();
122   // CHECK: !DISubprogram(name: "f1<const unsigned _BitInt(5)>",
123 
124   // Add a parameter just so this differs from other attributed function types
125   // that don't mangle differently.
126   int fnrt() __attribute__((noreturn));
127   f1<decltype(fnrt)>();
128   // CHECK: !DISubprogram(name: "f1<int () __attribute__((noreturn))>",
129 
130   f4<UnnamedEnum1>();
131   // CHECK: !DISubprogram(name: "f4<((unnamed enum at {{.*}}))0>"
132 }
133