<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">The patch I committed moved CXXRecordDecl::CanPassInRegisters to RecordDecl. It looks like ASTImporter::ImportDefinition no longer copies the bit for CanPassInRegisters after that change. I’m not sure that is what’s causing tests to fail.</div><div dir="auto" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Mar 12, 2018, at 9:29 AM, Eric Liu <<a href="mailto:ioeric@google.com" class="">ioeric@google.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">I have been trying to reduce a reproducer for this but haven't gotten any luck yet. The error happens in conversion between different version of STL containers and is a bit hard to reduce. I'll keep trying to create a reproducer.<div class=""><br class=""></div><div class="">Could you please also take a quick look to see if ASTImporter/Reader/Writer is actually missing something?</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Eric<br class=""><div class=""><br class=""></div><div class=""><div class="gmail_quote"><div dir="ltr" class="">On Mon, Mar 12, 2018 at 5:14 PM Akira Hatanaka <<a href="mailto:ahatanaka@apple.com" target="_blank" class="">ahatanaka@apple.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space" class="">Do you have a reproducer?</div><div style="word-wrap:break-word;line-break:after-white-space" class=""><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Mar 12, 2018, at 9:07 AM, Eric Liu <<a href="mailto:ioeric@google.com" target="_blank" class="">ioeric@google.com</a>> wrote:</div><br class="m_7846865040433365454m_-1167700157740649905Apple-interchange-newline"><div class=""><div dir="ltr" class="">I think there is a bug in the ASTImporter/Reader/Writer, but I'm not sure what's the right way to fix it. I'll revert this commit for now to unblock integration. Let me know if you need more information from us.<div class=""><br class=""></div><div class="">Regards,</div><div class="">Eric<br class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">On Mon, Mar 12, 2018 at 4:51 PM Eric Liu <<a href="mailto:ioeric@google.com" target="_blank" class="">ioeric@google.com</a>> wrote:<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="">The tests only failed with module enabled. FWIW, I think the change in ASTImporter (<a href="https://reviews.llvm.org/rL327206#change-1q8vFFjJ6Cqk" target="_blank" class="">https://reviews.llvm.org/rL327206#change-1q8vFFjJ6Cqk</a>) needs additional changes to make imports work for RecordDecl. </div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Mon, Mar 12, 2018 at 3:56 PM Eric Liu <<a href="mailto:ioeric@google.com" target="_blank" class="">ioeric@google.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="">Hi Akira,<div class=""><br class=""></div><div class="">It seems that this commit also changes behavior for compiling C++ code as we are seeing test failures caused by this change in our internal tests.</div><div class=""><br class=""></div><div class="">I'm still trying to reduce a reproducer for the failure. In the meantime, could you please double check if this affects C++?</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Eric</div></div><div dir="ltr" class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Sat, Mar 10, 2018 at 7:38 AM Akira Hatanaka via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ahatanak<br class="">
Date: Fri Mar  9 22:36:08 2018<br class="">
New Revision: 327206<br class="">
<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=327206&view=rev" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=327206&view=rev</a><br class="">
Log:<br class="">
[ObjC] Allow declaring __weak pointer fields in C structs in ARC.<br class="">
<br class="">
This patch uses the infrastructure added in r326307 for enabling<br class="">
non-trivial fields to be declared in C structs to allow __weak fields in<br class="">
C structs in ARC.<br class="">
<br class="">
<a class="">rdar://problem/33599681</a><br class="">
<br class="">
Differential Revision: <a href="https://reviews.llvm.org/D44095" rel="noreferrer" target="_blank" class="">https://reviews.llvm.org/D44095</a><br class="">
<br class="">
Added:<br class="">
    cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m<br class="">
Modified:<br class="">
    cfe/trunk/include/clang/AST/Decl.h<br class="">
    cfe/trunk/include/clang/AST/DeclCXX.h<br class="">
    cfe/trunk/include/clang/AST/Type.h<br class="">
    cfe/trunk/lib/AST/ASTImporter.cpp<br class="">
    cfe/trunk/lib/AST/Decl.cpp<br class="">
    cfe/trunk/lib/AST/DeclCXX.cpp<br class="">
    cfe/trunk/lib/AST/Type.cpp<br class="">
    cfe/trunk/lib/CodeGen/CGBlocks.cpp<br class="">
    cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp<br class="">
    cfe/trunk/lib/CodeGen/CGObjC.cpp<br class="">
    cfe/trunk/lib/CodeGen/CodeGenFunction.h<br class="">
    cfe/trunk/lib/CodeGen/TargetInfo.cpp<br class="">
    cfe/trunk/lib/Sema/SemaDecl.cpp<br class="">
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br class="">
    cfe/trunk/lib/Serialization/ASTWriter.cpp<br class="">
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp<br class="">
    cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m<br class="">
<br class="">
Modified: cfe/trunk/include/clang/AST/Decl.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/AST/Decl.h (original)<br class="">
+++ cfe/trunk/include/clang/AST/Decl.h Fri Mar  9 22:36:08 2018<br class="">
@@ -3553,6 +3553,12 @@ class RecordDecl : public TagDecl {<br class="">
   bool NonTrivialToPrimitiveCopy : 1;<br class="">
   bool NonTrivialToPrimitiveDestroy : 1;<br class="">
<br class="">
+  /// True if this class can be passed in a non-address-preserving fashion<br class="">
+  /// (such as in registers).<br class="">
+  /// This does not imply anything about how the ABI in use will actually<br class="">
+  /// pass an object of this class.<br class="">
+  bool CanPassInRegisters : 1;<br class="">
+<br class="">
 protected:<br class="">
   RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,<br class="">
              SourceLocation StartLoc, SourceLocation IdLoc,<br class="">
@@ -3636,6 +3642,18 @@ public:<br class="">
     NonTrivialToPrimitiveDestroy = true;<br class="">
   }<br class="">
<br class="">
+  /// Determine whether this class can be passed in registers. In C++ mode,<br class="">
+  /// it must have at least one trivial, non-deleted copy or move constructor.<br class="">
+  /// FIXME: This should be set as part of completeDefinition.<br class="">
+  bool canPassInRegisters() const {<br class="">
+    return CanPassInRegisters;<br class="">
+  }<br class="">
+<br class="">
+  /// Set that we can pass this RecordDecl in registers.<br class="">
+  void setCanPassInRegisters(bool CanPass) {<br class="">
+    CanPassInRegisters = CanPass;<br class="">
+  }<br class="">
+<br class="">
   /// \brief Determines whether this declaration represents the<br class="">
   /// injected class name.<br class="">
   ///<br class="">
<br class="">
Modified: cfe/trunk/include/clang/AST/DeclCXX.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)<br class="">
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Mar  9 22:36:08 2018<br class="">
@@ -467,12 +467,6 @@ class CXXRecordDecl : public RecordDecl<br class="">
     /// constructor.<br class="">
     unsigned HasDefaultedDefaultConstructor : 1;<br class="">
