[cfe-commits] r157524 - in /cfe/trunk: lib/AST/MicrosoftMangle.cpp test/CodeGenCXX/mangle-ms-templates.cpp
Charles Davis
cdavis at mines.edu
Sat May 26 16:12:20 PDT 2012
Author: cdavis
Date: Sat May 26 18:12:19 2012
New Revision: 157524
URL: http://llvm.org/viewvc/llvm-project?rev=157524&view=rev
Log:
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!
Added:
cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp
Modified:
cfe/trunk/lib/AST/MicrosoftMangle.cpp
Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=157524&r1=157523&r2=157524&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Sat May 26 18:12:19 2012
@@ -42,6 +42,7 @@
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 @@
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 @@
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::mangleNumber(int64_t Number) {
- // <number> ::= [?] <decimal digit> # <= 9
- // ::= [?] <hex digit>+ @ # > 9; A = 0, B = 1, etc...
+ // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
+ // ::= [?] <hex digit>+ @ # 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<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
MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
DeclarationName Name) {
// <unqualified-name> ::= <operator-name>
// ::= <ctor-dtor-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()) {
case DeclarationName::Identifier: {
if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
@@ -364,7 +431,6 @@
void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
bool NoFunction) {
// <postfix> ::= <unqualified-name> [<postfix>]
- // ::= <template-postfix> <template-args> [<postfix>]
// ::= <template-param>
// ::= <substitution> [<postfix>]
@@ -523,10 +589,69 @@
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) {
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,
bool IsMember) {
// <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
Added: cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp?rev=157524&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-templates.cpp Sat May 26 18:12:19 2012
@@ -0,0 +1,43 @@
+// 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 at VTypename@@@@QAEXXZ"
+
+ Class<Nested<Typename> > c2;
+ c2.method();
+// CHECK: call {{.*}} @"\01?method@?$Class at V?$Nested at VTypename@@@@@@QAEXXZ"
+
+ BoolTemplate<false> _false;
+// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE at XZ"
+
+ BoolTemplate<true> _true;
+// CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE at XZ"
+}
+
+namespace space {
+ template<class T> const T& foo(const T& l) { return l; }
+}
+// CHECK: "\01??$foo at H@space@@YAABHABH at Z"
+
+void use() {
+ space::foo(42);
+}
More information about the cfe-commits
mailing list