[cfe-commits] r106937 - in /cfe/trunk: lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/mangle-ms.cpp

Charles Davis cdavis at mines.edu
Fri Jun 25 20:50:05 PDT 2010


Author: cdavis
Date: Fri Jun 25 22:50:05 2010
New Revision: 106937

URL: http://llvm.org/viewvc/llvm-project?rev=106937&view=rev
Log:
Mangle pointer and (lvalue) reference types in the Microsoft C++ Mangler.

Also, fix mangling of throw specs. Turns out MSVC totally ignores throw
specs when mangling names.

Modified:
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
    cfe/trunk/test/CodeGenCXX/mangle-ms.cpp

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=106937&r1=106936&r2=106937&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri Jun 25 22:50:05 2010
@@ -69,7 +69,7 @@
 #include "clang/AST/TypeNodes.def"
   
   void mangleType(const TagType*);
-  void mangleType(const FunctionType *T, bool IsStructor);
+  void mangleType(const FunctionType *T, bool IsStructor, bool IsInstMethod);
   void mangleFunctionClass(const FunctionDecl *FD);
   void mangleCallingConvention(const FunctionType *T);
   void mangleThrowSpecification(const FunctionProtoType *T);
@@ -202,11 +202,13 @@
   
   // We should never ever see a FunctionNoProtoType at this point.
   // We don't even know how to mangle their types anyway :).
-  FunctionProtoType *OldType = cast<FunctionProtoType>(FD->getType());
+  const FunctionProtoType *FT = cast<FunctionProtoType>(FD->getType());
 
-  bool InStructor = false;
+  bool InStructor = false, InInstMethod = false;
   const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
   if (MD) {
+    if (MD->isInstance())
+      InInstMethod = true;
     if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
       InStructor = true;
   }
@@ -214,29 +216,7 @@
   // First, the function class.
   mangleFunctionClass(FD);
 
-  // If this is a C++ instance method, mangle the CVR qualifiers for the
-  // this pointer.
-  if (MD && MD->isInstance())
-    mangleQualifiers(Qualifiers::fromCVRMask(OldType->getTypeQuals()), false);
-
-  // Do the canonicalization out here because parameter types can
-  // undergo additional canonicalization (e.g. array decay).
-  const FunctionProtoType *FT = cast<FunctionProtoType>(getASTContext()
-                                                    .getCanonicalType(OldType));
-  // If the function's type had a throw spec, canonicalization removed it.
-  // Get it back.
-  FT = cast<FunctionProtoType>(getASTContext().getFunctionType(
-                                                FT->getResultType(),
-                                                FT->arg_type_begin(),
-                                                FT->getNumArgs(),
-                                                FT->isVariadic(),
-                                                FT->getTypeQuals(),
-                                                OldType->hasExceptionSpec(),
-                                                OldType->hasAnyExceptionSpec(),
-                                                OldType->getNumExceptions(),
-                                                OldType->exception_begin(),
-                                                FT->getExtInfo()).getTypePtr());
-  mangleType(FT, InStructor);
+  mangleType(FT, InStructor, InInstMethod);
 }
 
 void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
@@ -263,9 +243,17 @@
     Out << '4';
   // Now mangle the type.
   // <variable-type> ::= <type> <cvr-qualifiers>
+  //                 ::= <type> A # pointers and references
+  // Pointers and references are odd. The type of 'int * const foo;' gets
+  // mangled as 'QAHA' instead of 'PAHB', for example.
   QualType Ty = VD->getType();
-  mangleType(Ty.getLocalUnqualifiedType());
-  mangleQualifiers(Ty.getLocalQualifiers(), false);
+  if (Ty->isPointerType() || Ty->isReferenceType()) {
+    mangleType(Ty);
+    Out << 'A';
+  } else {
+    mangleType(Ty.getLocalUnqualifiedType());
+    mangleQualifiers(Ty.getLocalQualifiers(), false);
+  }
 }
 
 void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
@@ -642,6 +630,32 @@
   // Only operate on the canonical type!
   T = getASTContext().getCanonicalType(T);
   
+  Qualifiers Quals = T.getLocalQualifiers();
+  if (Quals) {
+    // We have to mangle these now, while we still have enough information.
+    // <pointer-cvr-qualifiers> ::= P # pointer
+    //                          ::= Q # const pointer
+    //                          ::= R # volatile pointer
+    //                          ::= S # const volatile pointer
+    if (T->isPointerType()) {
+      if (!Quals.hasVolatile()) {
+        Out << 'Q';
+      } else {
+        if (!Quals.hasConst())
+          Out << 'R';
+        else
+          Out << 'S';
+      }
+    } else
+      // Just emit qualifiers like normal.
+      // NB: When we mangle a pointer/reference type, and the pointee
+      // type has no qualifiers, the lack of qualifier gets mangled
+      // in there.
+      mangleQualifiers(Quals, false);
+  }
+  else if (T->isPointerType()) {
+    Out << 'P';
+  }
   switch (T->getTypeClass()) {
 #define ABSTRACT_TYPE(CLASS, PARENT)
 #define NON_CANONICAL_TYPE(CLASS, PARENT) \
@@ -659,6 +673,12 @@
   case Type::Record:
     mangleType(static_cast<RecordType *>(T.getTypePtr()));
     break;
+  case Type::Pointer:
+    mangleType(static_cast<PointerType *>(T.getTypePtr()));
+    break;
+  case Type::LValueReference:
+    mangleType(static_cast<LValueReferenceType *>(T.getTypePtr()));
+    break;
   default:
     assert(false && "Don't know how to mangle this type!");
     break;
@@ -743,22 +763,29 @@
 void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T) {
   // Structors only appear in decls, so at this point we know it's not a
   // structor type.
-  mangleType(T, false);
+  // I'll probably have mangleType(MemberPointerType) call 
+  mangleType(T, false, false);
 }
 void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T) {
   llvm_unreachable("Can't mangle K&R function prototypes");
 }
 
 void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
