[ms-cxxabi] Mangle in an implicit 'E' for certain types on win64

Most of the complexity of this patch is figuring out which types get the
qualifier and which don't.  If we implement __ptr32/64, then we should
check the qualifier instead of assuming all pointers are 64-bit.

This fixes PR13792.

Patch by Warren Hunt!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181825 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index d242cd9..dbd37f0 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/Basic/ABI.h"
 #include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/TargetInfo.h"
 #include <map>
 
 using namespace clang;
@@ -58,18 +59,26 @@
 
   ASTContext &getASTContext() const { return Context.getASTContext(); }
 
+  // FIXME: If we add support for __ptr32/64 qualifiers, then we should push
+  // this check into mangleQualifiers().
+  const bool PointersAre64Bit;
+
 public:
   enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
 
   MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
     : Context(C), Out(Out_),
       Structor(0), StructorType(-1),
+      PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+                       64),
       UseNameBackReferences(true) { }
 
   MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_,
                           const CXXDestructorDecl *D, CXXDtorType Type)
     : Context(C), Out(Out_),
       Structor(getStructor(D)), StructorType(Type),
+      PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
+                       64),
       UseNameBackReferences(true) { }
 
   raw_ostream &getStream() const { return Out; }
@@ -1228,32 +1237,36 @@
 }
 
 void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
-  // <function-class> ::= A # private: near
-  //                  ::= B # private: far
-  //                  ::= C # private: static near
-  //                  ::= D # private: static far
-  //                  ::= E # private: virtual near
-  //                  ::= F # private: virtual far
-  //                  ::= G # private: thunk near
-  //                  ::= H # private: thunk far
-  //                  ::= I # protected: near
-  //                  ::= J # protected: far
-  //                  ::= K # protected: static near
-  //                  ::= L # protected: static far
-  //                  ::= M # protected: virtual near
-  //                  ::= N # protected: virtual far
-  //                  ::= O # protected: thunk near
-  //                  ::= P # protected: thunk far
-  //                  ::= Q # public: near
-  //                  ::= R # public: far
-  //                  ::= S # public: static near
-  //                  ::= T # public: static far
-  //                  ::= U # public: virtual near
-  //                  ::= V # public: virtual far
-  //                  ::= W # public: thunk near
-  //                  ::= X # public: thunk far
-  //                  ::= Y # global near
-  //                  ::= Z # global far
+  // <function-class>  ::= <member-function> E? # E designates a 64-bit 'this'
+  //                                            # pointer. in 64-bit mode *all*
+  //                                            # 'this' pointers are 64-bit.
+  //                   ::= <global-function>
+  // <member-function> ::= A # private: near
+  //                   ::= B # private: far
+  //                   ::= C # private: static near
+  //                   ::= D # private: static far
+  //                   ::= E # private: virtual near
+  //                   ::= F # private: virtual far
+  //                   ::= G # private: thunk near
+  //                   ::= H # private: thunk far
+  //                   ::= I # protected: near
+  //                   ::= J # protected: far
+  //                   ::= K # protected: static near
+  //                   ::= L # protected: static far
+  //                   ::= M # protected: virtual near
+  //                   ::= N # protected: virtual far
+  //                   ::= O # protected: thunk near
+  //                   ::= P # protected: thunk far
+  //                   ::= Q # public: near
+  //                   ::= R # public: far
+  //                   ::= S # public: static near
+  //                   ::= T # public: static far
+  //                   ::= U # public: virtual near
+  //                   ::= V # public: virtual far
+  //                   ::= W # public: thunk near
+  //                   ::= X # public: thunk far
+  // <global-function> ::= Y # global near
+  //                   ::= Z # global far
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
     switch (MD->getAccess()) {
       default:
@@ -1281,6 +1294,8 @@
         else
           Out << 'Q';
     }
+    if (PointersAre64Bit && !MD->isStatic())
+      Out << 'E';
   } else
     Out << 'Y';
 }
@@ -1380,9 +1395,9 @@
 // <type>       ::= <array-type>
 // <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
 //                  [Y <dimension-count> <dimension>+]
-//                  <element-type> # as global
-//              ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
-//                  <element-type> # as param
+//                  <element-type> # as global, E is never required
+//              ::= Q E? <cvr-qualifiers> [Y <dimension-count> <dimension>+]
+//                  <element-type> # as param, E is required for 64-bit
 // 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.
@@ -1394,6 +1409,8 @@
     manglePointerQualifiers(T->getElementType().getQualifiers());
   } else {
     Out << 'Q';
+    if (PointersAre64Bit)
+      Out << 'E';
   }
   mangleType(T->getElementType(), SourceRange());
 }
@@ -1494,10 +1511,13 @@
 }
 
 // <type> ::= <pointer-type>
-// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+// <pointer-type> ::= E? <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+//                       # the E is required for 64-bit non static pointers
 void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
                                          SourceRange Range) {
   QualType PointeeTy = T->getPointeeType();
+  if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
+    Out << 'E';
   mangleType(PointeeTy, Range);
 }
 void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
@@ -1508,18 +1528,24 @@
 }
 
 // <type> ::= <reference-type>
-// <reference-type> ::= A <cvr-qualifiers> <type>
+// <reference-type> ::= A E? <cvr-qualifiers> <type>
+//                 # the E is required for 64-bit non static lvalue references
 void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
                                          SourceRange Range) {
   Out << 'A';
+  if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
+    Out << 'E';
   mangleType(T->getPointeeType(), Range);
 }
 
 // <type> ::= <r-value-reference-type>
-// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>
+// <r-value-reference-type> ::= $$Q E? <cvr-qualifiers> <type>
+//                 # the E is required for 64-bit non static rvalue references
 void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
                                          SourceRange Range) {
   Out << "$$Q";
+  if (PointersAre64Bit && !T->getPointeeType()->isFunctionType())
+    Out << 'E';
   mangleType(T->getPointeeType(), Range);
 }
 
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index f27b502..eb39d08 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -211,7 +211,7 @@
   if (!RD->isEmpty())
     return;
 
-  // If we have empty structures inside an union, we can assign both
+  // If we have empty structures inside a union, we can assign both
   // the same offset. Just avoid pushing them twice in the list.
   ClassVectorTy& Classes = EmptyClassOffsets[Offset];
   if (std::find(Classes.begin(), Classes.end(), RD) != Classes.end())
diff --git a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
index d03ba52..ed7027d 100644
--- a/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
+++ b/test/CodeGenCXX/mangle-ms-arg-qualifiers.cpp
@@ -1,123 +1,164 @@
 // RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix=X64 %s
 
 void foo(const unsigned int) {}
 // CHECK: "\01?foo@@YAXI@Z"
+// X64: "\01?foo@@YAXI@Z"
 
 void foo(const double) {}
 // CHECK: "\01?foo@@YAXN@Z"
+// X64: "\01?foo@@YAXN@Z"
 
 void bar(const volatile double) {}
 // CHECK: "\01?bar@@YAXN@Z"
+// X64: "\01?bar@@YAXN@Z"
 
 void foo_pad(char * x) {}
 // CHECK: "\01?foo_pad@@YAXPAD@Z"
+// X64: "\01?foo_pad@@YAXPEAD@Z"
 
 void foo_pbd(const char * x) {}
 // CHECK: "\01?foo_pbd@@YAXPBD@Z"
+// X64: "\01?foo_pbd@@YAXPEBD@Z"
 
 void foo_pcd(volatile char * x) {}
 // CHECK: "\01?foo_pcd@@YAXPCD@Z"
+// X64: "\01?foo_pcd@@YAXPECD@Z"
 
 void foo_qad(char * const x) {}
 // CHECK: "\01?foo_qad@@YAXQAD@Z"
+// X64: "\01?foo_qad@@YAXQEAD@Z"
 
 void foo_rad(char * volatile x) {}
 // CHECK: "\01?foo_rad@@YAXRAD@Z"
+// X64: "\01?foo_rad@@YAXREAD@Z"
 
 void foo_sad(char * const volatile x) {}
 // CHECK: "\01?foo_sad@@YAXSAD@Z"
+// X64: "\01?foo_sad@@YAXSEAD@Z"
 
 void foo_papad(char ** x) {}
 // CHECK: "\01?foo_papad@@YAXPAPAD@Z"
+// X64: "\01?foo_papad@@YAXPEAPEAD@Z"
 
 void foo_papbd(char const ** x) {}
 // CHECK: "\01?foo_papbd@@YAXPAPBD@Z"
+// X64: "\01?foo_papbd@@YAXPEAPEBD@Z"
 
 void foo_papcd(char volatile ** x) {}
 // CHECK: "\01?foo_papcd@@YAXPAPCD@Z"
