Skip to content

Commit e772a26

Browse files
authored
[Clang] Emit DW_TAG_template_alias for template aliases (#87623)
Fix issue #54624 Add front end flags -gtemplate-alias (also a cc1 flag) and -gno-template-alias to enable/disable usage of the feature. It's enabled by default in the front end for SCE debugger tuning only. GCC emits DW_TAG_typedef for template aliases (as does Clang with this feature disabled), and GDB and LLDB appear not to support DW_TAG_template_alias. The -Xclang option -gsimple-template-names=mangled is treated the same as =full, which is not a regression from current behaviour for template aliases. The current implementation omits defaulted arguments and as a consequence also omits empty parameter packs that come after defaulted arguments. Again, this isn't a regression as the DW_TAG_typedef name doesn't contain defaulted arguments. LLVM support added in #88943 Added template-alias.cpp - Check the metadata construction & interaction with -gsimple-template-names. Added variadic-template-alias.cpp - Check template parameter packs work. Added defaulted-template-alias.cpp - Check defaulted args (don't) work. Modified debug-options.c - Check Clang generates correct cc1 flags.
1 parent 76600ae commit e772a26

File tree

11 files changed

+260
-47
lines changed

11 files changed

+260
-47
lines changed

clang/include/clang/Basic/DebugOptions.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ DEBUGOPT(CodeViewCommandLine, 1, 0)
129129
/// Whether emit extra debug info for sample pgo profile collection.
130130
DEBUGOPT(DebugInfoForProfiling, 1, 0)
131131

132+
/// Whether to emit DW_TAG_template_alias for template aliases.
133+
DEBUGOPT(DebugTemplateAlias, 1, 0)
134+
132135
/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames.
133136
DEBUGOPT(DebugNameTable, 2, 0)
134137

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4309,6 +4309,8 @@ def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
43094309
Values<"split,single">;
43104310
def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group<g_flags_Group>,
43114311
Visibility<[ClangOption, CLOption, DXCOption]>;
4312+
def gtemplate_alias : Flag<["-"], "gtemplate-alias">, Group<g_flags_Group>, Visibility<[ClangOption, CC1Option]>;
4313+
def gno_template_alias : Flag<["-"], "gno-template-alias">, Group<g_flags_Group>, Visibility<[ClangOption]>;
43124314
def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group<g_flags_Group>;
43134315
def gsimple_template_names_EQ
43144316
: Joined<["-"], "gsimple-template-names=">,

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 112 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,44 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
13131313
return DBuilder.createPointerType(EltTy, Size);
13141314
}
13151315

