Hi timurrrr,

This includes the following fixes:
 - Implement 4 subtly different variants of qualifier mangling and use them
   in what I believe are the right places.
 - Fix handling of array types.  Previously we were always decaying them,
   which is wrong if the type appears as a template argument, pointee,
   referent etc.
Fixes PR13182.

http://llvm-reviews.chandlerc.com/D709

Files:
  lib/AST/MicrosoftMangle.cpp
  test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
  test/CodeGenCXX/mangle-ms-templates.cpp
  test/CodeGenCXX/mangle-ms.cpp
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -59,6 +59,8 @@
   ASTContext &getASTContext() const { return Context.getASTContext(); }
 
 public:
+  enum MangleQualifiers { MQ_Drop, MQ_Escape, MQ_Mangle, MQ_Result };
+
   MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
     : Context(C), Out(Out_),
       Structor(0), StructorType(-1),
@@ -78,7 +80,7 @@
   void mangleVariableEncoding(const VarDecl *VD);
   void mangleNumber(int64_t Number);
   void mangleNumber(const llvm::APSInt &Value);
-  void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true);
+  void mangleType(QualType T, SourceRange Range, MangleQualifiers MQ = MQ_Mangle);
 
 private:
   void disableBackReferences() { UseNameBackReferences = false; }
@@ -112,10 +114,10 @@
 #undef TYPE
   
   void mangleType(const TagType*);
-  void mangleType(const FunctionType *T, const FunctionDecl *D,
-                  bool IsStructor, bool IsInstMethod);
-  void mangleType(const ArrayType *T, bool IsGlobal);
-  void mangleExtraDimensions(QualType T);
+  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 mangleFunctionClass(const FunctionDecl *FD);
   void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
   void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
@@ -264,7 +266,7 @@
   // First, the function class.
   mangleFunctionClass(FD);
 
-  mangleType(FT, FD, InStructor, InInstMethod);
+  mangleFunctionType(FT, FD, InStructor, InInstMethod);
 }
 
 void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
@@ -297,14 +299,17 @@
   TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();
   QualType Ty = TL.getType();
   if (Ty->isPointerType() || Ty->isReferenceType()) {
-    mangleType(Ty, TL.getSourceRange());
+    mangleType(Ty, TL.getSourceRange(), MQ_Drop);
     mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
   } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
     // Global arrays are funny, too.
-    mangleType(AT, true);
-    mangleQualifiers(Ty.getQualifiers(), false);
+    mangleDecayedArrayType(AT, true);
+    if (AT->getElementType()->isArrayType())
+      Out << 'A';
+    else
+      mangleQualifiers(Ty.getQualifiers(), false);
   } else {
-    mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange());
+    mangleType(Ty, TL.getSourceRange(), MQ_Drop);
     mangleQualifiers(Ty.getLocalQualifiers(), false);
   }
 }
@@ -826,9 +831,7 @@
       llvm_unreachable("Can't mangle null template arguments!");
     case TemplateArgument::Type: {
       QualType T = TA.getAsType();
-      if (T.hasQualifiers())
-        Out << "$$C";
-      mangleType(T, SourceRange());
+      mangleType(T, SourceRange(), MQ_Escape);
       break;
     }
     case TemplateArgument::Declaration:
@@ -968,7 +971,14 @@
   if (Found == TypeBackReferences.end()) {
     size_t OutSizeBefore = Out.GetNumBytesInBuffer();
 
-    mangleType(T, Range, false);
+    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);
+    } else {
+      mangleType(T, Range, MQ_Drop);
+    }
 
     // See if it's worth creating a back reference.
     // Only types longer than 1 character are considered
@@ -984,28 +994,48 @@
 }
 
 void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
