[Lldb-commits] [lldb] r302833 - [DWARF parser] Produce correct template parameter packs

Sean Callanan via lldb-commits lldb-commits at lists.llvm.org
Thu May 11 15:08:06 PDT 2017


Author: spyffe
Date: Thu May 11 17:08:05 2017
New Revision: 302833

URL: http://llvm.org/viewvc/llvm-project?rev=302833&view=rev
Log:
[DWARF parser] Produce correct template parameter packs

Templates can end in parameter packs, like this

template <class T...> struct MyStruct 
  { /*...*/ };

LLDB does not currently support these parameter packs; 
it does not emit them into the template argument list
at all. This causes problems when you specialize, e.g.:

template <> struct MyStruct<int> 
  { /*...*/ };
template <> struct MyStruct<int, int> : MyStruct<int> 
  { /*...*/ };

LLDB generates two template specializations, each with 
no template arguments, and then when they are imported 
by the ASTImporter into a parser's AST context we get a 
single specialization that inherits from itself, 
causing Clang's record layout mechanism to smash its
stack.

This patch fixes the problem for classes and adds
tests. The tests for functions fail because Clang's
ASTImporter can't import them at the moment, so I've
xfailed that test.

Differential Revision: https://reviews.llvm.org/D33025

Added:
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py
    lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp
Modified:
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
    lldb/trunk/source/Symbol/ClangASTContext.cpp

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=302833&r1=302832&r2=302833&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Thu May 11 17:08:05 2017
@@ -275,17 +275,16 @@ public:
     bool IsValid() const {
       if (args.empty())
         return false;
-      return args.size() == names.size();
-    }
-
-    size_t GetSize() const {
-      if (IsValid())
-        return args.size();
-      return 0;
+      return args.size() == names.size() &&
+        ((bool)pack_name == (bool)packed_args) &&
+        (!packed_args || !packed_args->packed_args);
     }
 
     llvm::SmallVector<const char *, 2> names;
     llvm::SmallVector<clang::TemplateArgument, 2> args;
+    
+    const char * pack_name = nullptr;
+    std::unique_ptr<TemplateParameterInfos> packed_args;
   };
 
   clang::FunctionTemplateDecl *

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile?rev=302833&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/Makefile Thu May 11 17:08:05 2017
@@ -0,0 +1,3 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py?rev=302833&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py Thu May 11 17:08:05 2017
@@ -0,0 +1,7 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(
+    __file__, globals(), [
+        decorators.expectedFailureAll(
+            oslist=["windows"], bugnumber="llvm.org/pr24764")])

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp?rev=302833&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/main.cpp Thu May 11 17:08:05 2017
@@ -0,0 +1,61 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LIDENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+template <class T, int... Args> struct C {
+  T member;
+  bool isSixteenThirtyTwo() { return false; }
+};
+
+template <> struct C<int, 16> {
+  int member;
+  bool isSixteenThirtyTwo() { return false; }
+};
+
+template <> struct C<int, 16, 32> : C<int, 16> {
+  bool isSixteenThirtyTwo() { return true; }
+};
+
+template <class T, typename... Args> struct D {
+  T member;
+  bool isIntBool() { return false; }
+};
+
+template <> struct D<int, int> {
+  int member;
+  bool isIntBool() { return false; }
+};
+
+template <> struct D<int, int, bool> : D<int, int> {
+  bool isIntBool() { return true; }
+};
+
+int main (int argc, char const *argv[])
+{
+    C<int,16,32> myC;
+    C<int,16> myLesserC;
+    myC.member = 64;
+    (void)C<int,16,32>().isSixteenThirtyTwo();
+    (void)C<int,16>().isSixteenThirtyTwo();
+    (void)(myC.member != 64);   //% self.expect("expression -- myC", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["64"])
+                                //% self.expect("expression -- C<int, 16>().isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"])
+                                //% self.expect("expression -- C<int, 16, 32>().isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"])
+                                //% self.expect("expression -- myLesserC.isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"])
+                                //% self.expect("expression -- myC.isSixteenThirtyTwo()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"])
+   
+    D<int,int,bool> myD;
+    D<int,int> myLesserD;
+    myD.member = 64;
+    (void)D<int,int,bool>().isIntBool();
+    (void)D<int,int>().isIntBool();
+    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"])
+                                //% self.expect("expression -- myLesserD.isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["false"])
+                                //% self.expect("expression -- myD.isIntBool()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["true"])
+}

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile?rev=302833&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/Makefile Thu May 11 17:08:05 2017
@@ -0,0 +1,3 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py?rev=302833&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/TestFunctionTemplateParameterPack.py Thu May 11 17:08:05 2017
@@ -0,0 +1,6 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(
+    __file__, globals(), [
+        decorators.expectedFailureAll(bugnumber="rdar://problem/32096064")])

