r329617 - [ObjC++] Never pass structs that transitively contain __weak fields in

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 9 15:53:49 PDT 2018


Sorry for the breakage, I reverted the patch in r329627 and reapplied it with a fix in r329635. Let me know if the tests are still failing.

> On Apr 9, 2018, at 3:47 PM, Galina Kistanova <gkistanova at gmail.com> wrote:
> 
> Hello Akira,
> 
> This commit added broken tests to one of our builders:
> http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/8964 <http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/8964>
> 
> Failing Tests (8):
>     Clang :: CodeGenObjCXX/objc-struct-cxx-abi.mm <http://objc-struct-cxx-abi.mm/>
>     Clang :: SemaObjCXX/attr-trivial-abi.mm <http://attr-trivial-abi.mm/>
> . . .
> Please have a look?
> 
> The builder was red and did not send notifications.
> 
> Thanks
> 
> Galina
> 
> On Mon, Apr 9, 2018 at 1:39 PM, Akira Hatanaka via cfe-commits <cfe-commits at lists.llvm.org <mailto:cfe-commits at lists.llvm.org>> wrote:
> Author: ahatanak
> Date: Mon Apr  9 13:39:47 2018
> New Revision: 329617
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=329617&view=rev <http://llvm.org/viewvc/llvm-project?rev=329617&view=rev>
> Log:
> [ObjC++] Never pass structs that transitively contain __weak fields in
> registers.
> 
> This patch fixes a bug in r328731 that caused structs transitively
> containing __weak fields to be passed in registers. The patch replaces
> the flag RecordDecl::CanPassInRegisters with a 2-bit enum that indicates
> whether the struct or structs containing the struct are forced to be
> passed indirectly.
> 
> rdar://problem/39194693
> 
> Modified:
>     cfe/trunk/include/clang/AST/Decl.h
>     cfe/trunk/include/clang/AST/Type.h
>     cfe/trunk/lib/AST/Decl.cpp
>     cfe/trunk/lib/AST/DeclCXX.cpp
>     cfe/trunk/lib/AST/Type.cpp
>     cfe/trunk/lib/Sema/SemaDecl.cpp
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>     cfe/trunk/lib/Serialization/ASTWriter.cpp
>     cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
>     cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm <http://objc-struct-cxx-abi.mm/>
> 
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Mon Apr  9 13:39:47 2018
> @@ -3541,6 +3541,31 @@ public:
>  ///   union Y { int A, B; };     // Has body with members A and B (FieldDecls).
>  /// This decl will be marked invalid if *any* members are invalid.
>  class RecordDecl : public TagDecl {
> +public:
> +  /// Enum that represents the different ways arguments are passed to and
> +  /// returned from function calls. This takes into account the target-specific
> +  /// and version-specific rules along with the rules determined by the
> +  /// language.
> +  enum ArgPassingKind {
> +    /// The argument of this type can be passed directly in registers.
> +    APK_CanPassInRegs,
> +
> +    /// The argument of this type cannot be passed directly in registers.
> +    /// Records containing this type as a subobject are not forced to be passed
> +    /// indirectly. This value is used only in C++. This value is required by
> +    /// C++ because, in uncommon situations, it is possible for a class to have
> +    /// only trivial copy/move constructors even when one of its subobjects has
> +    /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move
> +    /// constructor in the derived class is deleted).
> +    APK_CannotPassInRegs,
> +
> +    /// The argument of this type cannot be passed directly in registers.
> +    /// Records containing this type as a subobject are forced to be passed
> +    /// indirectly.
> +    APK_CanNeverPassInRegs
> +  };
> +
> +private:
>    friend class DeclContext;
> 
>    // FIXME: This can be packed into the bitfields in Decl.
> @@ -3571,17 +3596,14 @@ 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;
> -
>    /// Indicates whether this struct is destroyed in the callee. This flag is
>    /// meaningless when Microsoft ABI is used since parameters are always
>    /// destroyed in the callee.
>    bool ParamDestroyedInCallee : 1;
> 
> +  /// Represents the way this type is passed to a function.
> +  ArgPassingKind ArgPassingRestrictions : 2;
> +
>  protected:
>    RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
>               SourceLocation StartLoc, SourceLocation IdLoc,
> @@ -3669,12 +3691,15 @@ public:
>    /// 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;
> +    return ArgPassingRestrictions == APK_CanPassInRegs;
> +  }
> +
> +  ArgPassingKind getArgPassingRestrictions() const {
> +    return ArgPassingRestrictions;
>    }
> 
> -  /// Set that we can pass this RecordDecl in registers.
> -  void setCanPassInRegisters(bool CanPass) {
> -    CanPassInRegisters = CanPass;
> +  void setArgPassingRestrictions(ArgPassingKind Kind) {
> +    ArgPassingRestrictions = Kind;
>    }
> 
>    bool isParamDestroyedInCallee() const {
> 
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Mon Apr  9 13:39:47 2018
> @@ -1149,8 +1149,6 @@ 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/Decl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/AST/Decl.cpp (original)
> +++ cfe/trunk/lib/AST/Decl.cpp Mon Apr  9 13:39:47 2018
> @@ -3956,7 +3956,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind
>        LoadedFieldsFromExternalStorage(false),
>        NonTrivialToPrimitiveDefaultInitialize(false),
>        NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),
> -      CanPassInRegisters(true), ParamDestroyedInCallee(false) {
> +      ParamDestroyedInCallee(false), ArgPassingRestrictions(APK_CanPassInRegs) {
>    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=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Apr  9 13:39:47 2018
> @@ -421,6 +421,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier
>      if (BaseClassDecl->hasVolatileMember())
>        setHasVolatileMember(true);
> 
> +    if (BaseClassDecl->getArgPassingRestrictions() ==
> +        RecordDecl::APK_CanNeverPassInRegs)
> +      setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
> +
>      // Keep track of the presence of mutable fields.
>      if (BaseClassDecl->hasMutableFields()) {
>        data().HasMutableFields = true;
> @@ -950,7 +954,7 @@ void CXXRecordDecl::addedMember(Decl *D)
> 
>          // Structs with __weak fields should never be passed directly.
>          if (LT == Qualifiers::OCL_Weak)
> -          setCanPassInRegisters(false);
> +          setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
> 
>          Data.HasIrrelevantDestructor = false;
>        } else if (!Context.getLangOpts().ObjCAutoRefCount) {
> @@ -1117,6 +1121,9 @@ void CXXRecordDecl::addedMember(Decl *D)
>            setHasObjectMember(true);
>          if (FieldRec->hasVolatileMember())
>            setHasVolatileMember(true);
> +        if (FieldRec->getArgPassingRestrictions() ==
> +            RecordDecl::APK_CanNeverPassInRegs)
> +          setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
> 
>          // C++0x [class]p7:
>          //   A standard-layout class is a class that:
> 
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Mon Apr  9 13:39:47 2018
> @@ -2239,17 +2239,6 @@ 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/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Apr  9 13:39:47 2018
> @@ -15465,8 +15465,13 @@ void Sema::ActOnFields(Scope *S, SourceL
>          Record->setNonTrivialToPrimitiveDestroy(true);
>          Record->setParamDestroyedInCallee(true);
>        }
> -      if (!FT.canPassInRegisters())
> -        Record->setCanPassInRegisters(false);
> +
> +      if (const auto *RT = FT->getAs<RecordType>()) {
> +        if (RT->getDecl()->getArgPassingRestrictions() ==
> +            RecordDecl::APK_CanNeverPassInRegs)
> +          Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
> +      } else if (FT.getQualifiers().getObjCLifetime() == Qualifiers::OCL_Weak)
> +        Record->setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);
>      }
> 
>      if (Record && FD->getType().isVolatileQualified())
> 
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Apr  9 13:39:47 2018
> @@ -5847,20 +5847,20 @@ static bool paramCanBeDestroyedInCallee(
>    return HasNonDeletedCopyOrMove;
>  }
> 
> -static bool computeCanPassInRegister(bool DestroyedInCallee,
> -                                     const CXXRecordDecl *RD,
> -                                     TargetInfo::CallingConvKind CCK,
> -                                     Sema &S) {
> +static RecordDecl::ArgPassingKind
> +computeArgPassingRestrictions(bool DestroyedInCallee, const CXXRecordDecl *RD,
> +                              TargetInfo::CallingConvKind CCK, Sema &S) {
>    if (RD->isDependentType() || RD->isInvalidDecl())
> -    return true;
> +    return RecordDecl::APK_CanPassInRegs;
> 
> -  // The param cannot be passed in registers if CanPassInRegisters is already
> -  // set to false.
> -  if (!RD->canPassInRegisters())
> -    return false;
> +  // The param cannot be passed in registers if ArgPassingRestrictions is set to
> +  // APK_CanNeverPassInRegs.
> +  if (RD->getArgPassingRestrictions() == RecordDecl::APK_CanNeverPassInRegs)
> +    return RecordDecl::APK_CanNeverPassInRegs;
> 
>    if (CCK != TargetInfo::CCK_MicrosoftX86_64)
> -    return DestroyedInCallee;
> +    return DestroyedInCallee ? RecordDecl::APK_CanPassInRegs
> +                             : RecordDecl::APK_CannotPassInRegs;
> 
>    bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
>    bool DtorIsTrivialForCall = false;
> @@ -5900,7 +5900,7 @@ static bool computeCanPassInRegister(boo
> 
>    // If the copy ctor and dtor are both trivial-for-calls, pass direct.
>    if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
> -    return true;
> +    return RecordDecl::APK_CanPassInRegs;
> 
>    // If a class has a destructor, we'd really like to pass it indirectly
>    // because it allows us to elide copies.  Unfortunately, MSVC makes that
> @@ -5914,8 +5914,8 @@ static bool computeCanPassInRegister(boo
>    // passed in registers, which is non-conforming.
>    if (CopyCtorIsTrivial &&
>        S.getASTContext().getTypeSize(RD->getTypeForDecl()) <= 64)
> -    return true;
> -  return false;
> +    return RecordDecl::APK_CanPassInRegs;
> +  return RecordDecl::APK_CannotPassInRegs;
>  }
> 
>  /// \brief Perform semantic checks on a class definition that has been
> @@ -6090,8 +6090,8 @@ void Sema::CheckCompletedCXXClass(CXXRec
>    if (Record->hasNonTrivialDestructor())
>      Record->setParamDestroyedInCallee(DestroyedInCallee);
> 
> -  Record->setCanPassInRegisters(
> -      computeCanPassInRegister(DestroyedInCallee, Record, CCK, *this));
> +  Record->setArgPassingRestrictions(
> +      computeArgPassingRestrictions(DestroyedInCallee, Record, CCK, *this));
>  }
> 
>  /// Look up the special member function that would be called by a special
> 
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Apr  9 13:39:47 2018
> @@ -742,8 +742,8 @@ ASTDeclReader::VisitRecordDeclImpl(Recor
>    RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt());
>    RD->setNonTrivialToPrimitiveCopy(Record.readInt());
>    RD->setNonTrivialToPrimitiveDestroy(Record.readInt());
> -  RD->setCanPassInRegisters(Record.readInt());
>    RD->setParamDestroyedInCallee(Record.readInt());
> +  RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt());
>    return Redecl;
>  }
> 
> @@ -4114,8 +4114,9 @@ void ASTDeclReader::UpdateDecl(Decl *D,
>        bool HadRealDefinition =
>            OldDD && (OldDD->Definition != RD ||
>                      !Reader.PendingFakeDefinitionData.count(OldDD));
> -      RD->setCanPassInRegisters(Record.readInt());
>        RD->setParamDestroyedInCallee(Record.readInt());
> +      RD->setArgPassingRestrictions(
> +          (RecordDecl::ArgPassingKind)Record.readInt());
>        ReadCXXRecordDefinition(RD, /*Update*/true);
> 
>        // Visible update is handled separately.
> 
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Apr  9 13:39:47 2018
> @@ -5193,8 +5193,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(R
>        case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
>          auto *RD = cast<CXXRecordDecl>(D);
>          UpdatedDeclContexts.insert(RD->getPrimaryContext());
> -        Record.push_back(RD->canPassInRegisters());
>          Record.push_back(RD->isParamDestroyedInCallee());
> +        Record.push_back(RD->getArgPassingRestrictions());
>          Record.AddCXXDefinitionData(RD);
>          Record.AddOffset(WriteDeclContextLexicalBlock(
>              *Context, const_cast<CXXRecordDecl *>(RD)));
> 
> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Mon Apr  9 13:39:47 2018
> @@ -469,8 +469,8 @@ void ASTDeclWriter::VisitRecordDecl(Reco
>    Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize());
>    Record.push_back(D->isNonTrivialToPrimitiveCopy());
>    Record.push_back(D->isNonTrivialToPrimitiveDestroy());
> -  Record.push_back(D->canPassInRegisters());
>    Record.push_back(D->isParamDestroyedInCallee());
> +  Record.push_back(D->getArgPassingRestrictions());
> 
>    if (D->getDeclContext() == D->getLexicalDeclContext() &&
>        !D->hasAttrs() &&
> @@ -1913,9 +1913,10 @@ void ASTWriter::WriteDeclAbbrevs() {
>    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
>    // isNonTrivialToPrimitiveDestroy
>    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
> -  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // canPassInRegisters
>    // isParamDestroyedInCallee
>    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
> +  // getArgPassingRestrictions
> +  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));
> 
>    // DC
>    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset
> 
> Modified: cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm <http://objc-struct-cxx-abi.mm/>
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm?rev=329617&r1=329616&r2=329617&view=diff <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm?rev=329617&r1=329616&r2=329617&view=diff>
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm <http://objc-struct-cxx-abi.mm/> (original)
> +++ cfe/trunk/test/CodeGenObjCXX/objc-struct-cxx-abi.mm <http://objc-struct-cxx-abi.mm/> Mon Apr  9 13:39:47 2018
> @@ -8,6 +8,8 @@
>  // pointer fields are passed directly.
> 
>  // CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* }
> +// CHECK: %[[STRUCT_CONTAINSSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
> +// CHECK: %[[STRUCT_DERIVEDSTRONGWEAK:.*]] = type { %[[STRUCT_STRONGWEAK]] }
>  // CHECK: %[[STRUCT_STRONG:.*]] = type { i8* }
>  // CHECK: %[[STRUCT_S:.*]] = type { i8* }
>  // CHECK: %[[STRUCT_CONTAINSNONTRIVIAL:.*]] = type { %{{.*}}, i8* }
> @@ -22,6 +24,21 @@ struct StrongWeak {
>  };
> 
>  #ifdef TRIVIALABI
> +struct __attribute__((trivial_abi)) ContainsStrongWeak {
> +#else
> +struct ContainsStrongWeak {
> +#endif
> +  StrongWeak sw;
> +};
> +
> +#ifdef TRIVIALABI
> +struct __attribute__((trivial_abi)) DerivedStrongWeak : StrongWeak {
> +#else
> +struct DerivedStrongWeak : StrongWeak {
> +#endif
> +};
> +
> +#ifdef TRIVIALABI
>  struct __attribute__((trivial_abi)) Strong {
>  #else
>  struct Strong {
> @@ -84,6 +101,18 @@ StrongWeak testReturnStrongWeak(StrongWe
>    return *a;
>  }
> 
> +// CHECK: define void @_Z27testParamContainsStrongWeak18ContainsStrongWeak(%[[STRUCT_CONTAINSSTRONGWEAK]]* %[[A:.*]])
> +// CHECK: call %[[STRUCT_CONTAINSSTRONGWEAK]]* @_ZN18ContainsStrongWeakD1Ev(%[[STRUCT_CONTAINSSTRONGWEAK]]* %[[A]])
> +
> +void testParamContainsStrongWeak(ContainsStrongWeak a) {
> +}
> +
> +// CHECK: define void @_Z26testParamDerivedStrongWeak17DerivedStrongWeak(%[[STRUCT_DERIVEDSTRONGWEAK]]* %[[A:.*]])
> +// CHECK: call %[[STRUCT_DERIVEDSTRONGWEAK]]* @_ZN17DerivedStrongWeakD1Ev(%[[STRUCT_DERIVEDSTRONGWEAK]]* %[[A]])
> +
> +void testParamDerivedStrongWeak(DerivedStrongWeak a) {
> +}
> +
>  // CHECK: define void @_Z15testParamStrong6Strong(i64 %[[A_COERCE:.*]])
>  // CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG]], align 8
>  // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[A]], i32 0, i32 0
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org <mailto:cfe-commits at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits <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/20180409/55d40371/attachment-0001.html>


More information about the cfe-commits mailing list