+// X64: "\01?foo_papcd@@YAXPEAPECD@Z"
 
 void foo_pbqad(char * const* x) {}
 // CHECK: "\01?foo_pbqad@@YAXPBQAD@Z"
+// X64: "\01?foo_pbqad@@YAXPEBQEAD@Z"
 
 void foo_pcrad(char * volatile* x) {}
 // CHECK: "\01?foo_pcrad@@YAXPCRAD@Z"
+// X64: "\01?foo_pcrad@@YAXPECREAD@Z"
 
 void foo_qapad(char ** const x) {}
 // CHECK: "\01?foo_qapad@@YAXQAPAD@Z"
+// X64: "\01?foo_qapad@@YAXQEAPEAD@Z"
 
 void foo_rapad(char ** volatile x) {}
 // CHECK: "\01?foo_rapad@@YAXRAPAD@Z"
+// X64: "\01?foo_rapad@@YAXREAPEAD@Z"
 
 void foo_pbqbd(const char * const* x) {}
 // CHECK: "\01?foo_pbqbd@@YAXPBQBD@Z"
+// X64: "\01?foo_pbqbd@@YAXPEBQEBD@Z"
 
 void foo_pbqcd(volatile char * const* x) {}
 // CHECK: "\01?foo_pbqcd@@YAXPBQCD@Z"
+// X64: "\01?foo_pbqcd@@YAXPEBQECD@Z"
 
 void foo_pcrbd(const char * volatile* x) {}
 // CHECK: "\01?foo_pcrbd@@YAXPCRBD@Z"
+// X64: "\01?foo_pcrbd@@YAXPECREBD@Z"
 
 void foo_pcrcd(volatile char * volatile* x) {}
 // CHECK: "\01?foo_pcrcd@@YAXPCRCD@Z"
+// X64: "\01?foo_pcrcd@@YAXPECRECD@Z"
 
 void foo_aad(char &x) {}
 // CHECK: "\01?foo_aad@@YAXAAD@Z"
+// X64: "\01?foo_aad@@YAXAEAD@Z"
 
 void foo_abd(const char &x) {}
 // CHECK: "\01?foo_abd@@YAXABD@Z"
+// X64: "\01?foo_abd@@YAXAEBD@Z"
 
 void foo_aapad(char *&x) {}
 // CHECK: "\01?foo_aapad@@YAXAAPAD@Z"
+// X64: "\01?foo_aapad@@YAXAEAPEAD@Z"
 
 void foo_aapbd(const char *&x) {}
 // CHECK: "\01?foo_aapbd@@YAXAAPBD@Z"
+// X64: "\01?foo_aapbd@@YAXAEAPEBD@Z"
 
 void foo_abqad(char * const &x) {}
 // CHECK: "\01?foo_abqad@@YAXABQAD@Z"
+// X64: "\01?foo_abqad@@YAXAEBQEAD@Z"
 
 void foo_abqbd(const char * const &x) {}
 // CHECK: "\01?foo_abqbd@@YAXABQBD@Z"
+// X64: "\01?foo_abqbd@@YAXAEBQEBD@Z"
 
 void foo_aay144h(int (&x)[5][5]) {}
 // CHECK: "\01?foo_aay144h@@YAXAAY144H@Z"
+// X64: "\01?foo_aay144h@@YAXAEAY144H@Z"
 
 void foo_aay144cbh(const int (&x)[5][5]) {}
 // CHECK: "\01?foo_aay144cbh@@YAXAAY144$$CBH@Z"
+// X64: "\01?foo_aay144cbh@@YAXAEAY144$$CBH@Z"
 
 void foo_qay144h(int (&&x)[5][5]) {}
 // CHECK: "\01?foo_qay144h@@YAX$$QAY144H@Z"
+// X64: "\01?foo_qay144h@@YAX$$QEAY144H@Z"
 
 void foo_qay144cbh(const int (&&x)[5][5]) {}
 // CHECK: "\01?foo_qay144cbh@@YAX$$QAY144$$CBH@Z"
+// X64: "\01?foo_qay144cbh@@YAX$$QEAY144$$CBH@Z"
 
 void foo_p6ahxz(int x()) {}
 // CHECK: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
+// X64: "\01?foo_p6ahxz@@YAXP6AHXZ@Z"
 
 void foo_a6ahxz(int (&x)()) {}
 // CHECK: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
+// X64: "\01?foo_a6ahxz@@YAXA6AHXZ@Z"
 
 void foo_q6ahxz(int (&&x)()) {}
 // CHECK: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
