diff options
| author | Akira Hatanaka <ahatanaka@apple.com> | 2018-04-09 22:48:22 +0000 |
|---|---|---|
| committer | Akira Hatanaka <ahatanaka@apple.com> | 2018-04-09 22:48:22 +0000 |
| commit | e6313ace66129a8fd91238ec960031ed2fbab810 (patch) | |
| tree | a438012ad9297b6a3dfa38bb92e7768cf19b8f92 /clang/lib | |
| parent | 3539c09d3bd6118c87c8557df80391cdc3ba102b (diff) | |
| download | bcm5719-llvm-e6313ace66129a8fd91238ec960031ed2fbab810.tar.gz bcm5719-llvm-e6313ace66129a8fd91238ec960031ed2fbab810.zip | |
[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.
This reapplies r329617. r329617 didn't specify the underlying type for
enum ArgPassingKind, which caused regression tests to fail on a windows
bot.
rdar://problem/39194693
Differential Revision: https://reviews.llvm.org/D45384
llvm-svn: 329635
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/AST/Type.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 30 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 5 |
8 files changed, 38 insertions, 35 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index b49fda08a7c..18ef94ba225 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3956,7 +3956,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, 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!"); } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 99ff1ca31e7..dd653d8f573 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -421,6 +421,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 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: diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index cca5ddc1e48..a2a60772b77 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2239,17 +2239,6 @@ QualType::isNonTrivialToPrimitiveDestructiveMove() const { 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; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f650e046c0d..9228d65250c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15465,8 +15465,13 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, 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()) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 55c7a9ae24d..08d3bc21a24 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5847,20 +5847,20 @@ static bool paramCanBeDestroyedInCallee(Sema &S, CXXRecordDecl *D, 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(bool DestroyedInCallee, // 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(bool DestroyedInCallee, // 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(CXXRecordDecl *Record) { 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 diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index a6cc69d623f..af4cf84b9b3 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -742,8 +742,8 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { 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. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 3369a543685..7f1199f1b6c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5193,8 +5193,8 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { 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))); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 06ea8e7f2bc..189de14cff1 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -469,8 +469,8 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { 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 |

