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
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();
}
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: {
/// 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
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(
return template_param_list;
}
+std::string TypeSystemClang::PrintTemplateParams(
+ const TemplateParameterInfos &template_param_infos) {
+ llvm::SmallVector<NamedDecl *, 8> ignore;
+ clang::TemplateParameterList *template_param_list =
+ CreateTemplateParameterList(getASTContext(), template_param_infos,
+ ignore);
+ llvm::SmallVector<clang::TemplateArgument, 2> 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,
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.
--- /dev/null
+CXX_SOURCES := main.cpp
+
+CFLAGS_EXTRAS = $(TEST_CFLAGS_EXTRAS) $(LIMIT_DEBUG_INFO_FLAGS)
+
+include Makefile.rules
--- /dev/null
+"""
+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<int>'", 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"))
--- /dev/null
+struct Outer {
+ Outer() {}
+
+ template <class T>
+ struct Inner {};
+};
+
+int main() {
+ Outer::Inner<int> oi;
+}