[cfe-commits] r117732 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/AST/ExternalASTSource.h include/clang/Serialization/ASTBitCodes.h include/clang/Serialization/ASTReader.h include/clang/Serialization/ASTWriter.h lib/AST/DeclCXX.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp lib/Serialization/ASTWriterDecl.cpp test/PCH/cxx-templates.cpp test/PCH/cxx-templates.h
Douglas Gregor
dgregor at apple.com
Fri Oct 29 15:39:52 PDT 2010
Author: dgregor
Date: Fri Oct 29 17:39:52 2010
New Revision: 117732
URL: http://llvm.org/viewvc/llvm-project?rev=117732&view=rev
Log:
Make the deserialization of C++ base class specifiers lazy, improving
the performance of C++ PCH and reducing stack depth in the reader.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/ExternalASTSource.h
cfe/trunk/include/clang/Serialization/ASTBitCodes.h
cfe/trunk/include/clang/Serialization/ASTReader.h
cfe/trunk/include/clang/Serialization/ASTWriter.h
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/PCH/cxx-templates.cpp
cfe/trunk/test/PCH/cxx-templates.h
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Oct 29 17:39:52 2010
@@ -342,19 +342,19 @@
/// \brief Whether we have already declared a destructor within the class.
bool DeclaredDestructor : 1;
- /// Bases - Base classes of this class.
- /// FIXME: This is wasted space for a union.
- CXXBaseSpecifier *Bases;
-
/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
-
- /// VBases - direct and indirect virtual base classes of this class.
- CXXBaseSpecifier *VBases;
-
+
/// NumVBases - The number of virtual base class specifiers in VBases.
unsigned NumVBases;
+ /// Bases - Base classes of this class.
+ /// FIXME: This is wasted space for a union.
+ LazyCXXBaseSpecifiersPtr Bases;
+
+ /// VBases - direct and indirect virtual base classes of this class.
+ LazyCXXBaseSpecifiersPtr VBases;
+
/// Conversions - Overload set containing the conversion functions
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
@@ -376,6 +376,15 @@
/// in reverse order.
FriendDecl *FirstFriend;
+ /// \brief Retrieve the set of direct base classes.
+ CXXBaseSpecifier *getBases() const {
+ return Bases.get(Definition->getASTContext().getExternalSource());
+ }
+
+ /// \brief Retrieve the set of virtual base classes.
+ CXXBaseSpecifier *getVBases() const {
+ return VBases.get(Definition->getASTContext().getExternalSource());
+ }
} *DefinitionData;
struct DefinitionData &data() {
@@ -480,8 +489,8 @@
/// class.
unsigned getNumBases() const { return data().NumBases; }
- base_class_iterator bases_begin() { return data().Bases; }
- base_class_const_iterator bases_begin() const { return data().Bases; }
+ base_class_iterator bases_begin() { return data().getBases(); }
+ base_class_const_iterator bases_begin() const { return data().getBases(); }
base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
base_class_const_iterator bases_end() const {
return bases_begin() + data().NumBases;
@@ -503,8 +512,8 @@
/// class.
unsigned getNumVBases() const { return data().NumVBases; }
- base_class_iterator vbases_begin() { return data().VBases; }
- base_class_const_iterator vbases_begin() const { return data().VBases; }
+ base_class_iterator vbases_begin() { return data().getVBases(); }
+ base_class_const_iterator vbases_begin() const { return data().getVBases(); }
base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; }
base_class_const_iterator vbases_end() const {
return vbases_begin() + data().NumVBases;
Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Fri Oct 29 17:39:52 2010
@@ -25,6 +25,7 @@
namespace clang {
class ASTConsumer;
+class CXXBaseSpecifier;
class Decl;
class DeclContext;
class DeclContextLookupResult;
@@ -92,6 +93,10 @@
/// FunctionDecl::setLazyBody when building decls.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0;
+ /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// stream into an array of specifiers.
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0;
+
/// \brief Finds all declarations with the given name in the
/// given context.
///
@@ -248,6 +253,11 @@
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
+/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
+typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
+ &ExternalASTSource::GetExternalCXXBaseSpecifiers>
+ LazyCXXBaseSpecifiersPtr;
+
} // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Oct 29 17:39:52 2010
@@ -124,6 +124,10 @@
/// \brief An ID number that refers to an ObjC selctor in an AST file.
typedef uint32_t SelectorID;
+ /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an
+ /// AST file.
+ typedef uint32_t CXXBaseSpecifiersID;
+
/// \brief Describes the various kinds of blocks that occur within
/// an AST file.
enum BlockIDs {
@@ -333,7 +337,11 @@
/// \brief Record of updates for a declaration that was modified after
/// being deserialized.
- DECL_UPDATES = 36
+ DECL_UPDATES = 36,
+
+ /// \brief Record code for the table of offsets to CXXBaseSpecifier
+ /// sets.
+ CXX_BASE_SPECIFIER_OFFSETS = 37
};
/// \brief Record types used within a source manager block.
@@ -705,7 +713,9 @@
/// \brief A TemplateTemplateParmDecl record.
DECL_TEMPLATE_TEMPLATE_PARM,
/// \brief A StaticAssertDecl record.
- DECL_STATIC_ASSERT
+ DECL_STATIC_ASSERT,
+ /// \brief A record containing CXXBaseSpecifiers.
+ DECL_CXX_BASE_SPECIFIERS
};
/// \brief Record codes for each kind of statement or expression.
Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri Oct 29 17:39:52 2010
@@ -336,6 +336,13 @@
/// is the instantiation location.
llvm::SmallVector<uint64_t, 64> PendingInstantiations;
+ /// \brief The number of C++ base specifier sets in this AST file.
+ unsigned LocalNumCXXBaseSpecifiers;
+
+ /// \brief Offset of each C++ base specifier set within the bitstream,
+ /// indexed by the C++ base specifier set ID (-1).
+ const uint32_t *CXXBaseSpecifiersOffsets;
+
// === Types ===
/// \brief The number of types in this AST file.
@@ -867,6 +874,9 @@
return static_cast<unsigned>(MacroDefinitionsLoaded.size());
}
+ /// \brief Returns the number of C++ base specifiers found in the chain.
+ unsigned getTotalNumCXXBaseSpecifiers() const;
+
/// \brief Reads a TemplateArgumentLocInfo appropriate for the
/// given TemplateArgument kind.
TemplateArgumentLocInfo
@@ -904,6 +914,12 @@
Decl *GetDecl(serialization::DeclID ID);
virtual Decl *GetExternalDecl(uint32_t ID);
+ /// \brief Resolve a CXXBaseSpecifiers ID into an offset into the chain
+ /// of loaded AST files.
+ uint64_t GetCXXBaseSpecifiersOffset(serialization::CXXBaseSpecifiersID ID);
+
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
+
/// \brief Resolve the offset of a statement into a statement.
///
/// This operation will read a new statement from the external
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Fri Oct 29 17:39:52 2010
@@ -264,6 +264,35 @@
/// file.
unsigned NumVisibleDeclContexts;
+ /// \brief The offset of each CXXBaseSpecifier set within the AST.
+ llvm::SmallVector<uint32_t, 4> CXXBaseSpecifiersOffsets;
+
+ /// \brief The first ID number we can use for our own base specifiers.
+ serialization::CXXBaseSpecifiersID FirstCXXBaseSpecifiersID;
+
+ /// \brief The base specifiers ID that will be assigned to the next new
+ /// set of C++ base specifiers.
+ serialization::CXXBaseSpecifiersID NextCXXBaseSpecifiersID;
+
+ /// \brief A set of C++ base specifiers that is queued to be written into the
+ /// AST file.
+ struct QueuedCXXBaseSpecifiers {
+ QueuedCXXBaseSpecifiers() : ID(), Bases(), BasesEnd() { }
+
+ QueuedCXXBaseSpecifiers(serialization::CXXBaseSpecifiersID ID,
+ CXXBaseSpecifier const *Bases,
+ CXXBaseSpecifier const *BasesEnd)
+ : ID(ID), Bases(Bases), BasesEnd(BasesEnd) { }
+
+ serialization::CXXBaseSpecifiersID ID;
+ CXXBaseSpecifier const * Bases;
+ CXXBaseSpecifier const * BasesEnd;
+ };
+
+ /// \brief Queue of C++ base specifiers to be written to the AST file,
+ /// in the order they should be written.
+ llvm::SmallVector<QueuedCXXBaseSpecifiers, 2> CXXBaseSpecifiersToWrite;
+
/// \brief Write the given subexpression to the bitstream.
void WriteSubStmt(Stmt *S);
@@ -344,6 +373,11 @@
/// \brief Emit a CXXTemporary.
void AddCXXTemporary(const CXXTemporary *Temp, RecordDataImpl &Record);
+ /// \brief Emit a set of C++ base specifiers to the record.
+ void AddCXXBaseSpecifiersRef(CXXBaseSpecifier const *Bases,
+ CXXBaseSpecifier const *BasesEnd,
+ RecordDataImpl &Record);
+
/// \brief Get the unique number used to refer to the given selector.
serialization::SelectorID getSelectorRef(Selector Sel);
@@ -394,6 +428,7 @@
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordDataImpl &Record);
+
/// \brief Force a declaration to be emitted and get its ID.
serialization::DeclID GetDeclRef(const Decl *D);
@@ -478,6 +513,10 @@
/// been added to the queue via AddStmt().
void FlushStmts();
+ /// \brief Flush all of the C++ base specifier sets that have been added
+ /// via \c AddCXXBaseSpecifiersRef().
+ void FlushCXXBaseSpecifiers();
+
/// \brief Record an ID for the given switch-case statement.
unsigned RecordSwitchCaseID(SwitchCase *S);
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Oct 29 17:39:52 2010
@@ -36,7 +36,7 @@
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 @@
// 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 @@
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 *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);
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Oct 29 17:39:52 2010
@@ -2069,6 +2069,17 @@
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 @@
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 @@
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 @@
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)
{}
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Oct 29 17:39:52 2010
@@ -773,8 +773,6 @@
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 @@
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 @@
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");
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Oct 29 17:39:52 2010
@@ -1725,7 +1725,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
FirstIdentID == NextIdentID &&
FirstSelectorID == NextSelectorID &&
FirstMacroID == NextMacroID &&
+ FirstCXXBaseSpecifiersID == NextCXXBaseSpecifiersID &&
"Setting chain after writing has started.");
Chain = Reader;
@@ -3238,11 +3299,13 @@
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) {
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Oct 29 17:39:52 2010
@@ -1182,6 +1182,12 @@
// 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.
Modified: cfe/trunk/test/PCH/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.cpp?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-templates.cpp (original)
+++ cfe/trunk/test/PCH/cxx-templates.cpp Fri Oct 29 17:39:52 2010
@@ -37,3 +37,5 @@
}
template struct S4<int>;
+
+S7<int[5]> s7_5;
Modified: cfe/trunk/test/PCH/cxx-templates.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.h?rev=117732&r1=117731&r2=117732&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-templates.h (original)
+++ cfe/trunk/test/PCH/cxx-templates.h Fri Oct 29 17:39:52 2010
@@ -164,3 +164,8 @@
typedef t1& t2;
};
+template<typename T>
+ struct S7;
+
+template<unsigned N>
+struct S7<int[N]> : S6<const int[N]> { };
More information about the cfe-commits
mailing list