forked from OSchip/llvm-project
[modules] Deserialize CXXCtorInitializer list for a constructor lazily.
Previously we'd deserialize the list of mem-initializers for a constructor when we deserialized the declaration of the constructor. That could trigger a significant amount of unnecessary work (pulling in all base classes recursively, for a start) and was causing problems for the modules buildbot due to cyclic deserializations. We now deserialize these on demand. This creates a certain amount of duplication with the handling of CXXBaseSpecifiers; I'll look into reducing that next. llvm-svn: 233052
This commit is contained in:
parent
20f3da11e8
commit
c2bb81860b
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
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_DELEGATING:
|
||||
TInfo = GetTypeSourceInfo(F, Record, Idx);
|
||||
break;
|
||||
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));
|
||||
}
|
||||
|
||||
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 {
|
||||
BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc,
|
||||
LParenLoc, Init, RParenLoc,
|
||||
Indices.data(), Indices.size());
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWritten)
|
||||
BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
|
||||
CtorInitializers[i] = BOMInit;
|
||||
case CTOR_INITIALIZER_INDIRECT_MEMBER:
|
||||
IndirectMember = ReadDeclAs<IndirectFieldDecl>(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));
|
||||
}
|
||||
|
||||
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 {
|
||||
BOMInit = CXXCtorInitializer::Create(
|
||||
Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc,
|
||||
Indices.data(), Indices.size());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue