diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 10 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 79 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 22 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 77 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 6 |
5 files changed, 167 insertions, 27 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 0e70053866..88ede82d92 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -36,7 +36,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasTrivialDestructor(true), ComputedVisibleConversions(false), DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), DeclaredCopyAssignment(false), DeclaredDestructor(false), - Bases(0), NumBases(0), VBases(0), NumVBases(0), + NumBases(0), NumVBases(0), Bases(), VBases(), Definition(D), FirstFriend(0) { } @@ -77,8 +77,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // no base classes [...]. data().Aggregate = false; - if (data().Bases) - C.Deallocate(data().Bases); + if (!data().Bases.isOffset() && data().NumBases > 0) + C.Deallocate(data().getBases()); // The set of seen virtual base types. llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes; @@ -89,7 +89,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().Bases = new(C) CXXBaseSpecifier [NumBases]; data().NumBases = NumBases; for (unsigned i = 0; i < NumBases; ++i) { - data().Bases[i] = *Bases[i]; + data().getBases()[i] = *Bases[i]; // Keep track of inherited vbases for this base class. const CXXBaseSpecifier *Base = Bases[i]; QualType BaseType = Base->getType(); @@ -193,7 +193,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>( VBaseTypeInfo->getType()->getAs<RecordType>()->getDecl()); - data().VBases[I] = + data().getVBases()[I] = CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true, VBaseClassDecl->getTagKind() == TTK_Class, VBases[I]->getAccessSpecifier(), VBaseTypeInfo); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 6497b78772..aa76765dc9 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2069,6 +2069,17 @@ ASTReader::ReadASTBlock(PerFileData &F) { std::make_pair(&F, Record[I+1]); 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 *)BlobStart; + break; + } } First = false; } @@ -3207,6 +3218,14 @@ TypeIdx ASTReader::GetTypeIdx(QualType T) const { return I->second; } +unsigned ASTReader::getTotalNumCXXBaseSpecifiers() const { + unsigned Result = 0; + for (unsigned I = 0, N = Chain.size(); I != N; ++I) + Result += Chain[I]->LocalNumCXXBaseSpecifiers; + + return Result; +} + TemplateArgumentLocInfo ASTReader::GetTemplateArgumentLocInfo(PerFileData &F, TemplateArgument::ArgKind Kind, @@ -3249,6 +3268,63 @@ Decl *ASTReader::GetExternalDecl(uint32_t ID) { return GetDecl(ID); } +uint64_t +ASTReader::GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID) { + if (ID == 0) + return 0; + + --ID; + uint64_t Offset = 0; + for (unsigned I = 0, N = Chain.size(); I != N; ++I) { + if (ID < Chain[I]->LocalNumCXXBaseSpecifiers) + return Offset + Chain[I]->CXXBaseSpecifiersOffsets[ID]; + + ID -= Chain[I]->LocalNumCXXBaseSpecifiers; + Offset += Chain[I]->SizeInBits; + } + + assert(false && "CXXBaseSpecifiers not found"); + return 0; +} + +CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) { + // Figure out which AST file contains this offset. + PerFileData *F = 0; + for (unsigned I = 0, N = Chain.size(); I != N; ++I) { + if (Offset < Chain[I]->SizeInBits) { + F = Chain[I]; + break; + } + + Offset -= Chain[I]->SizeInBits; + } + + if (!F) { + Error("Malformed AST file: C++ base specifiers at impossible offset"); + return 0; + } + + llvm::BitstreamCursor &Cursor = F->DeclsCursor; + SavedStreamPosition SavedPosition(Cursor); + Cursor.JumpToBit(Offset); + ReadingKindTracker ReadingKind(Read_Decl, *this); + RecordData Record; + unsigned Code = Cursor.ReadCode(); + unsigned RecCode = Cursor.ReadRecord(Code, Record); + if (RecCode != DECL_CXX_BASE_SPECIFIERS) { + Error("Malformed AST file: missing C++ base specifiers"); + return 0; + } + + unsigned Idx = 0; + unsigned NumBases = Record[Idx++]; + void *Mem = Context->Allocate(sizeof(CXXBaseSpecifier) * NumBases); + CXXBaseSpecifier *Bases = new (Mem) CXXBaseSpecifier [NumBases]; + for (unsigned I = 0; I != NumBases; ++I) + Bases[I] = ReadCXXBaseSpecifier(*F, Record, Idx); + return Bases; +} + TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() { if (!DeclsLoaded[0]) { ReadDeclRecord(0, 1); @@ -4411,7 +4487,8 @@ ASTReader::PerFileData::PerFileData(ASTFileType Ty) IdentifierLookupTable(0), LocalNumMacroDefinitions(0), MacroDefinitionOffsets(0), LocalNumSelectors(0), SelectorOffsets(0), SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0), - DeclOffsets(0), LocalNumTypes(0), TypeOffsets(0), StatCache(0), + DeclOffsets(0), LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0), + LocalNumTypes(0), TypeOffsets(0), StatCache(0), NumPreallocatedPreprocessingEntities(0), NextInSource(0) {} diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index d63dce9f2b..c6cb8db439 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -773,8 +773,6 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( void ASTDeclReader::ReadCXXDefinitionData( struct CXXRecordDecl::DefinitionData &Data, const RecordData &Record, unsigned &Idx) { - ASTContext &C = *Reader.getContext(); - Data.UserDeclaredConstructor = Record[Idx++]; Data.UserDeclaredCopyConstructor = Record[Idx++]; Data.UserDeclaredCopyAssignment = Record[Idx++]; @@ -793,20 +791,13 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.DeclaredCopyConstructor = Record[Idx++]; Data.DeclaredCopyAssignment = Record[Idx++]; Data.DeclaredDestructor = Record[Idx++]; - - // setBases() is unsuitable since it may try to iterate the bases of an - // uninitialized base. Data.NumBases = Record[Idx++]; - Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases]; - for (unsigned i = 0; i != Data.NumBases; ++i) - Data.Bases[i] = Reader.ReadCXXBaseSpecifier(F, Record, Idx); - - // FIXME: Make VBases lazily computed when needed to avoid storing them. + if (Data.NumBases) + Data.Bases = Reader.GetCXXBaseSpecifiersOffset(Record[Idx++]); Data.NumVBases = Record[Idx++]; - Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases]; - for (unsigned i = 0; i != Data.NumVBases; ++i) - Data.VBases[i] = Reader.ReadCXXBaseSpecifier(F, Record, Idx); - + if (Data.NumVBases) + Data.VBases = Reader.GetCXXBaseSpecifiersOffset(Record[Idx++]); + Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx); Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx); assert(Data.Definition && "Data.Definition should be already set!"); @@ -1508,6 +1499,9 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { case DECL_BLOCK: D = BlockDecl::Create(*Context, 0, SourceLocation()); break; + case DECL_CXX_BASE_SPECIFIERS: + Error("attempt to read a C++ base-specifier record as a declaration"); + return 0; } assert(D && "Unknown declaration reading AST file"); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 114f9205d4..1fec22be4e 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1725,7 +1725,7 @@ void ASTWriter::WriteSelectors(Sema &SemaRef) { // Create a blob abbreviation for the selector table offsets. Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev); @@ -2230,7 +2230,9 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) NextSelectorID(FirstSelectorID), FirstMacroID(1), NextMacroID(FirstMacroID), CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), - NumVisibleDeclContexts(0) { + NumVisibleDeclContexts(0), FirstCXXBaseSpecifiersID(1), + NextCXXBaseSpecifiersID(1) +{ } void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls, @@ -2401,6 +2403,26 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, WriteTypeDeclOffsets(); + // Write the C++ base-specifier set offsets. + if (!CXXBaseSpecifiersOffsets.empty()) { + // Create a blob abbreviation for the C++ base specifiers offsets. + using namespace llvm; + + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(CXX_BASE_SPECIFIER_OFFSETS)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned BaseSpecifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + + // Write the selector offsets table. + Record.clear(); + Record.push_back(CXX_BASE_SPECIFIER_OFFSETS); + Record.push_back(CXXBaseSpecifiersOffsets.size()); + Stream.EmitRecordWithBlob(BaseSpecifierOffsetAbbrev, Record, + (const char *)CXXBaseSpecifiersOffsets.data(), + CXXBaseSpecifiersOffsets.size() * sizeof(uint32_t)); + } + // Write the record containing external, unnamed definitions. if (!ExternalDefinitions.empty()) Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions); @@ -2798,6 +2820,16 @@ void ASTWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record AddDeclRef(Temp->getDestructor(), Record); } +void ASTWriter::AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases, + CXXBaseSpecifier const *BasesEnd, + RecordDataImpl &Record) { + assert(Bases != BasesEnd && "Empty base-specifier sets are not recorded"); + CXXBaseSpecifiersToWrite.push_back( + QueuedCXXBaseSpecifiers(NextCXXBaseSpecifiersID, + Bases, BasesEnd)); + Record.push_back(NextCXXBaseSpecifiersID++); +} + void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg, RecordDataImpl &Record) { @@ -3155,6 +3187,32 @@ void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, AddSourceRange(Base.getSourceRange(), Record); } +void ASTWriter::FlushCXXBaseSpecifiers() { + RecordData Record; + for (unsigned I = 0, N = CXXBaseSpecifiersToWrite.size(); I != N; ++I) { + Record.clear(); + + // Record the offset of this base-specifier set. + unsigned Index = CXXBaseSpecifiersToWrite[I].ID - FirstCXXBaseSpecifiersID; + if (Index == CXXBaseSpecifiersOffsets.size()) + CXXBaseSpecifiersOffsets.push_back(Stream.GetCurrentBitNo()); + else { + if (Index > CXXBaseSpecifiersOffsets.size()) + CXXBaseSpecifiersOffsets.resize(Index + 1); + CXXBaseSpecifiersOffsets[Index] = Stream.GetCurrentBitNo(); + } + + const CXXBaseSpecifier *B = CXXBaseSpecifiersToWrite[I].Bases, + *BEnd = CXXBaseSpecifiersToWrite[I].BasesEnd; + Record.push_back(BEnd - B); + for (; B != BEnd; ++B) + AddCXXBaseSpecifier(*B, Record); + Stream.EmitRecord(serialization::DECL_CXX_BASE_SPECIFIERS, Record); + } + + CXXBaseSpecifiersToWrite.clear(); +} + void ASTWriter::AddCXXBaseOrMemberInitializers( const CXXBaseOrMemberInitializer * const *BaseOrMembers, unsigned NumBaseOrMembers, RecordDataImpl &Record) { @@ -3208,13 +3266,15 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Data.DeclaredDestructor); Record.push_back(Data.NumBases); - for (unsigned i = 0; i != Data.NumBases; ++i) - AddCXXBaseSpecifier(Data.Bases[i], Record); - + if (Data.NumBases > 0) + AddCXXBaseSpecifiersRef(Data.getBases(), Data.getBases() + Data.NumBases, + Record); + // FIXME: Make VBases lazily computed when needed to avoid storing them. Record.push_back(Data.NumVBases); - for (unsigned i = 0; i != Data.NumVBases; ++i) - AddCXXBaseSpecifier(Data.VBases[i], Record); + if (Data.NumVBases > 0) + AddCXXBaseSpecifiersRef(Data.getVBases(), Data.getVBases() + Data.NumVBases, + Record); AddUnresolvedSet(Data.Conversions, Record); AddUnresolvedSet(Data.VisibleConversions, Record); @@ -3230,6 +3290,7 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { FirstIdentID == NextIdentID && FirstSelectorID == NextSelectorID && FirstMacroID == NextMacroID && + FirstCXXBaseSpecifiersID == NextCXXBaseSpecifiersID && "Setting chain after writing has started."); Chain = Reader; @@ -3238,11 +3299,13 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { FirstIdentID += Chain->getTotalNumIdentifiers(); FirstSelectorID += Chain->getTotalNumSelectors(); FirstMacroID += Chain->getTotalNumMacroDefinitions(); + FirstCXXBaseSpecifiersID += Chain->getTotalNumCXXBaseSpecifiers(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; NextSelectorID = FirstSelectorID; NextMacroID = FirstMacroID; + NextCXXBaseSpecifiersID = FirstCXXBaseSpecifiersID; } void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 37c7765dc8..7d80f31856 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1182,6 +1182,12 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { // Flush any expressions that were written as part of this declaration. FlushStmts(); + + // Flush C++ base specifiers, if there are any. + FlushCXXBaseSpecifiers(); + + // Flush any expressions that were written as part of the base specifiers. + FlushStmts(); // Note "external" declarations so that we can add them to a record in the // AST file later. |