1316+
static llvm::SmallVector<TemplateArgument>
1317+
GetTemplateArgs(const TemplateDecl *TD, const TemplateSpecializationType *Ty) {
1318+
assert(Ty->isTypeAlias());
1319+
// TemplateSpecializationType doesn't know if its template args are
1320+
// being substituted into a parameter pack. We can find out if that's
1321+
// the case now by inspecting the TypeAliasTemplateDecl template
1322+
// parameters. Insert Ty's template args into SpecArgs, bundling args
1323+
// passed to a parameter pack into a TemplateArgument::Pack. It also
1324+
// doesn't know the value of any defaulted args, so collect those now
1325+
// too.
1326+
SmallVector<TemplateArgument> SpecArgs;
1327+
ArrayRef SubstArgs = Ty->template_arguments();
1328+
for (const NamedDecl *Param : TD->getTemplateParameters()->asArray()) {
1329+
// If Param is a parameter pack, pack the remaining arguments.
1330+
if (Param->isParameterPack()) {
1331+
SpecArgs.push_back(TemplateArgument(SubstArgs));
1332+
break;
1333+
}
1334+
1335+
// Skip defaulted args.
1336+
// FIXME: Ideally, we wouldn't do this. We can read the default values
1337+
// for each parameter. However, defaulted arguments which are dependent
1338+
// values or dependent types can't (easily?) be resolved here.
1339+
if (SubstArgs.empty()) {
1340+
// If SubstArgs is now empty (we're taking from it each iteration) and
1341+
// this template parameter isn't a pack, then that should mean we're
1342+
// using default values for the remaining template parameters (after
1343+
// which there may be an empty pack too which we will ignore).
1344+
break;
1345+
}
1346+
1347+
// Take the next argument.
1348+
SpecArgs.push_back(SubstArgs.front());
1349+
SubstArgs = SubstArgs.drop_front();
1350+
}
1351+
return SpecArgs;
1352+
}
1353+
13161354
llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
13171355
llvm::DIFile *Unit) {
13181356
assert(Ty->isTypeAlias());
@@ -1332,6 +1370,31 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
13321370
auto PP = getPrintingPolicy();
13331371
Ty->getTemplateName().print(OS, PP, TemplateName::Qualified::None);
13341372

1373+
SourceLocation Loc = AliasDecl->getLocation();
1374+
1375+
if (CGM.getCodeGenOpts().DebugTemplateAlias) {
1376+
auto ArgVector = ::GetTemplateArgs(TD, Ty);
1377+
TemplateArgs Args = {TD->getTemplateParameters(), ArgVector};
1378+
1379+
// FIXME: Respect DebugTemplateNameKind::Mangled, e.g. by using GetName.
1380+
// Note we can't use GetName without additional work: TypeAliasTemplateDecl
1381+
// doesn't have instantiation information, so
1382+
// TypeAliasTemplateDecl::getNameForDiagnostic wouldn't have access to the
1383+
// template args.
1384+
std::string Name;
1385+
llvm::raw_string_ostream OS(Name);
1386+
TD->getNameForDiagnostic(OS, PP, /*Qualified=*/false);
1387+
if (CGM.getCodeGenOpts().getDebugSimpleTemplateNames() !=
1388+
llvm::codegenoptions::DebugTemplateNamesKind::Simple ||
1389+
!HasReconstitutableArgs(Args.Args))
1390+
printTemplateArgumentList(OS, Args.Args, PP);
1391+
1392+
llvm::DIDerivedType *AliasTy = DBuilder.createTemplateAlias(
1393+
Src, Name, getOrCreateFile(Loc), getLineNumber(Loc),
1394+
getDeclContextDescriptor(AliasDecl), CollectTemplateParams(Args, Unit));
1395+
return AliasTy;
1396+
}
1397+
13351398
// Disable PrintCanonicalTypes here because we want
13361399
// the DW_AT_name to benefit from the TypePrinter's ability
13371400
// to skip defaulted template arguments.
@@ -1343,8 +1406,6 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
13431406
PP.PrintCanonicalTypes = false;
13441407
printTemplateArgumentList(OS, Ty->template_arguments(), PP,
13451408
TD->getTemplateParameters());
1346-
1347-
SourceLocation Loc = AliasDecl->getLocation();
13481409
return DBuilder.createTypedef(Src, OS.str(), getOrCreateFile(Loc),
13491410
getLineNumber(Loc),
13501411
getDeclContextDescriptor(AliasDecl));
@@ -5363,6 +5424,54 @@ static bool IsReconstitutableType(QualType QT) {
53635424
return T.Reconstitutable;
53645425
}
53655426

5427+
bool CGDebugInfo::HasReconstitutableArgs(
5428+
ArrayRef<TemplateArgument> Args) const {
5429+
return llvm::all_of(Args, [&](const TemplateArgument &TA) {
5430+
switch (TA.getKind()) {
5431+
case TemplateArgument::Template:
5432+
// Easy to reconstitute - the value of the parameter in the debug
5433+
// info is the string name of the template. The template name
5434+
// itself won't benefit from any name rebuilding, but that's a
5435+
// representational limitation - maybe DWARF could be
5436+
// changed/improved to use some more structural representation.
5437+
return true;
5438+
case TemplateArgument::Declaration:
5439+
// Reference and pointer non-type template parameters point to
5440+
// variables, functions, etc and their value is, at best (for
5441+
// variables) represented as an address - not a reference to the
5442+
// DWARF describing the variable/function/etc. This makes it hard,
5443+
// possibly impossible to rebuild the original name - looking up
5444+
// the address in the executable file's symbol table would be
5445+
// needed.
5446+
return false;
5447+
case TemplateArgument::NullPtr:
5448+
// These could be rebuilt, but figured they're close enough to the
5449+
// declaration case, and not worth rebuilding.
5450+
return false;
5451+
case TemplateArgument::Pack:
5452+
// A pack is invalid if any of the elements of the pack are
5453+
// invalid.
5454+
return HasReconstitutableArgs(TA.getPackAsArray());
5455+
case TemplateArgument::Integral:
5456+
// Larger integers get encoded as DWARF blocks which are a bit
5457+
// harder to parse back into a large integer, etc - so punting on
5458+
// this for now. Re-parsing the integers back into APInt is
5459+
// probably feasible some day.
5460+
return TA.getAsIntegral().getBitWidth() <= 64 &&
5461+
IsReconstitutableType(TA.getIntegralType());
5462+
case TemplateArgument::StructuralValue:
5463+
return false;
5464+
case TemplateArgument::Type:
5465+
return IsReconstitutableType(TA.getAsType());
5466+
case TemplateArgument::Expression:
5467+
return IsReconstitutableType(TA.getAsExpr()->getType());
5468+
default:
5469+
llvm_unreachable("Other, unresolved, template arguments should "
5470+
"not be seen here");
5471+
}
5472+
});
5473+
}
5474+
53665475
std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const {
53675476
std::string Name;
53685477
llvm::raw_string_ostream OS(Name);
@@ -5389,49 +5498,7 @@ std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const {
53895498
} else if (auto *VD = dyn_cast<VarDecl>(ND)) {
53905499
Args = GetTemplateArgs(VD);
53915500
}
5392-
std::function<bool(ArrayRef<TemplateArgument>)> HasReconstitutableArgs =
5393-
[&](ArrayRef<TemplateArgument> Args) {
5394-
return llvm::all_of(Args, [&](const TemplateArgument &TA) {
5395-
switch (TA.getKind()) {
5396-
case TemplateArgument::Template:
5397-
// Easy to reconstitute - the value of the parameter in the debug
5398-
// info is the string name of the template. (so the template name
5399-
// itself won't benefit from any name rebuilding, but that's a
5400-
// representational limitation - maybe DWARF could be
5401-
// changed/improved to use some more structural representation)
5402-
return true;
5403-
case TemplateArgument::Declaration:
5404-
// Reference and pointer non-type template parameters point to
5405-
// variables, functions, etc and their value is, at best (for
5406-
// variables) represented as an address - not a reference to the
5407-
// DWARF describing the variable/function/etc. This makes it hard,
5408-
// possibly impossible to rebuild the original name - looking up the
5409-
// address in the executable file's symbol table would be needed.
5410-
return false;
5411-
case TemplateArgument::NullPtr:
5412-
// These could be rebuilt, but figured they're close enough to the
5413-
// declaration case, and not worth rebuilding.
5414-
return false;
5415-
case TemplateArgument::Pack:
5416-
// A pack is invalid if any of the elements of the pack are invalid.
5417-
return HasReconstitutableArgs(TA.getPackAsArray());
5418-
case TemplateArgument::Integral:
5419-
// Larger integers get encoded as DWARF blocks which are a bit
5420-
// harder to parse back into a large integer, etc - so punting on
5421-
// this for now. Re-parsing the integers back into APInt is probably
5422-
// feasible some day.
5423-
return TA.getAsIntegral().getBitWidth() <= 64 &&
5424-
IsReconstitutableType(TA.getIntegralType());
5425-
case TemplateArgument::StructuralValue:
5426-
return false;
5427-
case TemplateArgument::Type:
5428-
return IsReconstitutableType(TA.getAsType());
5429-
default:
5430-
llvm_unreachable("Other, unresolved, template arguments should "
5431-
"not be seen here");
5432-
}
5433-
});
5434-
};
5501+
54355502
// A conversion operator presents complications/ambiguity if there's a
54365503
// conversion to class template that is itself a template, eg:
54375504
// template<typename T>

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,8 @@ class CGDebugInfo {
626626
llvm::DIType *WrappedType;
627627
};
628628

629-
std::string GetName(const Decl*, bool Qualified = false) const;
629+
bool HasReconstitutableArgs(ArrayRef<TemplateArgument> Args) const;
630+
std::string GetName(const Decl *, bool Qualified = false) const;
630631

631632
/// Build up structure info for the byref. See \a BuildByRefType.
632633
BlockByRefType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4632,6 +4632,21 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
46324632
}
46334633
}
46344634

