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 09:57:01 PDT 2018
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/9e8d9905/attachment-0001.html>
More information about the cfe-commits
mailing list