<br class="">
-    /// \brief True if this class can be passed in a non-address-preserving<br class="">
-    /// fashion (such as in registers) according to the C++ language rules.<br class="">
-    /// This does not imply anything about how the ABI in use will actually<br class="">
-    /// pass an object of this class.<br class="">
-    unsigned CanPassInRegisters : 1;<br class="">
-<br class="">
     /// \brief True if a defaulted default constructor for this class would<br class="">
     /// be constexpr.<br class="">
     unsigned DefaultedDefaultConstructorIsConstexpr : 1;<br class="">
@@ -1474,18 +1468,6 @@ public:<br class="">
     return data().HasIrrelevantDestructor;<br class="">
   }<br class="">
<br class="">
-  /// \brief Determine whether this class has at least one trivial, non-deleted<br class="">
-  /// copy or move constructor.<br class="">
-  bool canPassInRegisters() const {<br class="">
-    return data().CanPassInRegisters;<br class="">
-  }<br class="">
-<br class="">
-  /// \brief Set that we can pass this RecordDecl in registers.<br class="">
-  // FIXME: This should be set as part of completeDefinition.<br class="">
-  void setCanPassInRegisters(bool CanPass) {<br class="">
-    data().CanPassInRegisters = CanPass;<br class="">
-  }<br class="">
-<br class="">
   /// Determine whether the triviality for the purpose of calls for this class<br class="">
   /// is overridden to be trivial because this class or the type of one of its<br class="">
   /// subobjects has attribute "trivial_abi".<br class="">
<br class="">
Modified: cfe/trunk/include/clang/AST/Type.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/AST/Type.h (original)<br class="">
+++ cfe/trunk/include/clang/AST/Type.h Fri Mar  9 22:36:08 2018<br class="">
@@ -1097,6 +1097,10 @@ public:<br class="">
     /// with the ARC __strong qualifier.<br class="">
     PDIK_ARCStrong,<br class="">
<br class="">
+    /// The type is an Objective-C retainable pointer type that is qualified<br class="">
+    /// with the ARC __weak qualifier.<br class="">
+    PDIK_ARCWeak,<br class="">
+<br class="">
     /// The type is a struct containing a field whose type is not PCK_Trivial.<br class="">
     PDIK_Struct<br class="">
   };<br class="">
@@ -1124,6 +1128,10 @@ public:<br class="">
     /// with the ARC __strong qualifier.<br class="">
     PCK_ARCStrong,<br class="">
<br class="">
+    /// The type is an Objective-C retainable pointer type that is qualified<br class="">
+    /// with the ARC __weak qualifier.<br class="">
+    PCK_ARCWeak,<br class="">
+<br class="">
     /// The type is a struct containing a field whose type is neither<br class="">
     /// PCK_Trivial nor PCK_VolatileTrivial.<br class="">
     /// Note that a C++ struct type does not necessarily match this; C++ copying<br class="">
@@ -1146,6 +1154,8 @@ public:<br class="">
   /// source object is placed in an uninitialized state.<br class="">
   PrimitiveCopyKind isNonTrivialToPrimitiveDestructiveMove() const;<br class="">
<br class="">
+  bool canPassInRegisters() const;<br class="">
+<br class="">
   enum DestructionKind {<br class="">
     DK_none,<br class="">
     DK_cxx_destructor,<br class="">
<br class="">
Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br class="">
+++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -1105,7 +1105,6 @@ bool ASTNodeImporter::ImportDefinition(R<br class="">
       = FromData.HasConstexprNonCopyMoveConstructor;<br class="">
     ToData.HasDefaultedDefaultConstructor<br class="">
       = FromData.HasDefaultedDefaultConstructor;<br class="">
-    ToData.CanPassInRegisters = FromData.CanPassInRegisters;<br class="">
     ToData.DefaultedDefaultConstructorIsConstexpr<br class="">
       = FromData.DefaultedDefaultConstructorIsConstexpr;<br class="">
     ToData.HasConstexprDefaultConstructor<br class="">
<br class="">
Modified: cfe/trunk/lib/AST/Decl.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/AST/Decl.cpp (original)<br class="">
+++ cfe/trunk/lib/AST/Decl.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -3931,7 +3931,8 @@ RecordDecl::RecordDecl(Kind DK, TagKind<br class="">
       HasObjectMember(false), HasVolatileMember(false),<br class="">
       LoadedFieldsFromExternalStorage(false),<br class="">
       NonTrivialToPrimitiveDefaultInitialize(false),<br class="">
-      NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false) {<br class="">
+      NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),<br class="">
+      CanPassInRegisters(true) {<br class="">
   assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");<br class="">
 }<br class="">
<br class="">
<br class="">
Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)<br class="">
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -93,7 +93,6 @@ CXXRecordDecl::DefinitionData::Definitio<br class="">
       DeclaredNonTrivialSpecialMembersForCall(0), HasIrrelevantDestructor(true),<br class="">
       HasConstexprNonCopyMoveConstructor(false),<br class="">
       HasDefaultedDefaultConstructor(false),<br class="">
-      CanPassInRegisters(true),<br class="">
       DefaultedDefaultConstructorIsConstexpr(true),<br class="">
       HasConstexprDefaultConstructor(false),<br class="">
       HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),<br class="">
<br class="">
Modified: cfe/trunk/lib/AST/Type.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/AST/Type.cpp (original)<br class="">
+++ cfe/trunk/lib/AST/Type.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -2214,11 +2214,14 @@ QualType::isNonTrivialToPrimitiveDefault<br class="">
     if (RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize())<br class="">
       return PDIK_Struct;<br class="">
<br class="">
-  Qualifiers::ObjCLifetime Lifetime = getQualifiers().getObjCLifetime();<br class="">
-  if (Lifetime == Qualifiers::OCL_Strong)<br class="">
+  switch (getQualifiers().getObjCLifetime()) {<br class="">
+  case Qualifiers::OCL_Strong:<br class="">
     return PDIK_ARCStrong;<br class="">
-<br class="">
-  return PDIK_Trivial;<br class="">
+  case Qualifiers::OCL_Weak:<br class="">
+    return PDIK_ARCWeak;<br class="">
+  default:<br class="">
+    return PDIK_Trivial;<br class="">
+  }<br class="">
 }<br class="">
<br class="">
 QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const {<br class="">
@@ -2228,10 +2231,14 @@ QualType::PrimitiveCopyKind QualType::is<br class="">
       return PCK_Struct;<br class="">
<br class="">
   Qualifiers Qs = getQualifiers();<br class="">
-  if (Qs.getObjCLifetime() == Qualifiers::OCL_Strong)<br class="">
+  switch (Qs.getObjCLifetime()) {<br class="">
+  case Qualifiers::OCL_Strong:<br class="">
     return PCK_ARCStrong;<br class="">
-<br class="">
-  return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;<br class="">
+  case Qualifiers::OCL_Weak:<br class="">
+    return PCK_ARCWeak;<br class="">
+  default:<br class="">
+    return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;<br class="">
+  }<br class="">
 }<br class="">
<br class="">
 QualType::PrimitiveCopyKind<br class="">
@@ -2239,6 +2246,17 @@ QualType::isNonTrivialToPrimitiveDestruc<br class="">
   return isNonTrivialToPrimitiveCopy();<br class="">
 }<br class="">
<br class="">
+bool QualType::canPassInRegisters() const {<br class="">
+  if (const auto *RT =<br class="">
+          getTypePtr()->getBaseElementTypeUnsafe()->getAs<RecordType>())<br class="">
+    return RT->getDecl()->canPassInRegisters();<br class="">
+<br class="">
+  if (getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak)<br class="">
+    return false;<br class="">
+<br class="">
+  return true;<br class="">
+}<br class="">
+<br class="">
 bool Type::isLiteralType(const ASTContext &Ctx) const {<br class="">
   if (isDependentType())<br class="">
     return false;<br class="">
<br class="">
Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)<br class="">
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -1525,6 +1525,9 @@ computeCopyInfoForBlockCapture(const Blo<br class="">
   case QualType::PCK_Struct:<br class="">
     return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,<br class="">
                           BlockFieldFlags());<br class="">
+  case QualType::PCK_ARCWeak:<br class="">
+    // We need to register __weak direct captures with the runtime.<br class="">
+    return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);<br class="">
   case QualType::PCK_ARCStrong:<br class="">
     // We need to retain the copied value for __strong direct captures.<br class="">
     // If it's a block pointer, we have to copy the block and assign that to<br class="">
@@ -1542,10 +1545,6 @@ computeCopyInfoForBlockCapture(const Blo<br class="">
     // Special rules for ARC captures:<br class="">
     Qualifiers QS = T.getQualifiers();<br class="">
<br class="">
-    // We need to register __weak direct captures with the runtime.<br class="">
-    if (QS.getObjCLifetime() == Qualifiers::OCL_Weak)<br class="">
-      return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);<br class="">
-<br class="">
     // Non-ARC captures of retainable pointers are strong and<br class="">
     // therefore require a call to _Block_object_assign.<br class="">
     if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount)<br class="">
<br class="">
Modified: cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp (original)<br class="">
+++ cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -77,6 +77,8 @@ struct DefaultInitializedTypeVisitor {<br class="">
     switch (PDIK) {<br class="">
     case QualType::PDIK_ARCStrong:<br class="">
       return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);<br class="">
+    case QualType::PDIK_ARCWeak:<br class="">
+      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);<br class="">
     case QualType::PDIK_Struct:<br class="">
       return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);<br class="">
     case QualType::PDIK_Trivial:<br class="">
@@ -108,6 +110,8 @@ struct CopiedTypeVisitor {<br class="">
     switch (PCK) {<br class="">
     case QualType::PCK_ARCStrong:<br class="">
       return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);<br class="">
+    case QualType::PCK_ARCWeak:<br class="">
+      return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);<br class="">
     case QualType::PCK_Struct:<br class="">
       return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);<br class="">
     case QualType::PCK_Trivial:<br class="">
@@ -141,11 +145,6 @@ template <class Derived> struct StructVi<br class="">
<br class="">
   template <class... Ts> void visitTrivial(Ts... Args) {}<br class="">
<br class="">
-  template <class... Ts> void visitARCWeak(Ts... Args) {<br class="">
-    // FIXME: remove this when visitARCWeak is implemented in the subclasses.<br class="">
-    llvm_unreachable("weak field is not expected");<br class="">
-  }<br class="">
-<br class="">
   template <class... Ts> void visitCXXDestructor(Ts... Args) {<br class="">
     llvm_unreachable("field of a C++ struct type is not expected");<br class="">
   }<br class="">