4635+
// Emit DW_TAG_template_alias for template aliases? True by default for SCE.
4636+
bool UseDebugTemplateAlias =
4637+
DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 5;
4638+
if (const auto *DebugTemplateAlias = Args.getLastArg(
4639+
options::OPT_gtemplate_alias, options::OPT_gno_template_alias)) {
4640+
// DW_TAG_template_alias is only supported from DWARFv5 but if a user
4641+
// asks for it we should let them have it (if the target supports it).
4642+
if (checkDebugInfoOption(DebugTemplateAlias, Args, D, TC)) {
4643+
const auto &Opt = DebugTemplateAlias->getOption();
4644+
UseDebugTemplateAlias = Opt.matches(options::OPT_gtemplate_alias);
4645+
}
4646+
}
4647+
if (UseDebugTemplateAlias)
4648+
CmdArgs.push_back("-gtemplate-alias");
4649+
46354650
if (const Arg *A = Args.getLastArg(options::OPT_gsrc_hash_EQ)) {
46364651
StringRef v = A->getValue();
46374652
CmdArgs.push_back(Args.MakeArgString("-gsrc-hash=" + v));

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,9 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
15561556
llvm::DICompileUnit::DebugNameTableKind::Default))
15571557
GenerateArg(Consumer, OPT_gpubnames);
15581558

