<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 28 March 2018 at 14:13, Akira Hatanaka via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ahatanak<br>
Date: Wed Mar 28 14:13:14 2018<br>
New Revision: 328731<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=328731&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=328731&view=rev</a><br>
Log:<br>
[ObjC++] Make parameter passing and function return compatible with ObjC<br>
<br>
ObjC and ObjC++ pass non-trivial structs in a way that is incompatible<br>
with each other. For example:<br>
<br>
typedef struct {<br>
  id f0;<br>
  __weak id f1;<br>
} S;<br>
<br>
// this code is compiled in c++.<br>
extern "C" {<br>
  void foo(S s);<br>
}<br>
<br>
void caller() {<br>
  // the caller passes the parameter indirectly and destructs it.<br>
  foo(S());<br>
}<br>
<br>
// this function is compiled in c.<br>
// 'a' is passed directly and is destructed in the callee.<br>
void foo(S a) {<br>
}<br>
<br>
This patch fixes the incompatibility by passing and returning structs<br>
with __strong or weak fields using the C ABI in C++ mode. __strong and<br>
__weak fields in a struct do not cause the struct to be destructed in<br>
the caller and __strong fields do not cause the struct to be passed<br>
indirectly.<br>
<br>
Also, this patch fixes the microsoft ABI bug mentioned here:<br>
<br>
<a href="https://reviews.llvm.org/D41039?id=128767#inline-364710" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D41039?id=128767#inline-364710</a><br>
<br>
rdar://problem/38887866<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D44908" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D44908</a><br>
<br>
Added:<br>
    cfe/trunk/test/CodeGenObjCXX/<a href="http://objc-struct-cxx-abi.mm" rel="noreferrer" target="_blank">o<wbr>bjc-struct-cxx-abi.mm</a><br>
      - copied, changed from r328730, cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a><br>
Removed:<br>
    cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a><br>
Modified:<br>
    cfe/trunk/include/clang/AST/<wbr>Decl.h<br>
    cfe/trunk/include/clang/AST/<wbr>DeclCXX.h<br>
    cfe/trunk/include/clang/AST/<wbr>Type.h<br>
    cfe/trunk/include/clang/Basic/<wbr>LangOptions.def<br>
    cfe/trunk/include/clang/Basic/<wbr>LangOptions.h<br>
    cfe/trunk/include/clang/Basic/<wbr>TargetInfo.h<br>
    cfe/trunk/include/clang/<wbr>Frontend/CodeGenOptions.def<br>
    cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
    cfe/trunk/lib/AST/Decl.cpp<br>
    cfe/trunk/lib/AST/DeclCXX.cpp<br>
    cfe/trunk/lib/AST/Type.cpp<br>
    cfe/trunk/lib/Basic/<wbr>TargetInfo.cpp<br>
    cfe/trunk/lib/Basic/Targets/<wbr>X86.h<br>
    cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp<br>
    cfe/trunk/lib/CodeGen/<wbr>ItaniumCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/<wbr>MicrosoftCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/<wbr>TargetInfo.cpp<br>
    cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp<br>
    cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
    cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp<br>
    cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp<br>
    cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp<br>
    cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp<br>
    cfe/trunk/test/CodeGenCXX/<wbr>microsoft-abi-sret-and-byval.<wbr>cpp<br>
    cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-special-member-functions.mm" rel="noreferrer" target="_blank">a<wbr>rc-special-member-functions.mm</a><br>
    cfe/trunk/test/CodeGenObjCXX/<a href="http://property-dot-copy-elision.mm" rel="noreferrer" target="_blank">p<wbr>roperty-dot-copy-elision.mm</a><br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>Decl.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/Decl.h?rev=328731&<wbr>r1=328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>Decl.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>Decl.h Wed Mar 28 14:13:14 2018<br>
@@ -3559,6 +3559,11 @@ class RecordDecl : public TagDecl {<br>
   /// pass an object of this class.<br>
   bool CanPassInRegisters : 1;<br>
<br>
+  /// Indicates whether this struct is destroyed in the callee. This flag is<br>
+  /// meaningless when Microsoft ABI is used since parameters are always<br>
+  /// destroyed in the callee.<br>
+  bool ParamDestroyedInCallee : 1;<br>
+<br>
 protected:<br>
   RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,<br>
              SourceLocation StartLoc, SourceLocation IdLoc,<br>
@@ -3654,6 +3659,14 @@ public:<br>
     CanPassInRegisters = CanPass;<br>
   }<br>
<br>
+  bool isParamDestroyedInCallee() const {<br>
+    return ParamDestroyedInCallee;<br>
+  }<br>
+<br>
+  void setParamDestroyedInCallee(bool V) {<br>
+    ParamDestroyedInCallee = V;<br>
+  }<br>
+<br>
   /// \brief Determines whether this declaration represents the<br>
   /// injected class name.<br>
   ///<br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>DeclCXX.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/DeclCXX.h?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>DeclCXX.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>DeclCXX.h Wed Mar 28 14:13:14 2018<br>
@@ -1468,13 +1468,6 @@ public:<br>
     return data().<wbr>HasIrrelevantDestructor;<br>
   }<br>
<br>
-  /// Determine whether the triviality for the purpose of calls for this class<br>
-  /// is overridden to be trivial because this class or the type of one of its<br>
-  /// subobjects has attribute "trivial_abi".<br>
-  bool hasTrivialABIOverride() const {<br>
-    return canPassInRegisters() && hasNonTrivialDestructor();<br>
-  }<br>
-<br>
   /// \brief Determine whether this class has a non-literal or/ volatile type<br>
   /// non-static data member or base class.<br>
   bool hasNonLiteralTypeFieldsOrBases<wbr>() const {<br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>Type.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/Type.h?rev=328731&<wbr>r1=328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>Type.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>Type.h Wed Mar 28 14:13:14 2018<br>
@@ -808,11 +808,6 @@ public:<br>
   /// Return true if this is a trivially copyable type (C++0x [basic.types]p9)<br>
   bool isTriviallyCopyableType(const ASTContext &Context) const;<br>
<br>
-  /// Determine whether this is a class whose triviality for the purpose of<br>
-  /// calls is overridden to be trivial because the class or the type of one of<br>
-  /// its subobjects has attribute "trivial_abi".<br>
-  bool hasTrivialABIOverride() const;<br>
-<br>
   // Don't promise in the API that anything besides 'const' can be<br>
   // easily added.<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>LangOptions.def<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/LangOptions.def?<wbr>rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>LangOptions.def (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>LangOptions.def Wed Mar 28 14:13:14 2018<br>
@@ -284,6 +284,10 @@ LANGOPT(<wbr>XRayAlwaysEmitCustomEvents, 1, 0<br>
 BENIGN_LANGOPT(<wbr>AllowEditorPlaceholders, 1, 0,<br>
                "allow editor placeholders in source")<br>
<br>
+ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest,<br>
+             "version of Clang that we should attempt to be ABI-compatible "<br>
+             "with")<br>
+<br>
 #undef LANGOPT<br>
 #undef COMPATIBLE_LANGOPT<br>
 #undef BENIGN_LANGOPT<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>LangOptions.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/LangOptions.h?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>LangOptions.h (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>LangOptions.h Wed Mar 28 14:13:14 2018<br>
@@ -102,6 +102,23 @@ public:<br>
     MSVC2015 = 19<br>
   };<br>