@@ -245,6 +244,13 @@ template <class Derived> struct GenFuncN<br class="">
     appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));<br class="">
   }<br class="">
<br class="">
+  void visitARCWeak(QualType FT, const FieldDecl *FD,<br class="">
+                    CharUnits CurStructOffset) {<br class="">
+    appendStr("_w");<br class="">
+    CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);<br class="">
+    appendStr(getVolatileOffsetStr(FT.isVolatileQualified(), FieldOffset));<br class="">
+  }<br class="">
+<br class="">
   void visitStruct(QualType QT, const FieldDecl *FD,<br class="">
                    CharUnits CurStructOffset) {<br class="">
     CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);<br class="">
@@ -615,6 +621,12 @@ struct GenDestructor : StructVisitor<Gen<br class="">
         *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);<br class="">
   }<br class="">
<br class="">
+  void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,<br class="">
+                    std::array<Address, 1> Addrs) {<br class="">
+    CGF->destroyARCWeak(<br class="">
+        *CGF, getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);<br class="">
+  }<br class="">
+<br class="">
   void callSpecialFunction(QualType FT, CharUnits Offset,<br class="">
                            std::array<Address, 1> Addrs) {<br class="">
     CGF->callCStructDestructor(<br class="">
@@ -636,6 +648,12 @@ struct GenDefaultInitialize<br class="">
         getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);<br class="">
   }<br class="">
<br class="">
+  void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,<br class="">
+                    std::array<Address, 1> Addrs) {<br class="">
+    CGF->EmitNullInitialization(<br class="">
+        getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD), QT);<br class="">
+  }<br class="">
+<br class="">
   template <class FieldKind, size_t... Is><br class="">
   void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,<br class="">
                   CharUnits CurStackOffset, std::array<Address, 1> Addrs) {<br class="">
@@ -678,6 +696,14 @@ struct GenCopyConstructor : GenBinaryFun<br class="">
     llvm::Value *Val = CGF->EmitARCRetain(QT, SrcVal);<br class="">
     CGF->EmitStoreOfScalar(Val, CGF->MakeAddrLValue(Addrs[DstIdx], QT), true);<br class="">
   }<br class="">
+<br class="">
+  void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,<br class="">
+                    std::array<Address, 2> Addrs) {<br class="">
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);<br class="">
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);<br class="">
+    CGF->EmitARCCopyWeak(Addrs[DstIdx], Addrs[SrcIdx]);<br class="">
+  }<br class="">
+<br class="">
   void callSpecialFunction(QualType FT, CharUnits Offset,<br class="">
                            std::array<Address, 2> Addrs) {<br class="">
     CGF->callCStructCopyConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),<br class="">
@@ -700,6 +726,14 @@ struct GenMoveConstructor : GenBinaryFun<br class="">
     CGF->EmitStoreOfScalar(SrcVal, CGF->MakeAddrLValue(Addrs[DstIdx], QT),<br class="">
                            /* isInitialization */ true);<br class="">
   }<br class="">
+<br class="">
+  void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,<br class="">
+                    std::array<Address, 2> Addrs) {<br class="">
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);<br class="">
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);<br class="">
+    CGF->EmitARCMoveWeak(Addrs[DstIdx], Addrs[SrcIdx]);<br class="">
+  }<br class="">
+<br class="">
   void callSpecialFunction(QualType FT, CharUnits Offset,<br class="">
                            std::array<Address, 2> Addrs) {<br class="">
     CGF->callCStructMoveConstructor(CGF->MakeAddrLValue(Addrs[DstIdx], FT),<br class="">
@@ -720,6 +754,14 @@ struct GenCopyAssignment : GenBinaryFunc<br class="">
     CGF->EmitARCStoreStrong(CGF->MakeAddrLValue(Addrs[DstIdx], QT), SrcVal,<br class="">
                             false);<br class="">
   }<br class="">
+<br class="">
+  void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,<br class="">
+                    std::array<Address, 2> Addrs) {<br class="">
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);<br class="">
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);<br class="">
+    CGF->emitARCCopyAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);<br class="">
+  }<br class="">
+<br class="">
   void callSpecialFunction(QualType FT, CharUnits Offset,<br class="">
                            std::array<Address, 2> Addrs) {<br class="">
     CGF->callCStructCopyAssignmentOperator(<br class="">
@@ -747,6 +789,13 @@ struct GenMoveAssignment : GenBinaryFunc<br class="">
     CGF->EmitARCRelease(DstVal, ARCImpreciseLifetime);<br class="">
   }<br class="">
<br class="">
+  void visitARCWeak(QualType QT, const FieldDecl *FD, CharUnits CurStackOffset,<br class="">
+                    std::array<Address, 2> Addrs) {<br class="">
+    Addrs[DstIdx] = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);<br class="">
+    Addrs[SrcIdx] = getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);<br class="">
+    CGF->emitARCMoveAssignWeak(QT, Addrs[DstIdx], Addrs[SrcIdx]);<br class="">
+  }<br class="">
+<br class="">
   void callSpecialFunction(QualType FT, CharUnits Offset,<br class="">
                            std::array<Address, 2> Addrs) {<br class="">
     CGF->callCStructMoveAssignmentOperator(<br class="">
<br class="">
Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)<br class="">
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -2307,6 +2307,21 @@ void CodeGenFunction::EmitARCCopyWeak(Ad<br class="">
                        "objc_copyWeak");<br class="">
 }<br class="">
<br class="">
+void CodeGenFunction::emitARCCopyAssignWeak(QualType Ty, Address DstAddr,<br class="">
+                                            Address SrcAddr) {<br class="">
+  llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr);<br class="">
+  Object = EmitObjCConsumeObject(Ty, Object);<br class="">
+  EmitARCStoreWeak(DstAddr, Object, false);<br class="">
+}<br class="">
+<br class="">
+void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr,<br class="">
+                                            Address SrcAddr) {<br class="">
+  llvm::Value *Object = EmitARCLoadWeakRetained(SrcAddr);<br class="">
+  Object = EmitObjCConsumeObject(Ty, Object);<br class="">
+  EmitARCStoreWeak(DstAddr, Object, false);<br class="">
+  EmitARCDestroyWeak(SrcAddr);<br class="">
+}<br class="">
+<br class="">
 /// Produce the code to do a objc_autoreleasepool_push.<br class="">
 ///   call i8* \@objc_autoreleasePoolPush(void)<br class="">
 llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {<br class="">
<br class="">
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)<br class="">
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Mar  9 22:36:08 2018<br class="">
@@ -3548,6 +3548,8 @@ public:<br class="">
   llvm::Value *EmitARCLoadWeak(Address addr);<br class="">
   llvm::Value *EmitARCLoadWeakRetained(Address addr);<br class="">
   llvm::Value *EmitARCStoreWeak(Address addr, llvm::Value *value, bool ignored);<br class="">
+  void emitARCCopyAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr);<br class="">
+  void emitARCMoveAssignWeak(QualType Ty, Address DstAddr, Address SrcAddr);<br class="">
   void EmitARCCopyWeak(Address dst, Address src);<br class="">
   void EmitARCMoveWeak(Address dst, Address src);<br class="">
   llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value);<br class="">
<br class="">
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)<br class="">
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -140,8 +140,11 @@ bool SwiftABIInfo::isLegalVectorTypeForS<br class="">
 static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,<br class="">
                                               CGCXXABI &CXXABI) {<br class="">
   const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());<br class="">
-  if (!RD)<br class="">
+  if (!RD) {<br class="">
+    if (!RT->getDecl()->canPassInRegisters())<br class="">
+      return CGCXXABI::RAA_Indirect;<br class="">
     return CGCXXABI::RAA_Default;<br class="">
+  }<br class="">
   return CXXABI.getRecordArgABI(RD);<br class="">
 }<br class="">
<br class="">
@@ -153,6 +156,20 @@ static CGCXXABI::RecordArgABI getRecordA<br class="">
   return getRecordArgABI(RT, CXXABI);<br class="">
 }<br class="">
<br class="">
+static bool classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI,<br class="">
+                               const ABIInfo &Info) {<br class="">
+  QualType Ty = FI.getReturnType();<br class="">
+<br class="">
+  if (const auto *RT = Ty->getAs<RecordType>())<br class="">
+    if (!isa<CXXRecordDecl>(RT->getDecl()) &&<br class="">
+        !RT->getDecl()->canPassInRegisters()) {<br class="">
+      FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty);<br class="">
+      return true;<br class="">
+    }<br class="">
+<br class="">
+  return CXXABI.classifyReturnType(FI);<br class="">
+}<br class="">
+<br class="">
 /// Pass transparent unions as if they were the type of the first element. Sema<br class="">
 /// should ensure that all elements of the union have the same "machine type".<br class="">
 static QualType useFirstFieldIfTransparentUnion(QualType Ty) {<br class="">
@@ -1749,7 +1766,7 @@ void X86_32ABIInfo::computeInfo(CGFuncti<br class="">
   } else<br class="">
     State.FreeRegs = DefaultNumRegisterParameters;<br class="">
<br class="">
-  if (!getCXXABI().classifyReturnType(FI)) {<br class="">
+  if (!::classifyReturnType(getCXXABI(), FI, *this)) {<br class="">
     FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);<br class="">
   } else if (FI.getReturnInfo().isIndirect()) {<br class="">
     // The C++ ABI is not aware of register usage, so we have to check if the<br class="">
@@ -3545,7 +3562,7 @@ void X86_64ABIInfo::computeInfo(CGFuncti<br class="">
   unsigned FreeSSERegs = IsRegCall ? 16 : 8;<br class="">
   unsigned NeededInt, NeededSSE;<br class="">
<br class="">
-  if (!getCXXABI().classifyReturnType(FI)) {<br class="">
+  if (!::classifyReturnType(getCXXABI(), FI, *this)) {<br class="">
     if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&<br class="">
         !FI.getReturnType()->getTypePtr()->isUnionType()) {<br class="">
       FI.getReturnInfo() =<br class="">
@@ -4895,7 +4912,7 @@ private:<br class="">
   bool isIllegalVectorType(QualType Ty) const;<br class="">
<br class="">
   void computeInfo(CGFunctionInfo &FI) const override {<br class="">
-    if (!getCXXABI().classifyReturnType(FI))<br class="">
+    if (!::classifyReturnType(getCXXABI(), FI, *this))<br class="">
       FI.getReturnInfo() = classifyReturnType(FI.getReturnType());<br class="">
<br class="">
     for (auto &it : FI.arguments())<br class="">
@@ -5626,7 +5643,7 @@ void WindowsARMTargetCodeGenInfo::setTar<br class="">
 }<br class="">
<br class="">
 void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {<br class="">
-  if (!getCXXABI().classifyReturnType(FI))<br class="">
+  if (!::classifyReturnType(getCXXABI(), FI, *this))<br class="">
     FI.getReturnInfo() =<br class="">
         classifyReturnType(FI.getReturnType(), FI.isVariadic());<br class="">
<br class="">
<br class="">
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br class="">
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -15260,7 +15260,6 @@ void Sema::ActOnFields(Scope *S, SourceL<br class="">
<br class="">
     // Get the type for the field.<br class="">
     const Type *FDTy = FD->getType().getTypePtr();<br class="">
-    Qualifiers QS = FD->getType().getQualifiers();<br class="">
<br class="">
     if (!FD->isAnonymousStructOrUnion()) {<br class="">
       // Remember all fields written by the user.<br class="">
@@ -15401,10 +15400,7 @@ void Sema::ActOnFields(Scope *S, SourceL<br class="">
       QualType T = Context.getObjCObjectPointerType(FD->getType());<br class="">
       FD->setType(T);<br class="">
     } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&<br class="">
-               Record && !ObjCFieldLifetimeErrReported &&<br class="">
-               ((!getLangOpts().CPlusPlus &&<br class="">
-                 QS.getObjCLifetime() == Qualifiers::OCL_Weak) ||<br class="">
-                Record->isUnion())) {<br class="">
+               Record && !ObjCFieldLifetimeErrReported && Record->isUnion()) {<br class="">
       // It's an error in ARC or Weak if a field has lifetime.<br class="">
       // We don't want to report this in a system header, though,<br class="">
       // so we just make the field unavailable.<br class="">
@@ -15450,6 +15446,8 @@ void Sema::ActOnFields(Scope *S, SourceL<br class="">
         Record->setNonTrivialToPrimitiveCopy();<br class="">
       if (FT.isDestructedType())<br class="">
         Record->setNonTrivialToPrimitiveDestroy();<br class="">
+      if (!FT.canPassInRegisters())<br class="">
+        Record->setCanPassInRegisters(false);<br class="">
     }<br class="">
<br class="">
     if (Record && FD->getType().isVolatileQualified())<br class="">
<br class="">
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)<br class="">
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -739,6 +739,7 @@ ASTDeclReader::VisitRecordDeclImpl(Recor<br class="">
   RD->setAnonymousStructOrUnion(Record.readInt());<br class="">
   RD->setHasObjectMember(Record.readInt());<br class="">
   RD->setHasVolatileMember(Record.readInt());<br class="">
+  RD->setCanPassInRegisters(Record.readInt());<br class="">
   return Redecl;<br class="">
 }<br class="">
<br class="">
@@ -1584,7 +1585,6 @@ void ASTDeclReader::ReadCXXDefinitionDat<br class="">
   Data.HasIrrelevantDestructor = Record.readInt();<br class="">
   Data.HasConstexprNonCopyMoveConstructor = Record.readInt();<br class="">
   Data.HasDefaultedDefaultConstructor = Record.readInt();<br class="">
-  Data.CanPassInRegisters = Record.readInt();<br class="">
   Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();<br class="">
   Data.HasConstexprDefaultConstructor = Record.readInt();<br class="">
   Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();<br class="">
@@ -1724,7 +1724,6 @@ void ASTDeclReader::MergeDefinitionData(<br class="">
   MATCH_FIELD(HasIrrelevantDestructor)<br class="">
   OR_FIELD(HasConstexprNonCopyMoveConstructor)<br class="">
   OR_FIELD(HasDefaultedDefaultConstructor)<br class="">
-  MATCH_FIELD(CanPassInRegisters)<br class="">
   MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)<br class="">
   OR_FIELD(HasConstexprDefaultConstructor)<br class="">
   MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)<br class="">
<br class="">
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br class="">
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -6018,7 +6018,6 @@ void ASTRecordWriter::AddCXXDefinitionDa<br class="">
   Record->push_back(Data.HasIrrelevantDestructor);<br class="">
   Record->push_back(Data.HasConstexprNonCopyMoveConstructor);<br class="">
   Record->push_back(Data.HasDefaultedDefaultConstructor);<br class="">
-  Record->push_back(Data.CanPassInRegisters);<br class="">
   Record->push_back(Data.DefaultedDefaultConstructorIsConstexpr);<br class="">
   Record->push_back(Data.HasConstexprDefaultConstructor);<br class="">
   Record->push_back(Data.HasNonLiteralTypeFieldsOrBases);<br class="">
<br class="">
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)<br class="">
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Mar  9 22:36:08 2018<br class="">
@@ -465,6 +465,7 @@ void ASTDeclWriter::VisitRecordDecl(Reco<br class="">
   Record.push_back(D->isAnonymousStructOrUnion());<br class="">
   Record.push_back(D->hasObjectMember());<br class="">
   Record.push_back(D->hasVolatileMember());<br class="">
+  Record.push_back(D->canPassInRegisters());<br class="">
<br class="">
   if (D->getDeclContext() == D->getLexicalDeclContext() &&<br class="">
       !D->hasAttrs() &&<br class="">
@@ -1899,6 +1900,7 @@ void ASTWriter::WriteDeclAbbrevs() {<br class="">
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion<br class="">
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasObjectMember<br class="">
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasVolatileMember<br class="">
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // canPassInRegisters<br class="">
   // DC<br class="">
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset<br class="">
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // VisibleOffset<br class="">
<br class="">
Modified: cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m?rev=327206&r1=327205&r2=327206&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m?rev=327206&r1=327205&r2=327206&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m (original)<br class="">
+++ cfe/trunk/test/CodeGenObjC/nontrivial-c-struct-exception.m Fri Mar  9 22:36:08 2018<br class="">
@@ -1,12 +1,18 @@<br class="">
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -fobjc-exceptions -fexceptions -fobjc-arc-exceptions -emit-llvm -o - %s | FileCheck %s<br class="">
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -fobjc-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s<br class="">
<br class="">
 // CHECK: %[[STRUCT_STRONG:.*]] = type { i32, i8* }<br class="">
+// CHECK: %[[STRUCT_WEAK:.*]] = type { i32, i8* }<br class="">
<br class="">
 typedef struct {<br class="">
   int i;<br class="">
   id f1;<br class="">
 } Strong;<br class="">
<br class="">
+typedef struct {<br class="">
+  int i;<br class="">
+  __weak id f1;<br class="">
+} Weak;<br class="">
+<br class="">
 // CHECK: define void @testStrongException()<br class="">
 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8<br class="">
 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_STRONG]], align 8<br class="">
@@ -31,3 +37,26 @@ void calleeStrong(Strong, Strong);<br class="">
 void testStrongException(void) {<br class="">
   calleeStrong(genStrong(), genStrong());<br class="">
 }<br class="">
+<br class="">
+// CHECK: define void @testWeakException()<br class="">
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]], align 8<br class="">
+// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_WEAK]], align 8<br class="">
+// CHECK: call void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP]])<br class="">
+// CHECK: invoke void @genWeak(%[[STRUCT_WEAK]]* sret %[[AGG_TMP1]])<br class="">
+<br class="">
+// CHECK: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]], %[[STRUCT_WEAK]]* %[[AGG_TMP1]])<br class="">
+// CHECK: ret void<br class="">
+<br class="">
+// CHECK: landingpad { i8*, i32 }<br class="">
+// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8**<br class="">
+// CHECK: call void @__destructor_8_w8(i8** %[[V3]])<br class="">
+// CHECK: br label<br class="">
+<br class="">
+// CHECK: resume<br class="">
+<br class="">
+Weak genWeak(void);<br class="">
+void calleeWeak(Weak, Weak);<br class="">
+<br class="">
+void testWeakException(void) {<br class="">
+  calleeWeak(genWeak(), genWeak());<br class="">
+}<br class="">
<br class="">
Added: cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m?rev=327206&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m?rev=327206&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m (added)<br class="">
+++ cfe/trunk/test/CodeGenObjC/weak-in-c-struct.m Fri Mar  9 22:36:08 2018<br class="">
@@ -0,0 +1,193 @@<br class="">
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - %s | FileCheck -check-prefix=ARM64 -check-prefix=COMMON %s<br class="">
+// RUN: %clang_cc1 -triple thumbv7-apple-ios10 -fobjc-arc -fblocks -fobjc-runtime=ios-10.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s<br class="">
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.13 -fobjc-arc -fblocks -fobjc-runtime=macosx-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s<br class="">
+// RUN: %clang_cc1 -triple i386-apple-macosx10.13.0 -fobjc-arc -fblocks -fobjc-runtime=macosx-fragile-10.13.0 -emit-llvm -o - %s | FileCheck -check-prefix=COMMON %s<br class="">
+<br class="">
+typedef void (^BlockTy)(void);<br class="">
+<br class="">
+// COMMON: %[[STRUCT_WEAK:.*]] = type { i32, i8* }<br class="">
+<br class="">
+typedef struct {<br class="">
+  int f0;<br class="">
+  __weak id f1;<br class="">
+} Weak;<br class="">
+<br class="">
+Weak getWeak(void);<br class="">
+void calleeWeak(Weak);<br class="">
+<br class="">
+// ARM64: define void @test_constructor_destructor_Weak()<br class="">
+// ARM64: %[[T:.*]] = alloca %[[STRUCT_WEAK]], align 8<br class="">
+// ARM64: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8**<br class="">
+// ARM64: call void @__default_constructor_8_w8(i8** %[[V0]])<br class="">
+// ARM64: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[T]] to i8**<br class="">
+// ARM64: call void @__destructor_8_w8(i8** %[[V1]])<br class="">
+// ARM64: ret void<br class="">
+<br class="">
+// ARM64: define linkonce_odr hidden void @__default_constructor_8_w8(i8** %[[DST:.*]])<br class="">
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V1]] = bitcast i8** %[[V0]] to i8*<br class="">
+// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8<br class="">
+// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**<br class="">
+// ARM64: %[[V4:.*]] = bitcast i8** %[[V3]] to i8*<br class="">
+// ARM64: call void @llvm.memset.p0i8.i64(i8* align 8 %[[V4]], i8 0, i64 8, i1 false)<br class="">
+<br class="">
+// ARM64: define linkonce_odr hidden void @__destructor_8_w8(i8** %[[DST:.*]])<br class="">
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V1:.*]] = bitcast i8** %[[V0]] to i8*<br class="">
+// ARM64: %[[V2:.*]] = getelementptr inbounds i8, i8* %[[V1]], i64 8<br class="">
+// ARM64: %[[V3:.*]] = bitcast i8* %[[V2]] to i8**<br class="">
+// ARM64: call void @objc_destroyWeak(i8** %[[V3]])<br class="">
+<br class="">
+void test_constructor_destructor_Weak(void) {<br class="">
+  Weak t;<br class="">
+}<br class="">
+<br class="">
+// ARM64: define void @test_copy_constructor_Weak(%[[STRUCT_WEAK]]* %{{.*}})<br class="">
+// ARM64: call void @__copy_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})<br class="">
+// ARM64: call void @__destructor_8_w8(i8** %{{.*}})<br class="">
+<br class="">
+// ARM64: define linkonce_odr hidden void @__copy_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])<br class="">
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*<br class="">
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*<br class="">
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8<br class="">
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8<br class="">
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*<br class="">
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8<br class="">
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**<br class="">
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*<br class="">
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8<br class="">
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**<br class="">
+// ARM64: call void @objc_copyWeak(i8** %[[V7]], i8** %[[V10]])<br class="">
+<br class="">
+void test_copy_constructor_Weak(Weak *s) {<br class="">
+  Weak t = *s;<br class="">
+}<br class="">
+<br class="">
+// ARM64: define void @test_copy_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}}, %[[STRUCT_WEAK]]* %{{.*}})<br class="">
+// ARM64: call void @__copy_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})<br class="">
+<br class="">
+// ARM64: define linkonce_odr hidden void @__copy_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])<br class="">
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*<br class="">
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*<br class="">
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8<br class="">
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8<br class="">
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*<br class="">
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8<br class="">
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**<br class="">
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*<br class="">
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8<br class="">
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**<br class="">
+// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])<br class="">
+// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])<br class="">
+// ARM64: call void @objc_release(i8* %[[V11]])<br class="">
+<br class="">
+void test_copy_assignment_Weak(Weak *d, Weak *s) {<br class="">
+  *d = *s;<br class="">
+}<br class="">
+<br class="">
+// ARM64: define internal void @__Block_byref_object_copy_(i8*, i8*)<br class="">
+// ARM64: call void @__move_constructor_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})<br class="">
+<br class="">
+// ARM64: define linkonce_odr hidden void @__move_constructor_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])<br class="">
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*<br class="">
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*<br class="">
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8<br class="">
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8<br class="">
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*<br class="">
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8<br class="">
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**<br class="">
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*<br class="">
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8<br class="">
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**<br class="">
+// ARM64: call void @objc_moveWeak(i8** %[[V7]], i8** %[[V10]])<br class="">
+<br class="">
+void test_move_constructor_Weak(void) {<br class="">
+  __block Weak t;<br class="">
+  BlockTy b = ^{ (void)t; };<br class="">
+}<br class="">
+<br class="">
+// ARM64: define void @test_move_assignment_Weak(%[[STRUCT_WEAK]]* %{{.*}})<br class="">
+// ARM64: call void @__move_assignment_8_8_t0w4_w8(i8** %{{.*}}, i8** %{{.*}})<br class="">
+<br class="">
+// ARM64: define linkonce_odr hidden void @__move_assignment_8_8_t0w4_w8(i8** %[[DST:.*]], i8** %[[SRC:.*]])<br class="">
+// ARM64: %[[DST_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: %[[SRC_ADDR:.*]] = alloca i8**, align 8<br class="">
+// ARM64: store i8** %[[DST]], i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: store i8** %[[SRC]], i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V0:.*]] = load i8**, i8*** %[[DST_ADDR]], align 8<br class="">
+// ARM64: %[[V1:.*]] = load i8**, i8*** %[[SRC_ADDR]], align 8<br class="">
+// ARM64: %[[V2:.*]] = bitcast i8** %[[V0]] to i32*<br class="">
+// ARM64: %[[V3:.*]] = bitcast i8** %[[V1]] to i32*<br class="">
+// ARM64: %[[V4:.*]] = load i32, i32* %[[V3]], align 8<br class="">
+// ARM64: store i32 %[[V4]], i32* %[[V2]], align 8<br class="">
+// ARM64: %[[V5:.*]] = bitcast i8** %[[V0]] to i8*<br class="">
+// ARM64: %[[V6:.*]] = getelementptr inbounds i8, i8* %[[V5]], i64 8<br class="">
+// ARM64: %[[V7:.*]] = bitcast i8* %[[V6]] to i8**<br class="">
+// ARM64: %[[V8:.*]] = bitcast i8** %[[V1]] to i8*<br class="">
+// ARM64: %[[V9:.*]] = getelementptr inbounds i8, i8* %[[V8]], i64 8<br class="">
+// ARM64: %[[V10:.*]] = bitcast i8* %[[V9]] to i8**<br class="">
+// ARM64: %[[V11:.*]] = call i8* @objc_loadWeakRetained(i8** %[[V10]])<br class="">
+// ARM64: %[[V12:.*]] = call i8* @objc_storeWeak(i8** %[[V7]], i8* %[[V11]])<br class="">
+// ARM64: call void @objc_destroyWeak(i8** %[[V10]])<br class="">
+// ARM64: call void @objc_release(i8* %[[V11]])<br class="">
+<br class="">
+void test_move_assignment_Weak(Weak *p) {<br class="">
+  *p = getWeak();<br class="">
+}<br class="">
+<br class="">
+// COMMON: define void @test_parameter_Weak(%[[STRUCT_WEAK]]* %[[A:.*]])<br class="">
+// COMMON: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[A]] to i8**<br class="">
+// COMMON: call void @__destructor_{{.*}}(i8** %[[V0]])<br class="">
+<br class="">
+void test_parameter_Weak(Weak a) {<br class="">
+}<br class="">
+<br class="">
+// COMMON: define void @test_argument_Weak(%[[STRUCT_WEAK]]* %[[A:.*]])<br class="">
+// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]*<br class="">
+// COMMON: %[[AGG_TMP:.*]] = alloca %[[STRUCT_WEAK]]<br class="">
+// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]]<br class="">
+// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]]<br class="">
+// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_TMP]] to i8**<br class="">
+// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8**<br class="">
+// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]])<br class="">
+// COMMON: call void @calleeWeak(%[[STRUCT_WEAK]]* %[[AGG_TMP]])<br class="">
+// COMMON-NEXT: ret<br class="">
+<br class="">
+void test_argument_Weak(Weak *a) {<br class="">
+  calleeWeak(*a);<br class="">
+}<br class="">
+<br class="">
+// COMMON: define void @test_return_Weak(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]], %[[STRUCT_WEAK]]* %[[A:.*]])<br class="">
+// COMMON: %[[A_ADDR:.*]] = alloca %[[STRUCT_WEAK]]*<br class="">
+// COMMON: store %[[STRUCT_WEAK]]* %[[A]], %[[STRUCT_WEAK]]** %[[A_ADDR]]<br class="">
+// COMMON: %[[V0:.*]] = load %[[STRUCT_WEAK]]*, %[[STRUCT_WEAK]]** %[[A_ADDR]]<br class="">
+// COMMON: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8**<br class="">
+// COMMON: %[[V2:.*]] = bitcast %[[STRUCT_WEAK]]* %[[V0]] to i8**<br class="">
+// COMMON: call void @__copy_constructor_{{.*}}(i8** %[[V1]], i8** %[[V2]])<br class="">
+// COMMON: ret void<br class="">
+<br class="">
+Weak test_return_Weak(Weak *a) {<br class="">
+  return *a;<br class="">
+}<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
</blockquote></div></div></blockquote></div></blockquote></div></div></div></div></div>
</div></blockquote></div><br class=""></div></blockquote></div></div></div></div>
</div></blockquote></div><br class=""></div></body></html>