From: Charles Davis Date: Sat, 26 May 2012 23:12:19 +0000 (+0000) Subject: Mangle template instantiations properly (as of VC 7.x) when compiling for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9fd2359ee3b140557b808e4b79bc73a3b9d62304;p=clang 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 --- diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 6250f61198..6918ce4826 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -42,6 +42,7 @@ public: void mangleFunctionEncoding(const FunctionDecl *FD); void mangleVariableEncoding(const VarDecl *VD); void mangleNumber(int64_t Number); + void mangleNumber(const llvm::APSInt &Value); void mangleType(QualType T); private: @@ -54,6 +55,11 @@ private: void mangleOperatorName(OverloadedOperatorKind OO); 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); // Declare manglers for every type class. @@ -69,8 +75,12 @@ private: void mangleExtraDimensions(QualType T); void mangleFunctionClass(const FunctionDecl *FD); void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false); + void mangleIntegerLiteral(QualType T, const llvm::APSInt &Number); void mangleThrowSpecification(const FunctionProtoType *T); + void mangleTemplateArgs(const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, + SourceLocation InstantiationLoc); + }; /// MicrosoftMangleContext - Overrides the default MangleContext for the @@ -266,35 +276,92 @@ void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) { } void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) { - // ::= [?] # <= 9 - // ::= [?] + @ # > 9; A = 0, B = 1, etc... + // ::= [?] # 1 <= Number <= 10 + // ::= [?] + @ # 0 or > 9; A = 0, B = 1, etc... + // ::= [?] @ # 0 (alternate mangling, not emitted by VC) if (Number < 0) { Out << '?'; 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; - } else { + else { // We have to build up the encoding in reverse order, so it will come // out right when we write it out. char Encoding[16]; char *EndPtr = Encoding+sizeof(Encoding); char *CurPtr = EndPtr; - while (Number) { + do { *--CurPtr = 'A' + (Number % 16); Number /= 16; - } + } while (Number); Out.write(CurPtr, EndPtr-CurPtr); 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(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(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); + return Spec->getSpecializedTemplate(); + } + + return 0; +} + void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName 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()) { case DeclarationName::Identifier: { if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { @@ -364,7 +431,6 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, bool NoFunction) { // ::= [] - // ::= [] // ::= // ::= [] @@ -523,10 +589,69 @@ void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) { Out << II->getName() << '@'; } +void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation InstantiationLoc) { + // ::= + // ::= + // Always start with the unqualified name. + mangleUnscopedTemplateName(TD); + mangleTemplateArgs(TemplateArgs, NumTemplateArgs, InstantiationLoc); +} + void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { Context.mangleObjCMethodName(MD, Out); } +void +MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) { + // ::= ?$ + Out << "?$"; + mangleUnqualifiedName(TD); +} + +void +MicrosoftCXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) { + // ::= $0 + 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) { + // ::= { | }+ @ + 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, bool IsMember) { // ::= [E] [F] [I] diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp new file mode 100644 index 0000000000..357cc3b0e9 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-templates.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s + +template +class Class { + public: + void method() {} +}; + +class Typename { }; + +template +class Nested { }; + +template +class BoolTemplate { + public: + BoolTemplate() {} +}; + +void template_mangling() { + Class c1; + c1.method(); +// CHECK: call {{.*}} @"\01?method@?$Class@VTypename@@@@QAEXXZ" + + Class > c2; + c2.method(); +// CHECK: call {{.*}} @"\01?method@?$Class@V?$Nested@VTypename@@@@@@QAEXXZ" + + BoolTemplate _false; +// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ" + + BoolTemplate _true; +// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ" +} + +namespace space { + template const T& foo(const T& l) { return l; } +} +// CHECK: "\01??$foo@H@space@@YAABHABH@Z" + +void use() { + space::foo(42); +}