-                                         bool IsStructor) {
-  // <function-type> ::= <calling-convention> <return-type> <argument-list>
-  //                                                              <throw-spec>
-  mangleCallingConvention(T);
-
+                                         bool IsStructor,
+                                         bool IsInstMethod) {
+  // <function-type> ::= <this-cvr-qualifiers> <calling-convention>
+  //                     <return-type> <argument-list> <throw-spec>
   const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
 
-  // Structors always have a 'void' return type, but MSVC mangles them as an
-  // '@' (because they have no declared return type).
+  // If this is a C++ instance method, mangle the CVR qualifiers for the
+  // this pointer.
+  if (IsInstMethod)
+    mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);
+
+  mangleCallingConvention(T);
+
+  // <return-type> ::= <type>
+  //               ::= @ # structors (they have no declared return type)
   if (IsStructor)
     Out << '@';
   else
@@ -871,15 +898,10 @@
   // <throw-spec> ::= Z # throw(...) (default)
   //              ::= @ # throw() or __declspec/__attribute__((nothrow))
   //              ::= <type>+
-  if (!FT->hasExceptionSpec() || FT->hasAnyExceptionSpec())
-    Out << 'Z';
-  else {
-    for (unsigned Exception = 0, NumExceptions = FT->getNumExceptions();
-         Exception < NumExceptions;
-         ++Exception)
-      mangleType(FT->getExceptionType(Exception).getLocalUnqualifiedType());
-    Out << '@';
-  }
+  // NOTE: Since the Microsoft compiler ignores throw specifications, they are
+  // all actually mangled as 'Z'. (They're ignored because their associated
+  // functionality isn't implemented, and probably never will be.)
+  Out << 'Z';
 }
 
 // <type>        ::= <union-type> | <struct-type> | <class-type> | <enum-type>
@@ -913,6 +935,27 @@
   mangleName(T->getDecl());
 }
 
+// <type> ::= <pointer-type>
+// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+void MicrosoftCXXNameMangler::mangleType(const PointerType *T) {
+  QualType PointeeTy = T->getPointeeType();
+  if (!PointeeTy.hasLocalQualifiers())
+    // Lack of qualifiers is mangled as 'A'.
+    Out << 'A';
+  mangleType(PointeeTy);
+}
+
+// <type> ::= <reference-type>
+// <reference-type> ::= A <cvr-qualifiers> <type>
+void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T) {
+  Out << 'A';
+  QualType PointeeTy = T->getPointeeType();
+  if (!PointeeTy.hasLocalQualifiers())
+    // Lack of qualifiers is mangled as 'A'.
+    Out << 'A';
+  mangleType(PointeeTy);
+}
+
 void MicrosoftMangleContext::mangleName(const NamedDecl *D,
                                         llvm::SmallVectorImpl<char> &Name) {
   assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms.cpp?rev=106937&r1=106936&r2=106937&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms.cpp Fri Jun 25 22:50:05 2010
@@ -7,6 +7,7 @@
 // CHECK: @"\01?e at foo@@1JC"
 // CHECK: @"\01?f at foo@@2DD"
 // CHECK: @"\01?g at bar@@2HA"
+// CHECK: @"\01?h@@3QAHA"
 
 int a;
 
@@ -50,18 +51,23 @@
 
 int bar::g;
 
+extern int * const h = &a;
+
 // Static functions are mangled, too.
 // Also make sure calling conventions, arglists, and throw specs work.
 static void __stdcall alpha(float a, double b) throw() {}
 bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
-// CHECK: @"\01?beta@@YI_N_J_W at CE@"
+// CHECK: @"\01?beta@@YI_N_J_W at Z"
   alpha(0.f, 0.0);
   return false;
 }
 
-// CHECK: @"\01?alpha@@YGXMN@@"
+// CHECK: @"\01?alpha@@YGXMN at Z"
 
 // Make sure tag-type mangling works.
 void gamma(class foo, struct bar, union baz, enum quux) {}
 // CHECK: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
 
+// Make sure pointer/reference-type mangling works.
+void delta(int * const a, const long &) {}
+// CHECK: @"\01?delta@@YAXQAHABJ at Z"





More information about the cfe-commits mailing list