Skip to content

Commit 5dd7c16

Browse files
committed
[lldb] Don't create Clang AST nodes in GetDIEClassTemplateParams
Otherwise we may be inserting a decl into a DeclContext that's not fully defined yet. This simplifies/removes some clang AST node creation code. Instead, use clang::printTemplateArgumentList(). Reviewed By: Michael137 Differential Revision: https://reviews.llvm.org/D142413
1 parent 0f07ff8 commit 5dd7c16

File tree

7 files changed

+65
-32
lines changed

7 files changed

+65
-32
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -745,28 +745,9 @@ DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) {
745745
if (llvm::StringRef(die.GetName()).contains("<"))
746746
return ConstString();
747747

748-
clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr);
749748
TypeSystemClang::TemplateParameterInfos template_param_infos;
750749
if (ParseTemplateParameterInfos(die, template_param_infos)) {
751-
// Most of the parameters here don't matter, but we make sure the base name
752-
// is empty so when we print the name we only get the template parameters.
753-
clang::ClassTemplateDecl *class_template_decl =
754-
m_ast.ParseClassTemplateDecl(decl_ctx, GetOwningClangModule(die),
755-
eAccessPublic, "", clang::TTK_Struct,
756-
template_param_infos);
757-
if (!class_template_decl)
758-
return ConstString();
759-
760-
clang::ClassTemplateSpecializationDecl *class_specialization_decl =
761-
m_ast.CreateClassTemplateSpecializationDecl(
762-
decl_ctx, GetOwningClangModule(die), class_template_decl,
763-
clang::TTK_Struct, template_param_infos);
764-
if (!class_specialization_decl)
765-
return ConstString();
766-
CompilerType clang_type =
767-
m_ast.CreateClassTemplateSpecializationType(class_specialization_decl);
768-
ConstString name = clang_type.GetTypeName(/*BaseOnly*/ true);
769-
return name;
750+
return ConstString(m_ast.PrintTemplateParams(template_param_infos));
770751
}
771752
return ConstString();
772753
}
@@ -1541,9 +1522,9 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) {
15411522
DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE();
15421523
// TODO: change this to get the correct decl context parent....
15431524
while (parent_decl_ctx_die) {
1544-
// The name may not contain template parameters due to simplified template
1545-
// names; we must reconstruct the full name from child template parameter
1546-
// dies via GetTemplateParametersString().
1525+
// The name may not contain template parameters due to
1526+
// -gsimple-template-names; we must reconstruct the full name from child
1527+
// template parameter dies via GetDIEClassTemplateParams().
15471528
const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();
15481529
switch (parent_tag) {
15491530
case DW_TAG_namespace: {

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,6 @@ class DWARFASTParserClang : public DWARFASTParser {
9595
/// parameters from the DIE name and instead always adds template parameter
9696
/// children DIEs.
9797
///
98-
/// Currently this is only called in two places, when uniquing C++ classes and
99-
/// when looking up the definition for a declaration (which is then cached).
100-
/// If this is ever called more than twice per DIE, we need to start caching
101-
/// the results to prevent unbounded growth of the created clang AST nodes.
102-
///
10398
/// \param die The struct/class DWARFDIE containing template parameters.
10499
/// \return A string, including surrounding '<>', of the template parameters.
105100
/// If the DIE's name already has '<>', returns an empty ConstString because
@@ -146,10 +141,6 @@ class DWARFASTParserClang : public DWARFASTParser {
146141
lldb_private::TypeSystemClang::TemplateParameterInfos
147142
&template_param_infos);
148143

149-
/// Get the template parameters of a die as a string if the die name does not
150-
/// already contain them. This happens with -gsimple-template-names.
151-
std::string GetTemplateParametersString(const DWARFDIE &die);
152-
153144
std::string GetCPlusPlusQualifiedName(const DWARFDIE &die);
154145

155146
bool ParseChildMembers(

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,24 @@ static TemplateParameterList *CreateTemplateParameterList(
14311431
return template_param_list;
14321432
}
14331433

1434+
std::string TypeSystemClang::PrintTemplateParams(
1435+
const TemplateParameterInfos &template_param_infos) {
1436+
llvm::SmallVector<NamedDecl *, 8> ignore;
1437+
clang::TemplateParameterList *template_param_list =
1438+
CreateTemplateParameterList(getASTContext(), template_param_infos,
1439+
ignore);
1440+
llvm::SmallVector<clang::TemplateArgument, 2> args =
1441+
template_param_infos.args;
1442+
if (template_param_infos.hasParameterPack()) {
1443+
args.append(template_param_infos.packed_args->args);
1444+
}
1445+
std::string str;
1446+
llvm::raw_string_ostream os(str);
1447+
clang::printTemplateArgumentList(os, args, GetTypePrintingPolicy(),
1448+
template_param_list);
1449+
return str;
1450+
}
1451+
14341452
clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl(
14351453
clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module,
14361454
clang::FunctionDecl *func_decl,

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,10 @@ class TypeSystemClang : public TypeSystem {
10671067

10681068
bool SetDeclIsForcefullyCompleted(const clang::TagDecl *td);
10691069

1070+
/// Return the template parameters (including surrounding <>) in string form.
1071+
std::string
1072+
PrintTemplateParams(const TemplateParameterInfos &template_param_infos);
1073+
10701074
private:
10711075
/// Returns the PrintingPolicy used when generating the internal type names.
10721076
/// These type names are mostly used for the formatter selection.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CXX_SOURCES := main.cpp
2+
3+
CFLAGS_EXTRAS = $(TEST_CFLAGS_EXTRAS) $(LIMIT_DEBUG_INFO_FLAGS)
4+
5+
include Makefile.rules
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""
2+
Test that a nested template parameter works with simple template names.
3+
"""
4+
5+
import lldb
6+
import lldbsuite.test.lldbutil as lldbutil
7+
from lldbsuite.test.decorators import *
8+
from lldbsuite.test.lldbtest import *
9+
10+
class NestedTemplateTestCase(TestBase):
11+
def do_test(self, debug_flags):
12+
self.build(dictionary=debug_flags)
13+
self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
14+
self.expect("image lookup -A -t 'Inner<int>'", DATA_TYPES_DISPLAYED_CORRECTLY, substrs=["1 match found"])
15+
16+
@skipIf(compiler=no_match("clang"))
17+
@skipIf(compiler_version=["<", "15.0"])
18+
def test_simple_template_names(self):
19+
self.do_test(dict(TEST_CFLAGS_EXTRAS="-gsimple-template-names"))
20+
21+
@skipIf(compiler=no_match("clang"))
22+
@skipIf(compiler_version=["<", "15.0"])
23+
def test_no_simple_template_names(self):
24+
self.do_test(dict(TEST_CFLAGS_EXTRAS="-gno-simple-template-names"))
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
struct Outer {
2+
Outer() {}
3+
4+
template <class T>
5+
struct Inner {};
6+
};
7+
8+
int main() {
9+
Outer::Inner<int> oi;
10+
}

0 commit comments

Comments
 (0)