-                                         bool MangleQualifiers) {
+                                         MangleQualifiers MQ) {
   // Only operate on the canonical type!
   T = getASTContext().getCanonicalType(T);
-
   Qualifiers Quals = T.getLocalQualifiers();
-  // We have to mangle these now, while we still have enough information.
-  if (T->isAnyPointerType() || T->isMemberPointerType() ||
-      T->isBlockPointerType()) {
-    manglePointerQualifiers(Quals);
-  } else if (Quals && MangleQualifiers) {
-    mangleQualifiers(Quals, false);
+  bool IsPointer = T->isAnyPointerType() || T->isMemberPointerType() ||
+                   T->isBlockPointerType();
+
+  if (const ArrayType *AT = dyn_cast<ArrayType>(T)) {
+    if (MQ == MQ_Mangle)
+      Out << 'A';
+    else if (MQ == MQ_Escape || MQ == MQ_Result)
+      Out << "$$B";
+    mangleArrayType(AT, Quals);
+    return;
   }
 
-  SplitQualType split = T.split();
-  const Type *ty = split.Ty;
+  if (MQ == MQ_Result) {
+    if ((Quals && !IsPointer) || T->getAs<TagType>()) {
+      Out << '?';
+      MQ = MQ_Mangle;
+    } else {
+      MQ = MQ_Drop;
+    }
+  }
 
-  // If we're mangling a qualified array type, push the qualifiers to
-  // the element type.
-  if (split.Quals && isa<ArrayType>(T)) {
-    ty = Context.getASTContext().getAsArrayType(T);
+  if (MQ == MQ_Mangle) {
+    if (const FunctionType *FT = T->getAs<FunctionType>()) {
+      Out << '6';
+      mangleFunctionType(FT, 0, false, false);
+      return;
+    }
+    mangleQualifiers(Quals, false);
+  } else if (!IsPointer && MQ == MQ_Escape && Quals) {
+    Out << "$$C";
+    mangleQualifiers(Quals, false);
   }
 
+  // We have to mangle these now, while we still have enough information.
+  if (IsPointer)
+    manglePointerQualifiers(Quals);
+  const Type *ty = T.getTypePtr();
+
   switch (ty->getTypeClass()) {
 #define ABSTRACT_TYPE(CLASS, PARENT)
 #define NON_CANONICAL_TYPE(CLASS, PARENT) \
@@ -1115,17 +1145,17 @@
   // structor type.
   // FIXME: This may not be lambda-friendly.
   Out << "$$A6";
-  mangleType(T, NULL, false, false);
+  mangleFunctionType(T, NULL, false, false);
 }
 void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
                                          SourceRange) {
   llvm_unreachable("Can't mangle K&R function prototypes");
 }
 
-void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
-                                         const FunctionDecl *D,
-                                         bool IsStructor,
-                                         bool IsInstMethod) {
+void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
+                                                 const FunctionDecl *D,
+                                                 bool IsStructor,
+                                                 bool IsInstMethod) {
   // <function-type> ::= <this-cvr-qualifiers> <calling-convention>
   //                     <return-type> <argument-list> <throw-spec>
   const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
@@ -1151,21 +1181,7 @@
     }
     Out << '@';
   } else {
-    QualType Result = Proto->getResultType();
-    const Type* RT = Result.getTypePtr();
-    if (!RT->isAnyPointerType() && !RT->isReferenceType()) {
-      if (Result.hasQualifiers() || !RT->isBuiltinType())
-        Out << '?';
-      if (!RT->isBuiltinType() && !Result.hasQualifiers()) {
-        // Lack of qualifiers for user types is mangled as 'A'.
-        Out << 'A';
-      }
-    }
-
-    // FIXME: Get the source range for the result type. Or, better yet,
-    // implement the unimplemented stuff so we don't need accurate source
-    // location info anymore :).
-    mangleType(Result, SourceRange());
+    mangleType(Proto->getResultType(), SourceRange(), MQ_Result);
   }
 
   // <argument-list> ::= X # void
@@ -1360,33 +1376,36 @@
 // It's supposed to be the other way around, but for some strange reason, it
 // isn't. Today this behavior is retained for the sole purpose of backwards
 // compatibility.