Added: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp?rev=302833&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/function-template-parameter-pack/main.cpp Thu May 11 17:08:05 2017
@@ -0,0 +1,24 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LIDENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+template <class T> int staticSizeof() {
+  return sizeof(T);
+}
+
+template <class T1, class T2, class... Ts> int staticSizeof() {
+  return staticSizeof<T2, Ts...>() + sizeof(T1);
+}
+
+int main (int argc, char const *argv[])
+{
+  int sz = staticSizeof<long, int, char>();
+  return staticSizeof<long, int, char>() != sz; //% self.expect("expression -- sz == staticSizeof<long, int, char>()", "staticSizeof<long, int, char> worked", substrs = ["true"])
+                                  //% self.expect("expression -- sz == staticSizeof<long, int>() + sizeof(char)", "staticSizeof<long, int> worked", substrs = ["true"])
+                                  //% self.expect("expression -- sz == staticSizeof<long>() + sizeof(int) + sizeof(char)", "staticSizeof<long> worked", substrs = ["true"])
+}

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp?rev=302833&r1=302832&r2=302833&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp Thu May 11 17:08:05 2017
@@ -1987,8 +1987,33 @@ void ClangExpressionDeclMap::AddOneFunct
                 .GetOpaqueDeclContext();
         clang::FunctionDecl *src_function_decl =
             llvm::dyn_cast_or_null<clang::FunctionDecl>(src_decl_context);
