From: Reid Kleckner Date: Tue, 2 Jul 2013 18:10:07 +0000 (+0000) Subject: [ms-cxxabi] Mangle variadic template parameter packs X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5d90d1805c99e0f14c623adf2cbedc725184bc4b;p=clang [ms-cxxabi] Mangle variadic template parameter packs Unlike Itanium, there is no code to indicate the beginning of a parameter pack. I tested this with MSVC 2013, which is the only version that implements variadic templates so far. This is needed to compile APInt.cpp for the MS C++ ABI. Reviewers: timurrrr Differential Revision: http://llvm-reviews.chandlerc.com/D1077 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185454 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index e2b42e7e30..8c02b3310d 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -134,7 +134,8 @@ private: void mangleTemplateArgs(const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs); - + void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA, + int ArgIndex); }; /// MicrosoftMangleContext - Overrides the default MangleContext for the @@ -848,44 +849,57 @@ MicrosoftCXXNameMangler::mangleTemplateArgs(const TemplateDecl *TD, unsigned NumTemplateArgs = TemplateArgs.size(); for (unsigned i = 0; i < NumTemplateArgs; ++i) { const TemplateArgument &TA = TemplateArgs[i]; - switch (TA.getKind()) { - case TemplateArgument::Null: - llvm_unreachable("Can't mangle null template arguments!"); - case TemplateArgument::Type: { - QualType T = TA.getAsType(); - mangleType(T, SourceRange(), QMM_Escape); - break; - } - case TemplateArgument::Declaration: - mangle(cast(TA.getAsDecl()), "$1?"); - break; - case TemplateArgument::Integral: - mangleIntegerLiteral(TA.getAsIntegral(), - TA.getIntegralType()->isBooleanType()); - break; - case TemplateArgument::Expression: - mangleExpression(TA.getAsExpr()); - break; - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - case TemplateArgument::NullPtr: - case TemplateArgument::Pack: { - // Issue a diagnostic. - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle template argument %0 of kind %select{ERROR|ERROR|" - "pointer/reference|nullptr|integral|template|template pack expansion|" - "ERROR|parameter pack}1 yet"); - Diags.Report(TD->getLocation(), DiagID) - << i + 1 - << TA.getKind() - << TD->getSourceRange(); - } - } + mangleTemplateArg(TD, TA, i); } Out << '@'; } +void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, + const TemplateArgument &TA, + int ArgIndex) { + switch (TA.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Can't mangle null template arguments!"); + case TemplateArgument::Type: { + QualType T = TA.getAsType(); + mangleType(T, SourceRange(), QMM_Escape); + break; + } + case TemplateArgument::Declaration: + mangle(cast(TA.getAsDecl()), "$1?"); + break; + case TemplateArgument::Integral: + mangleIntegerLiteral(TA.getAsIntegral(), + TA.getIntegralType()->isBooleanType()); + break; + case TemplateArgument::Expression: + mangleExpression(TA.getAsExpr()); + break; + case TemplateArgument::Pack: + // Unlike Itanium, there is no character code to indicate an argument pack. + // FIXME: ArgIndex will be off, but we only use if for diagnostics that + // should ultimately be removed. + for (TemplateArgument::pack_iterator I = TA.pack_begin(), E = TA.pack_end(); + I != E; ++I) + mangleTemplateArg(TD, *I, ArgIndex); + break; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + case TemplateArgument::NullPtr: { + // Issue a diagnostic. + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle template argument %0 of kind %select{ERROR|ERROR|" + "pointer/reference|nullptr|integral|template|template pack expansion|" + "ERROR|parameter pack}1 yet"); + Diags.Report(TD->getLocation(), DiagID) + << ArgIndex + 1 + << TA.getKind() + << TD->getSourceRange(); + } + } +} + void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, bool IsMember) { // ::= [E] [F] [I] diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp index c52b6b4b7a..363583a65f 100644 --- a/test/CodeGenCXX/mangle-ms-templates.cpp +++ b/test/CodeGenCXX/mangle-ms-templates.cpp @@ -133,3 +133,26 @@ void spam() { // CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ" // X64: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ" } + +// 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) { } +void variadic_fn_instantiate() { + variadic_fn_template(0, 1, 3, 4); + variadic_fn_template(0, 1, 'a', "b"); +} +// CHECK: "\01??$variadic_fn_template@HHHH@@YAXABH000@Z" +// CHECK: "\01??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z" + +template +struct VariadicClass { + VariadicClass() { } + int x; +}; +void variadic_class_instantiate() { + VariadicClass a; + VariadicClass b; +} +// CHECK: call {{.*}} @"\01??0?$VariadicClass@HD_N@@QAE@XZ" +// CHECK: call {{.*}} @"\01??0?$VariadicClass@_NDH@@QAE@XZ"