-void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {
+void MicrosoftCXXNameMangler::mangleDecayedArrayType(const ArrayType *T,
+                                                     bool IsGlobal) {
   // This isn't a recursive mangling, so now we have to do it all in this
   // one call.
   if (IsGlobal) {
     manglePointerQualifiers(T->getElementType().getQualifiers());
   } else {
     Out << 'Q';
   }
-  mangleExtraDimensions(T->getElementType());
+  mangleType(T->getElementType(), SourceRange());
 }
 void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
                                          SourceRange) {
-  mangleType(cast<ArrayType>(T), false);
+  llvm_unreachable("Should have been special cased");
 }
 void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,
                                          SourceRange) {
-  mangleType(cast<ArrayType>(T), false);
+  llvm_unreachable("Should have been special cased");
 }
 void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
                                          SourceRange) {
-  mangleType(cast<ArrayType>(T), false);
+  llvm_unreachable("Should have been special cased");
 }
 void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
                                          SourceRange) {
-  mangleType(cast<ArrayType>(T), false);
+  llvm_unreachable("Should have been special cased");
 }
-void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
+void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T,
+                                              Qualifiers Quals) {
+  QualType ElementTy(T, 0);
   SmallVector<llvm::APInt, 3> Dimensions;
   for (;;) {
     if (const ConstantArrayType *CAT =
@@ -1412,20 +1431,20 @@
       Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)
         << DSAT->getBracketsRange();
       return;
-    } else if (ElementTy->isIncompleteArrayType()) continue;
-    else break;
-  }
-  mangleQualifiers(ElementTy.getQualifiers(), false);
-  // If there are any additional dimensions, mangle them now.
-  if (Dimensions.size() > 0) {
-    Out << 'Y';
-    // <dimension-count> ::= <number> # number of extra dimensions
-    mangleNumber(Dimensions.size());
-    for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) {
-      mangleNumber(Dimensions[Dim].getLimitedValue());
+    } else if (const IncompleteArrayType *IAT =
+          getASTContext().getAsIncompleteArrayType(ElementTy)) {
+      Dimensions.push_back(llvm::APInt(32, 0));
+      ElementTy = IAT->getElementType();
     }
+    else break;
   }
-  mangleType(ElementTy.getLocalUnqualifiedType(), SourceRange());
+  Out << 'Y';
+  // <dimension-count> ::= <number> # number of extra dimensions
+  mangleNumber(Dimensions.size());
+  for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim)
+    mangleNumber(Dimensions[Dim].getLimitedValue());
+  mangleType(getASTContext().getQualifiedType(ElementTy.getTypePtr(), Quals),
+             SourceRange(), MQ_Escape);
 }
 
 // <type>                   ::= <pointer-to-member-type>
@@ -1437,11 +1456,11 @@
   if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
     Out << '8';
     mangleName(T->getClass()->castAs<RecordType>()->getDecl());
-    mangleType(FPT, NULL, false, true);
+    mangleFunctionType(FPT, NULL, false, true);
   } else {
     mangleQualifiers(PointeeType.getQualifiers(), true);
     mangleName(T->getClass()->castAs<RecordType>()->getDecl());
-    mangleType(PointeeType.getLocalUnqualifiedType(), Range);
+    mangleType(PointeeType, Range, MQ_Drop);
   }
 }
 