+// X64: "\01?foo_q6ahxz@@YAX$$Q6AHXZ@Z"
 
 void foo_qay04h(int x[5][5]) {}
 // CHECK: "\01?foo_qay04h@@YAXQAY04H@Z"
+// X64: "\01?foo_qay04h@@YAXQEAY04H@Z"
 
 void foo_qay04cbh(const int x[5][5]) {}
 // CHECK: "\01?foo_qay04cbh@@YAXQAY04$$CBH@Z"
+// X64: "\01?foo_qay04cbh@@YAXQEAY04$$CBH@Z"
 
 typedef double Vector[3];
 
 void foo(Vector*) {}
 // CHECK: "\01?foo@@YAXPAY02N@Z"
+// X64: "\01?foo@@YAXPEAY02N@Z"
 
 void foo(Vector) {}
 // CHECK: "\01?foo@@YAXQAN@Z"
+// X64: "\01?foo@@YAXQEAN@Z"
 
 void foo_const(const Vector) {}
 // CHECK: "\01?foo_const@@YAXQBN@Z"
+// X64: "\01?foo_const@@YAXQEBN@Z"
 
 void foo_volatile(volatile Vector) {}
 // CHECK: "\01?foo_volatile@@YAXQCN@Z"
+// X64: "\01?foo_volatile@@YAXQECN@Z"
 
 void foo(Vector*, const Vector, const double) {}
 // CHECK: "\01?foo@@YAXPAY02NQBNN@Z"
