diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 12 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Basic/TargetInfo.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Basic/Targets/X86.h | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 15 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 55 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 54 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 98 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 3 |
16 files changed, 165 insertions, 119 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 77c06f21dfb..ea96a077631 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2643,9 +2643,11 @@ void ASTContext::adjustExceptionSpec( } bool ASTContext::isParamDestroyedInCallee(QualType T) const { - return getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee() || - T.hasTrivialABIOverride() || - T.isDestructedType() == QualType::DK_nontrivial_c_struct; + if (getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee()) + return true; + if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>()) + return RT->getDecl()->isParamDestroyedInCallee(); + return false; } /// getComplexType - Return the uniqued reference to the type for a complex diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index ed80dd8fca2..4fb687d0fdd 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3951,7 +3951,7 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, LoadedFieldsFromExternalStorage(false), NonTrivialToPrimitiveDefaultInitialize(false), NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false), - CanPassInRegisters(true) { + CanPassInRegisters(true), ParamDestroyedInCallee(false) { assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 271872352cd..1e1ee439d8d 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -801,7 +801,17 @@ void CXXRecordDecl::addedMember(Decl *D) { struct DefinitionData &Data = data(); Data.PlainOldData = false; Data.HasTrivialSpecialMembers = 0; - Data.HasTrivialSpecialMembersForCall = 0; + + // __strong or __weak fields do not make special functions non-trivial + // for the purpose of calls. + Qualifiers::ObjCLifetime LT = T.getQualifiers().getObjCLifetime(); + if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak) + data().HasTrivialSpecialMembersForCall = 0; + + // Structs with __weak fields should never be passed directly. + if (LT == Qualifiers::OCL_Weak) + setCanPassInRegisters(false); + Data.HasIrrelevantDestructor = false; } else if (!Context.getLangOpts().ObjCAutoRefCount) { setHasObjectMember(true); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 2985aac66b2..d8b9967cdc8 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2195,12 +2195,6 @@ bool QualType::isTriviallyCopyableType(const ASTContext &Context) const { return false; } -bool QualType::hasTrivialABIOverride() const { - if (const auto *RD = getTypePtr()->getAsCXXRecordDecl()) - return RD->hasTrivialABIOverride(); - return false; -} - bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const { return !Context.getLangOpts().ObjCAutoRefCount && Context.getLangOpts().ObjCWeak && diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 36c8b106c7b..497ae34895e 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -357,6 +357,14 @@ bool TargetInfo::initFeatureMap( return true; } +TargetInfo::CallingConvKind +TargetInfo::getCallingConvKind(bool ClangABICompat4) const { + if (getCXXABI() != TargetCXXABI::Microsoft && + (ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4)) + return CCK_ClangABI4OrPS4; + return CCK_Default; +} + LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const { switch (TK) { case OCLTK_Image: diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 660e5847d68..f8029400e80 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -728,6 +728,11 @@ public: Builder.defineMacro("_M_X64", "100"); Builder.defineMacro("_M_AMD64", "100"); } + + TargetInfo::CallingConvKind + getCallingConvKind(bool ClangABICompat4) const override { + return CCK_MicrosoftX86_64; + } }; // x86-64 MinGW target diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 784797eea64..01caadba92d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3540,24 +3540,13 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, else Slot = CreateAggTemp(type, "agg.tmp"); - bool DestroyedInCallee = true, NeedsEHCleanup = true; - if (const auto *RD = type->getAsCXXRecordDecl()) { - DestroyedInCallee = - RD && RD->hasNonTrivialDestructor() && - (CGM.getCXXABI().getRecordArgABI(RD) != CGCXXABI::RAA_Default || - RD->hasTrivialABIOverride()); - } else { - NeedsEHCleanup = needsEHCleanup(type.isDestructedType()); - } - - if (DestroyedInCallee) - Slot.setExternallyDestructed(); + Slot.setExternallyDestructed(); EmitAggExpr(E, Slot); RValue RV = Slot.asRValue(); args.add(RV, type); - if (DestroyedInCallee && NeedsEHCleanup) { + if (type->getAsCXXRecordDecl() || needsEHCleanup(type.isDestructedType())) { // Create a no-op GEP between the placeholder and the cleanup so we can // RAUW it successfully. It also serves as a marker of the first // instruction where the cleanup is active. diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 20021808f75..55e74cd4258 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -63,13 +63,6 @@ public: bool classifyReturnType(CGFunctionInfo &FI) const override; bool passClassIndirect(const CXXRecordDecl *RD) const { - // Clang <= 4 used the pre-C++11 rule, which ignores move operations. - // The PS4 platform ABI follows the behavior of Clang 3.2. - if (CGM.getCodeGenOpts().getClangABICompat() <= - CodeGenOptions::ClangABI::Ver4 || - CGM.getTriple().getOS() == llvm::Triple::PS4) - return RD->hasNonTrivialDestructorForCall() || - RD->hasNonTrivialCopyConstructorForCall(); return !canCopyArgument(RD); } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 6ee423bb82e..542e1bf5fa3 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -829,60 +829,7 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const { return RAA_Default; case llvm::Triple::x86_64: - bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false; - bool DtorIsTrivialForCall = false; - - // If a class has at least one non-deleted, trivial copy constructor, it - // is passed according to the C ABI. Otherwise, it is passed indirectly. - // - // Note: This permits classes with non-trivial copy or move ctors to be - // passed in registers, so long as they *also* have a trivial copy ctor, - // which is non-conforming. - if (RD->needsImplicitCopyConstructor()) { - if (!RD->defaultedCopyConstructorIsDeleted()) { - if (RD->hasTrivialCopyConstructor()) - CopyCtorIsTrivial = true; - if (RD->hasTrivialCopyConstructorForCall()) - CopyCtorIsTrivialForCall = true; - } - } else { - for (const CXXConstructorDecl *CD : RD->ctors()) { - if (CD->isCopyConstructor() && !CD->isDeleted()) { - if (CD->isTrivial()) - CopyCtorIsTrivial = true; - if (CD->isTrivialForCall()) - CopyCtorIsTrivialForCall = true; - } - } - } - - if (RD->needsImplicitDestructor()) { - if (!RD->defaultedDestructorIsDeleted() && - RD->hasTrivialDestructorForCall()) - DtorIsTrivialForCall = true; - } else if (const auto *D = RD->getDestructor()) { - if (!D->isDeleted() && D->isTrivialForCall()) - DtorIsTrivialForCall = true; - } - - // If the copy ctor and dtor are both trivial-for-calls, pass direct. - if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall) - return RAA_Default; - - // 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 - // impossible for small types, which it will pass in a single register or - // stack slot. Most objects with dtors are large-ish, so handle that early. - // We can't call out all large objects as being indirect because there are - // multiple x64 calling conventions and the C++ ABI code shouldn't dictate - // how we pass large POD types. - - // Note: This permits small classes with nontrivial destructors to be - // passed in registers, which is non-conforming. - if (CopyCtorIsTrivial && - getContext().getTypeSize(RD->getTypeForDecl()) <= 64) - return RAA_Default; - return RAA_Indirect; + return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default; } llvm_unreachable("invalid enum"); diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 45c0ec41e0e..8f3676e7d2e 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2131,8 +2131,8 @@ class X86_64ABIInfo : public SwiftABIInfo { /// classify it as INTEGER (for compatibility with older clang compilers). bool classifyIntegerMMXAsSSE() const { // Clang <= 3.8 did not do this. - if (getCodeGenOpts().getClangABICompat() <= - CodeGenOptions::ClangABI::Ver3_8) + if (getContext().getLangOpts().getClangABICompat() <= + LangOptions::ClangABI::Ver3_8) return false; const llvm::Triple &Triple = getTarget().getTriple(); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d8bd500cde0..84eee0e75cd 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -633,33 +633,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, if (!Opts.ProfileInstrumentUsePath.empty()) setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath); - if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) { - Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest); - - StringRef Ver = A->getValue(); - std::pair<StringRef, StringRef> VerParts = Ver.split('.'); - unsigned Major, Minor = 0; - - // Check the version number is valid: either 3.x (0 <= x <= 9) or - // y or y.0 (4 <= y <= current version). - if (!VerParts.first.startswith("0") && - !VerParts.first.getAsInteger(10, Major) && - 3 <= Major && Major <= CLANG_VERSION_MAJOR && - (Major == 3 ? VerParts.second.size() == 1 && - !VerParts.second.getAsInteger(10, Minor) - : VerParts.first.size() == Ver.size() || - VerParts.second == "0")) { - // Got a valid version number. - if (Major == 3 && Minor <= 8) - Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8); - else if (Major <= 4) - Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4); - } else if (Ver != "latest") { - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); - } - } - Opts.CoverageMapping = Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false); Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping); @@ -2670,6 +2643,33 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // -fallow-editor-placeholders Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); + + if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) { + Opts.setClangABICompat(LangOptions::ClangABI::Latest); + + StringRef Ver = A->getValue(); + std::pair<StringRef, StringRef> VerParts = Ver.split('.'); + unsigned Major, Minor = 0; + + // Check the version number is valid: either 3.x (0 <= x <= 9) or + // y or y.0 (4 <= y <= current version). + if (!VerParts.first.startswith("0") && + !VerParts.first.getAsInteger(10, Major) && + 3 <= Major && Major <= CLANG_VERSION_MAJOR && + (Major == 3 ? VerParts.second.size() == 1 && + !VerParts.second.getAsInteger(10, Minor) + : VerParts.first.size() == Ver.size() || + VerParts.second == "0")) { + // Got a valid version number. + if (Major == 3 && Minor <= 8) + Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8); + else if (Major <= 4) + Opts.setClangABICompat(LangOptions::ClangABI::Ver4); + } else if (Ver != "latest") { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } } static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6cfc5012f67..a4ae32e460c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15461,8 +15461,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy(); if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial) Record->setNonTrivialToPrimitiveCopy(true); - if (FT.isDestructedType()) + if (FT.isDestructedType()) { Record->setNonTrivialToPrimitiveDestroy(true); + Record->setParamDestroyedInCallee(true); + } if (!FT.canPassInRegisters()) Record->setCanPassInRegisters(false); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a56869f6234..f8a3d9444aa 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5791,12 +5791,21 @@ static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD, } } -/// Determine whether a type is permitted to be passed or returned in -/// registers, per C++ [class.temporary]p3. -static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) { +/// Determine whether a type would be destructed in the callee if it had a +/// non-trivial destructor. The rules here are based on C++ [class.temporary]p3, +/// which determines whether a struct can be passed to or returned from +/// functions in registers. +static bool paramCanBeDestroyedInCallee(Sema &S, CXXRecordDecl *D, + TargetInfo::CallingConvKind CCK) { if (D->isDependentType() || D->isInvalidDecl()) return false; + // Clang <= 4 used the pre-C++11 rule, which ignores move operations. + // The PS4 platform ABI follows the behavior of Clang 3.2. + if (CCK == TargetInfo::CCK_ClangABI4OrPS4) + return !D->hasNonTrivialDestructorForCall() && + !D->hasNonTrivialCopyConstructorForCall(); + // Per C++ [class.temporary]p3, the relevant condition is: // each copy constructor, move constructor, and destructor of X is // either trivial or deleted, and X has at least one non-deleted copy @@ -5838,6 +5847,77 @@ static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) { return HasNonDeletedCopyOrMove; } +static bool computeCanPassInRegister(bool DestroyedInCallee, + const CXXRecordDecl *RD, + TargetInfo::CallingConvKind CCK, + Sema &S) { + if (RD->isDependentType() || RD->isInvalidDecl()) + return true; + + // The param cannot be passed in registers if CanPassInRegisters is already + // set to false. + if (!RD->canPassInRegisters()) + return false; + + if (CCK != TargetInfo::CCK_MicrosoftX86_64) + return DestroyedInCallee; + + bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false; + bool DtorIsTrivialForCall = false; + + // If a class has at least one non-deleted, trivial copy constructor, it + // is passed according to the C ABI. Otherwise, it is passed indirectly. + // + // Note: This permits classes with non-trivial copy or move ctors to be + // passed in registers, so long as they *also* have a trivial copy ctor, + // which is non-conforming. + if (RD->needsImplicitCopyConstructor()) { + if (!RD->defaultedCopyConstructorIsDeleted()) { + if (RD->hasTrivialCopyConstructor()) + CopyCtorIsTrivial = true; + if (RD->hasTrivialCopyConstructorForCall()) + CopyCtorIsTrivialForCall = true; + } + } else { + for (const CXXConstructorDecl *CD : RD->ctors()) { + if (CD->isCopyConstructor() && !CD->isDeleted()) { + if (CD->isTrivial()) + CopyCtorIsTrivial = true; + if (CD->isTrivialForCall()) + CopyCtorIsTrivialForCall = true; + } + } + } + + if (RD->needsImplicitDestructor()) { + if (!RD->defaultedDestructorIsDeleted() && + RD->hasTrivialDestructorForCall()) + DtorIsTrivialForCall = true; + } else if (const auto *D = RD->getDestructor()) { + if (!D->isDeleted() && D->isTrivialForCall()) + DtorIsTrivialForCall = true; + } + + // If the copy ctor and dtor are both trivial-for-calls, pass direct. + if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall) + return true; + + // 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 + // impossible for small types, which it will pass in a single register or + // stack slot. Most objects with dtors are large-ish, so handle that early. + // We can't call out all large objects as being indirect because there are + // multiple x64 calling conventions and the C++ ABI code shouldn't dictate + // how we pass large POD types. + + // Note: This permits small classes with nontrivial destructors to be + // passed in registers, which is non-conforming. + if (CopyCtorIsTrivial && + S.getASTContext().getTypeSize(RD->getTypeForDecl()) <= 64) + return true; + return false; +} + /// \brief Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. @@ -6001,7 +6081,17 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { checkClassLevelDLLAttribute(Record); - Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record)); + bool ClangABICompat4 = + Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4; + TargetInfo::CallingConvKind CCK = + Context.getTargetInfo().getCallingConvKind(ClangABICompat4); + bool DestroyedInCallee = paramCanBeDestroyedInCallee(*this, Record, CCK); + + if (Record->hasNonTrivialDestructor()) + Record->setParamDestroyedInCallee(DestroyedInCallee); + + Record->setCanPassInRegisters( + computeCanPassInRegister(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 a90e8657a7d..0c9151cf80a 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -743,6 +743,7 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { RD->setNonTrivialToPrimitiveCopy(Record.readInt()); RD->setNonTrivialToPrimitiveDestroy(Record.readInt()); RD->setCanPassInRegisters(Record.readInt()); + RD->setParamDestroyedInCallee(Record.readInt()); return Redecl; } @@ -4109,6 +4110,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, OldDD && (OldDD->Definition != RD || !Reader.PendingFakeDefinitionData.count(OldDD)); RD->setCanPassInRegisters(Record.readInt()); + RD->setParamDestroyedInCallee(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 f2d20ddf3a3..c2aabf59d5e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5194,6 +5194,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { auto *RD = cast<CXXRecordDecl>(D); UpdatedDeclContexts.insert(RD->getPrimaryContext()); Record.push_back(RD->canPassInRegisters()); + Record.push_back(RD->isParamDestroyedInCallee()); 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 d70debaf85f..254b5175d7b 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -470,6 +470,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { Record.push_back(D->isNonTrivialToPrimitiveCopy()); Record.push_back(D->isNonTrivialToPrimitiveDestroy()); Record.push_back(D->canPassInRegisters()); + Record.push_back(D->isParamDestroyedInCallee()); if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && @@ -1912,6 +1913,8 @@ void ASTWriter::WriteDeclAbbrevs() { // isNonTrivialToPrimitiveDestroy Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // canPassInRegisters + // isParamDestroyedInCallee + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // DC Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset |