From: Arthur Eubanks Date: Mon, 23 Jan 2023 23:37:57 +0000 (-0800) Subject: [lldb] Don't create Clang AST nodes in GetDIEClassTemplateParams X-Git-Tag: upstream/17.0.6~19723 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5dd7c16c3dcfd3154a53ee59e0e092c1e0092197;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 9ebc494..56bd089 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -745,28 +745,9 @@ DWARFASTParserClang::GetDIEClassTemplateParams(const DWARFDIE &die) { if (llvm::StringRef(die.GetName()).contains("<")) return ConstString(); - clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); TypeSystemClang::TemplateParameterInfos template_param_infos; if (ParseTemplateParameterInfos(die, template_param_infos)) { - // Most of the parameters here don't matter, but we make sure the base name - // is empty so when we print the name we only get the template parameters. - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, GetOwningClangModule(die), - eAccessPublic, "", clang::TTK_Struct, - template_param_infos); - if (!class_template_decl) - return ConstString(); - - clang::ClassTemplateSpecializationDecl *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, GetOwningClangModule(die), class_template_decl, - clang::TTK_Struct, template_param_infos); - if (!class_specialization_decl) - return ConstString(); - CompilerType clang_type = - m_ast.CreateClassTemplateSpecializationType(class_specialization_decl); - ConstString name = clang_type.GetTypeName(/*BaseOnly*/ true); - return name; + return ConstString(m_ast.PrintTemplateParams(template_param_infos)); } return ConstString(); } @@ -1541,9 +1522,9 @@ DWARFASTParserClang::GetCPlusPlusQualifiedName(const DWARFDIE &die) { DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE(); // TODO: change this to get the correct decl context parent.... while (parent_decl_ctx_die) { - // The name may not contain template parameters due to simplified template - // names; we must reconstruct the full name from child template parameter - // dies via GetTemplateParametersString(). + // The name may not contain template parameters due to + // -gsimple-template-names; we must reconstruct the full name from child + // template parameter dies via GetDIEClassTemplateParams(). const dw_tag_t parent_tag = parent_decl_ctx_die.Tag(); switch (parent_tag) { case DW_TAG_namespace: { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index c078d997..0733d22 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -95,11 +95,6 @@ public: /// parameters from the DIE name and instead always adds template parameter /// children DIEs. /// - /// Currently this is only called in two places, when uniquing C++ classes and - /// when looking up the definition for a declaration (which is then cached). - /// If this is ever called more than twice per DIE, we need to start caching - /// the results to prevent unbounded growth of the created clang AST nodes. - /// /// \param die The struct/class DWARFDIE containing template parameters. /// \return A string, including surrounding '<>', of the template parameters. /// If the DIE's name already has '<>', returns an empty ConstString because @@ -146,10 +141,6 @@ protected: lldb_private::TypeSystemClang::TemplateParameterInfos &template_param_infos); - /// Get the template parameters of a die as a string if the die name does not - /// already contain them. This happens with -gsimple-template-names. - std::string GetTemplateParametersString(const DWARFDIE &die); - std::string GetCPlusPlusQualifiedName(const DWARFDIE &die); bool ParseChildMembers( diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index d1745d9..e3c61b0 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -1431,6 +1431,24 @@ static TemplateParameterList *CreateTemplateParameterList( return template_param_list; } +std::string TypeSystemClang::PrintTemplateParams( + const TemplateParameterInfos &template_param_infos) { + llvm::SmallVector ignore; + clang::TemplateParameterList *template_param_list = + CreateTemplateParameterList(getASTContext(), template_param_infos, + ignore); + llvm::SmallVector args = + template_param_infos.args; + if (template_param_infos.hasParameterPack()) { + args.append(template_param_infos.packed_args->args); + } + std::string str; + llvm::raw_string_ostream os(str); + clang::printTemplateArgumentList(os, args, GetTypePrintingPolicy(), + template_param_list); + return str; +} + clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, clang::FunctionDecl *func_decl, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 8307fa5..f94a055 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -1067,6 +1067,10 @@ public: bool SetDeclIsForcefullyCompleted(const clang::TagDecl *td); + /// Return the template parameters (including surrounding <>) in string form. + std::string + PrintTemplateParams(const TemplateParameterInfos &template_param_infos); + private: /// Returns the PrintingPolicy used when generating the internal type names. /// These type names are mostly used for the formatter selection. diff --git a/lldb/test/API/lang/cpp/nested-template/Makefile b/lldb/test/API/lang/cpp/nested-template/Makefile new file mode 100644 index 0000000..e49374fb --- /dev/null +++ b/lldb/test/API/lang/cpp/nested-template/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS = $(TEST_CFLAGS_EXTRAS) $(LIMIT_DEBUG_INFO_FLAGS) + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/nested-template/TestNestedTemplate.py b/lldb/test/API/lang/cpp/nested-template/TestNestedTemplate.py new file mode 100644 index 0000000..e44ce7e --- /dev/null +++ b/lldb/test/API/lang/cpp/nested-template/TestNestedTemplate.py @@ -0,0 +1,24 @@ +""" +Test that a nested template parameter works with simple template names. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class NestedTemplateTestCase(TestBase): + def do_test(self, debug_flags): + self.build(dictionary=debug_flags) + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.expect("image lookup -A -t 'Inner'", DATA_TYPES_DISPLAYED_CORRECTLY, substrs=["1 match found"]) + + @skipIf(compiler=no_match("clang")) + @skipIf(compiler_version=["<", "15.0"]) + def test_simple_template_names(self): + self.do_test(dict(TEST_CFLAGS_EXTRAS="-gsimple-template-names")) + + @skipIf(compiler=no_match("clang")) + @skipIf(compiler_version=["<", "15.0"]) + def test_no_simple_template_names(self): + self.do_test(dict(TEST_CFLAGS_EXTRAS="-gno-simple-template-names")) diff --git a/lldb/test/API/lang/cpp/nested-template/main.cpp b/lldb/test/API/lang/cpp/nested-template/main.cpp new file mode 100644 index 0000000..06d1094 --- /dev/null +++ b/lldb/test/API/lang/cpp/nested-template/main.cpp @@ -0,0 +1,10 @@ +struct Outer { + Outer() {} + + template + struct Inner {}; +}; + +int main() { + Outer::Inner oi; +}