-
-        if (src_function_decl) {
+        if (src_function_decl &&
+            src_function_decl->getTemplateSpecializationInfo()) {
+          clang::FunctionTemplateDecl *function_template =
+              src_function_decl->getTemplateSpecializationInfo()->getTemplate();
+          clang::FunctionTemplateDecl *copied_function_template =
+              llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(
+                 m_ast_importer_sp->CopyDecl(m_ast_context,
+                                             src_ast->getASTContext(),
+                                             function_template));
+          if (copied_function_template) {
+            if (log) {
+              ASTDumper ast_dumper((clang::Decl *)copied_function_template);
+              
+              StreamString ss;
+              
+              function->DumpSymbolContext(&ss);
+              
+              log->Printf("  CEDM::FEVD[%u] Imported decl for function template"
+                          " %s (description %s), returned %s",
+                          current_id,
+                          copied_function_template->getNameAsString().c_str(),
+                          ss.GetData(), ast_dumper.GetCString());
+            }
+            
+            context.AddNamedDecl(copied_function_template);
+          }
+        } else if (src_function_decl) {
           if (clang::FunctionDecl *copied_function_decl =
                   llvm::dyn_cast_or_null<clang::FunctionDecl>(
                       m_ast_importer_sp->CopyDecl(m_ast_context,

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp?rev=302833&r1=302832&r2=302833&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp Thu May 11 17:08:05 2017
@@ -1595,24 +1595,17 @@ TypeSP DWARFASTParserClang::ParseTypeFro
                                             : containing_decl_ctx,
                   type_name_cstr, clang_type, storage, is_inline);
 
-              //                            if (template_param_infos.GetSize() >
-              //                            0)
-              //                            {
-              //                                clang::FunctionTemplateDecl
-              //                                *func_template_decl =
-              //                                CreateFunctionTemplateDecl
-              //                                (containing_decl_ctx,
-              //                                                                                                              function_decl,
-              //                                                                                                              type_name_cstr,
-              //                                                                                                              template_param_infos);
-              //
-              //                                CreateFunctionTemplateSpecializationInfo
-              //                                (function_decl,
-              //                                                                          func_template_decl,
-              //                                                                          template_param_infos);
-              //                            }
-              // Add the decl to our DIE to decl context map
-
+              if (has_template_params) {
+                ClangASTContext::TemplateParameterInfos template_param_infos;
+                ParseTemplateParameterInfos(die, template_param_infos);
+                clang::FunctionTemplateDecl *func_template_decl =
+                    m_ast.CreateFunctionTemplateDecl(
+                        containing_decl_ctx, function_decl, type_name_cstr,
+                        template_param_infos);
+                m_ast.CreateFunctionTemplateSpecializationInfo(
+                    function_decl, func_template_decl, template_param_infos);
+              }
+              
               lldbassert(function_decl);
 
               if (function_decl) {
@@ -1951,6 +1944,19 @@ bool DWARFASTParserClang::ParseTemplateD
   const dw_tag_t tag = die.Tag();
 
   switch (tag) {
+  case DW_TAG_GNU_template_parameter_pack: {
+    template_param_infos.packed_args.reset(
+      new ClangASTContext::TemplateParameterInfos);
+    for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
+         child_die = child_die.GetSibling()) {
+      if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args))
+        return false;
+    }
+    if (const char *name = die.GetName()) {
+      template_param_infos.pack_name = name;
+    }
+    return true;
+  }
   case DW_TAG_template_type_parameter:
   case DW_TAG_template_value_parameter: {
     DWARFAttributes attributes;
@@ -2040,6 +2046,7 @@ bool DWARFASTParserClang::ParseTemplateP
     switch (tag) {
     case DW_TAG_template_type_parameter:
     case DW_TAG_template_value_parameter:
+    case DW_TAG_GNU_template_parameter_pack:
       ParseTemplateDIE(die, template_param_infos);
       break;
 
@@ -3450,6 +3457,7 @@ size_t DWARFASTParserClang::ParseChildPa
 
     case DW_TAG_template_type_parameter:
     case DW_TAG_template_value_parameter:
+    case DW_TAG_GNU_template_parameter_pack:
       // The one caller of this was never using the template_param_infos,
       // and the local variable was taking up a large amount of stack space
       // in SymbolFileDWARF::ParseType() so this was removed. If we ever need

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp?rev=302833&r1=302832&r2=302833&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp Thu May 11 17:08:05 2017
@@ -1647,6 +1647,8 @@ bool DWARFDebugInfoEntry::LookupAddress(
       break;
     case DW_TAG_template_value_parameter:
       break;
+    case DW_TAG_GNU_template_parameter_pack:
+      break;
     case DW_TAG_thrown_type:
       break;
     case DW_TAG_try_block:

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp?rev=302833&r1=302832&r2=302833&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp Thu May 11 17:08:05 2017
@@ -610,6 +610,8 @@ DW_TAG_CategoryEnum get_tag_category(uin
     return TagCategoryType;
   case DW_TAG_template_value_parameter:
     return TagCategoryType;
+  case DW_TAG_GNU_template_parameter_pack:
+    return TagCategoryType;
   case DW_TAG_thrown_type:
     return TagCategoryType;
   case DW_TAG_try_block:

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=302833&r1=302832&r2=302833&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu May 11 17:08:05 2017
@@ -1394,6 +1394,12 @@ CompilerType ClangASTContext::CreateReco
   return CompilerType();
 }
 
+namespace {
+  bool IsValueParam(const clang::TemplateArgument &argument) {
+    return argument.getKind() == TemplateArgument::Integral;
+  }
+}
+
 static TemplateParameterList *CreateTemplateParameterList(
     ASTContext *ast,
     const ClangASTContext::TemplateParameterInfos &template_param_infos,
@@ -1401,31 +1407,51 @@ static TemplateParameterList *CreateTemp
   const bool parameter_pack = false;
   const bool is_typename = false;
   const unsigned depth = 0;
-  const size_t num_template_params = template_param_infos.GetSize();
+  const size_t num_template_params = template_param_infos.args.size();
+  DeclContext *const decl_context =
+      ast->getTranslationUnitDecl(); // Is this the right decl context?,
   for (size_t i = 0; i < num_template_params; ++i) {
     const char *name = template_param_infos.names[i];
 
     IdentifierInfo *identifier_info = nullptr;
     if (name && name[0])
       identifier_info = &ast->Idents.get(name);
-    if (template_param_infos.args[i].getKind() == TemplateArgument::Integral) {
+    if (IsValueParam(template_param_infos.args[i])) {
       template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
-          *ast,
-          ast->getTranslationUnitDecl(), // Is this the right decl context?,
-                                         // SourceLocation StartLoc,
+          *ast, decl_context,
           SourceLocation(), SourceLocation(), depth, i, identifier_info,
           template_param_infos.args[i].getIntegralType(), parameter_pack,
           nullptr));
 
     } else {
       template_param_decls.push_back(TemplateTypeParmDecl::Create(
-          *ast,
-          ast->getTranslationUnitDecl(), // Is this the right decl context?
+          *ast, decl_context,
           SourceLocation(), SourceLocation(), depth, i, identifier_info,
           is_typename, parameter_pack));
     }
   }
-
+  
+  if (template_param_infos.packed_args &&
+      template_param_infos.packed_args->args.size()) {
+    IdentifierInfo *identifier_info = nullptr;
+    if (template_param_infos.pack_name && template_param_infos.pack_name[0])
+      identifier_info = &ast->Idents.get(template_param_infos.pack_name);
+    const bool parameter_pack_true = true;
+    if (IsValueParam(template_param_infos.packed_args->args[0])) {
+      template_param_decls.push_back(NonTypeTemplateParmDecl::Create(
+          *ast, decl_context,
+          SourceLocation(), SourceLocation(), depth, num_template_params,
+          identifier_info,
+          template_param_infos.packed_args->args[0].getIntegralType(),
+          parameter_pack_true, nullptr));
+    } else {
+      template_param_decls.push_back(TemplateTypeParmDecl::Create(
+          *ast, decl_context,
+          SourceLocation(), SourceLocation(), depth, num_template_params,
+          identifier_info,
+          is_typename, parameter_pack_true));
+    }
+  }
   clang::Expr *const requires_clause = nullptr; // TODO: Concepts
   TemplateParameterList *template_param_list = TemplateParameterList::Create(
       *ast, SourceLocation(), SourceLocation(), template_param_decls,
@@ -1535,10 +1561,19 @@ ClangASTContext::CreateClassTemplateSpec
     DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind,
     const TemplateParameterInfos &template_param_infos) {
   ASTContext *ast = getASTContext();
+  llvm::SmallVector<clang::TemplateArgument, 2> args(
+      template_param_infos.args.size() +
+      (template_param_infos.packed_args ? 1 : 0));
+  std::copy(template_param_infos.args.begin(), template_param_infos.args.end(),
+            args.begin());
+  if (template_param_infos.packed_args) {
+    args[args.size() - 1] = TemplateArgument::CreatePackCopy(
+        *ast, template_param_infos.packed_args->args);
+  }
   ClassTemplateSpecializationDecl *class_template_specialization_decl =
       ClassTemplateSpecializationDecl::Create(
           *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(),
-          SourceLocation(), class_template_decl, template_param_infos.args,
+          SourceLocation(), class_template_decl, args,
           nullptr);
 
   class_template_specialization_decl->setSpecializationKind(




More information about the lldb-commits mailing list