r327206 - [ObjC] Allow declaring __weak pointer fields in C structs in ARC.

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 12 10:14:09 PDT 2018


Thanks a lot Akira!

FWIW, it seems that the FIXME here might be related
https://github.com/llvm-mirror/clang/blob/master/include/clang/AST/DeclCXX.h#L1484

On Mon, Mar 12, 2018 at 6:03 PM Akira Hatanaka <ahatanaka at apple.com> wrote:

> I’m not sure if this a bug r327206 introduced or an existing bug in
> ASTImporter as there are other bits in RecordDecl that are not copied, but
> I think I should revert the patch for now.
>
> On Mar 12, 2018, at 9:57 AM, Eric Liu <ioeric at google.com> wrote:
>
> I think it's likely as our tests only fail with module enabled (without
> module, ASTImporter isn't really used).
>
> On Mon, Mar 12, 2018 at 5:51 PM Akira Hatanaka <ahatanaka at apple.com>
> wrote:
>
>> 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.
>>
>> On Mar 12, 2018, at 9:29 AM, Eric Liu <ioeric at google.com> wrote:
>>
>> 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.
>>
>> Could you please also take a quick look to see if
>> ASTImporter/Reader/Writer is actually missing something?
>>
>> Thanks,
>> Eric
>>
>> On Mon, Mar 12, 2018 at 5:14 PM Akira Hatanaka <ahatanaka at apple.com>
>> wrote:
>>
>>> Do you have a reproducer?
>>>
>>>
>>> On Mar 12, 2018, at 9:07 AM, Eric Liu <ioeric at google.com> wrote:
>>>
>>> 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 <ioeric at 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 <ioeric at 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 at 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 at lists.llvm.org
>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>>>>
>>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180312/1f099577/attachment-0001.html>


More information about the cfe-commits mailing list