Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -277,11 +277,11 @@ class TemplateParameterInfos { public: bool IsValid() const { - if (args.empty()) + if (args.empty() && (!packed_args || packed_args->args.empty())) return false; return args.size() == names.size() && - ((bool)pack_name == (bool)packed_args) && - (!packed_args || !packed_args->packed_args); + ((bool)pack_name == (bool)packed_args) && + (!packed_args || !packed_args->args.empty()); } llvm::SmallVector names; @@ -784,16 +784,17 @@ const char *name, bool omit_empty_base_classes, std::vector &child_indexes) override; - size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override; + size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack = false) override; lldb::TemplateArgumentKind - GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, - size_t idx) override; + GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack) override; CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, - size_t idx) override; + size_t idx, bool expand_pack) override; llvm::Optional - GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, - size_t idx) override; + GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack) override; CompilerType GetTypeForFormatters(void *type) override; Index: include/lldb/Symbol/CompilerType.h =================================================================== --- include/lldb/Symbol/CompilerType.h +++ include/lldb/Symbol/CompilerType.h @@ -364,14 +364,16 @@ GetIndexOfChildMemberWithName(const char *name, bool omit_empty_base_classes, std::vector &child_indexes) const; - size_t GetNumTemplateArguments() const; + size_t GetNumTemplateArguments(bool expand_pack = false) const; - lldb::TemplateArgumentKind GetTemplateArgumentKind(size_t idx) const; - CompilerType GetTypeTemplateArgument(size_t idx) const; + lldb::TemplateArgumentKind + GetTemplateArgumentKind(size_t idx, bool expand_pack = false) const; + CompilerType GetTypeTemplateArgument(size_t idx, + bool expand_pack = false) const; // Returns the value of the template argument and its type. llvm::Optional - GetIntegralTemplateArgument(size_t idx) const; + GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const; CompilerType GetTypeForFormatters() const; Index: include/lldb/Symbol/GoASTContext.h =================================================================== --- include/lldb/Symbol/GoASTContext.h +++ include/lldb/Symbol/GoASTContext.h @@ -310,7 +310,8 @@ const char *name, bool omit_empty_base_classes, std::vector &child_indexes) override; - size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override { + size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack) override { return 0; } Index: include/lldb/Symbol/JavaASTContext.h =================================================================== --- include/lldb/Symbol/JavaASTContext.h +++ include/lldb/Symbol/JavaASTContext.h @@ -201,7 +201,8 @@ unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override; - size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override; + size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack) override; int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override; Index: include/lldb/Symbol/OCamlASTContext.h =================================================================== --- include/lldb/Symbol/OCamlASTContext.h +++ include/lldb/Symbol/OCamlASTContext.h @@ -227,7 +227,8 @@ const char *name, bool omit_empty_base_classes, std::vector &child_indexes) override; - size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override { + size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack) override { return 0; } Index: include/lldb/Symbol/TypeSystem.h =================================================================== --- include/lldb/Symbol/TypeSystem.h +++ include/lldb/Symbol/TypeSystem.h @@ -347,14 +347,18 @@ const char *name, bool omit_empty_base_classes, std::vector &child_indexes) = 0; - virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) = 0; + virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack = false) = 0; virtual lldb::TemplateArgumentKind - GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx); - virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, - size_t idx); + GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack = false); + virtual CompilerType + GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack = false); virtual llvm::Optional - GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx); + GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack = false); //---------------------------------------------------------------------- // Dumping types Index: packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py @@ -0,0 +1,34 @@ +""" +Test that the type of arguments to C++ template classes that have variadic +parameters can be enumerated. +""" +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TemplatePackArgsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_template_argument_pack(self): + self.build() + (_, _, thread, _) = lldbutil.run_to_source_breakpoint(self, + 'breakpoint here', lldb.SBFileSpec('main.cpp'), exe_name = 'a.out') + frame = thread.GetSelectedFrame() + + only_pack = frame.FindVariable('onlyPack') + self.assertTrue(only_pack.IsValid(), + 'make sure we find the onlyPack variable') + self.assertEqual(only_pack.GetType().GetNumberOfTemplateArguments(), 4) + self.assertEqual(only_pack.GetType().GetTemplateArgumentType(0).GetName(), 'int') + self.assertEqual(only_pack.GetType().GetTemplateArgumentType(1).GetName(), 'char') + self.assertEqual(only_pack.GetType().GetTemplateArgumentType(2).GetName(), 'double') + # Access the C template parameter. + nested_template = only_pack.GetType().GetTemplateArgumentType(3) + self.assertEqual(nested_template.GetName(), 'D') + self.assertEqual(nested_template.GetNumberOfTemplateArguments(), 3) + self.assertEqual(nested_template.GetTemplateArgumentType(0).GetName(), 'int') + self.assertEqual(nested_template.GetTemplateArgumentType(1).GetName(), 'int') + self.assertEqual(nested_template.GetTemplateArgumentType(2).GetName(), 'bool') Index: packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp =================================================================== --- packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp +++ packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp @@ -35,8 +35,12 @@ bool isIntBool() { return true; } }; +template struct OnlyPack {}; + int main (int argc, char const *argv[]) { + OnlyPack> onlyPack; + C myC; C myLesserC; myC.member = 64; @@ -52,7 +56,7 @@ D myLesserD; myD.member = 64; (void)D().isIntBool(); - (void)D().isIntBool(); + (void)D().isIntBool(); // breakpoint here return myD.member != 64; //% self.expect("expression -- myD", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["64"]) //% self.expect("expression -- D().isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) //% self.expect("expression -- D().isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"]) Index: source/API/SBType.cpp =================================================================== --- source/API/SBType.cpp +++ source/API/SBType.cpp @@ -409,8 +409,10 @@ } uint32_t SBType::GetNumberOfTemplateArguments() { + bool expand_pack = true; if (IsValid()) - return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments(); + return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments( + expand_pack); return 0; } @@ -419,13 +421,15 @@ return SBType(); CompilerType type; + bool expand_pack = true; switch(GetTemplateArgumentKind(idx)) { case eTemplateArgumentKindType: - type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument(idx); + type = m_opaque_sp->GetCompilerType(false).GetTypeTemplateArgument( + idx, expand_pack); break; case eTemplateArgumentKindIntegral: type = m_opaque_sp->GetCompilerType(false) - .GetIntegralTemplateArgument(idx) + .GetIntegralTemplateArgument(idx, expand_pack) ->type; break; default: @@ -437,8 +441,10 @@ } lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) { + bool expand_pack = true; if (IsValid()) - return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind(idx); + return m_opaque_sp->GetCompilerType(false).GetTemplateArgumentKind( + idx, expand_pack); return eTemplateArgumentKindNull; } Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2089,9 +2089,8 @@ break; } } - if (template_param_infos.args.empty()) - return false; - return template_param_infos.args.size() == template_param_infos.names.size(); + + return template_param_infos.IsValid(); } bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -7546,7 +7546,8 @@ } size_t -ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { +ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack) { if (!type) return 0; @@ -7561,8 +7562,16 @@ const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast( cxx_record_decl); - if (template_decl) - return template_decl->getTemplateArgs().size(); + if (template_decl) { + const auto &template_arg_list = template_decl->getTemplateArgs(); + int num_args = template_arg_list.size(); + if (expand_pack) { + auto &pack = template_arg_list[num_args - 1]; + if (pack.getKind() == clang::TemplateArgument::Pack) + num_args += pack.pack_size() - 1; + } + return num_args; + } } } break; @@ -7644,15 +7653,37 @@ } } +const TemplateArgument * +GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl, + int idx, bool expand_pack) { + const auto &args = decl->getTemplateArgs(); + + if (idx < args.size() - 1) + return &args[idx]; + + assert(args.size() && + "We shouldn't have a template specialization without any args"); + if (!expand_pack || + args[args.size() - 1].getKind() != clang::TemplateArgument::Pack) + return idx >= args.size() ? nullptr : &args[idx]; + + const auto &pack = args[args.size() - 1]; + return &pack.pack_elements()[idx - (args.size() - 1)]; +} + lldb::TemplateArgumentKind ClangASTContext::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, - size_t arg_idx) { + size_t arg_idx, bool expand_pack) { const clang::ClassTemplateSpecializationDecl *template_decl = GetAsTemplateSpecialization(type); - if (! template_decl || arg_idx >= template_decl->getTemplateArgs().size()) + if (!template_decl) + return eTemplateArgumentKindNull; + + const auto *arg = GetNthTemplateArgument(template_decl, arg_idx, expand_pack); + if (!arg) return eTemplateArgumentKindNull; - switch (template_decl->getTemplateArgs()[arg_idx].getKind()) { + switch (arg->getKind()) { case clang::TemplateArgument::Null: return eTemplateArgumentKindNull; @@ -7685,35 +7716,33 @@ CompilerType ClangASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, - size_t idx) { + size_t idx, bool expand_pack) { const clang::ClassTemplateSpecializationDecl *template_decl = GetAsTemplateSpecialization(type); - if (!template_decl || idx >= template_decl->getTemplateArgs().size()) + if (!template_decl) return CompilerType(); - const clang::TemplateArgument &template_arg = - template_decl->getTemplateArgs()[idx]; - if (template_arg.getKind() != clang::TemplateArgument::Type) + const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack); + if (!arg || arg->getKind() != clang::TemplateArgument::Type) return CompilerType(); - return CompilerType(getASTContext(), template_arg.getAsType()); + return CompilerType(getASTContext(), arg->getAsType()); } llvm::Optional ClangASTContext::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, - size_t idx) { + size_t idx, bool expand_pack) { const clang::ClassTemplateSpecializationDecl *template_decl = GetAsTemplateSpecialization(type); - if (! template_decl || idx >= template_decl->getTemplateArgs().size()) + if (!template_decl) return llvm::None; - const clang::TemplateArgument &template_arg = - template_decl->getTemplateArgs()[idx]; - if (template_arg.getKind() != clang::TemplateArgument::Integral) + const auto *arg = GetNthTemplateArgument(template_decl, idx, expand_pack); + if (!arg || arg->getKind() != clang::TemplateArgument::Integral) return llvm::None; - return {{template_arg.getAsIntegral(), - CompilerType(getASTContext(), template_arg.getIntegralType())}}; + return {{arg->getAsIntegral(), + CompilerType(getASTContext(), arg->getIntegralType())}}; } CompilerType ClangASTContext::GetTypeForFormatters(void *type) { Index: source/Symbol/CompilerType.cpp =================================================================== --- source/Symbol/CompilerType.cpp +++ source/Symbol/CompilerType.cpp @@ -680,30 +680,32 @@ return 0; } -size_t CompilerType::GetNumTemplateArguments() const { +size_t CompilerType::GetNumTemplateArguments(bool expand_pack) const { if (IsValid()) { - return m_type_system->GetNumTemplateArguments(m_type); + return m_type_system->GetNumTemplateArguments(m_type, expand_pack); } return 0; } -TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx) const { +TemplateArgumentKind +CompilerType::GetTemplateArgumentKind(size_t idx, bool expand_pack) const { if (IsValid()) - return m_type_system->GetTemplateArgumentKind(m_type, idx); + return m_type_system->GetTemplateArgumentKind(m_type, idx, expand_pack); return eTemplateArgumentKindNull; } -CompilerType CompilerType::GetTypeTemplateArgument(size_t idx) const { +CompilerType CompilerType::GetTypeTemplateArgument(size_t idx, + bool expand_pack) const { if (IsValid()) { - return m_type_system->GetTypeTemplateArgument(m_type, idx); + return m_type_system->GetTypeTemplateArgument(m_type, idx, expand_pack); } return CompilerType(); } llvm::Optional -CompilerType::GetIntegralTemplateArgument(size_t idx) const { +CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const { if (IsValid()) - return m_type_system->GetIntegralTemplateArgument(m_type, idx); + return m_type_system->GetIntegralTemplateArgument(m_type, idx, expand_pack); return llvm::None; } Index: source/Symbol/JavaASTContext.cpp =================================================================== --- source/Symbol/JavaASTContext.cpp +++ source/Symbol/JavaASTContext.cpp @@ -879,7 +879,8 @@ } size_t -JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { +JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack) { return 0; } Index: source/Symbol/TypeSystem.cpp =================================================================== --- source/Symbol/TypeSystem.cpp +++ source/Symbol/TypeSystem.cpp @@ -102,18 +102,19 @@ } TemplateArgumentKind -TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) { +TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx, + bool expand_pack) { return eTemplateArgumentKindNull; } CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, - size_t idx) { + size_t idx, bool expand_pack) { return CompilerType(); } llvm::Optional -TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, - size_t idx) { +TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx, + bool expand_pack) { return llvm::None; }