friss updated this revision to Diff 163399. friss added a comment. Address feedback
https://reviews.llvm.org/D51387 Files: include/lldb/Symbol/ClangASTContext.h include/lldb/Symbol/CompilerType.h include/lldb/Symbol/TypeSystem.h packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestTemplatePackArgs.py packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp source/API/SBType.cpp source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp source/Symbol/ClangASTContext.cpp source/Symbol/CompilerType.cpp source/Symbol/TypeSystem.cpp
Index: source/Symbol/TypeSystem.cpp =================================================================== --- source/Symbol/TypeSystem.cpp +++ source/Symbol/TypeSystem.cpp @@ -101,23 +101,25 @@ return CompilerType(this, type); } -size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { +size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack) { return 0; } 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<CompilerType::IntegralTemplateArgument> -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; } 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::IntegralTemplateArgument> -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/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,19 @@ const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>( 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(); + assert( + num_args && + "We shouldn't have a template specialization without any args"); + 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 +7656,37 @@ } } +const TemplateArgument * +GetNthTemplateArgument(const clang::ClassTemplateSpecializationDecl *decl, + int idx, bool expand_pack) { + const auto &args = decl->getTemplateArgs(); + assert(args.size() && + "We shouldn't have a template specialization without any args"); + + if (idx < args.size() - 1) + return &args[idx]; + + 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 +7719,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<CompilerType::IntegralTemplateArgument> 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/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/API/SBType.cpp =================================================================== --- source/API/SBType.cpp +++ source/API/SBType.cpp @@ -409,23 +409,27 @@ } 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; } lldb::SBType SBType::GetTemplateArgumentType(uint32_t idx) { if (!IsValid()) 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: 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,14 @@ bool isIntBool() { return true; } }; +template <typename... Args> struct OnlyPack {}; +template <typename T, typename... Args> struct EmptyPack {}; + int main (int argc, char const *argv[]) { + EmptyPack<int> emptyPack; + OnlyPack<int, char, double, D<int, int, bool>> onlyPack; + C<int,16,32> myC; C<int,16> myLesserC; myC.member = 64; @@ -52,7 +58,7 @@ D<int,int> myLesserD; myD.member = 64; (void)D<int,int,bool>().isIntBool(); - (void)D<int,int>().isIntBool(); + (void)D<int,int>().isIntBool(); // breakpoint here return myD.member != 64; //% self.expect("expression -- myD", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["64"]) //% self.expect("expression -- D<int, int>().isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"]) //% self.expect("expression -- D<int, int, bool>().isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"]) 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,39 @@ +""" +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() + + empty_pack = frame.FindVariable('emptyPack') + self.assertTrue(empty_pack.IsValid(), + 'make sure we find the emptyPack variable') + self.assertEqual(empty_pack.GetType().GetNumberOfTemplateArguments(), 1) + + 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<double, 42> template parameter. + nested_template = only_pack.GetType().GetTemplateArgumentType(3) + self.assertEqual(nested_template.GetName(), 'D<int, int, bool>') + 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: 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<uint32_t> &child_indexes) = 0; - virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type); + virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack); 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); + virtual CompilerType + GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack); virtual llvm::Optional<CompilerType::IntegralTemplateArgument> - GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx); + GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack); //---------------------------------------------------------------------- // Dumping types Index: include/lldb/Symbol/CompilerType.h =================================================================== --- include/lldb/Symbol/CompilerType.h +++ include/lldb/Symbol/CompilerType.h @@ -364,14 +364,28 @@ GetIndexOfChildMemberWithName(const char *name, bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) const; - size_t GetNumTemplateArguments() const; - - lldb::TemplateArgumentKind GetTemplateArgumentKind(size_t idx) const; - CompilerType GetTypeTemplateArgument(size_t idx) const; + // Return the number of template arguments the type has. + // If expand_pack is true, then variadic argument packs are automatically + // expanded to their supplied arguments. If it is false an argument pack will + // only count as 1 argument. + size_t GetNumTemplateArguments(bool expand_pack = false) const; + + // Return the TemplateArgumentKind of the template argument at index idx. + // If expand_pack is true, then variadic argument packs are automatically + // expanded to their supplied arguments. With expand_pack set to false, + // an arguement pack will count as 1 argument and return a type of Pack. + 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. + // If expand_pack is true, then variadic argument packs are automatically + // expanded to their supplied arguments. With expand_pack set to false, + // an arguement pack will count as 1 argument and it is invalid to call + // this method on the pack argument. llvm::Optional<IntegralTemplateArgument> - GetIntegralTemplateArgument(size_t idx) const; + GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const; CompilerType GetTypeForFormatters() const; Index: include/lldb/Symbol/ClangASTContext.h =================================================================== --- include/lldb/Symbol/ClangASTContext.h +++ include/lldb/Symbol/ClangASTContext.h @@ -277,11 +277,10 @@ class TemplateParameterInfos { public: bool IsValid() const { - if (args.empty()) + if (args.empty() && !packed_args) 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); } llvm::SmallVector<const char *, 2> names; @@ -784,16 +783,17 @@ const char *name, bool omit_empty_base_classes, std::vector<uint32_t> &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; 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<CompilerType::IntegralTemplateArgument> - 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;
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits