diff --git lib/CodeGen/CGCXXABI.h lib/CodeGen/CGCXXABI.h
index 702e59b..f01a252 100644
--- lib/CodeGen/CGCXXABI.h
+++ lib/CodeGen/CGCXXABI.h
@@ -101,6 +101,27 @@ public:
   /// kinds that the ABI says returns 'this'.
   virtual bool HasThisReturn(GlobalDecl GD) const { return false; }
 
+  /// Returns true if the given record type should be returned indirectly.
+  virtual bool isReturnTypeIndirect(const CXXRecordDecl *RD) const = 0;
+
+  /// Specify how one should pass an argument of a record type.
+  enum RecordArgABI {
+    /// Pass it using the normal C aggregate rules for the ABI, potentially
+    /// introducing extra copies and passing some or all of it in registers.
+    RAA_Default = 0,
+
+    /// Pass it on the stack using its defined layout.  The argument must be
+    /// evaluated directly into the correct stack position in the arguments area,
+    /// and the call machinery must not move it or introduce extra copies.
+    RAA_DirectInMemory,
+
+    /// Pass it as a pointer to temporary memory.
+    RAA_Indirect
+  };
+
+  /// Returns how an argument of the given record type should be passed.
+  virtual RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const = 0;
+
   /// Find the LLVM type used to represent the given member pointer
   /// type.
   virtual llvm::Type *
diff --git lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/ItaniumCXXABI.cpp
index e25d422..ef415e2 100644
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -41,6 +41,20 @@ public:
   ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) :
     CGCXXABI(CGM), IsARM(IsARM) { }
 
+  bool isReturnTypeIndirect(const CXXRecordDecl *RD) const {
+    // Structures with either a non-trivial destructor or a non-trivial
+    // copy constructor are always indirect.
+    return !RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor();
+  }
+
+  RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const {
+    // Structures with either a non-trivial destructor or a non-trivial
+    // copy constructor are always indirect.
+    if (!RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor())
+      return RAA_Indirect;
+    return RAA_Default;
+  }
+
   bool isZeroInitializable(const MemberPointerType *MPT);
 
   llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
