[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

llvm-svn: 185454
This commit is contained in:
Reid Kleckner 2013-07-02 18:10:07 +00:00
parent 5001ec9190
commit f0ae35b88c
2 changed files with 72 additions and 35 deletions

View File

@ -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<NamedDecl>(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<NamedDecl>(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) {
// <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>

View File

@ -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 <typename ...Ts> 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 <typename ...Ts>
struct VariadicClass {
VariadicClass() { }
int x;
};
void variadic_class_instantiate() {
VariadicClass<int, char, bool> a;
VariadicClass<bool, char, int> b;
}
// CHECK: call {{.*}} @"\01??0?$VariadicClass@HD_N@@QAE@XZ"
// CHECK: call {{.*}} @"\01??0?$VariadicClass@_NDH@@QAE@XZ"