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

Reply via email to