diff --git lib/CodeGen/MicrosoftCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp
index 2c7f89a..edf1382 100644
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -28,6 +28,14 @@ class MicrosoftCXXABI : public CGCXXABI {
 public:
   MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
 
+  bool isReturnTypeIndirect(const CXXRecordDecl *RD) const {
+    return !RD->isPOD();
+  }
+
+  RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const {
+    return RAA_DirectInMemory;
+  }
+
   StringRef GetPureVirtualCallName() { return "_purecall"; }
   // No known support for deleted functions in MSVC yet, so this choice is
   // arbitrary.
diff --git lib/CodeGen/TargetInfo.cpp lib/CodeGen/TargetInfo.cpp
index d0b4918..4ae9b91 100644
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -14,6 +14,7 @@
 
 #include "TargetInfo.h"
 #include "ABIInfo.h"
+#include "CGCXXABI.h"
 #include "CodeGenFunction.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Frontend/CodeGenOptions.h"
@@ -43,6 +44,27 @@ static bool isAggregateTypeForABI(QualType T) {
 
 ABIInfo::~ABIInfo() {}
 
+static bool isRecordReturnIndirect(QualType T, CodeGen::CodeGenTypes &CGT) {
+  const RecordType *RT = T->getAs<RecordType>();
+  if (!RT)
+    return false;
+  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+  if (!RD)
+    return false;
+  return CGT.CGM.getCXXABI().isReturnTypeIndirect(RD);
+}
+
+static CGCXXABI::RecordArgABI getRecordArgABI(QualType T,
+                                              CodeGen::CodeGenTypes &CGT) {
+  const RecordType *RT = T->getAs<RecordType>();
+  if (!RT)
+    return CGCXXABI::RAA_Default;
+  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+  if (!RD)
+    return CGCXXABI::RAA_Default;
+  return CGT.CGM.getCXXABI().getRecordArgABI(RD);
+}
+
 ASTContext &ABIInfo::getContext() const {
   return CGT.getContext();
 }
@@ -167,27 +189,6 @@ static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
   return true;
 }
 
-/// hasNonTrivialDestructorOrCopyConstructor - Determine if a type has either
-/// a non-trivial destructor or a non-trivial copy constructor.
-static bool hasNonTrivialDestructorOrCopyConstructor(const RecordType *RT) {
-  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
-  if (!RD)
-    return false;
-
-  return !RD->hasTrivialDestructor() || RD->hasNonTrivialCopyConstructor();
-}
-
-/// isRecordWithNonTrivialDestructorOrCopyConstructor - Determine if a type is
-/// a record type with either a non-trivial destructor or a non-trivial copy
-/// constructor.
-static bool isRecordWithNonTrivialDestructorOrCopyConstructor(QualType T) {
-  const RecordType *RT = T->getAs<RecordType>();
-  if (!RT)
-    return false;
-
-  return hasNonTrivialDestructorOrCopyConstructor(RT);
-}
-
 /// isSingleElementStruct - Determine if a structure is a "single
 /// element struct", i.e. it has exactly one non-empty field or
 /// exactly one field which is itself a single element
@@ -367,7 +368,7 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
   if (isAggregateTypeForABI(Ty)) {
     // Records with non trivial destructors/constructors should not be passed
     // by value.
-    if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
+    if (isRecordReturnIndirect(Ty, CGT))
       return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
 
     return ABIArgInfo::getIndirect(0);
@@ -437,11 +438,8 @@ llvm::Value *PNaClABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
 /// \brief Classify argument of given type \p Ty.
 ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const {
   if (isAggregateTypeForABI(Ty)) {
-    // In the PNaCl ABI we always pass records/structures on the stack. The
-    // byval attribute can be used if the record doesn't have non-trivial
-    // constructors/destructors.
-    if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
-      return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+    if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+      return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
     return ABIArgInfo::getIndirect(0);
   } else if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
     // Treat an enum type as its underlying type.
@@ -664,9 +662,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
 
   if (isAggregateTypeForABI(RetTy)) {
     if (const RecordType *RT = RetTy->getAs<RecordType>()) {
-      // Structures with either a non-trivial destructor or a non-trivial
-      // copy constructor are always indirect.
-      if (hasNonTrivialDestructorOrCopyConstructor(RT))
+      if (isRecordReturnIndirect(RetTy, CGT))
         return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
 
       // Structures with flexible arrays are always indirect.
@@ -847,13 +843,11 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
                                                bool IsFastCall) const {
   // FIXME: Set alignment on indirect arguments.
   if (isAggregateTypeForABI(Ty)) {
-    // Structures with flexible arrays are always indirect.
     if (const RecordType *RT = Ty->getAs<RecordType>()) {
-      // Structures with either a non-trivial destructor or a non-trivial
-      // copy constructor are always indirect.
-      if (hasNonTrivialDestructorOrCopyConstructor(RT))
-        return getIndirectResult(Ty, false, FreeRegs);
+      if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+        return getIndirectResult(Ty, RAA == CGCXXABI::RAA_DirectInMemory, FreeRegs);
 
+      // Structures with flexible arrays are always indirect.
       if (RT->getDecl()->hasFlexibleArrayMember())
         return getIndirectResult(Ty, true, FreeRegs);
     }
@@ -1528,7 +1522,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
     // AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial
     // copy constructor or a non-trivial destructor, it is passed by invisible
     // reference.
-    if (hasNonTrivialDestructorOrCopyConstructor(RT))
+    if (getRecordArgABI(Ty, CGT))
       return;
 
     const RecordDecl *RD = RT->getDecl();
@@ -1678,8 +1672,8 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty,
             ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
   }
 
-  if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
-    return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+    return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
 
   // Compute the byval alignment. We specify the alignment of the byval in all
   // cases so that the mid-level optimizer knows the alignment of the byval.
@@ -2167,7 +2161,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(
     // COMPLEX_X87, it is passed in memory.
   case X87:
   case ComplexX87:
-    if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
+    if (getRecordArgABI(Ty, CGT))
       ++neededInt;
     return getIndirectResult(Ty, freeIntRegs);
 
@@ -2509,8 +2503,10 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const {
   uint64_t Size = getContext().getTypeSize(Ty);
 
   if (const RecordType *RT = Ty->getAs<RecordType>()) {
-    if (hasNonTrivialDestructorOrCopyConstructor(RT) ||
-        RT->getDecl()->hasFlexibleArrayMember())
+    if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+      return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
+
+    if (RT->getDecl()->hasFlexibleArrayMember())
       return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
 
     // FIXME: mingw-w64-gcc emits 128-bit struct as i128
@@ -2770,10 +2766,8 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const {
     return ABIArgInfo::getDirect();
 
   if (isAggregateTypeForABI(Ty)) {
-    // Records with non trivial destructors/constructors should not be passed
-    // by value.
-    if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
-      return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+    if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+      return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
 
     return ABIArgInfo::getIndirect(0);
   }
@@ -3238,10 +3232,8 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, int *VFPRegs,
   if (isEmptyRecord(getContext(), Ty, true))
     return ABIArgInfo::getIgnore();
 
-  // Structures with either a non-trivial destructor or a non-trivial
-  // copy constructor are always indirect.
-  if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
-    return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+    return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
 
   if (getABIKind() == ARMABIInfo::AAPCS_VFP) {
     // Homogeneous Aggregates need to be expanded when we can fit the aggregate
@@ -3404,7 +3396,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
 
   // Structures with either a non-trivial destructor or a non-trivial
   // copy constructor are always indirect.
-  if (isRecordWithNonTrivialDestructorOrCopyConstructor(RetTy))
+  if (isRecordReturnIndirect(RetTy, CGT))
     return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
 
   // Are we following APCS?
@@ -3728,12 +3720,10 @@ ABIArgInfo AArch64ABIInfo::classifyGenericType(QualType Ty,
     return tryUseRegs(Ty, FreeIntRegs, RegsNeeded, /*IsInt=*/ true);
   }
 
-  // Structures with either a non-trivial destructor or a non-trivial
-  // copy constructor are always indirect.
-  if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) {
+  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT)) {
     if (FreeIntRegs > 0)
       --FreeIntRegs;
-    return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+    return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
   }
 
   if (isEmptyRecord(getContext(), Ty, true)) {
@@ -4418,11 +4408,9 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
     if (TySize == 0)
       return ABIArgInfo::getIgnore();
 
-    // Records with non trivial destructors/constructors should not be passed
-    // by value.
-    if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) {
+    if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT)) {
       Offset = OrigOffset + MinABIStackAlignInBytes;
-      return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+      return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
     }
 
     // If we have reached here, aggregates are passed directly by coercing to
@@ -4492,6 +4480,9 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
     return ABIArgInfo::getIgnore();
 
   if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) {
+    if (isRecordReturnIndirect(RetTy, CGT))
+      return ABIArgInfo::getIndirect(0);
+
     if (Size <= 128) {
       if (RetTy->isAnyComplexType())
         return ABIArgInfo::getDirect();
@@ -4500,7 +4491,7 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const {
       if (IsO32 && RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())
         return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
 
-      if (!IsO32 && !isRecordWithNonTrivialDestructorOrCopyConstructor(RetTy))
+      if (!IsO32)
         return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size));
     }
 
@@ -4710,10 +4701,8 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty) const {
   if (isEmptyRecord(getContext(), Ty, true))
     return ABIArgInfo::getIgnore();
 
-  // Structures with either a non-trivial destructor or a non-trivial
-  // copy constructor are always indirect.
-  if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
-    return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
+  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT))
+    return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
 
   uint64_t Size = getContext().getTypeSize(Ty);
   if (Size > 64)
@@ -4748,7 +4737,7 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const {
 
   // Structures with either a non-trivial destructor or a non-trivial
   // copy constructor are always indirect.
-  if (isRecordWithNonTrivialDestructorOrCopyConstructor(RetTy))
+  if (isRecordReturnIndirect(RetTy, CGT))
     return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
 
   if (isEmptyRecord(getContext(), RetTy, true))
diff --git test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
new file mode 100644
index 0000000..8c97e8b
--- /dev/null
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -0,0 +1,144 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -cxx-abi microsoft | FileCheck -check-prefix MSABI %s
+
+struct Empty {};
+
+struct EmptyWithCtor {
+  EmptyWithCtor() {}
+};
+
+struct Small {
+  int x;
+};
+
+struct SmallWithCtor {
+  SmallWithCtor() {}
+  int x;
+};
+
+struct SmallWithVftable {
+  int x;
+  virtual void foo();
+};
+
+struct Medium {
+  int x, y;
+};
+
+struct MediumWithSomeCtor {
+  MediumWithSomeCtor(const char *) {}
+  int x, y;
+};
+
+struct Big {
+  int a, b, c, d, e, f;
+};
+
+// Returning structs that fit into a register.
+Small small_return() { return Small(); }
+// LINUX: define void @_Z12small_returnv(%struct.Small* noalias sret %agg.result)
+// MSABI: define i32 @"\01?small_return@@YA?AUSmall@@XZ"()
+
+Medium medium_return() { return Medium(); }
+// LINUX: define void @_Z13medium_returnv(%struct.Medium* noalias sret %agg.result)
+// MSABI: define i64 @"\01?medium_return@@YA?AUMedium@@XZ"()
+
+// Returning structs that fit into a register but are not POD.
+SmallWithCtor small_with_ctor_return() { return SmallWithCtor(); }
+// LINUX: define void @_Z22small_with_ctor_returnv(%struct.SmallWithCtor* noalias sret %agg.result)
+// MSABI: define void @"\01?small_with_ctor_return@@YA?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result)
+
+SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
+// LINUX: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
+// MSABI: define void @"\01?small_with_vftable_return@@YA?AUSmallWithVftable@@XZ"(%struct.SmallWithVftable* noalias sret %agg.result)
+
+MediumWithSomeCtor medium_with_some_ctor_return() { return MediumWithSomeCtor(0); }
+// LINUX: define void @_Z28medium_with_some_ctor_returnv(%struct.MediumWithSomeCtor* noalias sret %agg.result)
+// MSABI: define void @"\01?medium_with_some_ctor_return@@YA?AUMediumWithSomeCtor@@XZ"(%struct.MediumWithSomeCtor* noalias sret %agg.result)
+
+// Returning a large struct that doesn't fit into a register.
+Big big_return() { return Big(); }
+// LINUX: define void @_Z10big_returnv(%struct.Big* noalias sret %agg.result)
+// MSABI: define void @"\01?big_return@@YA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result)
+
+
+void small_arg(Small s) {}
+// LINUX: define void @_Z9small_arg5Small(%struct.Small* byval align 4 %s)
+// MSABI: define void @"\01?small_arg@@YAXUSmall@@@Z"(%struct.Small* byval align 4 %s)
+
+void medium_arg(Medium s) {}
+// LINUX: define void @_Z10medium_arg6Medium(%struct.Medium* byval align 4 %s)
+// MSABI: define void @"\01?medium_arg@@YAXUMedium@@@Z"(%struct.Medium* byval align 4 %s)
+
+void small_arg_with_ctor(SmallWithCtor s) {}
+// LINUX: define void @_Z19small_arg_with_ctor13SmallWithCtor(%struct.SmallWithCtor* byval align 4 %s)
+// MSABI: define void @"\01?small_arg_with_ctor@@YAXUSmallWithCtor@@@Z"(%struct.SmallWithCtor* byval align 4 %s)
+
+void small_arg_with_vftable(SmallWithVftable s) {}
+// LINUX: define void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
+// MSABI: define void @"\01?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* byval align 4 %s)
+
+void medium_arg_with_some_ctor(MediumWithSomeCtor m) {}
+// LINUX: define void @_Z25medium_arg_with_some_ctor18MediumWithSomeCtor(%struct.MediumWithSomeCtor* byval align 4 %m)
+// MSABI: define void @"\01?medium_arg_with_some_ctor@@YAXUMediumWithSomeCtor@@@Z"(%struct.MediumWithSomeCtor* byval align 4 %m)
+
+void big_arg(Big s) {}
+// LINUX: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
+// MSABI: define void @"\01?big_arg@@YAXUBig@@@Z"(%struct.Big* byval align 4 %s)
+
+class Class {
+ public:
+  Small thiscall_method_small() { return Small(); }
+  // LINUX: define {{.*}} void @_ZN5Class21thiscall_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
+  // MSABI: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small@Class@@QAE?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
+
+  SmallWithCtor thiscall_method_small_with_ctor() { return SmallWithCtor(); }
+  // LINUX: define {{.*}} void @_ZN5Class31thiscall_method_small_with_ctorEv(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
+  // MSABI: define {{.*}} x86_thiscallcc void @"\01?thiscall_method_small_with_ctor@Class@@QAE?AUSmallWithCtor@@XZ"(%struct.SmallWithCtor* noalias sret %agg.result, %class.Class* %this)
+
+  Small __cdecl cdecl_method_small() { return Small(); }
+  // LINUX: define {{.*}} void @_ZN5Class18cdecl_method_smallEv(%struct.Small* noalias sret %agg.result, %class.Class* %this)
+  // FIXME: Interesting, cdecl returns structures differently for instance
+  // methods and global functions. This is not supported by Clang yet...
+  // FIXME: Replace MSABI-NOT with MSABI when this is fixed.
+  // MSABI-NOT: define {{.*}} void @"\01?cdecl_method_small@Class@@QAA?AUSmall@@XZ"(%struct.Small* noalias sret %agg.result, %class.Class* %this)
+
+  Big __cdecl cdecl_method_big() { return Big(); }
+  // LINUX: define {{.*}} void @_ZN5Class16cdecl_method_bigEv(%struct.Big* noalias sret %agg.result, %class.Class* %this)
+  // MSABI: define {{.*}} void @"\01?cdecl_method_big@Class@@QAA?AUBig@@XZ"(%struct.Big* noalias sret %agg.result, %class.Class* %this)
+
+  void thiscall_method_arg(Empty s) {}
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Empty(%class.Class* %this)
+  // MSABI: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmpty@@@Z"(%class.Class* %this, %struct.Empty* byval align 4 %s)
+
+  void thiscall_method_arg(EmptyWithCtor s) {}
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13EmptyWithCtor(%class.Class* %this)
+  // MSABI: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUEmptyWithCtor@@@Z"(%class.Class* %this, %struct.EmptyWithCtor* byval align 4 %s)
+
+  void thiscall_method_arg(Small s) {}
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE5Small(%class.Class* %this, %struct.Small* byval align 4 %s)
+  // MSABI: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmall@@@Z"(%class.Class* %this, %struct.Small* byval align 4 %s)
+
+  void thiscall_method_arg(SmallWithCtor s) {}
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE13SmallWithCtor(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
+  // MSABI: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUSmallWithCtor@@@Z"(%class.Class* %this, %struct.SmallWithCtor* byval align 4 %s)
+
+  void thiscall_method_arg(Big s) {}
+  // LINUX: define {{.*}} void @_ZN5Class19thiscall_method_argE3Big(%class.Class* %this, %struct.Big* byval align 4 %s)
+  // MSABI: define {{.*}} void @"\01?thiscall_method_arg@Class@@QAEXUBig@@@Z"(%class.Class* %this, %struct.Big* byval align 4 %s)
+};
+
+void use_class() {
+  Class c;
+  c.thiscall_method_small();
+  c.thiscall_method_small_with_ctor();
+
+  c.cdecl_method_small();
+  c.cdecl_method_big();
+
+  c.thiscall_method_arg(Empty());
+  c.thiscall_method_arg(EmptyWithCtor());
+  c.thiscall_method_arg(Small());
+  c.thiscall_method_arg(SmallWithCtor());
+  c.thiscall_method_arg(Big());
+}
