[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