<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 3 April 2018 at 13:07, 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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div dir="auto" style="word-wrap:break-word"><div dir="auto" style="word-wrap:break-word"><div dir="auto" style="word-wrap:break-word"><br><div><div><div class="gmail-h5"><br><blockquote type="cite"><div>On Apr 1, 2018, at 6:00 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:</div><br class="gmail-m_-3123202202555592205Apple-interchange-newline"><div><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration:none"><div class="gmail_extra"><div class="gmail_quote">On 28 March 2018 at 14:13, Akira Hatanaka via cfe-commits<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@<wbr>lists.llvm.org</a>></span><span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: ahatanak<br>Date: Wed Mar 28 14:13:14 2018<br>New Revision: 328731<br><br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=328731&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/<wbr>llvm-project?rev=328731&view=<wbr>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> <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>id f0;<br> <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>__weak id f1;<br>} S;<br><br>// this code is compiled in c++.<br>extern "C" {<br> <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>void foo(S s);<br>}<br><br>void caller() {<br> <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>// the caller passes the parameter indirectly and destructs it.<br> <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>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/D4103<wbr>9?id=128767#inline-364710</a><br><br><a>rdar://problem/38887866</a><br><br>Differential Revision:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><a href="https://reviews.llvm.org/D44908" rel="noreferrer" target="_blank">https://reviews.<wbr>llvm.org/D44908</a><br><br>Added:<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/test/<wbr>CodeGenObjCXX/<a href="http://objc-struct-cxx-abi.mm/" rel="noreferrer" target="_blank">objc-struct-cxx-<wbr>abi.mm</a><br>     <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>- 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>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/test/<wbr>CodeGenObjCXX/<a href="http://trivial_abi.mm/" rel="noreferrer" target="_blank">trivial_abi.mm</a><br>Modified:<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/include/clang/AST/<wbr>Decl.h<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/include/clang/AST/<wbr>DeclCXX.h<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/include/clang/AST/<wbr>Type.h<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/include/clang/<wbr>Basic/LangOptions.def<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/include/clang/<wbr>Basic/LangOptions.h<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/include/clang/<wbr>Basic/TargetInfo.h<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/include/clang/Fron<wbr>tend/CodeGenOptions.def<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/AST/<wbr>ASTContext.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/AST/Decl.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/AST/DeclCXX.<wbr>cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/AST/Type.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Basic/TargetIn<wbr>fo.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Basic/Targets/<wbr>X86.h<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/CodeGen/<wbr>CGCall.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/CodeGen/Itaniu<wbr>mCXXABI.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/CodeGen/Micros<wbr>oftCXXABI.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/CodeGen/Target<wbr>Info.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Frontend/Compi<wbr>lerInvocation.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Sema/SemaDeclC<wbr>XX.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/test/CodeGenCXX/mi<wbr>crosoft-abi-sret-and-byval.cpp<br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/test/<wbr>CodeGenObjCXX/<a href="http://arc-special-member-functions.mm/" rel="noreferrer" target="_blank">arc-special-<wbr>member-functions.mm</a><br>   <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>cfe/trunk/test/<wbr>CodeGenObjCXX/<a href="http://property-dot-copy-elision.mm/" rel="noreferrer" target="_blank">property-dot-<wbr>copy-elision.mm</a><br><br>Modified: cfe/trunk/include/clang/AST/De<wbr>cl.h<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/<wbr>include/clang/AST/Decl.h?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/include/clang/AST/De<wbr>cl.h (original)<br>+++ cfe/trunk/include/clang/AST/De<wbr>cl.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>             <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>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/De<wbr>clCXX.h<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/<wbr>include/clang/AST/DeclCXX.h?<wbr>rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/include/clang/AST/De<wbr>clCXX.h (original)<br>+++ cfe/trunk/include/clang/AST/De<wbr>clCXX.h Wed Mar 28 14:13:14 2018<br>@@ -1468,13 +1468,6 @@ public:<br>     return data().HasIrrelevantDestructor<wbr>;<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/Ty<wbr>pe.h<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/<wbr>include/clang/AST/Type.h?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/include/clang/AST/Ty<wbr>pe.h (original)<br>+++ cfe/trunk/include/clang/AST/Ty<wbr>pe.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:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/<wbr>include/clang/Basic/<wbr>LangOptions.def?rev=328731&r1=<wbr>328730&r2=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(XRayAlwaysEmitCustomEv<wbr>ents, 1, 0<br> BENIGN_LANGOPT(AllowEditorPla<wbr>ceholders, 1, 0,<br>               <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>"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:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/<wbr>include/clang/Basic/<wbr>LangOptions.h?rev=328731&r1=<wbr>328730&r2=328731&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:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/<wbr>include/clang/Basic/<wbr>TargetInfo.h?rev=328731&r1=<wbr>328730&r2=328731&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/Fronte<wbr>nd/CodeGenOptions.def<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/<wbr>include/clang/Frontend/<wbr>CodeGenOptions.def?rev=328731&<wbr>r1=328730&r2=328731&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/include/clang/Fronte<wbr>nd/CodeGenOptions.def (original)<br>+++ cfe/trunk/include/clang/Fronte<wbr>nd/CodeGenOptions.def Wed Mar 28 14:13:14 2018<br>@@ -138,9 +138,6 @@ ENUM_CODEGENOPT(ObjCDispatchMe<wbr>thod, ObjC<br> CODEGENOPT(OmitLeafFramePoint<wbr>er , 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(ClangABICompa<wbr>t, ClangABI, 4, ClangABI::Latest)<br>-<br> VALUE_CODEGENOPT(Optimization<wbr>Level, 2, 0) ///< The -O[0-3] option specified.<br> VALUE_CODEGENOPT(<wbr>OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.<br><br><br>Modified: cfe/trunk/lib/AST/ASTContext.c<wbr>pp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>AST/ASTContext.cpp?rev=328731&<wbr>r1=328730&r2=328731&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/AST/ASTContext.c<wbr>pp (original)<br>+++ cfe/trunk/lib/AST/ASTContext.c<wbr>pp Wed Mar 28 14:13:14 2018<br>@@ -2643,9 +2643,11 @@ void ASTContext::adjustExceptionSpe<wbr>c(<br> }<br><br> bool ASTContext::isParamDestroyedIn<wbr>Callee(QualType T) const {<br>-  return getTargetInfo().getCXXABI().ar<wbr>eArgsDestroyedLeftToRightInCal<wbr>lee() ||<br>-         T.hasTrivialABIOverride() ||<br>-         T.isDestructedType() == QualType::DK_nontrivial_c_stru<wbr>ct;<br>+  if (getTargetInfo().getCXXABI().a<wbr>reArgsDestroyedLeftToRightInCa<wbr>llee())<br>+    return true;<br>+  if (const auto *RT = T->getBaseElementTypeUnsafe()-<wbr>>getAs<RecordType>())<br>+    return RT->getDecl()->isParamDestroye<wbr>dInCallee();<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:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>AST/Decl.cpp?rev=328731&r1=<wbr>328730&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>       <wbr>LoadedFieldsFromExternalStorag<wbr>e(false),<br>       <wbr>NonTrivialToPrimitiveDefaultIn<wbr>itialize(false),<br>       NonTrivialToPrimitiveCopy(fal<wbr>se), NonTrivialToPrimitiveDestroy(f<wbr>alse),<br>-      CanPassInRegisters(true) {<br>+      CanPassInRegisters(true), ParamDestroyedInCallee(false) {<br>   assert(classof(static_cast<De<wbr>cl*>(this)) && "Invalid Kind!");<br> }<br><br><br>Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>AST/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(Dec<wbr>l *D)<br>         struct DefinitionData &Data = data();<br>         Data.PlainOldData = false;<br>         Data.HasTrivialSpecialMembers = 0;<br>-        Data.HasTrivialSpecialMembersF<wbr>orCall = 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().getObjCLifet<wbr>ime();<br>+        if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak)<br>+          data().HasTrivialSpecialMember<wbr>sForCall = 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().ObjCAu<wbr>toRefCount) {<br>         setHasObjectMember(true);<br><br>Modified: cfe/trunk/lib/AST/Type.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>AST/Type.cpp?rev=328731&r1=<wbr>328730&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::isTriviallyCopyableT<wbr>ype(c<br>   return false;<br> }<br><br>-bool QualType::hasTrivialABIOverrid<wbr>e() const {<br>-  if (const auto *RD = getTypePtr()->getAsCXXRecordDe<wbr>cl())<br>-    return RD->hasTrivialABIOverride();<br>-  return false;<br>-}<br>-<br> bool QualType::isNonWeakInMRRWithOb<wbr>jCWeak(const ASTContext &Context) const {<br>   return !Context.getLangOpts().ObjCAut<wbr>oRefCount &&<br>         <span class="gmail-m_-3123202202555592205Apple-converted-space"> </span>Context.getLangOpts().<wbr>ObjCWeak &&<br><br>Modified: cfe/trunk/lib/Basic/TargetInfo<wbr>.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>Basic/TargetInfo.cpp?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Basic/TargetInfo<wbr>.cpp (original)<br>+++ cfe/trunk/lib/Basic/TargetInfo<wbr>.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::getCallingConvKin<wbr>d(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::getOpenCLTypeAddrS<wbr>pace(OpenCLTypeKind TK) const {<br>   switch (TK) {<br>   case OCLTK_Image:<br><br>Modified: cfe/trunk/lib/Basic/Targets/X8<wbr>6.h<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>Basic/Targets/X86.h?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Basic/Targets/X8<wbr>6.h (original)<br>+++ cfe/trunk/lib/Basic/Targets/X8<wbr>6.h Wed Mar 28 14:13:14 2018<br>@@ -728,6 +728,11 @@ public:<br>     Builder.defineMacro("_M_X64", "100");<br>     Builder.defineMacro("_M_<wbr>AMD64", "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.c<wbr>pp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>CodeGen/CGCall.cpp?rev=328731&<wbr>r1=328730&r2=328731&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/CodeGen/CGCall.c<wbr>pp (original)<br>+++ cfe/trunk/lib/CodeGen/CGCall.c<wbr>pp Wed Mar 28 14:13:14 2018<br>@@ -3540,24 +3540,13 @@ void CodeGenFunction::EmitCallArg(C<wbr>allAr<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().getRecordArgA<wbr>BI(RD) != CGCXXABI::RAA_Default ||<br>-           RD->hasTrivialABIOverride());<br>-    } else {<br>-      NeedsEHCleanup = needsEHCleanup(type.isDestruct<wbr>edType());<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.isDestruct<wbr>edType())) {<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/ItaniumC<wbr>XXABI.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>CodeGen/ItaniumCXXABI.cpp?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/CodeGen/ItaniumC<wbr>XXABI.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/ItaniumC<wbr>XXABI.cpp Wed Mar 28 14:13:14 2018<br>@@ -63,13 +63,6 @@ public:<br>   bool classifyReturnType(CGFunctionI<wbr>nfo &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().getClang<wbr>ABICompat() <=<br>-            CodeGenOptions::ClangABI::Ver4 ||<br>-        CGM.getTriple().getOS() == llvm::Triple::PS4)<br>-      return RD->hasNonTrivialDestructorFor<wbr>Call() ||<br>-             RD->hasNonTrivialCopyConstruc<wbr>torForCall();<br>     return !canCopyArgument(RD);<br>   }<br><br><br>Modified: cfe/trunk/lib/CodeGen/Microsof<wbr>tCXXABI.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>CodeGen/MicrosoftCXXABI.cpp?<wbr>rev=328731&r1=328730&r2=<wbr>328731&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/CodeGen/Microsof<wbr>tCXXABI.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/Microsof<wbr>tCXXABI.cpp Wed Mar 28 14:13:14 2018<br>@@ -829,60 +829,7 @@ MicrosoftCXXABI::getRecordArgA<wbr>BI(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->needsImplicitCopyConstruc<wbr>tor()) {<br>-      if (!RD->defaultedCopyConstructor<wbr>IsDeleted()) {<br>-        if (RD->hasTrivialCopyConstructor<wbr>())<br>-          CopyCtorIsTrivial = true;<br>-        if (RD->hasTrivialCopyConstructor<wbr>ForCall())<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->defaultedDestructorIsDel<wbr>eted() &&<br>-          RD->hasTrivialDestructorForCal<wbr>l())<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->g<wbr>etTypeForDecl()) <= 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/TargetIn<wbr>fo.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>CodeGen/TargetInfo.cpp?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/CodeGen/TargetIn<wbr>fo.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/TargetIn<wbr>fo.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().getClangABIC<wbr>ompat() <=<br>-        CodeGenOptions::ClangABI::Ver3<wbr>_8)<br>+    if (getContext().getLangOpts().ge<wbr>tClangABICompat() <=<br>+        LangOptions::ClangABI::Ver3_8)<br>       return false;<br><br>     const llvm::Triple &Triple = getTarget().getTriple();<br><br>Modified: cfe/trunk/lib/Frontend/Compile<wbr>rInvocation.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/Fro<wbr>ntend/CompilerInvocation.cpp?<wbr>rev=328731&r1=328730&r2=328731<wbr>&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Frontend/Compile<wbr>rInvocation.cpp (original)<br>+++ cfe/trunk/lib/Frontend/Compile<wbr>rInvocation.cpp Wed Mar 28 14:13:14 2018<br>@@ -633,33 +633,6 @@ static bool ParseCodeGenArgs(CodeGenOpti<br>   if (!Opts.ProfileInstrumentUsePat<wbr>h.empty())<br>     setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath)<wbr>;<br><br>-  if (Arg *A = Args.getLastArg(OPT_fclang_abi<wbr>_compat_EQ)) {<br>-    Opts.setClangABICompat(CodeGen<wbr>Options::ClangABI::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("0<wbr>") &&<br>-        !VerParts.first.getAsInteger(1<wbr>0, 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(CodeGen<wbr>Options::ClangABI::Ver3_8);<br>-      else if (Major <= 4)<br>-        Opts.setClangABICompat(CodeGen<wbr>Options::ClangABI::Ver4);<br>-    } else if (Ver != "latest") {<br>-      Diags.Report(diag::err_drv_inv<wbr>alid_value)<br>-          << A->getAsString(Args) << A->getValue();<br>-    }<br>-  }<br>-<br>   Opts.CoverageMapping =<br>       Args.hasFlag(OPT_fcoverage_ma<wbr>pping, 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_abi<wbr>_compat_EQ)) {<br>+    Opts.setClangABICompat(LangOpt<wbr>ions::ClangABI::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("0<wbr>") &&<br>+        !VerParts.first.getAsInteger(1<wbr>0, 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(LangOpt<wbr>ions::ClangABI::Ver3_8);<br>+      else if (Major <= 4)<br>+        Opts.setClangABICompat(LangOpt<wbr>ions::ClangABI::Ver4);<br>+    } else if (Ver != "latest") {<br>+      Diags.Report(diag::err_drv_inv<wbr>alid_value)<br>+          << A->getAsString(Args) << A->getValue();<br>+    }<br>+  }<br> }<br><br> static bool isStrictlyPreprocessorAction(f<wbr>rontend::ActionKind Action) {<br><br>Modified: cfe/trunk/lib/Sema/SemaDecl.cp<wbr>p<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>Sema/SemaDecl.cpp?rev=328731&<wbr>r1=328730&r2=328731&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Sema/SemaDecl.cp<wbr>p (original)<br>+++ cfe/trunk/lib/Sema/SemaDecl.cp<wbr>p Wed Mar 28 14:13:14 2018<br>@@ -15461,8 +15461,10 @@ void Sema::ActOnFields(Scope *S, SourceL<br>       QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy<wbr>();<br>       if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)<br>         Record->setNonTrivialToPrimit<wbr>iveCopy(true);<br>-      if (FT.isDestructedType())<br>+      if (FT.isDestructedType()) {<br>         Record->setNonTrivialToPrimit<wbr>iveDestroy(true);<br>+        Record->setParamDestroyedInCal<wbr>lee(true);<br>+      }<br>       if (!FT.canPassInRegisters())<br>         Record-><wbr>setCanPassInRegisters(false);<br>     }<br><br>Modified: cfe/trunk/lib/Sema/SemaDeclCXX<wbr>.cpp<br>URL:<span class="gmail-m_-3123202202555592205Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/<wbr>Sema/SemaDeclCXX.cpp?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Sema/SemaDeclCXX<wbr>.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaDeclCXX<wbr>.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(Se<wbr>ma &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_ClangABI4OrPS4<wbr>)<br>+    return !D->hasNonTrivialDestructorFor<wbr>Call() &&<br>+           !D->hasNonTrivialCopyConstruc<wbr>torForCall();<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_6<wbr>4)<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->needsImplicitCopyConstruc<wbr>tor()) {<br>+    if (!RD->defaultedCopyConstructor<wbr>IsDeleted()) {<br>+      if (RD->hasTrivialCopyConstructor<wbr>())<br>+        CopyCtorIsTrivial = true;<br>+      if (RD->hasTrivialCopyConstructor<wbr>ForCall())<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->defaultedDestructorIsDel<wbr>eted() &&<br>+        RD->hasTrivialDestructorForCal<wbr>l())<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(C<wbr>XXRec<br><br>   checkClassLevelDLLAttribute(R<wbr>ecord);<br><br>-  Record->setCanPassInRegisters(<wbr>computeCanPassInRegisters(*thi<wbr>s, Record));<br>+  bool ClangABICompat4 =<br>+      Context.getLangOpts().getClang<wbr>ABICompat() <= LangOptions::ClangABI::Ver4;<br>+  TargetInfo::CallingConvKind CCK =<br>+      Context.getTargetInfo().getCal<wbr>lingConvKind(ClangABICompat4);<br>+  bool DestroyedInCallee = paramCanBeDestroyedInCallee(*t<wbr>his, Record, CCK);<br>+<br>+  if (Record->hasNonTrivialDestruct<wbr>or())<br>+    Record->setParamDestroyedInCal<wbr>lee(DestroyedInCallee);<br>+<br>+  Record->setCanPassInRegisters(<br>+      computeCanPassInRegister(Destr<wbr>oyedInCallee, 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></div></div></div></blockquote><div><br></div></div></div><div>Does this patch make more sense to you?</div></div></div></div></div></div></blockquote><div><br></div><div>Yes, thanks, but canPassInRegisters is still documented as computing the standard notion of "can be passed in registers" but is actually now computing an ABI-specific notion of "should be passed in registers" (which is the same except in the MSABI case where we pass some things in registers even when we're not actually allowed to); please update the comments to match, and consider renaming it to just "passInRegisters".</div><div><br></div><div>I'm also not clear why you need to store a bit for "param destroyed in callee", since it seems to always be equivalent to hasNonTrivialDestructor() && passInRegisters(). Are there cases where paramDestroyedInCallee() is intentionally different from that?</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div dir="auto" style="word-wrap:break-word"><div dir="auto" style="word-wrap:break-word"><div dir="auto" style="word-wrap:break-word"><div><div><div><div>The static function canPassInRegisters computes whether the record can be passed in registers depending on which of the three ABIs (clang-abi-compat=4.0, 64-bit microsoft, and Itanium C++ ABI) we are using. The function returns the correct answer except when ARC is enabled and the record has a __weak field, which is why CXXRecordDecl::<wbr>canPassInRegisters() has to be called too to check the presence of __weak fields when computing the value for flag RecordDecl::<wbr>CanPassInRegisters.  I discovered there is a bug which causes a struct containing another struct with __weak fields to be passed directly, but I think that can be fixed in a separate patch.</div><div><br></div><div>Sema::CheckCompletedCXXClass also computes the value for flag RecordDecl::<wbr>ParamDestroyedInCallee (note that this flag is meaningless when Microsoft ABI is used). This is how it works when a struct has __weak or __strong fields:</div><div><br></div><div>1. In CXXRecordDecl::addedMember, pretend that __weak or __strong fields do not make special functions non-trivial for the purpose of calls.</div><div>2. If canPassInRegisters returns true, use the C ABI to pass the record, which destructs records in the callee and passes records with __weak fields indirectly (records having __strong fields but no __weak fields are not forced to be passed indirectly). If it returns false, use the C++ ABI, which destructs the record in the caller and passes it indirectly.</div><div>3. Since we cannot count on canPassInRegisters to tell whether a record can be passed directly in the presence of a __weak field, CXXRecordDecl::addedMember calls setCanPassInRegisters(false) so that we know the record cannot be passed directly.</div><div><br></div><div>hasTrivialABIOverride (which computes "canPassInRegisters() && hasNonTrivialDestructor()") used to determine whether a struct is destructed in the callee, but the function can no longer be used since structs with __weak fields are always passed indirectly.</div><div><br></div></div></div></div><div><blockquote type="cite"><div><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration:none"><div class="gmail_extra"><div class="gmail_quote"><div>Please can you fix these names?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> /// Look up the special member function that would be called by a special<br><br>Modified: cfe/trunk/lib/Serialization/AS<wbr>TReaderDecl.cpp<br>URL:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/Ser<wbr>ialization/ASTReaderDecl.cpp?<wbr>rev=328731&r1=328730&r2=328731<wbr>&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Serialization/AS<wbr>TReaderDecl.cpp (original)<br>+++ cfe/trunk/lib/Serialization/AS<wbr>TReaderDecl.cpp Wed Mar 28 14:13:14 2018<br>@@ -743,6 +743,7 @@ ASTDeclReader::VisitRecordDecl<wbr>Impl(Recor<br>   RD->setNonTrivialToPrimitiveC<wbr>opy(Record.readInt());<br>   RD->setNonTrivialToPrimitiveD<wbr>estroy(Record.readInt());<br>   RD->setCanPassInRegisters(Rec<wbr>ord.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.PendingFakeDefinition<wbr>Data.count(OldDD));<br>       RD->setCanPassInRegisters(Rec<wbr>ord.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/AS<wbr>TWriter.cpp<br>URL:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/Ser<wbr>ialization/ASTWriter.cpp?rev=<wbr>328731&r1=328730&r2=328731&<wbr>view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp (original)<br>+++ cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp Wed Mar 28 14:13:14 2018<br>@@ -5194,6 +5194,7 @@ void ASTWriter::WriteDeclUpdatesBlo<wbr>cks(R<br>         auto *RD = cast<CXXRecordDecl>(D);<br>         UpdatedDeclContexts.insert(<wbr>RD->getPrimaryContext());<br>         Record.push_back(RD->canPassI<wbr>nRegisters());<br>+        Record.push_back(RD->isParamDe<wbr>stroyedInCallee());<br>         Record.AddCXXDefinitionData(R<wbr>D);<br>         Record.AddOffset(WriteDeclCon<wbr>textLexicalBlock(<br>             *Context, const_cast<CXXRecordDecl *>(RD)));<br><br>Modified: cfe/trunk/lib/Serialization/AS<wbr>TWriterDecl.cpp<br>URL:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/lib/Ser<wbr>ialization/ASTWriterDecl.cpp?<wbr>rev=328731&r1=328730&r2=328731<wbr>&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/lib/Serialization/AS<wbr>TWriterDecl.cpp (original)<br>+++ cfe/trunk/lib/Serialization/AS<wbr>TWriterDecl.cpp Wed Mar 28 14:13:14 2018<br>@@ -470,6 +470,7 @@ void ASTDeclWriter::VisitRecordDecl<wbr>(Reco<br>   Record.push_back(D->isNonTriv<wbr>ialToPrimitiveCopy());<br>   Record.push_back(D->isNonTriv<wbr>ialToPrimitiveDestroy());<br>   Record.push_back(D->canPassIn<wbr>Registers());<br>+  Record.push_back(D->isParamDes<wbr>troyedInCallee());<br><br>   if (D->getDeclContext() == D->getLexicalDeclContext() &&<br>       !D->hasAttrs() &&<br>@@ -1912,6 +1913,8 @@ void ASTWriter::WriteDeclAbbrevs() {<br>   // isNonTrivialToPrimitiveDestroy<br>   Abv->Add(BitCodeAbbrevOp(BitC<wbr>odeAbbrevOp::Fixed, 1));<br>   Abv->Add(BitCodeAbbrevOp(BitC<wbr>odeAbbrevOp::Fixed, 1)); // canPassInRegisters<br>+  // isParamDestroyedInCallee<br>+  Abv->Add(BitCodeAbbrevOp(BitCo<wbr>deAbbrevOp::Fixed, 1));<br><br>   // DC<br>   Abv->Add(BitCodeAbbrevOp(BitC<wbr>odeAbbrevOp::VBR, 6));   // LexicalOffset<br><br>Modified: cfe/trunk/test/CodeGenCXX/micr<wbr>osoft-abi-sret-and-byval.cpp<br>URL:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/test/Co<wbr>deGenCXX/microsoft-abi-sret-an<wbr>d-byval.cpp?rev=328731&r1=3287<wbr>30&r2=328731&view=diff</a><br>==============================<wbr>==============================<wbr>==================<br>--- cfe/trunk/test/CodeGenCXX/micr<wbr>osoft-abi-sret-and-byval.cpp (original)<br>+++ cfe/trunk/test/CodeGenCXX/micr<wbr>osoft-abi-sret-and-byval.cpp Wed Mar 28 14:13:14 2018<br>@@ -172,12 +172,9 @@ void small_arg_with_dtor(SmallWithD<wbr>tor s<br> void call_small_arg_with_dtor() {<br>   small_arg_with_dtor(SmallWith<wbr>Dtor());<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@@Y<wbr>AXXZ"()<br> // WIN64:   call %struct.SmallWithDtor* @"??0SmallWithDtor@@QEAA@XZ"<br> // WIN64:   call void @"?small_arg_with_dtor@@YAXUSm<wbr>allWithDtor@@@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:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/test/Co<wbr>deGenObjCXX/arc-special-member<wbr>-functions.mm?rev=328731&r1=<wbr>328730&r2=328731&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><span class="gmail-m_-8093432400557341289Apple-converted-space"><wbr> </span>(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><span class="gmail-m_-8093432400557341289Apple-converted-space"><wbr> </span>Wed Mar 28 14:13:14 2018<br>@@ -31,6 +31,8 @@ void test_ObjCMember_copy_construct<wbr>_dest<br> void test_ObjCMember_copy_assign(Ob<wbr>jCMember 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_cons<wbr>truct<br> void test_ObjCArrayMember_copy_assi<wbr>gn(ObjCArrayMember m1, ObjCArrayMember m2) {<br>   // CHECK: {{call.*@_ZN15ObjCArrayMembera<wbr>SERKS_}}<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_c<wbr>onstr<br> void test_ObjCBlockMember_copy_cons<wbr>truct_destruct(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_cons<wbr>truct<br> void test_ObjCBlockMember_copy_assi<wbr>gn(ObjCBlockMember m1, ObjCBlockMember m2) {<br>   // CHECK: {{call.*_ZN15ObjCBlockMemberaS<wbr>ERKS_}}<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><span class="gmail-m_-8093432400557341289Apple-converted-space"> </span>(from r328730, cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm/" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a>)<br>URL:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/test/Co<wbr>deGenObjCXX/objc-struct-cxx-ab<wbr>i.mm?p2=cfe/trunk/test/CodeGen<wbr>ObjCXX/objc-struct-cxx-abi.mm&<wbr>p1=cfe/trunk/test/CodeGenObjCX<wbr>X/trivial_abi.mm&r1=328730&r2=<wbr>328731&rev=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><span class="gmail-m_-8093432400557341289Apple-converted-space"> </span>(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><span class="gmail-m_-8093432400557341289Apple-converted-space"> </span>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 @_Z19testParamStrongWeak10Stro<wbr>ngWeak(%[[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_(%[[STR<wbr>UCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])<br> // CHECK: call void @_Z19testParamStrongWeak10Stro<wbr>ngWeak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])<br>-// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[STRUCT<wbr>_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 @_Z21testParamWeakTemplate1SIU<wbr>6__weakP11objc_objectE(%[[STRU<wbr>CT_S]]* %{{.*}})<br>+// CHECK: call %struct.S* @_ZN1SIU6__weakP11objc_objectE<wbr>D1Ev(<br>+// CHECK-NEXT: ret void<br>+<br>+void testParamWeakTemplate(S<__weak id> a) {<br>+}<br>+<br>+// CHECK: define void @_Z27testParamContainsNonTrivi<wbr>al18ContainsNonTrivial(%[[STRU<wbr>CT_CONTAINSNONTRIVIAL]]* %{{.*}})<br> // CHECK-NOT: call<br> // CHECK: ret void<br><br>-void testParamWeakTemplate(S<__weak id> a) {<br>+void testParamContainsNonTrivial(Co<wbr>ntainsNonTrivial a) {<br>+}<br>+<br>+// CHECK: define void @_Z26testCallContainsNonTrivia<wbr>lP18ContainsNonTrivial(<br>+// CHECK: call void @_Z27testParamContainsNonTrivi<wbr>al18ContainsNonTrivial(%[[STRU<wbr>CT_CONTAINSNONTRIVIAL]]* %{{.*}})<br>+// CHECK: call %struct.ContainsNonTrivial* @_ZN18ContainsNonTrivialD1Ev(%<wbr>[[STRUCT_CONTAINSNONTRIVIAL]]* %{{.*}})<br>+<br>+void testCallContainsNonTrivial(Con<wbr>tainsNonTrivial *a) {<br>+  testParamContainsNonTrivial(*a<wbr>);<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:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/test/Co<wbr>deGenObjCXX/property-dot-copy-<wbr>elision.mm?rev=328731&r1=32873<wbr>0&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><span class="gmail-m_-8093432400557341289Apple-converted-space"> </span>(<wbr>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><span class="gmail-m_-8093432400557341289Apple-converted-space"> </span>We<wbr>d 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:<span class="gmail-m_-8093432400557341289Apple-converted-space"> </span><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/<wbr>llvm-project/cfe/trunk/test/Co<wbr>deGenObjCXX/trivial_abi.mm?rev<wbr>=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><span class="gmail-m_-8093432400557341289Apple-converted-space"> </span>(original)<br>+++ cfe/trunk/test/CodeGenObjCXX/<a href="http://trivial_abi.mm/" rel="noreferrer" target="_blank">t<wbr>rivial_abi.mm</a><span class="gmail-m_-8093432400557341289Apple-converted-space"> </span>(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 @_Z19testParamStrongWeak10Stro<wbr>ngWeak(%[[STRUCT_STRONGWEAK]]* %{{.*}})<br>-// CHECK-NOT: call<br>-// CHECK: ret void<br>-<br>-void testParamStrongWeak(StrongWeak a) {<br>-}<br>-<br>-// CHECK: define void @_Z18testCallStrongWeakP10Stro<wbr>ngWeak(%[[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_(%[[STR<wbr>UCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])<br>-// CHECK: call void @_Z19testParamStrongWeak10Stro<wbr>ngWeak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]])<br>-// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[STRUCT<wbr>_STRONGWEAK]]* %[[AGG_TMP]])<br>-// CHECK: ret void<br>-<br>-void testCallStrongWeak(StrongWeak *a) {<br>-  testParamStrongWeak(*a);<br>-}<br>-<br>-// CHECK: define void @_Z20testReturnStrongWeakP10St<wbr>rongWeak(%[[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_(%[[STR<wbr>UCT_STRONGWEAK]]* %[[AGG_RESULT]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]])<br>-// CHECK: ret void<br>-<br>-StrongWeak testReturnStrongWeak(StrongWea<wbr>k *a) {<br>-  return *a;<br>-}<br>-<br>-// CHECK: define void @_Z15testParamStrong6Strong(i6<wbr>4 %[[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_STRO<wbr>NG]]* %[[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_S<wbr>TRONG]]* %[[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(i6<wbr>4 %[[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_S<wbr>TRONG]]* %[[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 @_Z21testParamWeakTemplate1SIU<wbr>6__weakP11objc_objectE(%[[STRU<wbr>CT_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" target="_blank">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></blockquote></div></div></div></div></blockquote></div><br></div></div></div></div><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>
<br></blockquote></div><br></div></div>