<br>
+  /// Clang versions with different platform ABI conformance.<br>
+  enum class ClangABI {<br>
+    /// Attempt to be ABI-compatible with code generated by Clang 3.8.x<br>
+    /// (SVN r257626). This causes <1 x long long> to be passed in an<br>
+    /// integer register instead of an SSE register on x64_64.<br>
+    Ver3_8,<br>
+<br>
+    /// Attempt to be ABI-compatible with code generated by Clang 4.0.x<br>
+    /// (SVN r291814). This causes move operations to be ignored when<br>
+    /// determining whether a class type can be passed or returned directly.<br>
+    Ver4,<br>
+<br>
+    /// Conform to the underlying platform's C and C++ ABIs as closely<br>
+    /// as we can.<br>
+    Latest<br>
+  };<br>
+<br>
   enum FPContractModeKind {<br>
     // Form fused FP ops only where result will not be affected.<br>
     FPC_Off,<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>TargetInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/TargetInfo.h?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>TargetInfo.h (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>TargetInfo.h Wed Mar 28 14:13:14 2018<br>
@@ -1053,6 +1053,14 @@ public:<br>
     }<br>
   }<br>
<br>
+  enum CallingConvKind {<br>
+    CCK_Default,<br>
+    CCK_ClangABI4OrPS4,<br>
+    CCK_MicrosoftX86_64<br>
+  };<br>
+<br>
+  virtual CallingConvKind getCallingConvKind(bool ClangABICompat4) const;<br>
+<br>
   /// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to<br>
   /// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.<br>
   virtual bool hasSjLjLowering() const {<br>
<br>
Modified: cfe/trunk/include/clang/<wbr>Frontend/CodeGenOptions.def<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CodeGenOptions.def?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Frontend/CodeGenOptions.<wbr>def?rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>Frontend/CodeGenOptions.def (original)<br>
+++ cfe/trunk/include/clang/<wbr>Frontend/CodeGenOptions.def Wed Mar 28 14:13:14 2018<br>
@@ -138,9 +138,6 @@ ENUM_CODEGENOPT(<wbr>ObjCDispatchMethod, ObjC<br>
 CODEGENOPT(<wbr>OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is<br>
                                         ///< enabled.<br>
<br>
-/// A version of Clang that we should attempt to be ABI-compatible with.<br>
-ENUM_CODEGENOPT(<wbr>ClangABICompat, ClangABI, 4, ClangABI::Latest)<br>
-<br>
 VALUE_CODEGENOPT(<wbr>OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.<br>
 VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ASTContext.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ASTContext.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTContext.<wbr>cpp Wed Mar 28 14:13:14 2018<br>
@@ -2643,9 +2643,11 @@ void ASTContext::<wbr>adjustExceptionSpec(<br>
 }<br>
<br>
 bool ASTContext::<wbr>isParamDestroyedInCallee(<wbr>QualType T) const {<br>
-  return getTargetInfo().getCXXABI().<wbr>areArgsDestroyedLeftToRightInC<wbr>allee() ||<br>
-         T.hasTrivialABIOverride() ||<br>
-         T.isDestructedType() == QualType::DK_nontrivial_c_<wbr>struct;<br>
+  if (getTargetInfo().getCXXABI().<wbr>areArgsDestroyedLeftToRightInC<wbr>allee())<br>
+    return true;<br>
+  if (const auto *RT = T->getBaseElementTypeUnsafe()-<wbr>>getAs<RecordType>())<br>
+    return RT->getDecl()-><wbr>isParamDestroyedInCallee();<br>
+  return false;<br>
 }<br>
<br>
 /// getComplexType - Return the uniqued reference to the type for a complex<br>
<br>
Modified: cfe/trunk/lib/AST/Decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>Decl.cpp?rev=328731&r1=328730&<wbr>r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/Decl.cpp (original)<br>
+++ cfe/trunk/lib/AST/Decl.cpp Wed Mar 28 14:13:14 2018<br>
@@ -3951,7 +3951,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind<br>
       LoadedFieldsFromExternalStorag<wbr>e(false),<br>
       NonTrivialToPrimitiveDefaultIn<wbr>itialize(false),<br>
       NonTrivialToPrimitiveCopy(<wbr>false), NonTrivialToPrimitiveDestroy(<wbr>false),<br>
-      CanPassInRegisters(true) {<br>
+      CanPassInRegisters(true), ParamDestroyedInCallee(false) {<br>
   assert(classof(static_cast<<wbr>Decl*>(this)) && "Invalid Kind!");<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>DeclCXX.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Mar 28 14:13:14 2018<br>
@@ -801,7 +801,17 @@ void CXXRecordDecl::addedMember(<wbr>Decl *D)<br>
         struct DefinitionData &Data = data();<br>
         Data.PlainOldData = false;<br>
         Data.HasTrivialSpecialMembers = 0;<br>
-        Data.<wbr>HasTrivialSpecialMembersForCal<wbr>l = 0;<br>
+<br>
+        // __strong or __weak fields do not make special functions non-trivial<br>
+        // for the purpose of calls.<br>
+        Qualifiers::ObjCLifetime LT = T.getQualifiers().<wbr>getObjCLifetime();<br>
+        if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak)<br>
+          data().<wbr>HasTrivialSpecialMembersForCal<wbr>l = 0;<br>
+<br>
+        // Structs with __weak fields should never be passed directly.<br>
+        if (LT == Qualifiers::OCL_Weak)<br>
+          setCanPassInRegisters(false);<br>
+<br>
         Data.HasIrrelevantDestructor = false;<br>
       } else if (!Context.getLangOpts().<wbr>ObjCAutoRefCount) {<br>
         setHasObjectMember(true);<br>
<br>
Modified: cfe/trunk/lib/AST/Type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>Type.cpp?rev=328731&r1=328730&<wbr>r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/Type.cpp (original)<br>
+++ cfe/trunk/lib/AST/Type.cpp Wed Mar 28 14:13:14 2018<br>
@@ -2195,12 +2195,6 @@ bool QualType::<wbr>isTriviallyCopyableType(c<br>
   return false;<br>
 }<br>
<br>
-bool QualType::<wbr>hasTrivialABIOverride() const {<br>
-  if (const auto *RD = getTypePtr()-><wbr>getAsCXXRecordDecl())<br>
-    return RD->hasTrivialABIOverride();<br>
-  return false;<br>
-}<br>
-<br>
 bool QualType::<wbr>isNonWeakInMRRWithObjCWeak(<wbr>const ASTContext &Context) const {<br>
   return !Context.getLangOpts().<wbr>ObjCAutoRefCount &&<br>
          Context.getLangOpts().ObjCWeak &&<br>
<br>
Modified: cfe/trunk/lib/Basic/<wbr>TargetInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/TargetInfo.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Basic/<wbr>TargetInfo.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Basic/<wbr>TargetInfo.cpp (original)<br>
+++ cfe/trunk/lib/Basic/<wbr>TargetInfo.cpp Wed Mar 28 14:13:14 2018<br>
@@ -357,6 +357,14 @@ bool TargetInfo::initFeatureMap(<br>
   return true;<br>
 }<br>
<br>
+TargetInfo::CallingConvKind<br>
+TargetInfo::<wbr>getCallingConvKind(bool ClangABICompat4) const {<br>
+  if (getCXXABI() != TargetCXXABI::Microsoft &&<br>
+      (ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4))<br>
+    return CCK_ClangABI4OrPS4;<br>
+  return CCK_Default;<br>
+}<br>
+<br>
 LangAS TargetInfo::<wbr>getOpenCLTypeAddrSpace(<wbr>OpenCLTypeKind TK) const {<br>
   switch (TK) {<br>
   case OCLTK_Image:<br>
<br>
Modified: cfe/trunk/lib/Basic/Targets/<wbr>X86.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/X86.h?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Basic/<wbr>Targets/X86.h?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Basic/Targets/<wbr>X86.h (original)<br>
+++ cfe/trunk/lib/Basic/Targets/<wbr>X86.h Wed Mar 28 14:13:14 2018<br>
@@ -728,6 +728,11 @@ public:<br>
     Builder.defineMacro("_M_X64", "100");<br>
     Builder.defineMacro("_M_AMD64"<wbr>, "100");<br>
   }<br>
+<br>
+  TargetInfo::CallingConvKind<br>
+  getCallingConvKind(bool ClangABICompat4) const override {<br>
+    return CCK_MicrosoftX86_64;<br>
+  }<br>
 };<br>
<br>
 // x86-64 MinGW target<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGCall.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp Wed Mar 28 14:13:14 2018<br>
@@ -3540,24 +3540,13 @@ void CodeGenFunction::EmitCallArg(<wbr>CallAr<br>
     else<br>
       Slot = CreateAggTemp(type, "agg.tmp");<br>
<br>
-    bool DestroyedInCallee = true, NeedsEHCleanup = true;<br>
-    if (const auto *RD = type->getAsCXXRecordDecl()) {<br>
-      DestroyedInCallee =<br>
-          RD && RD->hasNonTrivialDestructor() &&<br>
-          (CGM.getCXXABI().<wbr>getRecordArgABI(RD) != CGCXXABI::RAA_Default ||<br>
-           RD->hasTrivialABIOverride());<br>
-    } else {<br>
-      NeedsEHCleanup = needsEHCleanup(type.<wbr>isDestructedType());<br>
-    }<br>
-<br>
-    if (DestroyedInCallee)<br>
-      Slot.setExternallyDestructed()<wbr>;<br>
+    Slot.setExternallyDestructed()<wbr>;<br>
<br>
     EmitAggExpr(E, Slot);<br>
     RValue RV = Slot.asRValue();<br>
     args.add(RV, type);<br>
<br>
-    if (DestroyedInCallee && NeedsEHCleanup) {<br>
+    if (type->getAsCXXRecordDecl() || needsEHCleanup(type.<wbr>isDestructedType())) {<br>
       // Create a no-op GEP between the placeholder and the cleanup so we can<br>
       // RAUW it successfully.  It also serves as a marker of the first<br>
       // instruction where the cleanup is active.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>ItaniumCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>ItaniumCXXABI.cpp?rev=328731&<wbr>r1=328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>ItaniumCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>ItaniumCXXABI.cpp Wed Mar 28 14:13:14 2018<br>
@@ -63,13 +63,6 @@ public:<br>
   bool classifyReturnType(<wbr>CGFunctionInfo &FI) const override;<br>
<br>
   bool passClassIndirect(const CXXRecordDecl *RD) const {<br>
-    // Clang <= 4 used the pre-C++11 rule, which ignores move operations.<br>
-    // The PS4 platform ABI follows the behavior of Clang 3.2.<br>
-    if (CGM.getCodeGenOpts().<wbr>getClangABICompat() <=<br>
-            CodeGenOptions::ClangABI::Ver4 ||<br>
-        CGM.getTriple().getOS() == llvm::Triple::PS4)<br>
-      return RD-><wbr>hasNonTrivialDestructorForCall<wbr>() ||<br>
-             RD-><wbr>hasNonTrivialCopyConstructorFo<wbr>rCall();<br>
     return !canCopyArgument(RD);<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>MicrosoftCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>MicrosoftCXXABI.cpp?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>MicrosoftCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>MicrosoftCXXABI.cpp Wed Mar 28 14:13:14 2018<br>
@@ -829,60 +829,7 @@ MicrosoftCXXABI::<wbr>getRecordArgABI(const C<br>
     return RAA_Default;<br>
<br>
   case llvm::Triple::x86_64:<br>
-    bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;<br>
-    bool DtorIsTrivialForCall = false;<br>
-<br>
-    // If a class has at least one non-deleted, trivial copy constructor, it<br>
-    // is passed according to the C ABI. Otherwise, it is passed indirectly.<br>
-    //<br>
-    // Note: This permits classes with non-trivial copy or move ctors to be<br>
-    // passed in registers, so long as they *also* have a trivial copy ctor,<br>
-    // which is non-conforming.<br>
-    if (RD-><wbr>needsImplicitCopyConstructor()<wbr>) {<br>
-      if (!RD-><wbr>defaultedCopyConstructorIsDele<wbr>ted()) {<br>
-        if (RD-><wbr>hasTrivialCopyConstructor())<br>
-          CopyCtorIsTrivial = true;<br>
-        if (RD-><wbr>hasTrivialCopyConstructorForCa<wbr>ll())<br>
-          CopyCtorIsTrivialForCall = true;<br>
-      }<br>
-    } else {<br>
-      for (const CXXConstructorDecl *CD : RD->ctors()) {<br>
-        if (CD->isCopyConstructor() && !CD->isDeleted()) {<br>
-          if (CD->isTrivial())<br>
-            CopyCtorIsTrivial = true;<br>
-          if (CD->isTrivialForCall())<br>
-            CopyCtorIsTrivialForCall = true;<br>
-        }<br>
-      }<br>
-    }<br>
-<br>
-    if (RD->needsImplicitDestructor()<wbr>) {<br>
-      if (!RD-><wbr>defaultedDestructorIsDeleted() &&<br>
-          RD-><wbr>hasTrivialDestructorForCall())<br>
-        DtorIsTrivialForCall = true;<br>
-    } else if (const auto *D = RD->getDestructor()) {<br>
-      if (!D->isDeleted() && D->isTrivialForCall())<br>
-        DtorIsTrivialForCall = true;<br>
-    }<br>
-<br>
-    // If the copy ctor and dtor are both trivial-for-calls, pass direct.<br>
-    if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)<br>
-      return RAA_Default;<br>
-<br>
-    // If a class has a destructor, we'd really like to pass it indirectly<br>
-    // because it allows us to elide copies.  Unfortunately, MSVC makes that<br>
-    // impossible for small types, which it will pass in a single register or<br>
-    // stack slot. Most objects with dtors are large-ish, so handle that early.<br>
-    // We can't call out all large objects as being indirect because there are<br>
-    // multiple x64 calling conventions and the C++ ABI code shouldn't dictate<br>
-    // how we pass large POD types.<br>
-<br>
-    // Note: This permits small classes with nontrivial destructors to be<br>
-    // passed in registers, which is non-conforming.<br>
-    if (CopyCtorIsTrivial &&<br>
-        getContext().getTypeSize(RD-><wbr>getTypeForDecl()) <= 64)<br>
-      return RAA_Default;<br>
-    return RAA_Indirect;<br>
+    return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default;<br>
   }<br>
<br>
   llvm_unreachable("invalid enum");<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>TargetInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>TargetInfo.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>TargetInfo.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>TargetInfo.cpp Wed Mar 28 14:13:14 2018<br>
@@ -2131,8 +2131,8 @@ class X86_64ABIInfo : public SwiftABIInf<br>
   /// classify it as INTEGER (for compatibility with older clang compilers).<br>
   bool classifyIntegerMMXAsSSE() const {<br>
     // Clang <= 3.8 did not do this.<br>
-    if (getCodeGenOpts().<wbr>getClangABICompat() <=<br>
-        CodeGenOptions::ClangABI::<wbr>Ver3_8)<br>
+    if (getContext().getLangOpts().<wbr>getClangABICompat() <=<br>
+        LangOptions::ClangABI::Ver3_8)<br>
       return false;<br>
<br>
     const llvm::Triple &Triple = getTarget().getTriple();<br>
<br>
Modified: cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Frontend/CompilerInvocation.<wbr>cpp?rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp Wed Mar 28 14:13:14 2018<br>
@@ -633,33 +633,6 @@ static bool ParseCodeGenArgs(CodeGenOpti<br>
   if (!Opts.<wbr>ProfileInstrumentUsePath.<wbr>empty())<br>
     setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath)<wbr>;<br>
<br>
-  if (Arg *A = Args.getLastArg(OPT_fclang_<wbr>abi_compat_EQ)) {<br>
-    Opts.setClangABICompat(<wbr>CodeGenOptions::ClangABI::<wbr>Latest);<br>
-<br>
-    StringRef Ver = A->getValue();<br>
-    std::pair<StringRef, StringRef> VerParts = Ver.split('.');<br>
-    unsigned Major, Minor = 0;<br>
-<br>
-    // Check the version number is valid: either 3.x (0 <= x <= 9) or<br>
-    // y or y.0 (4 <= y <= current version).<br>
-    if (!VerParts.first.startswith("<wbr>0") &&<br>
-        !VerParts.first.getAsInteger(<wbr>10, Major) &&<br>
-        3 <= Major && Major <= CLANG_VERSION_MAJOR &&<br>
-        (Major == 3 ? VerParts.second.size() == 1 &&<br>
-                      !VerParts.second.getAsInteger(<wbr>10, Minor)<br>
-                    : VerParts.first.size() == Ver.size() ||<br>
-                      VerParts.second == "0")) {<br>
-      // Got a valid version number.<br>
-      if (Major == 3 && Minor <= 8)<br>
-        Opts.setClangABICompat(<wbr>CodeGenOptions::ClangABI::<wbr>Ver3_8);<br>
-      else if (Major <= 4)<br>
-        Opts.setClangABICompat(<wbr>CodeGenOptions::ClangABI::<wbr>Ver4);<br>
-    } else if (Ver != "latest") {<br>
-      Diags.Report(diag::err_drv_<wbr>invalid_value)<br>
-          << A->getAsString(Args) << A->getValue();<br>
-    }<br>
-  }<br>
-<br>
   Opts.CoverageMapping =<br>
       Args.hasFlag(OPT_fcoverage_<wbr>mapping, OPT_fno_coverage_mapping, false);<br>
   Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_<wbr>mapping);<br>
@@ -2670,6 +2643,33 @@ static void ParseLangArgs(LangOptions &O<br>
<br>
   // -fallow-editor-placeholders<br>
   Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_<wbr>placeholders);<br>
+<br>
+  if (Arg *A = Args.getLastArg(OPT_fclang_<wbr>abi_compat_EQ)) {<br>
+    Opts.setClangABICompat(<wbr>LangOptions::ClangABI::Latest)<wbr>;<br>
+<br>
+    StringRef Ver = A->getValue();<br>
+    std::pair<StringRef, StringRef> VerParts = Ver.split('.');<br>
+    unsigned Major, Minor = 0;<br>
+<br>
+    // Check the version number is valid: either 3.x (0 <= x <= 9) or<br>
+    // y or y.0 (4 <= y <= current version).<br>
+    if (!VerParts.first.startswith("<wbr>0") &&<br>
+        !VerParts.first.getAsInteger(<wbr>10, Major) &&<br>
+        3 <= Major && Major <= CLANG_VERSION_MAJOR &&<br>
+        (Major == 3 ? VerParts.second.size() == 1 &&<br>
+                      !VerParts.second.getAsInteger(<wbr>10, Minor)<br>
+                    : VerParts.first.size() == Ver.size() ||<br>
+                      VerParts.second == "0")) {<br>
+      // Got a valid version number.<br>
+      if (Major == 3 && Minor <= 8)<br>
+        Opts.setClangABICompat(<wbr>LangOptions::ClangABI::Ver3_8)<wbr>;<br>
+      else if (Major <= 4)<br>
+        Opts.setClangABICompat(<wbr>LangOptions::ClangABI::Ver4);<br>
+    } else if (Ver != "latest") {<br>
+      Diags.Report(diag::err_drv_<wbr>invalid_value)<br>
+          << A->getAsString(Args) << A->getValue();<br>
+    }<br>
+  }<br>
 }<br>
<br>
 static bool isStrictlyPreprocessorAction(<wbr>frontend::ActionKind Action) {<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDecl.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp Wed Mar 28 14:13:14 2018<br>
@@ -15461,8 +15461,10 @@ void Sema::ActOnFields(Scope *S, SourceL<br>
       QualType::PrimitiveCopyKind PCK = FT.<wbr>isNonTrivialToPrimitiveCopy();<br>
       if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)<br>
         Record-><wbr>setNonTrivialToPrimitiveCopy(<wbr>true);<br>
-      if (FT.isDestructedType())<br>
+      if (FT.isDestructedType()) {<br>
         Record-><wbr>setNonTrivialToPrimitiveDestro<wbr>y(true);<br>
+        Record-><wbr>setParamDestroyedInCallee(<wbr>true);<br>
+      }<br>
       if (!FT.canPassInRegisters())<br>
         Record->setCanPassInRegisters(<wbr>false);<br>
     }<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp Wed Mar 28 14:13:14 2018<br>
@@ -5791,12 +5791,21 @@ static void DefineImplicitSpecialMember(<br>
   }<br>
 }<br>
<br>
-/// Determine whether a type is permitted to be passed or returned in<br>
-/// registers, per C++ [class.temporary]p3.<br>
-static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) {<br>
+/// Determine whether a type would be destructed in the callee if it had a<br>
+/// non-trivial destructor. The rules here are based on C++ [class.temporary]p3,<br>
+/// which determines whether a struct can be passed to or returned from<br>
+/// functions in registers.<br>
+static bool paramCanBeDestroyedInCallee(<wbr>Sema &S, CXXRecordDecl *D,<br>
+                                        TargetInfo::CallingConvKind CCK) {<br>
   if (D->isDependentType() || D->isInvalidDecl())<br>
     return false;<br>
<br>
+  // Clang <= 4 used the pre-C++11 rule, which ignores move operations.<br>
+  // The PS4 platform ABI follows the behavior of Clang 3.2.<br>
+  if (CCK == TargetInfo::CCK_<wbr>ClangABI4OrPS4)<br>
+    return !D-><wbr>hasNonTrivialDestructorForCall<wbr>() &&<br>
+           !D-><wbr>hasNonTrivialCopyConstructorFo<wbr>rCall();<br>
+<br>
   // Per C++ [class.temporary]p3, the relevant condition is:<br>
   //   each copy constructor, move constructor, and destructor of X is<br>
   //   either trivial or deleted, and X has at least one non-deleted copy<br>
@@ -5838,6 +5847,77 @@ static bool computeCanPassInRegisters(Se<br>
   return HasNonDeletedCopyOrMove;<br>
 }<br>
<br>
+static bool computeCanPassInRegister(bool DestroyedInCallee,<br>
+                                     const CXXRecordDecl *RD,<br>
+                                     TargetInfo::CallingConvKind CCK,<br>
+                                     Sema &S) {<br>
+  if (RD->isDependentType() || RD->isInvalidDecl())<br>
+    return true;<br>
+<br>
+  // The param cannot be passed in registers if CanPassInRegisters is already<br>
+  // set to false.<br>
+  if (!RD->canPassInRegisters())<br>
+    return false;<br>
+<br>
+  if (CCK != TargetInfo::CCK_MicrosoftX86_<wbr>64)<br>
+    return DestroyedInCallee;<br>
+<br>
+  bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;<br>
+  bool DtorIsTrivialForCall = false;<br>
+<br>
+  // If a class has at least one non-deleted, trivial copy constructor, it<br>
+  // is passed according to the C ABI. Otherwise, it is passed indirectly.<br>
+  //<br>
+  // Note: This permits classes with non-trivial copy or move ctors to be<br>
+  // passed in registers, so long as they *also* have a trivial copy ctor,<br>
+  // which is non-conforming.<br>
+  if (RD-><wbr>needsImplicitCopyConstructor()<wbr>) {<br>
+    if (!RD-><wbr>defaultedCopyConstructorIsDele<wbr>ted()) {<br>
+      if (RD-><wbr>hasTrivialCopyConstructor())<br>
+        CopyCtorIsTrivial = true;<br>
+      if (RD-><wbr>hasTrivialCopyConstructorForCa<wbr>ll())<br>
+        CopyCtorIsTrivialForCall = true;<br>
+    }<br>
+  } else {<br>
+    for (const CXXConstructorDecl *CD : RD->ctors()) {<br>
+      if (CD->isCopyConstructor() && !CD->isDeleted()) {<br>
+        if (CD->isTrivial())<br>
+          CopyCtorIsTrivial = true;<br>
+        if (CD->isTrivialForCall())<br>
+          CopyCtorIsTrivialForCall = true;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  if (RD->needsImplicitDestructor()<wbr>) {<br>
+    if (!RD-><wbr>defaultedDestructorIsDeleted() &&<br>
+        RD-><wbr>hasTrivialDestructorForCall())<br>
+      DtorIsTrivialForCall = true;<br>
+  } else if (const auto *D = RD->getDestructor()) {<br>
+    if (!D->isDeleted() && D->isTrivialForCall())<br>
+      DtorIsTrivialForCall = true;<br>
+  }<br>
+<br>
+  // If the copy ctor and dtor are both trivial-for-calls, pass direct.<br>
+  if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)<br>
+    return true;<br>
+<br>
+  // If a class has a destructor, we'd really like to pass it indirectly<br>
+  // because it allows us to elide copies.  Unfortunately, MSVC makes that<br>
+  // impossible for small types, which it will pass in a single register or<br>
+  // stack slot. Most objects with dtors are large-ish, so handle that early.<br>
+  // We can't call out all large objects as being indirect because there are<br>
+  // multiple x64 calling conventions and the C++ ABI code shouldn't dictate<br>
+  // how we pass large POD types.<br>
+<br>
+  // Note: This permits small classes with nontrivial destructors to be<br>
+  // passed in registers, which is non-conforming.<br>
+  if (CopyCtorIsTrivial &&<br>
+      S.getASTContext().getTypeSize(<wbr>RD->getTypeForDecl()) <= 64)<br>
+    return true;<br>
+  return false;<br>
+}<br>
+<br>
 /// \brief Perform semantic checks on a class definition that has been<br>
 /// completing, introducing implicitly-declared members, checking for<br>
 /// abstract types, etc.<br>
@@ -6001,7 +6081,17 @@ void Sema::CheckCompletedCXXClass(<wbr>CXXRec<br>
<br>
   checkClassLevelDLLAttribute(<wbr>Record);<br>
<br>
-  Record->setCanPassInRegisters(<wbr>computeCanPassInRegisters(*<wbr>this, Record));<br>
+  bool ClangABICompat4 =<br>
+      Context.getLangOpts().<wbr>getClangABICompat() <= LangOptions::ClangABI::Ver4;<br>
+  TargetInfo::CallingConvKind CCK =<br>
+      Context.getTargetInfo().<wbr>getCallingConvKind(<wbr>ClangABICompat4);<br>
+  bool DestroyedInCallee = paramCanBeDestroyedInCallee(*<wbr>this, Record, CCK);<br>
+<br>
+  if (Record-><wbr>hasNonTrivialDestructor())<br>
+    Record-><wbr>setParamDestroyedInCallee(<wbr>DestroyedInCallee);<br>
+<br>
+  Record->setCanPassInRegisters(<br>
+      computeCanPassInRegister(<wbr>DestroyedInCallee, Record, CCK, *this));<br>
 }<br></blockquote><div><br></div><div>The naming you're using here doesn't make any sense to me.</div><div><br></div><div>"paramCanBeDestroyedInCallee" is computing whether the class is allowed to be passed in registers (per the language rules), not whether it's destroyed in callee (which is based on whether we're using the MS ABI, which sometimes destroys parameters in the callee).</div><div>"computeCanPassInRegister" appears to be computing whether the parameter *should* be passed in registers (per the quirks of the ABI), not whether it can be passed in registers. (Also I'm not sure why you converted the name from plural to singular -- we really do mean zero or more registers here, not exactly one.)</div><div><br></div><div>Please can you fix these names?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 /// Look up the special member function that would be called by a special<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTReaderDecl.<wbr>cpp?rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp Wed Mar 28 14:13:14 2018<br>
@@ -743,6 +743,7 @@ ASTDeclReader::<wbr>VisitRecordDeclImpl(Recor<br>
   RD-><wbr>setNonTrivialToPrimitiveCopy(<wbr>Record.readInt());<br>
   RD-><wbr>setNonTrivialToPrimitiveDestro<wbr>y(Record.readInt());<br>
   RD->setCanPassInRegisters(<wbr>Record.readInt());<br>
+  RD->setParamDestroyedInCallee(<wbr>Record.readInt());<br>
   return Redecl;<br>
 }<br>
<br>
@@ -4109,6 +4110,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,<br>
           OldDD && (OldDD->Definition != RD ||<br>
                     !Reader.<wbr>PendingFakeDefinitionData.<wbr>count(OldDD));<br>
       RD->setCanPassInRegisters(<wbr>Record.readInt());<br>
+      RD->setParamDestroyedInCallee(<wbr>Record.readInt());<br>
       ReadCXXRecordDefinition(RD, /*Update*/true);<br>
<br>
       // Visible update is handled separately.<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTWriter.cpp?<wbr>rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp Wed Mar 28 14:13:14 2018<br>
@@ -5194,6 +5194,7 @@ void ASTWriter::<wbr>WriteDeclUpdatesBlocks(R<br>
         auto *RD = cast<CXXRecordDecl>(D);<br>
         UpdatedDeclContexts.insert(RD-<wbr>>getPrimaryContext());<br>
         Record.push_back(RD-><wbr>canPassInRegisters());<br>
+        Record.push_back(RD-><wbr>isParamDestroyedInCallee());<br>
         Record.AddCXXDefinitionData(<wbr>RD);<br>
         Record.AddOffset(<wbr>WriteDeclContextLexicalBlock(<br>
             *Context, const_cast<CXXRecordDecl *>(RD)));<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTWriterDecl.<wbr>cpp?rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp Wed Mar 28 14:13:14 2018<br>
@@ -470,6 +470,7 @@ void ASTDeclWriter::<wbr>VisitRecordDecl(Reco<br>
   Record.push_back(D-><wbr>isNonTrivialToPrimitiveCopy())<wbr>;<br>
   Record.push_back(D-><wbr>isNonTrivialToPrimitiveDestroy<wbr>());<br>
   Record.push_back(D-><wbr>canPassInRegisters());<br>
+  Record.push_back(D-><wbr>isParamDestroyedInCallee());<br>
<br>
   if (D->getDeclContext() == D->getLexicalDeclContext() &&<br>
       !D->hasAttrs() &&<br>
@@ -1912,6 +1913,8 @@ void ASTWriter::WriteDeclAbbrevs() {<br>
   // isNonTrivialToPrimitiveDestroy<br>
   Abv->Add(BitCodeAbbrevOp(<wbr>BitCodeAbbrevOp::Fixed, 1));<br>
   Abv->Add(BitCodeAbbrevOp(<wbr>BitCodeAbbrevOp::Fixed, 1)); // canPassInRegisters<br>
+  // isParamDestroyedInCallee<br>
+  Abv->Add(BitCodeAbbrevOp(<wbr>BitCodeAbbrevOp::Fixed, 1));<br>
<br>
   // DC<br>
   Abv->Add(BitCodeAbbrevOp(<wbr>BitCodeAbbrevOp::VBR, 6));   // LexicalOffset<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/<wbr>microsoft-abi-sret-and-byval.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/microsoft-abi-sret-<wbr>and-byval.cpp?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/<wbr>microsoft-abi-sret-and-byval.<wbr>cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/<wbr>microsoft-abi-sret-and-byval.<wbr>cpp Wed Mar 28 14:13:14 2018<br>
@@ -172,12 +172,9 @@ void small_arg_with_dtor(<wbr>SmallWithDtor s<br>
 void call_small_arg_with_dtor() {<br>
   small_arg_with_dtor(<wbr>SmallWithDtor());<br>
 }<br>
-// The temporary is copied, so it's destroyed in the caller as well as the<br>
-// callee.<br>
 // WIN64-LABEL: define dso_local void @"?call_small_arg_with_dtor@@<wbr>YAXXZ"()<br>
 // WIN64:   call %struct.SmallWithDtor* @"??0SmallWithDtor@@QEAA@XZ"<br>
 // WIN64:   call void @"?small_arg_with_dtor@@<wbr>YAXUSmallWithDtor@@@Z"(i32 %{{.*}})<br>
-// WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"<br>
 // WIN64:   ret void<br>
<br>
 // Test that references aren't destroyed in the callee.<br>
<br>
Modified: cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-special-member-functions.mm" rel="noreferrer" target="_blank">a<wbr>rc-special-member-functions.mm</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenObjCXX/arc-special-<wbr>member-functions.mm?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-special-member-functions.mm" rel="noreferrer" target="_blank">a<wbr>rc-special-member-functions.mm</a> (original)<br>
+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://arc-special-member-functions.mm" rel="noreferrer" target="_blank">a<wbr>rc-special-member-functions.mm</a> Wed Mar 28 14:13:14 2018<br>
@@ -31,6 +31,8 @@ void test_ObjCMember_copy_<wbr>construct_dest<br>
 void test_ObjCMember_copy_assign(<wbr>ObjCMember m1, ObjCMember m2) {<br>
   // CHECK: {{call.*_ZN10ObjCMemberaSERKS_<wbr>}}<br>
   m1 = m2;<br>
+  // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(<br>
+  // CHECK-NEXT: call void @_ZN10ObjCMemberD1Ev(<br>
   // CHECK-NEXT: ret void<br>
 }<br>
<br>
@@ -58,6 +60,8 @@ void test_ObjCArrayMember_copy_<wbr>construct<br>
 void test_ObjCArrayMember_copy_<wbr>assign(ObjCArrayMember m1, ObjCArrayMember m2) {<br>
   // CHECK: {{call.*@_<wbr>ZN15ObjCArrayMemberaSERKS_}}<br>
   m1 = m2;<br>
+  // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(<br>
+  // CHECK-NEXT: call void @_ZN15ObjCArrayMemberD1Ev(<br>
   // CHECK-NEXT: ret void<br>
 }<br>
<br>
@@ -79,7 +83,8 @@ void test_ObjCBlockMember_default_<wbr>constr<br>
 void test_ObjCBlockMember_copy_<wbr>construct_destruct(<wbr>ObjCBlockMember m1) {<br>
   // CHECK: call void @_ZN15ObjCBlockMemberC1ERKS_<br>
   ObjCBlockMember m2 = m1;<br>
-  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev<br>
+  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(<br>
+  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(<br>
   // CHECK-NEXT: ret void<br>
 }<br>
<br>
@@ -87,6 +92,8 @@ void test_ObjCBlockMember_copy_<wbr>construct<br>
 void test_ObjCBlockMember_copy_<wbr>assign(ObjCBlockMember m1, ObjCBlockMember m2) {<br>
   // CHECK: {{call.*_<wbr>ZN15ObjCBlockMemberaSERKS_}}<br>
   m1 = m2;<br>
+  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(<br>
+  // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev(<br>
   // CHECK-NEXT: ret void<br>
 }<br>
<br>
<br>
Copied: cfe/trunk/test/CodeGenObjCXX/<a href="http://objc-struct-cxx-abi.mm" rel="noreferrer" target="_blank">o<wbr>bjc-struct-cxx-abi.mm</a> (from r328730, cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a>)<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm?p2=cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm&p1=cfe/trunk/test/CodeGenObjCXX/trivial_abi.mm&r1=328730&r2=328731&rev=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenObjCXX/objc-struct-cxx-<wbr>abi.mm?p2=cfe/trunk/test/<wbr>CodeGenObjCXX/objc-struct-cxx-<wbr>abi.mm&p1=cfe/trunk/test/<wbr>CodeGenObjCXX/trivial_abi.mm&<wbr>r1=328730&r2=328731&rev=<wbr>328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a> (original)<br>
+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://objc-struct-cxx-abi.mm" rel="noreferrer" target="_blank">o<wbr>bjc-struct-cxx-abi.mm</a> Wed Mar 28 14:13:14 2018<br>
@@ -1,27 +1,60 @@<br>
 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s<br>
 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s<br>
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s<br>
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - -DTRIVIALABI %s | FileCheck %s<br>
+<br>
+// Check that structs consisting solely of __strong or __weak pointer fields are<br>
+// destructed in the callee function and structs consisting solely of __strong<br>
+// pointer fields are passed directly.<br>
<br>
 // CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* }<br>
 // CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }<br>
 // CHECK: %[[STRUCT_S:.*]] = type { i8* }<br>
+// CHECK: %[[STRUCT_CONTAINSNONTRIVIAL:.<wbr>*]] = type { %{{.*}}, i8* }<br>
<br>
+#ifdef TRIVIALABI<br>
 struct __attribute__((trivial_abi)) StrongWeak {<br>
+#else<br>
+struct StrongWeak {<br>
+#endif<br>
   id fstrong;<br>
   __weak id fweak;<br>
 };<br>
<br>
+#ifdef TRIVIALABI<br>
 struct __attribute__((trivial_abi)) Strong {<br>
+#else<br>
+struct Strong {<br>
+#endif<br>
   id fstrong;<br>
 };<br>
<br>
 template<class T><br>
+#ifdef TRIVIALABI<br>
 struct __attribute__((trivial_abi)) S {<br>
+#else<br>
+struct S {<br>
+#endif<br>
   T a;<br>
 };<br>
<br>
+struct NonTrivial {<br>
+  NonTrivial();<br>
+  NonTrivial(const NonTrivial &);<br>
+  ~NonTrivial();<br>
+  int *a;<br>
+};<br>
+<br>
+// This struct is not passed directly nor destructed in the callee because f0<br>
+// has type NonTrivial.<br>
+struct ContainsNonTrivial {<br>
+  NonTrivial f0;<br>
+  id f1;<br>
+};<br>
+<br>
 // CHECK: define void @_<wbr>Z19testParamStrongWeak10Strong<wbr>Weak(%[[STRUCT_STRONGWEAK]]* %{{.*}})<br>
-// CHECK-NOT: call<br>
-// CHECK: ret void<br>
+// CHECK: call %struct.StrongWeak* @_ZN10StrongWeakD1Ev(<br>
+// CHECK-NEXT: ret void<br>
<br>
 void testParamStrongWeak(StrongWeak a) {<br>
 }<br>
@@ -33,7 +66,7 @@ void testParamStrongWeak(StrongWeak a) {<br>
 // CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8<br>
 // CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[<wbr>STRUCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])<br>
 // CHECK: call void @_<wbr>Z19testParamStrongWeak10Strong<wbr>Weak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])<br>
-// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[<wbr>STRUCT_STRONGWEAK]]* %[[AGG_TMP]])<br>
+// CHECK-NOT: call<br>
 // CHECK: ret void<br>
<br>
 void testCallStrongWeak(StrongWeak *a) {<br>
@@ -96,8 +129,23 @@ Strong testReturnStrong(Strong *a) {<br>
 }<br>
<br>
 // CHECK: define void @_<wbr>Z21testParamWeakTemplate1SIU6_<wbr>_weakP11objc_objectE(%[[<wbr>STRUCT_S]]* %{{.*}})<br>
+// CHECK: call %struct.S* @_ZN1SIU6__weakP11objc_<wbr>objectED1Ev(<br>
+// CHECK-NEXT: ret void<br>
+<br>
+void testParamWeakTemplate(S<__weak id> a) {<br>
+}<br>
+<br>
+// CHECK: define void @_<wbr>Z27testParamContainsNonTrivial<wbr>18ContainsNonTrivial(%[[<wbr>STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})<br>
 // CHECK-NOT: call<br>
 // CHECK: ret void<br>
<br>
-void testParamWeakTemplate(S<__weak id> a) {<br>
+void testParamContainsNonTrivial(<wbr>ContainsNonTrivial a) {<br>
+}<br>
+<br>
+// CHECK: define void @_<wbr>Z26testCallContainsNonTrivialP<wbr>18ContainsNonTrivial(<br>
+// CHECK: call void @_<wbr>Z27testParamContainsNonTrivial<wbr>18ContainsNonTrivial(%[[<wbr>STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})<br>
+// CHECK: call %struct.ContainsNonTrivial* @_ZN18ContainsNonTrivialD1Ev(%<wbr>[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})<br>
+<br>
+void testCallContainsNonTrivial(<wbr>ContainsNonTrivial *a) {<br>
+  testParamContainsNonTrivial(*<wbr>a);<br>
 }<br>
<br>
Modified: cfe/trunk/test/CodeGenObjCXX/<a href="http://property-dot-copy-elision.mm" rel="noreferrer" target="_blank">p<wbr>roperty-dot-copy-elision.mm</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/property-dot-copy-elision.mm?rev=328731&r1=328730&r2=328731&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenObjCXX/property-dot-<wbr>copy-elision.mm?rev=328731&r1=<wbr>328730&r2=328731&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenObjCXX/<a href="http://property-dot-copy-elision.mm" rel="noreferrer" target="_blank">p<wbr>roperty-dot-copy-elision.mm</a> (original)<br>
+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://property-dot-copy-elision.mm" rel="noreferrer" target="_blank">p<wbr>roperty-dot-copy-elision.mm</a> Wed Mar 28 14:13:14 2018<br>
@@ -1,11 +1,13 @@<br>
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++1z -fobjc-arc -o - %s | FileCheck %s<br>
<br>
 struct S0 {<br>
+  ~S0();<br>
   id f;<br>
 };<br>
<br>
 struct S1 {<br>
   S1();<br>
+  ~S1();<br>
   S1(S0);<br>
   id f;<br>
 };<br>
<br>
Removed: cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/trivial_abi.mm?rev=328730&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenObjCXX/trivial_abi.mm?<wbr>rev=328730&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a> (original)<br>
+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a> (removed)<br>
@@ -1,103 +0,0 @@<br>
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s<br>
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc  -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s<br>
-<br>
-// CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* }<br>
-// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }<br>
-// CHECK: %[[STRUCT_S:.*]] = type { i8* }<br>
-<br>
-struct __attribute__((trivial_abi)) StrongWeak {<br>
-  id fstrong;<br>
-  __weak id fweak;<br>
-};<br>
-<br>
-struct __attribute__((trivial_abi)) Strong {<br>
-  id fstrong;<br>
-};<br>
-<br>
-template<class T><br>
-struct __attribute__((trivial_abi)) S {<br>
-  T a;<br>
-};<br>
-<br>
-// CHECK: define void @_<wbr>Z19testParamStrongWeak10Strong<wbr>Weak(%[[STRUCT_STRONGWEAK]]* %{{.*}})<br>
-// CHECK-NOT: call<br>
-// CHECK: ret void<br>
-<br>
-void testParamStrongWeak(StrongWeak a) {<br>
-}<br>
-<br>
-// CHECK: define void @_<wbr>Z18testCallStrongWeakP10Strong<wbr>Weak(%[[STRUCT_STRONGWEAK]]* %[[A:.*]])<br>
-// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8<br>
-// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8<br>
-// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[<wbr>STRUCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])<br>
-// CHECK: call void @_<wbr>Z19testParamStrongWeak10Strong<wbr>Weak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])<br>
-// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[<wbr>STRUCT_STRONGWEAK]]* %[[AGG_TMP]])<br>
-// CHECK: ret void<br>
-<br>
-void testCallStrongWeak(StrongWeak *a) {<br>
-  testParamStrongWeak(*a);<br>
-}<br>
-<br>
-// CHECK: define void @_<wbr>Z20testReturnStrongWeakP10Stro<wbr>ngWeak(%[[STRUCT_STRONGWEAK:.*<wbr>]]* noalias sret %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* %[[A:.*]])<br>
-// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8<br>
-// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[<wbr>STRUCT_STRONGWEAK]]* %[[AGG_RESULT]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])<br>
-// CHECK: ret void<br>
-<br>
-StrongWeak testReturnStrongWeak(<wbr>StrongWeak *a) {<br>
-  return *a;<br>
-}<br>
-<br>
-// CHECK: define void @_Z15testParamStrong6Strong(<wbr>i64 %[[A_COERCE:.*]])<br>
-// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG]], align 8<br>
-// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[A]], i32 0, i32 0<br>
-// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i8*<br>
-// CHECK: store i8* %[[COERCE_VAL_IP]], i8** %[[COERCE_DIVE]], align 8<br>
-// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_<wbr>STRONG]]* %[[A]])<br>
-// CHECK: ret void<br>
-<br>
-// CHECK: define linkonce_odr %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(<br>
-<br>
-void testParamStrong(Strong a) {<br>
-}<br>
-<br>
-// CHECK: define void @_Z14testCallStrongP6Strong(%[<wbr>[STRUCT_STRONG]]* %[[A:.*]])<br>
-// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8<br>
-// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8<br>
-// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_<wbr>STRONG]]* %[[AGG_TMP]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]])<br>
-// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[AGG_TMP]], i32 0, i32 0<br>
-// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8<br>
-// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64<br>
-// CHECK: call void @_Z15testParamStrong6Strong(<wbr>i64 %[[COERCE_VAL_PI]])<br>
-// CHECK: ret void<br>
-<br>
-void testCallStrong(Strong *a) {<br>
-  testParamStrong(*a);<br>
-}<br>
-<br>
-// CHECK: define i64 @_Z16testReturnStrongP6Strong(<wbr>%[[STRUCT_STRONG]]* %[[A:.*]])<br>
-// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8<br>
-// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8<br>
-// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8<br>
-// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_<wbr>STRONG]]* %[[RETVAL]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]])<br>
-// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0<br>
-// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8<br>
-// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64<br>
-// CHECK: ret i64 %[[COERCE_VAL_PI]]<br>
-<br>
-Strong testReturnStrong(Strong *a) {<br>
-  return *a;<br>
-}<br>
-<br>
-// CHECK: define void @_<wbr>Z21testParamWeakTemplate1SIU6_<wbr>_weakP11objc_objectE(%[[<wbr>STRUCT_S]]* %{{.*}})<br>
-// CHECK-NOT: call<br>
-// CHECK: ret void<br>
-<br>
-void testParamWeakTemplate(S<__weak id> a) {<br>
-}<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>