1559+
if (Opts.DebugTemplateAlias)
1560+
GenerateArg(Consumer, OPT_gtemplate_alias);
1561+
15591562
auto TNK = Opts.getDebugSimpleTemplateNames();
15601563
if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {
15611564
if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)
@@ -1827,6 +1830,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
18271830
Opts.BinutilsVersion =
18281831
std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));
18291832

1833+
Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias);
1834+
18301835
Opts.DebugNameTable = static_cast<unsigned>(
18311836
Args.hasArg(OPT_ggnu_pubnames)
18321837
? llvm::DICompileUnit::DebugNameTableKind::GNU

clang/test/CodeGenCXX/debug-info-alias.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang -g -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
1+
// RUN: %clang -g -gno-template-alias -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
22

33
template<typename T>
44
struct foo {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=simple \
2+
// RUN: | FileCheck %s
3+
4+
//// Check that -gtemplate-alias causes DW_TAG_template_alias emission for
5+
//// template aliases with default parameter values. See template-alias.cpp for
6+
//// more template alias tests.
7+
//// FIXME: We currently do not emit defaulted arguments.
8+
9+
template<typename T>
10+
struct X {
11+
char m;
12+
};
13+
14+
template<typename T>
15+
struct Y {
16+
char n;
17+
};
18+
19+
template <typename NonDefault, template <typename C> class T = Y, int I = 5, typename... Ts>
20+
using A = X<NonDefault>;
21+
22+
//// We should be able to emit type alias metadata which describes all the
23+
//// values, including the defaulted parameters and empty parameter pack.
24+
A<int> a;
25+
26+
// CHECK: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]])
27+
// CHECK: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X",
28+
// CHECK: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
29+
// CHECK: ![[extraData]] = !{![[NonDefault:[0-9]+]]}
30+
// CHECK: ![[NonDefault]] = !DITemplateTypeParameter(name: "NonDefault", type: ![[int]])
31+
32+
//// FIXME: Ideally, we would describe the deafulted args, like this:
33+
// : ![[extraData]] = !{![[NonDefault:[0-9]+]], ![[T:[0-9]+]], ![[I:[0-9]+]], ![[Ts:[0-9]+]]}
34+
// : ![[NonDefault]] = !DITemplateTypeParameter(name: "NonDefault", type: ![[int]])
35+
// : ![[T]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "T", defaulted: true, value: !"Y")
36+
// : ![[I]] = !DITemplateValueParameter(name: "I", type: ![[int]], defaulted: true, value: i32 5)
37+
// : ![[Ts]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Ts", value: ![[types:[0-9]+]])
38+
// : ![[types]] = !{}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=simple \
2+
// RUN: | FileCheck %s --check-prefixes=ALIAS-SIMPLE,ALIAS-ALL
3+
4+
// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=mangled \
5+
// RUN: | FileCheck %s --check-prefixes=ALIAS-MANGLED,ALIAS-ALL
6+
7+
// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s \
8+
// RUN: | FileCheck %s --check-prefixes=ALIAS-FULL,ALIAS-ALL
9+
10+
// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone %s \
11+
// RUN: | FileCheck %s --check-prefixes=TYPEDEF
12+
13+
14+
//// Check that -gtemplate-alias causes DW_TAG_template_alias emission for
15+
//// template aliases, and that respects gsimple-template-names.
16+
////
17+
//// Test type and value template parameters.
18+
19+
template<typename Y, int Z>
20+
struct X {
21+
Y m1 = Z;
22+
};
23+
24+
template<typename B, int C>
25+
using A = X<B, C>;
26+
27+
A<int, 5> a;
28+
29+
30+
// ALIAS-SIMPLE: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]])
31+
// ALIAS-SIMPLE: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X",
32+
33+
// FIXME: Mangled name is wrong (not a regression).
34+
// ALIAS-MANGLED: !DIDerivedType(tag: DW_TAG_template_alias, name: "A<int, 5>", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]])
35+
// ALIAS-MANGLED: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "_STN|X|<int, 5>",
36+
37+
// ALIAS-FULL: !DIDerivedType(tag: DW_TAG_template_alias, name: "A<int, 5>", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]])
38+
// ALIAS-FULL: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X<int, 5>",
39+
40+
// ALIAS-ALL: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
41+
// ALIAS-ALL: ![[extraData]] = !{![[B:[0-9]+]], ![[C:[0-9]+]]}
42+
// ALIAS-ALL: ![[B]] = !DITemplateTypeParameter(name: "B", type: ![[int]])
43+
// ALIAS-ALL: ![[C]] = !DITemplateValueParameter(name: "C", type: ![[int]], value: i32 5)
44+
45+
// TYPEDEF: !DIDerivedType(tag: DW_TAG_typedef, name: "A<int, 5>", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]])
46+
// TYPEDEF: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X<int, 5>",
47+
// TYPEDEF: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -triple x86_64-unk-unk -o - -emit-llvm -debug-info-kind=standalone -gtemplate-alias %s -gsimple-template-names=simple \
2+
// RUN: | FileCheck %s
3+
4+
//// Check that -gtemplate-alias causes DW_TAG_template_alias emission for
5+
//// variadic template aliases. See template-alias.cpp for more template alias
6+
//// tests.
7+
8+
template<typename Y, int Z>
9+
struct X {
10+
Y m1 = Z;
11+
};
12+
13+
template<int I, typename... Ts>
14+
using A = X<Ts..., I>;
15+
16+
A<5, int> a;
17+
18+
// CHECK: !DIDerivedType(tag: DW_TAG_template_alias, name: "A", file: ![[#]], line: [[#]], baseType: ![[baseType:[0-9]+]], extraData: ![[extraData:[0-9]+]])
19+
// CHECK: ![[baseType]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X",
20+
// CHECK: ![[int:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
21+
// CHECK: ![[extraData]] = !{![[I:[0-9]+]], ![[Ts:[0-9]+]]}
22+
// CHECK: ![[I]] = !DITemplateValueParameter(name: "I", type: ![[int]], value: i32 5)
23+
// CHECK: ![[Ts]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "Ts", value: ![[types:[0-9]+]])
24+
// CHECK: ![[types]] = !{![[int_template_param:[0-9]+]]}
25+
// CHECK: ![[int_template_param]] = !DITemplateTypeParameter(type: ![[int]])

clang/test/Driver/debug-options.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,3 +465,13 @@
465465
// MANGLED_TEMP_NAMES: error: unknown argument '-gsimple-template-names=mangled'; did you mean '-Xclang -gsimple-template-names=mangled'
466466
// RUN: %clang -### -target x86_64 -c -g %s 2>&1 | FileCheck --check-prefix=FULL_TEMP_NAMES --implicit-check-not=debug-forward-template-params %s
467467
// FULL_TEMP_NAMES-NOT: -gsimple-template-names
468+
469+
//// Test -g[no-]template-alias (enabled by default with SCE debugger tuning and DWARFv5).
470+
// RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS
471+
// RUN: %clang -### -target x86_64 -c -gdwarf-4 -gsce %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS
472+
// RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce -gtemplate-alias %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS
473+
// RUN: %clang -### -target x86_64 -c -gdwarf-5 -gsce -gno-template-alias %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS
474+
// RUN: %clang -### -target x86_64 -c -gdwarf-5 -gtemplate-alias %s 2>&1 | FileCheck %s --check-prefixes=TEMPLATE-ALIAS
475+
// RUN: %clang -### -target x86_64 -c -gdwarf-5 -gtemplate-alias -gno-template-alias %s 2>&1 | FileCheck %s --check-prefixes=NO-TEMPLATE-ALIAS
476+
// TEMPLATE-ALIAS: "-gtemplate-alias"
477+
// NO-TEMPLATE-ALIAS-NOT: "-gtemplate-alias"

0 commit comments

Comments
 (0)