+// X64: "\01?foo@@YAXPEAY02NQEBNN@Z"
diff --git a/test/CodeGenCXX/mangle-ms-templates.cpp b/test/CodeGenCXX/mangle-ms-templates.cpp
index 10e6824..c52b6b4 100644
--- a/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
 
 template<typename T>
 class Class {
@@ -33,65 +34,87 @@
 void template_mangling() {
   Class<Typename> c1;
 // CHECK: call {{.*}} @"\01??0?$Class@VTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@VTypename@@@@QEAA@XZ"
 
   Class<const Typename> c1_const;
 // CHECK: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CBVTypename@@@@QEAA@XZ"
   Class<volatile Typename> c1_volatile;
 // CHECK: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CCVTypename@@@@QEAA@XZ"
   Class<const volatile Typename> c1_cv;
 // CHECK: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$CDVTypename@@@@QEAA@XZ"
 
   Class<Nested<Typename> > c2;
 // CHECK: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ"
 
   Class<int * const> c_intpc;
 // CHECK: call {{.*}} @"\01??0?$Class@QAH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@QEAH@@QEAA@XZ"
   Class<int()> c_ft;
 // CHECK: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$A6AHXZ@@QEAA@XZ"
   Class<int[]> c_inti;
 // CHECK: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY0A@H@@QEAA@XZ"
   Class<int[5]> c_int5;
 // CHECK: call {{.*}} @"\01??0?$Class@$$BY04H@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04H@@QEAA@XZ"
   Class<const int[5]> c_intc5;
 // CHECK: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04$$CBH@@QEAA@XZ"
   Class<int * const[5]> c_intpc5;
 // CHECK: call {{.*}} @"\01??0?$Class@$$BY04QAH@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$Class@$$BY04QEAH@@QEAA@XZ"
 
   BoolTemplate<false> _false;
 // CHECK: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$BoolTemplate@$0A@@@QEAA@XZ"
 
   BoolTemplate<true> _true;
   // PR13158
   _true.Foo(1);
 // CHECK: call {{.*}} @"\01??0?$BoolTemplate@$00@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$BoolTemplate@$00@@QEAA@XZ"
 // CHECK: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z"
+// X64: call {{.*}} @"\01??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z"
 
   IntTemplate<0> zero;
 // CHECK: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0A@@@QEAA@XZ"
 
   IntTemplate<5> five;
 // CHECK: call {{.*}} @"\01??0?$IntTemplate@$04@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$04@@QEAA@XZ"
 
   IntTemplate<11> eleven;
 // CHECK: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0L@@@QEAA@XZ"
 
   IntTemplate<256> _256;
 // CHECK: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0BAA@@@QEAA@XZ"
 
   IntTemplate<513> _513;
 // CHECK: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0CAB@@@QEAA@XZ"
 
   IntTemplate<1026> _1026;
 // CHECK: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0EAC@@@QEAA@XZ"
 
   IntTemplate<65535> ffff;
 // CHECK: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QAE@XZ"
+// X64: call {{.*}} @"\01??0?$IntTemplate@$0PPPP@@@QEAA@XZ"
 }
 
 namespace space {
   template<class T> const T& foo(const T& l) { return l; }
 }
 // CHECK: "\01??$foo@H@space@@YAABHABH@Z"
+// X64: "\01??$foo@H@space@@YAAEBHAEBH@Z"
 
 void use() {
   space::foo(42);
@@ -108,4 +131,5 @@
 void spam() {
   FunctionPointerTemplate<spam>();
 // CHECK: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
+// X64: "\01??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ"
 }
diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp
index 1b98a84..3f80e54 100644
--- a/test/CodeGenCXX/mangle-ms.cpp
+++ b/test/CodeGenCXX/mangle-ms.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
-// RUN: %clang_cc1 -fms-compatibility -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
 
 // CHECK: @"\01?a@@3HA"
 // CHECK: @"\01?b@N@@3HA"
@@ -33,6 +33,7 @@
 static int c;
 int _c(void) {return N::anonymous + c;}
 // CHECK: @"\01?_c@@YAHXZ"
+// X64: @"\01?_c@@YAHXZ"
 
 class foo {
   static const short d;
@@ -43,15 +44,19 @@
   int operator+(int a);
   foo(){}
 //CHECK: @"\01??0foo@@QAE@XZ"
+//X64: @"\01??0foo@@QEAA@XZ"
 
   ~foo(){}
 //CHECK: @"\01??1foo@@QAE@XZ"
+//X64: @"\01??1foo@@QEAA@XZ
 
   foo(int i){}
 //CHECK: @"\01??0foo@@QAE@H@Z"
+//X64: @"\01??0foo@@QEAA@H@Z"
 
   foo(char *q){}
 //CHECK: @"\01??0foo@@QAE@PAD@Z"
+//X64: @"\01??0foo@@QEAA@PEAD@Z"
 
   static foo* static_method() { return 0; }
 
@@ -77,12 +82,15 @@
 
 foo bar() { return foo(); }
 //CHECK: @"\01?bar@@YA?AVfoo@@XZ"
+//X64: @"\01?bar@@YA?AVfoo@@XZ"
 
 int foo::operator+(int a) {
 //CHECK: @"\01??Hfoo@@QAEHH@Z"
+//X64: @"\01??Hfoo@@QEAAHH@Z"
 
   foo::static_method();
 //CHECK: @"\01?static_method@foo@@SAPAV1@XZ"
+//X64: @"\01?static_method@foo@@SAPEAV1@XZ"
   bar();
   return a;
 }
@@ -109,6 +117,7 @@
 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@Z"
+// X64: @"\01?beta@@YA_N_J_W@Z"
   alpha(0.f, 0.0);
   return false;
 }
@@ -119,17 +128,21 @@
 // Make sure tag-type mangling works.
 void gamma(class foo, struct bar, union baz, enum quux) {}
 // CHECK: @"\01?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
+// X64: @"\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@Z"
+// X64: @"\01?delta@@YAXQEAHAEBJ@Z"
 
 // Array mangling.
 void epsilon(int a[][10][20]) {}
 // CHECK: @"\01?epsilon@@YAXQAY19BE@H@Z"
+// X64: @"\01?epsilon@@YAXQEAY19BE@H@Z"
 
 void zeta(int (*)(int, int)) {}
 // CHECK: @"\01?zeta@@YAXP6AHHH@Z@Z"
+// X64: @"\01?zeta@@YAXP6AHHH@Z@Z"
 
 // Blocks mangling (Clang extension). A block should be mangled slightly
 // differently from a similar function pointer.
@@ -158,6 +171,7 @@
 void (redundant_parens)();
 void redundant_parens_use() { redundant_parens(); }
 // CHECK: @"\01?redundant_parens@@YAXXZ"
+// X64: @"\01?redundant_parens@@YAXXZ"
 
 // PR13047
 typedef double RGB[3];
@@ -169,10 +183,12 @@
 // PR12603
 enum E {};
 // CHECK: "\01?fooE@@YA?AW4E@@XZ"
+// X64: "\01?fooE@@YA?AW4E@@XZ"
 E fooE() { return E(); }
 
 class X {};
 // CHECK: "\01?fooX@@YA?AVX@@XZ"
+// X64: "\01?fooX@@YA?AVX@@XZ"
 X fooX() { return X(); }
 
 namespace PR13182 {