blob: 73a8f49967a76a95c87de058e71a7f980e648bc9 [file] [log] [blame]
// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown_unknown -debug-info-kind=limited -gsimple-template-names=mangled %s -o - -w -std=c++17 | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown_unknown -debug-info-kind=limited -gsimple-template-names=simple %s -o - -w -std=c++17 | FileCheck --check-prefix=SIMPLE --implicit-check-not=_STN %s
// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown_unknown -debug-info-kind=limited %s -o - -w -std=c++17 | FileCheck --check-prefix=FULL --implicit-check-not=_STN %s
template <typename... T>
void f1() {}
template <typename T, T V>
void f2() {}
template <typename... T>
struct t1 {};
extern int x;
int x;
struct t2 {
template <typename T = float>
operator t1<int>() { __builtin_unreachable(); }
};
template <template <typename...> class T>
void f3() {}
void f() {
// Basic examples of simplifiable/rebuildable names
f1<>();
// CHECK: !DISubprogram(name: "_STNf1|<>",
// SIMPLE: !DISubprogram(name: "f1",
// FULL: !DISubprogram(name: "f1<>",
f1<int>();
// CHECK: !DISubprogram(name: "_STNf1|<int>",
f1<void()>();
// CHECK: !DISubprogram(name: "_STNf1|<void ()>",
f2<int, 42>();
// CHECK: !DISubprogram(name: "_STNf2|<int, 42>",
// Check that even though the nested name can't be rebuilt, it'll carry its
// full name and the outer name can be rebuilt from that.
f1<t1<void() noexcept>>();
// CHECK: !DISubprogram(name: "_STNf1|<t1<void () noexcept> >",
// Vector array types are encoded in DWARF but the decoding in llvm-dwarfdump
// isn't implemented yet.
f1<__attribute__((__vector_size__((sizeof(int) * 2)))) int>();
// CHECK: !DISubprogram(name: "f1<__attribute__((__vector_size__(2 * sizeof(int)))) int>",
// noexcept is part of function types in C++17 onwards, but not encoded in
// DWARF
f1<void() noexcept>();
// CHECK: !DISubprogram(name: "f1<void () noexcept>",
// Unnamed entities (lambdas, structs/classes, enums) can't be fully rebuilt
// since we don't emit the column number. Also lambdas and unnamed classes are
// ambiguous with each other - there's no DWARF that designates a lambda as
// anything other than another unnamed class/struct.
auto A = [] {};
f1<decltype(A)>();
// CHECK: !DISubprogram(name: "f1<(lambda at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 2]]:12)>",
struct {
} unnamed_struct;
f1<decltype(unnamed_struct)>();
// CHECK: !DISubprogram(name: "f1<(unnamed struct at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 3]]:3)>",
f1<void (decltype(unnamed_struct))>();
// CHECK: !DISubprogram(name: "f1<void ((unnamed struct at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 5]]:3))>",
enum {} unnamed_enum;
f1<decltype(unnamed_enum)>();
// CHECK: !DISubprogram(name: "f1<(unnamed enum at {{.*}}debug-info-simple-template-names.cpp:[[# @LINE - 2]]:3)>",
// Declarations can't readily be reversed as the value in the DWARF only
// contains the address of the value - we'd have to do symbol lookup to find
// the name of that value (& rely on it not having been stripped out, etc).
f2<int *, &x>();
// CHECK: !DISubprogram(name: "f2<int *, &x>",
// We could probably handle \/ this case, but since it's a small subset of
// pointer typed non-type-template parameters which can't be handled it
// doesn't seem high priority.
f2<decltype(nullptr), nullptr>();
// CHECK: !DISubprogram(name: "f2<std::nullptr_t, nullptr>",
// These larger constants are encoded as data blocks which makes them a bit
// harder to re-render. I think they might be missing sign information, or at
// maybe it's just a question of doing APInt things to render such large
// values. Punting on this for now.
f2<__int128, ((__int128)9223372036854775807) * 2>();
// CHECK: !DISubprogram(name: "f2<__int128, (__int128)18446744073709551614>",
t2().operator t1<int>();
// FIXME: This should be something like "operator t1<int><float>"
// CHECK: !DISubprogram(name: "operator t1<float>",
// Function pointer non-type-template parameters currently don't get any DWARF
// value (GCC doesn't provide one either) and even if there was a value, if
// it's like variable/pointer non-type template parameters, it couldn't be
// rebuilt anyway (see the note above for details on that) so we don't have to
// worry about seeing conversion operators as parameters to other templates.
f3<t1>();
// CHECK: !DISubprogram(name: "_STNf3|<t1>",
}