diff options
-rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 21 | ||||
-rw-r--r-- | clang/include/clang/AST/DeclObjC.h | 15 | ||||
-rw-r--r-- | clang/include/clang/AST/ExternalASTSource.h | 14 | ||||
-rw-r--r-- | clang/include/clang/Sema/MultiplexExternalSemaSource.h | 8 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTBitCodes.h | 12 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTReader.h | 18 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTWriter.h | 47 | ||||
-rw-r--r-- | clang/include/clang/Serialization/Module.h | 7 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/ExternalASTSource.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Frontend/ChainedIncludesSource.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/MultiplexExternalSemaSource.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 196 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 77 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 29 | ||||
-rw-r--r-- | clang/lib/Serialization/Module.cpp | 1 |
18 files changed, 360 insertions, 138 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index a5b44f4e80a..332238fd542 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2149,7 +2149,7 @@ class CXXConstructorDecl : public CXXMethodDecl { /// \name Support for base and member initializers. /// \{ /// \brief The arguments used to initialize the base or member. - CXXCtorInitializer **CtorInitializers; + LazyCXXCtorInitializersPtr CtorInitializers; unsigned NumCtorInitializers; /// \} @@ -2188,7 +2188,7 @@ public: typedef CXXCtorInitializer **init_iterator; /// \brief Iterates through the member/base initializer list. - typedef CXXCtorInitializer * const * init_const_iterator; + typedef CXXCtorInitializer *const *init_const_iterator; typedef llvm::iterator_range<init_iterator> init_range; typedef llvm::iterator_range<init_const_iterator> init_const_range; @@ -2199,17 +2199,20 @@ public: } /// \brief Retrieve an iterator to the first initializer. - init_iterator init_begin() { return CtorInitializers; } + init_iterator init_begin() { + const auto *ConstThis = this; + return const_cast<init_iterator>(ConstThis->init_begin()); + } /// \brief Retrieve an iterator to the first initializer. - init_const_iterator init_begin() const { return CtorInitializers; } + init_const_iterator init_begin() const; /// \brief Retrieve an iterator past the last initializer. init_iterator init_end() { - return CtorInitializers + NumCtorInitializers; + return init_begin() + NumCtorInitializers; } /// \brief Retrieve an iterator past the last initializer. init_const_iterator init_end() const { - return CtorInitializers + NumCtorInitializers; + return init_begin() + NumCtorInitializers; } typedef std::reverse_iterator<init_iterator> init_reverse_iterator; @@ -2240,14 +2243,14 @@ public: NumCtorInitializers = numCtorInitializers; } - void setCtorInitializers(CXXCtorInitializer ** initializers) { - CtorInitializers = initializers; + void setCtorInitializers(CXXCtorInitializer **Initializers) { + CtorInitializers = Initializers; } /// \brief Determine whether this constructor is a delegating constructor. bool isDelegatingConstructor() const { return (getNumCtorInitializers() == 1) && - CtorInitializers[0]->isDelegatingInitializer(); + init_begin()[0]->isDelegatingInitializer(); } /// \brief When this constructor delegates to another, retrieve the target. diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 3c24d05dc5b..4a5b4f3d075 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -2002,8 +2002,8 @@ class ObjCImplementationDecl : public ObjCImplDecl { SourceLocation IvarRBraceLoc; /// Support for ivar initialization. - /// IvarInitializers - The arguments used to initialize the ivars - CXXCtorInitializer **IvarInitializers; + /// \brief The arguments used to initialize the ivars + LazyCXXCtorInitializersPtr IvarInitializers; unsigned NumIvarInitializers; /// Do the ivars of this class require initialization other than @@ -2052,17 +2052,20 @@ public: } /// init_begin() - Retrieve an iterator to the first initializer. - init_iterator init_begin() { return IvarInitializers; } + init_iterator init_begin() { + const auto *ConstThis = this; + return const_cast<init_iterator>(ConstThis->init_begin()); + } /// begin() - Retrieve an iterator to the first initializer. - init_const_iterator init_begin() const { return IvarInitializers; } + init_const_iterator init_begin() const; /// init_end() - Retrieve an iterator past the last initializer. init_iterator init_end() { - return IvarInitializers + NumIvarInitializers; + return init_begin() + NumIvarInitializers; } /// end() - Retrieve an iterator past the last initializer. init_const_iterator init_end() const { - return IvarInitializers + NumIvarInitializers; + return init_begin() + NumIvarInitializers; } /// getNumArgs - Number of ivars which must be initialized. unsigned getNumIvarInitializers() const { diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 728af7c7a3b..9a760807621 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -22,6 +22,7 @@ namespace clang { class ASTConsumer; class CXXBaseSpecifier; +class CXXCtorInitializer; class DeclarationName; class ExternalSemaSource; // layering violation required for downcasting class FieldDecl; @@ -121,6 +122,12 @@ public: /// The default implementation of this method is a no-op. virtual Stmt *GetExternalDeclStmt(uint64_t Offset); + /// \brief Resolve the offset of a set of C++ constructor initializers in + /// the decl stream into an array of initializers. + /// + /// The default implementation of this method is a no-op. + virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset); + /// \brief Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. /// @@ -553,8 +560,13 @@ typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> LazyDeclPtr; +/// \brief A lazy pointer to a set of CXXCtorInitializers. +typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t, + &ExternalASTSource::GetExternalCXXCtorInitializers> + LazyCXXCtorInitializersPtr; + /// \brief A lazy pointer to a set of CXXBaseSpecifiers. -typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, +typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, &ExternalASTSource::GetExternalCXXBaseSpecifiers> LazyCXXBaseSpecifiersPtr; diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index d90eefd302d..7a57abc0106 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -86,10 +86,14 @@ public: /// stream into an array of specifiers. CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; + /// \brief Resolve a handle to a list of ctor initializers into the list of + /// initializers themselves. + CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; + /// \brief Find all declarations with the given name in the /// given context. - bool - FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override; + bool FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) override; /// \brief Ensures that the table of all visible declarations inside this /// context is up to date. diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 3668d4c6320..c7c0c8ce08c 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -149,7 +149,11 @@ namespace clang { /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an /// AST file. typedef uint32_t CXXBaseSpecifiersID; - + + /// \brief An ID number that refers to a list of CXXCtorInitializers in an + /// AST file. + typedef uint32_t CXXCtorInitializersID; + /// \brief An ID number that refers to an entity in the detailed /// preprocessing record. typedef uint32_t PreprocessedEntityID; @@ -555,6 +559,10 @@ namespace clang { /// \brief Record code for potentially unused local typedef names. UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52, + + /// \brief Record code for the table of offsets to CXXCtorInitializers + /// lists. + CXX_CTOR_INITIALIZERS_OFFSETS = 53, }; /// \brief Record types used within a source manager block. @@ -1074,6 +1082,8 @@ namespace clang { DECL_STATIC_ASSERT, /// \brief A record containing CXXBaseSpecifiers. DECL_CXX_BASE_SPECIFIERS, + /// \brief A record containing CXXCtorInitializers. + DECL_CXX_CTOR_INITIALIZERS, /// \brief A IndirectFieldDecl record. DECL_INDIRECTFIELD, /// \brief A NonTypeTemplateParmDecl record that stores an expanded diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index c6310595190..1471910db47 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -943,9 +943,6 @@ private: /// passing decls to consumer. bool PassingDeclsToConsumer; - /// Number of CXX base specifiers currently loaded - unsigned NumCXXBaseSpecifiersLoaded; - /// \brief The set of identifiers that were read while the AST reader was /// (recursively) loading declarations. /// @@ -1583,11 +1580,6 @@ public: return Result; } - /// \brief Returns the number of C++ base specifiers found in the chain. - unsigned getTotalNumCXXBaseSpecifiers() const { - return NumCXXBaseSpecifiersLoaded; - } - /// \brief Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind. TemplateArgumentLocInfo @@ -1993,10 +1985,18 @@ public: const RecordData &Record,unsigned &Idx); /// \brief Read a CXXCtorInitializer array. - std::pair<CXXCtorInitializer **, unsigned> + CXXCtorInitializer ** ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx); + /// \brief Read a CXXCtorInitializers ID from the given record and + /// return its global bit offset. + uint64_t ReadCXXCtorInitializersRef(ModuleFile &M, const RecordData &Record, + unsigned &Idx); + + /// \brief Read the contents of a CXXCtorInitializer array. + CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; + /// \brief Read a source location from raw form. SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, unsigned Raw) const { SourceLocation Loc = SourceLocation::getFromRawEncoding(Raw); diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 27c8424693a..678ba687cb8 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -415,7 +415,7 @@ private: unsigned NumVisibleDeclContexts; /// \brief The offset of each CXXBaseSpecifier set within the AST. - SmallVector<uint32_t, 4> CXXBaseSpecifiersOffsets; + SmallVector<uint32_t, 16> CXXBaseSpecifiersOffsets; /// \brief The first ID number we can use for our own base specifiers. serialization::CXXBaseSpecifiersID FirstCXXBaseSpecifiersID; @@ -443,6 +443,33 @@ private: /// in the order they should be written. SmallVector<QueuedCXXBaseSpecifiers, 2> CXXBaseSpecifiersToWrite; + /// \brief The offset of each CXXCtorInitializer list within the AST. + SmallVector<uint32_t, 16> CXXCtorInitializersOffsets; + + /// \brief The first ID number we can use for our own ctor initializers. + serialization::CXXCtorInitializersID FirstCXXCtorInitializersID; + + /// \brief The ctor initializers ID that will be assigned to the next new + /// list of C++ ctor initializers. + serialization::CXXCtorInitializersID NextCXXCtorInitializersID; + + /// \brief A set of C++ ctor initializers that is queued to be written + /// into the AST file. + struct QueuedCXXCtorInitializers { + QueuedCXXCtorInitializers() : ID() {} + + QueuedCXXCtorInitializers(serialization::CXXCtorInitializersID ID, + ArrayRef<CXXCtorInitializer*> Inits) + : ID(ID), Inits(Inits) {} + + serialization::CXXCtorInitializersID ID; + ArrayRef<CXXCtorInitializer*> Inits; + }; + + /// \brief Queue of C++ ctor initializers to be written to the AST file, + /// in the order they should be written. + SmallVector<QueuedCXXCtorInitializers, 2> CXXCtorInitializersToWrite; + /// \brief A mapping from each known submodule to its ID number, which will /// be a positive integer. llvm::DenseMap<Module *, unsigned> SubmoduleIDs; @@ -471,6 +498,7 @@ private: void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, bool isModule); void WriteCXXBaseSpecifiersOffsets(); + void WriteCXXCtorInitializersOffsets(); unsigned TypeExtQualAbbrev; unsigned TypeFunctionProtoAbbrev; @@ -675,6 +703,11 @@ public: void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordDataImpl &Record); + /// \brief Emit the ID for a CXXCtorInitializer array and register the array + /// for later serialization. + void AddCXXCtorInitializersRef(ArrayRef<CXXCtorInitializer *> Inits, + RecordDataImpl &Record); + /// \brief Emit a CXXCtorInitializer array. void AddCXXCtorInitializers( const CXXCtorInitializer * const *CtorInitializers, @@ -747,6 +780,18 @@ public: /// via \c AddCXXBaseSpecifiersRef(). void FlushCXXBaseSpecifiers(); + /// \brief Flush all of the C++ constructor initializer lists that have been + /// added via \c AddCXXCtorInitializersRef(). + void FlushCXXCtorInitializers(); + + /// \brief Flush all pending records that are tacked onto the end of + /// decl and decl update records. + void FlushPendingAfterDecl() { + FlushStmts(); + FlushCXXBaseSpecifiers(); + FlushCXXCtorInitializers(); + } + /// \brief Record an ID for the given switch-case statement. unsigned RecordSwitchCaseID(SwitchCase *S); diff --git a/clang/include/clang/Serialization/Module.h b/clang/include/clang/Serialization/Module.h index 3eec83ca724..5571d91a541 100644 --- a/clang/include/clang/Serialization/Module.h +++ b/clang/include/clang/Serialization/Module.h @@ -404,6 +404,13 @@ public: /// indexed by the C++ base specifier set ID (-1). const uint32_t *CXXBaseSpecifiersOffsets; + /// \brief The number of C++ ctor initializer lists in this AST file. + unsigned LocalNumCXXCtorInitializers; + + /// \brief Offset of each C++ ctor initializer list within the bitstream, + /// indexed by the C++ ctor initializer list ID minus 1. + const uint32_t *CXXCtorInitializersOffsets; + typedef llvm::DenseMap<const DeclContext *, DeclContextInfo> DeclContextInfosMap; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 82fb2a6950a..8dc62dd07f2 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1739,6 +1739,10 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isImplicitlyDeclared, isConstexpr); } +CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const { + return CtorInitializers.get(getASTContext().getExternalSource()); +} + CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const { assert(isDelegatingConstructor() && "Not a delegating constructor!"); Expr *E = (*init_begin())->getInit()->IgnoreImplicit(); diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 77995b5261f..a63ba7e698a 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -1820,6 +1820,11 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, } } +ObjCImplementationDecl::init_const_iterator +ObjCImplementationDecl::init_begin() const { + return IvarInitializers.get(getASTContext().getExternalSource()); +} + raw_ostream &clang::operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID) { OS << ID.getName(); diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index 88941075dd0..730842a28f6 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -66,6 +66,11 @@ Stmt *ExternalASTSource::GetExternalDeclStmt(uint64_t Offset) { return nullptr; } +CXXCtorInitializer ** +ExternalASTSource::GetExternalCXXCtorInitializers(uint64_t Offset) { + return nullptr; +} + CXXBaseSpecifier * ExternalASTSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return nullptr; diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index cb260b4f4c6..be99b78295d 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -43,6 +43,7 @@ protected: Selector GetExternalSelector(uint32_t ID) override; uint32_t GetNumExternalSelectors() override; Stmt *GetExternalDeclStmt(uint64_t Offset) override; + CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override; @@ -232,6 +233,10 @@ CXXBaseSpecifier * ChainedIncludesSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { return getFinalReader().GetExternalCXXBaseSpecifiers(Offset); } +CXXCtorInitializer ** +ChainedIncludesSource::GetExternalCXXCtorInitializers(uint64_t Offset) { + return getFinalReader().GetExternalCXXCtorInitializers(Offset); +} bool ChainedIncludesSource::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 194c3693c1d..bd7e785780b 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -86,6 +86,14 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers( return nullptr; } +CXXCtorInitializer ** +MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) { + for (auto *S : Sources) + if (auto *R = S->GetExternalCXXCtorInitializers(Offset)) + return R; + return nullptr; +} + bool MultiplexExternalSemaSource:: FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { bool AnyDeclsFound = false; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 529af4ecbfe..2273979883a 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3204,16 +3204,26 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { case OBJC_CATEGORIES: F.ObjCCategories.swap(Record); break; - + case CXX_BASE_SPECIFIER_OFFSETS: { if (F.LocalNumCXXBaseSpecifiers != 0) { Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file"); return Failure; } - + F.LocalNumCXXBaseSpecifiers = Record[0]; F.CXXBaseSpecifiersOffsets = (const uint32_t *)Blob.data(); - NumCXXBaseSpecifiersLoaded += F.LocalNumCXXBaseSpecifiers; + break; + } + + case CXX_CTOR_INITIALIZERS_OFFSETS: { + if (F.LocalNumCXXCtorInitializers != 0) { + Error("duplicate CXX_CTOR_INITIALIZERS_OFFSETS record in AST file"); + return Failure; + } + + F.LocalNumCXXCtorInitializers = Record[0]; + F.CXXCtorInitializersOffsets = (const uint32_t *)Blob.data(); break; } @@ -6187,6 +6197,38 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { } } +uint64_t ASTReader::ReadCXXCtorInitializersRef(ModuleFile &M, + const RecordData &Record, + unsigned &Idx) { + if (Idx >= Record.size() || Record[Idx] > M.LocalNumCXXCtorInitializers) { + Error("malformed AST file: missing C++ ctor initializers"); + return 0; + } + + unsigned LocalID = Record[Idx++]; + return getGlobalBitOffset(M, M.CXXCtorInitializersOffsets[LocalID - 1]); +} + +CXXCtorInitializer ** +ASTReader::GetExternalCXXCtorInitializers(uint64_t Offset) { + RecordLocation Loc = getLocalBitOffset(Offset); + BitstreamCursor &Cursor = Loc.F->DeclsCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(Loc.Offset); + ReadingKindTracker ReadingKind(Read_Decl, *this); + + RecordData Record; + unsigned Code = Cursor.ReadCode(); + unsigned RecCode = Cursor.readRecord(Code, Record); + if (RecCode != DECL_CXX_CTOR_INITIALIZERS) { + Error("malformed AST file: missing C++ ctor initializers"); + return nullptr; + } + + unsigned Idx = 0; + return ReadCXXCtorInitializers(*Loc.F, Record, Idx); +} + uint64_t ASTReader::readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record, unsigned &Idx) { @@ -7918,92 +7960,89 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F, return Result; } -std::pair<CXXCtorInitializer **, unsigned> +CXXCtorInitializer ** ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx) { - CXXCtorInitializer **CtorInitializers = nullptr; unsigned NumInitializers = Record[Idx++]; - if (NumInitializers) { - CtorInitializers - = new (Context) CXXCtorInitializer*[NumInitializers]; - for (unsigned i=0; i != NumInitializers; ++i) { - TypeSourceInfo *TInfo = nullptr; - bool IsBaseVirtual = false; - FieldDecl *Member = nullptr; - IndirectFieldDecl *IndirectMember = nullptr; - - CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; - switch (Type) { - case CTOR_INITIALIZER_BASE: - TInfo = GetTypeSourceInfo(F, Record, Idx); - IsBaseVirtual = Record[Idx++]; - break; - - case CTOR_INITIALIZER_DELEGATING: - TInfo = GetTypeSourceInfo(F, Record, Idx); - break; + assert(NumInitializers && "wrote ctor initializers but have no inits"); + auto **CtorInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; + for (unsigned i = 0; i != NumInitializers; ++i) { + TypeSourceInfo *TInfo = nullptr; + bool IsBaseVirtual = false; + FieldDecl *Member = nullptr; + IndirectFieldDecl *IndirectMember = nullptr; + + CtorInitializerType Type = (CtorInitializerType)Record[Idx++]; + switch (Type) { + case CTOR_INITIALIZER_BASE: + TInfo = GetTypeSourceInfo(F, Record, Idx); + IsBaseVirtual = Record[Idx++]; + break; - case CTOR_INITIALIZER_MEMBER: - Member = ReadDeclAs<FieldDecl>(F, Record, Idx); - break; + case CTOR_INITIALIZER_DELEGATING: + TInfo = GetTypeSourceInfo(F, Record, Idx); + break; - case CTOR_INITIALIZER_INDIRECT_MEMBER: - IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx); - break; - } + case CTOR_INITIALIZER_MEMBER: + Member = ReadDeclAs<FieldDecl>(F, Record, Idx); + break; - SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx); - Expr *Init = ReadExpr(F); - SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); - SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); - bool IsWritten = Record[Idx++]; - unsigned SourceOrderOrNumArrayIndices; - SmallVector<VarDecl *, 8> Indices; - if (IsWritten) { - SourceOrderOrNumArrayIndices = Record[Idx++]; - } else { - SourceOrderOrNumArrayIndices = Record[Idx++]; - Indices.reserve(SourceOrderOrNumArrayIndices); - for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) - Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx)); - } + case CTOR_INITIALIZER_INDIRECT_MEMBER: + IndirectMember = ReadDeclAs<IndirectFieldDecl>(F, Record, Idx); + break; + } - CXXCtorInitializer *BOMInit; - if (Type == CTOR_INITIALIZER_BASE) { - BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, IsBaseVirtual, - LParenLoc, Init, RParenLoc, - MemberOrEllipsisLoc); - } else if (Type == CTOR_INITIALIZER_DELEGATING) { - BOMInit = new (Context) CXXCtorInitializer(Context, TInfo, LParenLoc, - Init, RParenLoc); - } else if (IsWritten) { - if (Member) - BOMInit = new (Context) CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc); - else - BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember, - MemberOrEllipsisLoc, LParenLoc, - Init, RParenLoc); + SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx); + Expr *Init = ReadExpr(F); + SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); + SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); + bool IsWritten = Record[Idx++]; + unsigned SourceOrderOrNumArrayIndices; + SmallVector<VarDecl *, 8> Indices; + if (IsWritten) { + SourceOrderOrNumArrayIndices = Record[Idx++]; + } else { + SourceOrderOrNumArrayIndices = Record[Idx++]; + Indices.reserve(SourceOrderOrNumArrayIndices); + for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i) + Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx)); + } + + CXXCtorInitializer *BOMInit; + if (Type == CTOR_INITIALIZER_BASE) { + BOMInit = new (Context) + CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init, + RParenLoc, MemberOrEllipsisLoc); + } else if (Type == CTOR_INITIALIZER_DELEGATING) { + BOMInit = new (Context) + CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc); + } else if (IsWritten) { + if (Member) + BOMInit = new (Context) CXXCtorInitializer( + Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc); + else + BOMInit = new (Context) + CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, + LParenLoc, Init, RParenLoc); + } else { + if (IndirectMember) { + assert(Indices.empty() && "Indirect field improperly initialized"); + BOMInit = new (Context) + CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc, + LParenLoc, Init, RParenLoc); } else { - if (IndirectMember) { - assert(Indices.empty() && "Indirect field improperly initialized"); - BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember, - MemberOrEllipsisLoc, LParenLoc, - Init, RParenLoc); - } else { - BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc, - Indices.data(), Indices.size()); - } + BOMInit = CXXCtorInitializer::Create( + Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc, + Indices.data(), Indices.size()); } - - if (IsWritten) - BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices); - CtorInitializers[i] = BOMInit; } + + if (IsWritten) + BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices); + CtorInitializers[i] = BOMInit; } - return std::make_pair(CtorInitializers, NumInitializers); + return CtorInitializers; } NestedNameSpecifier * @@ -8680,8 +8719,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), - PassingDeclsToConsumer(false), NumCXXBaseSpecifiersLoaded(0), - ReadingKind(Read_None) { + PassingDeclsToConsumer(false), ReadingKind(Read_None) { SourceMgr.setExternalSLocEntrySource(this); } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 5c6820f4834..d384f3d46e8 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -405,6 +405,12 @@ void ASTDeclReader::Visit(Decl *D) { // module). // FIXME: Can we diagnose ODR violations somehow? if (Record[Idx++]) { + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { + CD->NumCtorInitializers = Record[Idx++]; + if (CD->NumCtorInitializers) + CD->CtorInitializers = + Reader.ReadCXXCtorInitializersRef(F, Record, Idx); + } Reader.PendingBodies[FD] = GetCurrentCursorOffset(); HasPendingBody = true; } @@ -992,8 +998,9 @@ void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx)); D->setHasNonZeroConstructors(Record[Idx++]); D->setHasDestructors(Record[Idx++]); - std::tie(D->IvarInitializers, D->NumIvarInitializers) = - Reader.ReadCXXCtorInitializers(F, Record, Idx); + D->NumIvarInitializers = Record[Idx++]; + if (D->NumIvarInitializers) + D->IvarInitializers = Reader.ReadCXXCtorInitializersRef(F, Record, Idx); } @@ -1623,9 +1630,6 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { if (D->isCanonicalDecl()) D->setInheritedConstructor(CD); D->IsExplicitSpecified = Record[Idx++]; - // FIXME: We should defer loading this until we need the constructor's body. - std::tie(D->CtorInitializers, D->NumCtorInitializers) = - Reader.ReadCXXCtorInitializers(F, Record, Idx); } void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { @@ -3146,6 +3150,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CXX_BASE_SPECIFIERS: Error("attempt to read a C++ base-specifier record as a declaration"); return nullptr; + case DECL_CXX_CTOR_INITIALIZERS: + Error("attempt to read a C++ ctor initializer record as a declaration"); + return nullptr; case DECL_IMPORT: // Note: last entry of the ImportDecl record is the number of stored source // locations. @@ -3649,9 +3656,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, }); } FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx)); - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) - std::tie(CD->CtorInitializers, CD->NumCtorInitializers) = - Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx); + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { + CD->NumCtorInitializers = Record[Idx++]; + if (CD->NumCtorInitializers) + CD->CtorInitializers = + Reader.ReadCXXCtorInitializersRef(F, Record, Idx); + } // Store the offset of the body so we can lazily load it later. Reader.PendingBodies[FD] = GetCurrentCursorOffset(); HasPendingBody = true; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index e992685a83d..ced3d297f98 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -2694,6 +2694,29 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record); } +void ASTWriter::WriteCXXCtorInitializersOffsets() { + if (CXXCtorInitializersOffsets.empty()) + return; + + RecordData Record; + + // Create a blob abbreviation for the C++ ctor initializer offsets. + using namespace llvm; + + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(CXX_CTOR_INITIALIZERS_OFFSETS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned CtorInitializersOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + + // Write the base specifier offsets table. + Record.clear(); + Record.push_back(CXX_CTOR_INITIALIZERS_OFFSETS); + Record.push_back(CXXCtorInitializersOffsets.size()); + Stream.EmitRecordWithBlob(CtorInitializersOffsetAbbrev, Record, + data(CXXCtorInitializersOffsets)); +} + void ASTWriter::WriteCXXBaseSpecifiersOffsets() { if (CXXBaseSpecifiersOffsets.empty()) return; @@ -4154,7 +4177,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), NumVisibleDeclContexts(0), - NextCXXBaseSpecifiersID(1), TypeExtQualAbbrev(0), + NextCXXBaseSpecifiersID(1), NextCXXCtorInitializersID(1), + TypeExtQualAbbrev(0), TypeFunctionProtoAbbrev(0), DeclParmVarAbbrev(0), DeclContextLexicalAbbrev(0), DeclContextVisibleLookupAbbrev(0), UpdateVisibleAbbrev(0), DeclRecordAbbrev(0), DeclTypedefAbbrev(0), @@ -4559,6 +4583,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, if (!DeclUpdatesOffsetsRecord.empty()) Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); WriteCXXBaseSpecifiersOffsets(); + WriteCXXCtorInitializersOffsets(); WriteFileDeclIDsMap(); WriteSourceManagerBlock(Context.getSourceManager(), PP); @@ -4818,11 +4843,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { Stream.EmitRecord(DECL_UPDATES, Record); - // Flush any statements that were written as part of this update record. - FlushStmts(); - - // Flush C++ base specifiers, if there are any. - FlushCXXBaseSpecifiers(); + FlushPendingAfterDecl(); } } @@ -4934,8 +4955,16 @@ void ASTWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record AddDeclRef(Temp->getDestructor(), Record); } +void ASTWriter::AddCXXCtorInitializersRef(ArrayRef<CXXCtorInitializer *> Inits, + RecordDataImpl &Record) { + assert(!Inits.empty() && "Empty ctor initializer sets are not recorded"); + CXXCtorInitializersToWrite.push_back( + QueuedCXXCtorInitializers(NextCXXCtorInitializersID, Inits)); + Record.push_back(NextCXXCtorInitializersID++); +} + void ASTWriter::AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases, - CXXBaseSpecifier const *BasesEnd, + CXXBaseSpecifier const *BasesEnd, RecordDataImpl &Record) { assert(Bases != BasesEnd && "Empty base-specifier sets are not recorded"); CXXBaseSpecifiersToWrite.push_back( @@ -5496,7 +5525,8 @@ void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, void ASTWriter::FlushCXXBaseSpecifiers() { RecordData Record; - for (unsigned I = 0, N = CXXBaseSpecifiersToWrite.size(); I != N; ++I) { + unsigned N = CXXBaseSpecifiersToWrite.size(); + for (unsigned I = 0; I != N; ++I) { Record.clear(); // Record the offset of this base-specifier set. @@ -5520,6 +5550,8 @@ void ASTWriter::FlushCXXBaseSpecifiers() { FlushStmts(); } + assert(N == CXXBaseSpecifiersToWrite.size() && + "added more base specifiers while writing base specifiers"); CXXBaseSpecifiersToWrite.clear(); } @@ -5561,6 +5593,35 @@ void ASTWriter::AddCXXCtorInitializers( } } +void ASTWriter::FlushCXXCtorInitializers() { + RecordData Record; + + unsigned N = CXXCtorInitializersToWrite.size(); + for (auto &Init : CXXCtorInitializersToWrite) { + Record.clear(); + + // Record the offset of this mem-initializer list. + unsigned Index = Init.ID - 1; + if (Index == CXXCtorInitializersOffsets.size()) + CXXCtorInitializersOffsets.push_back(Stream.GetCurrentBitNo()); + else { + if (Index > CXXCtorInitializersOffsets.size()) + CXXCtorInitializersOffsets.resize(Index + 1); + CXXCtorInitializersOffsets[Index] = Stream.GetCurrentBitNo(); + } + + AddCXXCtorInitializers(Init.Inits.data(), Init.Inits.size(), Record); + Stream.EmitRecord(serialization::DECL_CXX_CTOR_INITIALIZERS, Record); + + // Flush any expressions that were written as part of the initializers. + FlushStmts(); + } + + assert(N == CXXCtorInitializersToWrite.size() && + "added more ctor initializers while writing ctor initializers"); + CXXCtorInitializersToWrite.clear(); +} + void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Record) { auto &Data = D->data(); Record.push_back(Data.IsLambda); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ee0d21999b3..1324f2c8c7f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -133,9 +133,12 @@ namespace clang { void AddFunctionDefinition(const FunctionDecl *FD) { assert(FD->doesThisDeclarationHaveABody()); - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) - Writer.AddCXXCtorInitializers(CD->CtorInitializers, - CD->NumCtorInitializers, Record); + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { + Record.push_back(CD->NumCtorInitializers); + if (CD->NumCtorInitializers) + Writer.AddCXXCtorInitializersRef( + llvm::makeArrayRef(CD->init_begin(), CD->init_end()), Record); + } Writer.AddStmt(FD->getBody()); } @@ -209,7 +212,7 @@ void ASTDeclWriter::Visit(Decl *D) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { Record.push_back(FD->doesThisDeclarationHaveABody()); if (FD->doesThisDeclarationHaveABody()) - Writer.AddStmt(FD->getBody()); + AddFunctionDefinition(FD); } } @@ -711,8 +714,10 @@ void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { Writer.AddSourceLocation(D->getIvarRBraceLoc(), Record); Record.push_back(D->hasNonZeroConstructors()); Record.push_back(D->hasDestructors()); - Writer.AddCXXCtorInitializers(D->IvarInitializers, D->NumIvarInitializers, - Record); + Record.push_back(D->NumIvarInitializers); + if (D->NumIvarInitializers) + Writer.AddCXXCtorInitializersRef( + llvm::makeArrayRef(D->init_begin(), D->init_end()), Record); Code = serialization::DECL_OBJC_IMPLEMENTATION; } @@ -1120,8 +1125,6 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { Writer.AddDeclRef(D->getInheritedConstructor(), Record); Record.push_back(D->IsExplicitSpecified); - Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers, - Record); Code = serialization::DECL_CXX_CONSTRUCTOR; } @@ -2066,12 +2069,10 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { D->getDeclKindName() + "'"); Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); - // Flush any expressions that were written as part of this declaration. - FlushStmts(); - - // Flush C++ base specifiers, if there are any. - FlushCXXBaseSpecifiers(); - + // Flush any expressions, base specifiers, and ctor initializers that + // were written as part of this declaration. + FlushPendingAfterDecl(); + // Note declarations that should be deserialized eagerly so that we can add // them to a record in the AST file later. if (isRequiredDecl(D, Context)) diff --git a/clang/lib/Serialization/Module.cpp b/clang/lib/Serialization/Module.cpp index 6c48a41187c..3b237d5529c 100644 --- a/clang/lib/Serialization/Module.cpp +++ b/clang/lib/Serialization/Module.cpp @@ -38,6 +38,7 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) SelectorLookupTableData(nullptr), SelectorLookupTable(nullptr), LocalNumDecls(0), DeclOffsets(nullptr), BaseDeclID(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr), + LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr), FileSortedDecls(nullptr), NumFileSortedDecls(0), RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0), ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0), |