@@ -1469,17 +1488,7 @@
 void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
                                          SourceRange Range) {
   QualType PointeeTy = T->getPointeeType();
-  if (PointeeTy->isArrayType()) {
-    // Pointers to arrays are mangled like arrays.
-    mangleExtraDimensions(PointeeTy);
-  } else if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
-    // Function pointers are special.
-    Out << '6';
-    mangleType(FT, NULL, false, false);
-  } else {
-    mangleQualifiers(PointeeTy.getQualifiers(), false);
-    mangleType(PointeeTy, Range, false);
-  }
+  mangleType(PointeeTy, Range);
 }
 void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
                                          SourceRange Range) {
@@ -1493,23 +1502,15 @@
 void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
                                          SourceRange Range) {
   Out << 'A';
-  QualType PointeeTy = T->getPointeeType();
-  if (!PointeeTy.hasQualifiers())
-    // Lack of qualifiers is mangled as 'A'.
-    Out << 'A';
-  mangleType(PointeeTy, Range);
+  mangleType(T->getPointeeType(), Range);
 }
 
 // <type> ::= <r-value-reference-type>
 // <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>
 void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
                                          SourceRange Range) {
   Out << "$$Q";
-  QualType PointeeTy = T->getPointeeType();
-  if (!PointeeTy.hasQualifiers())
-    // Lack of qualifiers is mangled as 'A'.
-    Out << 'A';
-  mangleType(PointeeTy, Range);
+  mangleType(T->getPointeeType(), Range);
 }
 
 void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
@@ -1591,7 +1592,7 @@
   Out << "_E";
 
   QualType pointee = T->getPointeeType();
-  mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false);
+  mangleFunctionType(pointee->castAs<FunctionProtoType>(), NULL, false, false);
 }
 
 void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T,
@@ -1751,20 +1752,17 @@
   llvm_unreachable("The MS C++ ABI does not have constructor vtables!");
 }
 void MicrosoftMangleContext::mangleCXXRTTI(QualType T,
-                                           raw_ostream &) {
-  // FIXME: Give a location...
-  unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
-    "cannot mangle RTTI descriptors for type %0 yet");
-  getDiags().Report(DiagID)
-    << T.getBaseTypeIdentifier();
+                                           raw_ostream &Out) {
+  MicrosoftCXXNameMangler Mangler(*this, Out);
+  Mangler.getStream() << "\01??_R0";
+  Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::MQ_Result);
+  Mangler.getStream() << "@8";
 }
 void MicrosoftMangleContext::mangleCXXRTTIName(QualType T,
-                                               raw_ostream &) {
-  // FIXME: Give a location...
-  unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
-    "cannot mangle the name of type %0 into RTTI descriptors yet");
-  getDiags().Report(DiagID)
-    << T.getBaseTypeIdentifier();
+                                               raw_ostream &Out) {
+  MicrosoftCXXNameMangler Mangler(*this, Out);
+  Mangler.getStream() << ".";
+  Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::MQ_Result);
 }
 void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
                                            CXXCtorType Type,
Index: test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -60,6 +60,51 @@
 void foo_pcrcd(volatile char * volatile* x) {}
 // CHECK: "\01?foo_pcrcd@@YAXPCRCD@Z"
 
+void foo_aad(char &x) {}
+// CHECK: "\01?foo_aad@@YAXAAD@Z"
+
+void foo_abd(const char &x) {}
+// CHECK: "\01?foo_abd@@YAXABD@Z"
+
+void foo_aapad(char *&x) {}
+// CHECK: "\01?foo_aapad@@YAXAAPAD@Z"
+
+void foo_aapbd(const char *&x) {}
+// CHECK: "\01?foo_aapbd@@YAXAAPBD@Z"
+
+void foo_abqad(char * const &x) {}
+// CHECK: "\01?foo_abqad@@YAXABQAD@Z"
+
+void foo_abqbd(const char * const &x) {}
+// CHECK: "\01?foo_abqbd@@YAXABQBD@Z"
+
+void foo_aay144h(int (&x)[5][5]) {}
+// CHECK: "\01?foo_aay144h@@YAXAAY144H@Z"
+
+void foo_aay144cbh(const int (&x)[5][5]) {}
+// CHECK: "\01?foo_aay144cbh@@YAXAAY144$$CBH@Z"
+
+void foo_qay144h(int (&&x)[5][5]) {}
+// CHECK: "\01?foo_qay144h@@YAX$$QAY144H@Z"
+
+void foo_qay144cbh(const int (&&x)[5][5]) {}
+// CHECK: "\01?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
+
+void foo_p6ahxz(int x()) {}
+// CHECK: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
+
+void foo_a6ahxz(int (&x)()) {}
+// CHECK: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
+
+void foo_q6ahxz(int (&&x)()) {}
+// CHECK: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+
+void foo_qay04h(int x[5][5]) {}
+// CHECK: "\01?foo_qay04h@@YAXQAY04H@Z"
+
+void foo_qay04cbh(const int x[5][5]) {}
+// CHECK: "\01?foo_qay04cbh@@YAXQAY04$$CBH@Z"
+
 typedef double Vector[3];
 
 void foo(Vector*) {}
Index: test/CodeGenCXX/mangle-ms-templates.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms-templates.cpp
+++ test/CodeGenCXX/mangle-ms-templates.cpp
@@ -3,7 +3,7 @@
 template<typename T>
 class Class {
  public:
-  void method() {}
+  Class() {}
 };
 
 class Typename { };
@@ -32,24 +32,30 @@
 
 void template_mangling() {
   Class<Typename> c1;
-  c1.method();
-// CHECK: call {{.*}} @"\01?method@?$Class@VTypename@@@@QAEXXZ"
+// CHECK: call {{.*}} @"\01??0?$Class@VTypename@@@@QAE@XZ"
 
   Class<const Typename> c1_const;
+// CHECK: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QAE@XZ"
   Class<volatile Typename> c1_volatile;
+// CHECK: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QAE@XZ"
   Class<const volatile Typename> c1_cv;
-  c1_const.method();
-  c1_volatile.method();
-  c1_cv.method();
-// Types with qualifiers have an extra $$C escape when used as template
-// arguments.  Not sure why.
-// CHECK: call {{.*}} @"\01?method@?$Class@$$CBVTypename@@@@QAEXXZ"
-// CHECK: call {{.*}} @"\01?method@?$Class@$$CCVTypename@@@@QAEXXZ"
-// CHECK: call {{.*}} @"\01?method@?$Class@$$CDVTypename@@@@QAEXXZ"
+// CHECK: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QAE@XZ"
 
   Class<Nested<Typename> > c2;
-  c2.method();
-// CHECK: call {{.*}} @"\01?method@?$Class@V?$Nested@VTypename@@@@@@QAEXXZ"
+// CHECK: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
+
+  Class<int * const> c_intpc;
+// CHECK: call {{.*}} @"\01??0?$Class@QAH@@QAE@XZ"
+  Class<int()> c_ft;
+// CHECK: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QAE@XZ"
+  Class<int[]> c_inti;
+// CHECK: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QAE@XZ"
+  Class<int[5]> c_int5;
+// CHECK: call {{.*}} @"\01??0?$Class@$$BY04H@@QAE@XZ"
+  Class<const int[5]> c_intc5;
+// CHECK: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QAE@XZ"
+  Class<int * const[5]> c_intpc5;
+// CHECK: call {{.*}} @"\01??0?$Class@$$BY04QAH@@QAE@XZ"
 
   BoolTemplate<false> _false;
 // CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
Index: test/CodeGenCXX/mangle-ms.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms.cpp
+++ test/CodeGenCXX/mangle-ms.cpp
@@ -17,11 +17,8 @@
 // CHECK: @"\01?l@@3P8foo@@AEHH@ZA"
 // CHECK: @"\01?color1@@3PANA"
 // CHECK: @"\01?color2@@3QBNB"
-
-// FIXME: The following three tests currently fail, see http://llvm.org/PR13182
-// Replace "CHECK-NOT" with "CHECK" when it is fixed.
-// CHECK-NOT: @"\01?color3@@3QAY02$$CBNA"
-// CHECK-NOT: @"\01?color4@@3QAY02$$CBNA"
+// CHECK: @"\01?color3@@3QAY02$$CBNA"
+// CHECK: @"\01?color4@@3QAY02$$CBNA"
 
 int a;
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to