From e2dd15785b281d842c35a4854c1bee28ebf70594 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sat, 8 Sep 2018 20:58:39 +0000 Subject: [PATCH] ms: Insert $$Z in mangling between directly consecutive parameter packs. Fixes PR38783. Differential Revision: https://reviews.llvm.org/D51784 llvm-svn: 341755 --- clang/lib/AST/MicrosoftMangle.cpp | 13 ++++++++++--- clang/test/CodeGenCXX/mangle-ms-templates.cpp | 28 ++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 348f05d..6f1a1f4 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -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, diff --git a/clang/test/CodeGenCXX/mangle-ms-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-templates.cpp index 8c6062b..6055465 100644 --- a/clang/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-templates.cpp @@ -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 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 void variadic_fn_template(const Ts &...args) { } +template void variadic_fn_template(const Ts &...args); +template +void multi_variadic_fn(Ts... ts, Us... us); +template +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(1, 2, 3, 4, 5); + multi_variadic_fn(1, 2, 3, 4, 5); + + // ...but not if another template parameter is between them. + multi_variadic_mixed(1, 2, 3); + multi_variadic_mixed(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 struct VariadicClass { -- 2.7.4