ms: Insert $$Z in mangling between directly consecutive parameter packs.
authorNico Weber <nicolasweber@gmx.de>
Sat, 8 Sep 2018 20:58:39 +0000 (20:58 +0000)
committerNico Weber <nicolasweber@gmx.de>
Sat, 8 Sep 2018 20:58:39 +0000 (20:58 +0000)
Fixes PR38783.
Differential Revision: https://reviews.llvm.org/D51784

llvm-svn: 341755

clang/lib/AST/MicrosoftMangle.cpp
clang/test/CodeGenCXX/mangle-ms-templates.cpp

index 348f05d368203a86b38b28d49fefe232e00f3041..6f1a1f4fed670c494909ec67640529f5e460e246 100644 (file)
@@ -1384,9 +1384,16 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
   assert(TPL->size() == TemplateArgs.size() &&
          "size mismatch between args and parms!");
 
-  unsigned Idx = 0;
-  for (const TemplateArgument &TA : TemplateArgs.asArray())
-    mangleTemplateArg(TD, TA, TPL->getParam(Idx++));
+  for (size_t i = 0; i < TemplateArgs.size(); ++i) {
+    const TemplateArgument &TA = TemplateArgs[i];
+
+    // Separate consecutive packs by $$Z.
+    if (i > 0 && TA.getKind() == TemplateArgument::Pack &&
+        TemplateArgs[i - 1].getKind() == TemplateArgument::Pack)
+      Out << "$$Z";
+
+    mangleTemplateArg(TD, TA, TPL->getParam(i));
+  }
 }
 
 void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
index 8c6062b6d5ee4ac535cfeab312e60f61981a5aed..6055465537448ec23b0a0adc5b218478a202eacb 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
-// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
+// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
 
 template<typename T>
 class Class {
@@ -185,13 +185,35 @@ void spam() {
 // Unlike Itanium, there is no character code to indicate an argument pack.
 // Tested with MSVC 2013, the first version which supports variadic templates.
 
-template <typename ...Ts> void variadic_fn_template(const Ts &...args) { }
+template <typename ...Ts> void variadic_fn_template(const Ts &...args);
+template <typename... Ts, typename... Us>
+void multi_variadic_fn(Ts... ts, Us... us);
+template <typename... Ts, typename C, typename... Us>
+void multi_variadic_mixed(Ts... ts, C c, Us... us);
 void variadic_fn_instantiate() {
   variadic_fn_template(0, 1, 3, 4);
   variadic_fn_template(0, 1, 'a', "b");
+
+  // Directlly consecutive packs are separated by $$Z...
+  multi_variadic_fn<int, int>(1, 2, 3, 4, 5);
+  multi_variadic_fn<int, int, int>(1, 2, 3, 4, 5);
+
+  // ...but not if another template parameter is between them.
+  multi_variadic_mixed<int, int>(1, 2, 3);
+  multi_variadic_mixed<int, int>(1, 2, 3, 4);
 }
 // CHECK: "??$variadic_fn_template@HHHH@@YAXABH000@Z"
+// X64:   "??$variadic_fn_template@HHHH@@YAXAEBH000@Z"
 // CHECK: "??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z"
+// X64:   "??$variadic_fn_template@HHD$$BY01D@@YAXAEBH0AEBDAEAY01$$CBD@Z"
+// CHECK: "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z"
+// X64:   "??$multi_variadic_fn@HH$$ZHHH@@YAXHHHHH@Z"
+// CHECK: "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z"
+// X64:   "??$multi_variadic_fn@HHH$$ZHH@@YAXHHHHH@Z"
+// CHECK: "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z"
+// X64:   "??$multi_variadic_mixed@HHH$$V@@YAXHHH@Z"
+// CHECK: "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z"
+// X64:   "??$multi_variadic_mixed@HHHH@@YAXHHHH@Z"
 
 template <typename ...Ts>
 struct VariadicClass {