Skip to content
Snippets Groups Projects
Commit 9fd2359e authored by Charles Davis's avatar Charles Davis
Browse files

Mangle template instantiations properly (as of VC 7.x) when compiling for

the Microsoft Visual C++ ABI. Currently limited to type and integral
non-type arguments. Based on a patch by Timur Iskhodzhanov!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157524 91177308-0d34-0410-b5e6-96231b3b80d8
parent 242cb065
No related branches found
No related tags found
No related merge requests found
...@@ -42,6 +42,7 @@ public: ...@@ -42,6 +42,7 @@ public:
void mangleFunctionEncoding(const FunctionDecl *FD); void mangleFunctionEncoding(const FunctionDecl *FD);
void mangleVariableEncoding(const VarDecl *VD); void mangleVariableEncoding(const VarDecl *VD);
void mangleNumber(int64_t Number); void mangleNumber(int64_t Number);
void mangleNumber(const llvm::APSInt &Value);
void mangleType(QualType T); void mangleType(QualType T);
private: private:
...@@ -54,6 +55,11 @@ private: ...@@ -54,6 +55,11 @@ private:
void mangleOperatorName(OverloadedOperatorKind OO); void mangleOperatorName(OverloadedOperatorKind OO);
void mangleQualifiers(Qualifiers Quals, bool IsMember); void mangleQualifiers(Qualifiers Quals, bool IsMember);
void mangleUnscopedTemplateName(const TemplateDecl *ND);
void mangleTemplateInstantiationName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation InstantiationLoc);
void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleObjCMethodName(const ObjCMethodDecl *MD);
// Declare manglers for every type class. // Declare manglers for every type class.
...@@ -69,8 +75,12 @@ private: ...@@ -69,8 +75,12 @@ private:
void mangleExtraDimensions(QualType T); void mangleExtraDimensions(QualType T);
void mangleFunctionClass(const FunctionDecl *FD); void mangleFunctionClass(const FunctionDecl *FD);
void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false); void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Number);
void mangleThrowSpecification(const FunctionProtoType *T); void mangleThrowSpecification(const FunctionProtoType *T);
void mangleTemplateArgs(const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs,
SourceLocation InstantiationLoc);
}; };
/// MicrosoftMangleContext - Overrides the default MangleContext for the /// MicrosoftMangleContext - Overrides the default MangleContext for the
...@@ -266,35 +276,92 @@ void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { ...@@ -266,35 +276,92 @@ void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
} }
void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) { void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
// <number> ::= [?] <decimal digit> # <= 9 // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
// ::= [?] <hex digit>+ @ # > 9; A = 0, B = 1, etc... // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...
// ::= [?] @ # 0 (alternate mangling, not emitted by VC)
if (Number < 0) { if (Number < 0) {
Out << '?'; Out << '?';
Number = -Number; Number = -Number;
} }
if (Number >= 1 && Number <= 10) { // Oddly enough, there's a special shorter mangling for 0, but Microsoft chose not
// to use it. Instead, 0 gets mangled as "A@". Oh well...
if (Number >= 1 && Number <= 10)
Out << Number-1; Out << Number-1;
} else { else {
// We have to build up the encoding in reverse order, so it will come // We have to build up the encoding in reverse order, so it will come
// out right when we write it out. // out right when we write it out.
char Encoding[16]; char Encoding[16];
char *EndPtr = Encoding+sizeof(Encoding); char *EndPtr = Encoding+sizeof(Encoding);
char *CurPtr = EndPtr; char *CurPtr = EndPtr;
while (Number) { do {
*--CurPtr = 'A' + (Number % 16); *--CurPtr = 'A' + (Number % 16);
Number /= 16; Number /= 16;
} } while (Number);
Out.write(CurPtr, EndPtr-CurPtr); Out.write(CurPtr, EndPtr-CurPtr);
Out << '@'; Out << '@';
} }
} }
void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
if (Value.isSigned() && Value.isNegative()) {
Out << '?';
mangleNumber(llvm::APSInt(Value.abs()));
return;
}
if (Value.uge(1) && Value.ule(10))
(Value-llvm::APSInt(llvm::APInt(Value.getBitWidth(), 1, Value.isSigned()))).print(Out,
false);
else {
// We have to build up the encoding in reverse order, so it will come
// out right when we write it out.
char Encoding[64];
char *EndPtr = Encoding+sizeof(Encoding);
char *CurPtr = EndPtr;
llvm::APSInt Fifteen(Value.getBitWidth(), 15);
for (int i = 0, e = Value.getActiveBits() / 4; i != e; ++i) {
*--CurPtr = 'A' + Value.And(Fifteen).lshr(i*4).getLimitedValue(15);
Fifteen = Fifteen.shl(4);
};
Out.write(CurPtr, EndPtr-CurPtr);
Out << '@';
}
}
static const TemplateDecl *
isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
// Check if we have a function template.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
TemplateArgs = FD->getTemplateSpecializationArgs();
return TD;
}
}
// Check if we have a class template.
if (const ClassTemplateSpecializationDecl *Spec =
dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
TemplateArgs = &Spec->getTemplateArgs();
return Spec->getSpecializedTemplate();
}
return 0;
}
void void
MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
DeclarationName Name) { DeclarationName Name) {
// <unqualified-name> ::= <operator-name> // <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-name> // ::= <ctor-dtor-name>
// ::= <source-name> // ::= <source-name>
// ::= <template-name>
const TemplateArgumentList *TemplateArgs;
// Check if we have a template.
if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
mangleTemplateInstantiationName(TD, TemplateArgs->data(), TemplateArgs->size(),
ND->getLocation());
return;
}
switch (Name.getNameKind()) { switch (Name.getNameKind()) {
case DeclarationName::Identifier: { case DeclarationName::Identifier: {
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
...@@ -364,7 +431,6 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, ...@@ -364,7 +431,6 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
bool NoFunction) { bool NoFunction) {
// <postfix> ::= <unqualified-name> [<postfix>] // <postfix> ::= <unqualified-name> [<postfix>]
// ::= <template-postfix> <template-args> [<postfix>]
// ::= <template-param> // ::= <template-param>
// ::= <substitution> [<postfix>] // ::= <substitution> [<postfix>]
...@@ -523,10 +589,69 @@ void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) { ...@@ -523,10 +589,69 @@ void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
Out << II->getName() << '@'; Out << II->getName() << '@';
} }
void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation InstantiationLoc) {
// <template-name> ::= <unscoped-template-name> <template-args>
// ::= <substitution>
// Always start with the unqualified name.
mangleUnscopedTemplateName(TD);
mangleTemplateArgs(TemplateArgs, NumTemplateArgs, InstantiationLoc);
}
void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
Context.mangleObjCMethodName(MD, Out); Context.mangleObjCMethodName(MD, Out);
} }
void
MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) {
// <unscoped-template-name> ::= ?$ <unqualified-name>
Out << "?$";
mangleUnqualifiedName(TD);
}
void
MicrosoftCXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) {
// <integer-literal> ::= $0 <number>
Out << "$0";
// Make sure booleans are encoded as 0/1.
if (T->isBooleanType())
Out << (Value.getBoolValue() ? "0" : "A@");
else
mangleNumber(Value);
}
void
MicrosoftCXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation InstantiationLoc) {
// <template-args> ::= {<type> | <integer-literal>}+ @
for (unsigned int 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:
mangleType(TA.getAsType());
break;
case TemplateArgument::Integral:
mangleIntegerLiteral(TA.getIntegralType(), *TA.getAsIntegral());
break;
default: {
// Issue a diagnostic.
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"cannot yet mangle this %select{null|type|pointer/reference|integral|template|"
"template pack expansion|expression|parameter pack}0 template argument");
Diags.Report(InstantiationLoc, DiagID)
<< TA.getKind();
}
}
}
Out << '@';
}
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
bool IsMember) { bool IsMember) {
// <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers> // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
......
// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
template<typename T>
class Class {
public:
void method() {}
};
class Typename { };
template<typename T>
class Nested { };
template<bool flag>
class BoolTemplate {
public:
BoolTemplate() {}
};
void template_mangling() {
Class<Typename> c1;
c1.method();
// CHECK: call {{.*}} @"\01?method@?$Class@VTypename@@@@QAEXXZ"
Class<Nested<Typename> > c2;
c2.method();
// CHECK: call {{.*}} @"\01?method@?$Class@V?$Nested@VTypename@@@@@@QAEXXZ"
BoolTemplate<false> _false;
// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
BoolTemplate<true> _true;
// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ"
}
namespace space {
template<class T> const T& foo(const T& l) { return l; }
}
// CHECK: "\01??$foo@H@space@@YAABHABH@Z"
void use() {
space::foo(42);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment