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.

Regards,
Eric

On Mon, Mar 12, 2018 at 4:51 PM Eric Liu <ioe...@google.com> wrote:

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

Reply via email to