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