r184777 - [ms-cxxabi] Use sugared types in the mangler instead of canonical types

Reid Kleckner reid at kleckner.net
Mon Jun 24 12:21:52 PDT 2013


Author: rnk
Date: Mon Jun 24 14:21:52 2013
New Revision: 184777

URL: http://llvm.org/viewvc/llvm-project?rev=184777&view=rev
Log:
[ms-cxxabi] Use sugared types in the mangler instead of canonical types

At this point, it's clear that the MSVC mangler uses the type-as-written
instead of the canonical type, so this should bring us closer to MSVC.
The main thrust of this change is to fix the way we mangle decayed array
parameters of function pointer parameters.  With a DecayedType sugar
node, this code can now be much simpler.

Fixes PR16096.

This also fixes a separate issue that Richard spotted in review.
Because separate declarations of the same entity can be spelled and
mangled differently, MSVC always mangles the earliest declaration in an
attempt to avoid link errors.  Clang now does the same.

Reviewers: rsmith

Differential Revision: http://llvm-reviews.chandlerc.com/D844

Modified:
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=184777&r1=184776&r2=184777&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Mon Jun 24 14:21:52 2013
@@ -125,7 +125,7 @@ private:
   void mangleFunctionType(const FunctionType *T, const FunctionDecl *D,
                           bool IsStructor, bool IsInstMethod);
   void mangleDecayedArrayType(const ArrayType *T, bool IsGlobal);
-  void mangleArrayType(const ArrayType *T, Qualifiers Quals);
+  void mangleArrayType(const ArrayType *T);
   void mangleFunctionClass(const FunctionDecl *FD);
   void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
   void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
@@ -257,13 +257,20 @@ void MicrosoftCXXNameMangler::mangle(con
 void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
   // <type-encoding> ::= <function-class> <function-type>
 
+  // Since MSVC operates on the type as written and not the canonical type, it
+  // actually matters which decl we have here.  MSVC appears to choose the
+  // first, since it is most likely to be the declaration in a header file.
+  FD = FD->getFirstDeclaration();
+
   // Don't mangle in the type if this isn't a decl we should typically mangle.
   if (!Context.shouldMangleDeclName(FD))
     return;
   
   // We should never ever see a FunctionNoProtoType at this point.
   // We don't even know how to mangle their types anyway :).
-  const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
+  TypeSourceInfo *TSI = FD->getTypeSourceInfo();
+  QualType T = TSI ? TSI->getType() : FD->getType();
+  const FunctionProtoType *FT = T->castAs<FunctionProtoType>();
 
   bool InStructor = false, InInstMethod = false;
   const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
@@ -980,17 +987,24 @@ void MicrosoftCXXNameMangler::manglePoin
 
 void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
                                                  SourceRange Range) {
+  // MSVC will backreference two canonically equivalent types that have slightly
+  // different manglings when mangled alone.
   void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
   ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
 
   if (Found == TypeBackReferences.end()) {
     size_t OutSizeBefore = Out.GetNumBytesInBuffer();
 
-    if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
-      mangleDecayedArrayType(AT, false);
-    } else if (const FunctionType *FT = T->getAs<FunctionType>()) {
-      Out << "P6";
-      mangleFunctionType(FT, 0, false, false);
+    if (const DecayedType *DT = T->getAs<DecayedType>()) {
+      QualType OT = DT->getOriginalType();
+      if (const ArrayType *AT = getASTContext().getAsArrayType(OT)) {
+        mangleDecayedArrayType(AT, false);
+      } else if (const FunctionType *FT = OT->getAs<FunctionType>()) {
+        Out << "P6";
+        mangleFunctionType(FT, 0, false, false);
+      } else {
+        llvm_unreachable("unexpected decayed type");
+      }
     } else {
       mangleType(T, Range, QMM_Drop);
     }
@@ -1010,16 +1024,18 @@ void MicrosoftCXXNameMangler::mangleArgu
 
 void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
                                          QualifierMangleMode QMM) {
-  // Only operate on the canonical type!
-  T = getASTContext().getCanonicalType(T);
+  // Don't use the canonical types.  MSVC includes things like 'const' on
+  // pointer arguments to function pointers that canonicalization strips away.
+  T = T.getDesugaredType(getASTContext());
   Qualifiers Quals = T.getLocalQualifiers();
-
-  if (const ArrayType *AT = dyn_cast<ArrayType>(T)) {
+  if (const ArrayType *AT = getASTContext().getAsArrayType(T)) {
+    // If there were any Quals, getAsArrayType() pushed them onto the array
+    // element type.
     if (QMM == QMM_Mangle)
       Out << 'A';
     else if (QMM == QMM_Escape || QMM == QMM_Result)
       Out << "$$B";
-    mangleArrayType(AT, Quals);
+    mangleArrayType(AT);
     return;
   }
 
@@ -1180,6 +1196,9 @@ void MicrosoftCXXNameMangler::mangleFunc
   //                     <return-type> <argument-list> <throw-spec>
   const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
 
+  SourceRange Range;
+  if (D) Range = D->getSourceRange();
+
   // If this is a C++ instance method, mangle the CVR qualifiers for the
   // this pointer.
   if (IsInstMethod)
@@ -1201,7 +1220,7 @@ void MicrosoftCXXNameMangler::mangleFunc
     }
     Out << '@';
   } else {
-    mangleType(Proto->getResultType(), SourceRange(), QMM_Result);
+    mangleType(Proto->getResultType(), Range, QMM_Result);
   }
 
   // <argument-list> ::= X # void
@@ -1210,23 +1229,11 @@ void MicrosoftCXXNameMangler::mangleFunc
   if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
     Out << 'X';
   } else {
-    if (D) {
-      // If we got a decl, use the type-as-written to make sure arrays
-      // get mangled right.  Note that we can't rely on the TSI
-      // existing if (for example) the parameter was synthesized.
-      for (FunctionDecl::param_const_iterator Parm = D->param_begin(),
-             ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
-        TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
-        QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
-        mangleArgumentType(Type, (*Parm)->getSourceRange());
-      }
-    } else {
-      // Happens for function pointer type arguments for example.
-      for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
-           ArgEnd = Proto->arg_type_end();
-           Arg != ArgEnd; ++Arg)
-        mangleArgumentType(*Arg, SourceRange());
-    }
+    // Happens for function pointer type arguments for example.
+    for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+         ArgEnd = Proto->arg_type_end();
+         Arg != ArgEnd; ++Arg)
+      mangleArgumentType(*Arg, Range);
     // <builtin-type>      ::= Z  # ellipsis
     if (Proto->isVariadic())
       Out << 'Z';
@@ -1431,8 +1438,7 @@ void MicrosoftCXXNameMangler::mangleType
                                          SourceRange) {
   llvm_unreachable("Should have been special cased");
 }
-void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T,
-                                              Qualifiers Quals) {
+void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) {
   QualType ElementTy(T, 0);
   SmallVector<llvm::APInt, 3> Dimensions;
   for (;;) {
@@ -1471,8 +1477,7 @@ void MicrosoftCXXNameMangler::mangleArra
   mangleNumber(Dimensions.size());
   for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim)
     mangleNumber(Dimensions[Dim].getLimitedValue());
-  mangleType(getASTContext().getQualifiedType(ElementTy.getTypePtr(), Quals),
-             SourceRange(), QMM_Escape);
+  mangleType(ElementTy, SourceRange(), QMM_Escape);
 }
 
 // <type>                   ::= <pointer-to-member-type>

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp?rev=184777&r1=184776&r2=184777&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp Mon Jun 24 14:21:52 2013
@@ -162,3 +162,45 @@ void foo_volatile(volatile Vector) {}
 void foo(Vector*, const Vector, const double) {}
 // CHECK: "\01?foo@@YAXPAY02NQBNN at Z"
 // X64: "\01?foo@@YAXPEAY02NQEBNN at Z"
+
+typedef void (*ConstFunPtr)(int *const d);
+void foo_fnptrconst(ConstFunPtr f) {  }
+// CHECK: "\01?foo_fnptrconst@@YAXP6AXQAH at Z@Z"
+// X64:   "\01?foo_fnptrconst@@YAXP6AXQEAH at Z@Z"
+
+typedef void (*ArrayFunPtr)(int d[1]);
+void foo_fnptrarray(ArrayFunPtr f) {  }
+// CHECK: "\01?foo_fnptrarray@@YAXP6AXQAH at Z@Z"
+// X64:   "\01?foo_fnptrarray@@YAXP6AXQEAH at Z@Z"
+
+void foo_fnptrbackref1(ArrayFunPtr f1, ArrayFunPtr f2) {  }
+// CHECK: "\01?foo_fnptrbackref1@@YAXP6AXQAH at Z1@Z"
+// X64:   "\01?foo_fnptrbackref1@@YAXP6AXQEAH at Z1@Z"
+
+void foo_fnptrbackref2(ArrayFunPtr f1, ConstFunPtr f2) {  }
+// CHECK: "\01?foo_fnptrbackref2@@YAXP6AXQAH at Z1@Z"
+// X64:   "\01?foo_fnptrbackref2@@YAXP6AXQEAH at Z1@Z"
+
+typedef void (*NormalFunPtr)(int *d);
+void foo_fnptrbackref3(ArrayFunPtr f1, NormalFunPtr f2) {  }
+// CHECK: "\01?foo_fnptrbackref3@@YAXP6AXQAH at Z1@Z"
+// X64:   "\01?foo_fnptrbackref3@@YAXP6AXQEAH at Z1@Z"
+
+void foo_fnptrbackref4(NormalFunPtr f1, ArrayFunPtr f2) {  }
+// CHECK: "\01?foo_fnptrbackref4@@YAXP6AXPAH at Z1@Z"
+// X64:   "\01?foo_fnptrbackref4@@YAXP6AXPEAH at Z1@Z"
+
+ArrayFunPtr ret_fnptrarray() { return 0; }
+// CHECK: "\01?ret_fnptrarray@@YAP6AXQAH at ZXZ"
+// X64:   "\01?ret_fnptrarray@@YAP6AXQEAH at ZXZ"
+
+// Test that we mangle the forward decl when we have a redeclaration with a
+// slightly different type.
+void mangle_fwd(char * const x);
+void mangle_fwd(char * x) {}
+// CHECK: "\01?mangle_fwd@@YAXQAD at Z"
+// X64:   "\01?mangle_fwd@@YAXQEAD at Z"
+
+void mangle_no_fwd(char * x) {}
+// CHECK: "\01?mangle_no_fwd@@YAXPAD at Z"
+// X64:   "\01?mangle_no_fwd@@YAXPEAD at Z"





More information about the cfe-commits mailing list