/// declarations.
TU_UPDATE_LEXICAL = 22,
- /// \brief Record code for the array describing the locations (in the
- /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by
- /// the first known ID.
- LOCAL_REDECLARATIONS_MAP = 23,
+ // ID 23 used to be for a list of local redeclarations.
/// \brief Record code for declarations that Sema keeps references of.
SEMA_DECL_REFS = 24,
/// imported by the AST file.
IMPORTED_MODULES = 43,
- // ID 40 used to be a table of merged canonical declarations.
-
- /// \brief Record code for the array of redeclaration chains.
- ///
- /// This array can only be interpreted properly using the local
- /// redeclarations map.
- LOCAL_REDECLARATIONS = 45,
+ // ID 44 used to be a table of merged canonical declarations.
+ // ID 45 used to be a list of declaration IDs of local redeclarations.
/// \brief Record code for the array of Objective-C categories (including
/// extensions).
/// For more information about predefined declarations, see the
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
const unsigned int NUM_PREDEF_DECL_IDS = 12;
+
+ /// \brief Record code for a list of local redeclarations of a declaration.
+ const unsigned int LOCAL_REDECLARATIONS = 50;
/// \brief Record codes for each kind of declaration.
///
std::deque<Decl *> InterestingDecls;
/// \brief The list of redeclaration chains that still need to be
- /// reconstructed.
- ///
- /// Each element is the canonical declaration of the chain.
- /// Elements in this vector should be unique; use
- /// PendingDeclChainsKnown to ensure uniqueness.
- SmallVector<Decl *, 16> PendingDeclChains;
+ /// reconstructed, and the local offset to the corresponding list
+ /// of redeclarations.
+ SmallVector<std::pair<Decl *, uint64_t>, 16> PendingDeclChains;
/// \brief The list of canonical declarations whose redeclaration chains
/// need to be marked as incomplete once we're done deserializing things.
RecordLocation DeclCursorForID(serialization::DeclID ID,
unsigned &RawLocation);
void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
- void loadPendingDeclChain(Decl *D);
+ void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,
unsigned PreviousGeneration = 0);
void WriteFPPragmaOptions(const FPOptions &Opts);
void WriteOpenCLExtensions(Sema &SemaRef);
void WriteObjCCategories();
- void WriteRedeclarations();
void WriteLateParsedTemplates(Sema &SemaRef);
void WriteOptimizePragmaOptions(Sema &SemaRef);
const serialization::DeclID *FileSortedDecls;
unsigned NumFileSortedDecls;
- /// \brief Array of redeclaration chain location information within this
- /// module file, sorted by the first declaration ID.
- const serialization::LocalRedeclarationsInfo *RedeclarationsMap;
-
- /// \brief The number of redeclaration info entries in RedeclarationsMap.
- unsigned LocalNumRedeclarationsInMap;
-
- /// \brief The redeclaration chains for declarations local to this
- /// module file.
- SmallVector<uint64_t, 1> RedeclarationChains;
-
/// \brief Array of category list location information within this
/// module file, sorted by the definition ID.
const serialization::ObjCCategoriesInfo *ObjCCategoriesMap;
break;
}
- case LOCAL_REDECLARATIONS: {
- F.RedeclarationChains.swap(Record);
- break;
- }
-
- case LOCAL_REDECLARATIONS_MAP: {
- if (F.LocalNumRedeclarationsInMap != 0) {
- Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
- return Failure;
- }
-
- F.LocalNumRedeclarationsInMap = Record[0];
- F.RedeclarationsMap = (const LocalRedeclarationsInfo *)Blob.data();
- break;
- }
-
case MACRO_OFFSET: {
if (F.LocalNumMacros != 0) {
Error("duplicate MACRO_OFFSET record in AST file");
// Load pending declaration chains.
for (unsigned I = 0; I != PendingDeclChains.size(); ++I)
- loadPendingDeclChain(PendingDeclChains[I]);
+ loadPendingDeclChain(PendingDeclChains[I].first, PendingDeclChains[I].second);
PendingDeclChains.clear();
// Make the most recent of the top-level declarations visible.
bool IsKeyDecl = ThisDeclID == FirstDeclID;
bool IsFirstLocalDecl = false;
+ uint64_t RedeclOffset = 0;
+
// 0 indicates that this declaration was the only declaration of its entity,
// and is used for space optimization.
if (FirstDeclID == 0) {
// declaration.
for (unsigned I = 0; I != N - 1; ++I)
MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
+
+ RedeclOffset = Record[Idx++];
} else {
// This declaration was not the first local declaration. Read the first
// local declaration now, to trigger the import of other redeclarations.
// above; this ensures that the redeclaration chain is built in the correct
// order.
if (IsFirstLocalDecl)
- Reader.PendingDeclChains.push_back(DAsT);
+ Reader.PendingDeclChains.push_back(std::make_pair(DAsT, RedeclOffset));
return RedeclarableResult(FirstDeclID, MergeWith, IsKeyDecl);
}
}
}
-void ASTReader::loadPendingDeclChain(Decl *FirstLocal) {
- ModuleFile &M = *getOwningModuleFile(FirstLocal);
- DeclID LocalID =
- mapGlobalIDToModuleFileGlobalID(M, FirstLocal->getGlobalID());
- assert(LocalID && "looking for redecl chain in wrong module file");
-
- // Perform a binary search to find the local redeclarations for this
- // declaration (if any).
- // FIXME: Just store an offset with the first declaration.
- const LocalRedeclarationsInfo Compare = {LocalID, 0};
- const LocalRedeclarationsInfo *Result = std::lower_bound(
- M.RedeclarationsMap,
- M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare);
+void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
+ // Attach FirstLocal to the end of the decl chain.
+ Decl *CanonDecl = FirstLocal->getCanonicalDecl();
+ if (FirstLocal != CanonDecl) {
+ Decl *PrevMostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
+ ASTDeclReader::attachPreviousDecl(
+ *this, FirstLocal, PrevMostRecent ? PrevMostRecent : CanonDecl,
+ CanonDecl);
+ }
- // Pull out the list of redeclarations.
- SmallVector<Decl*, 4> Chain;
- if (Result != M.RedeclarationsMap + M.LocalNumRedeclarationsInMap &&
- Result->FirstID == LocalID) {
- unsigned Offset = Result->Offset;
- unsigned N = M.RedeclarationChains[Offset++];
- for (unsigned I = 0; I != N; ++I)
- Chain.push_back(GetLocalDecl(M, M.RedeclarationChains[Offset++]));
+ if (!LocalOffset) {
+ ASTDeclReader::attachLatestDecl(CanonDecl, FirstLocal);
+ return;
}
- Chain.push_back(FirstLocal);
- // Hook up the chain.
- //
- // FIXME: We have three different dispatches on decl kind here; maybe
+ // Load the list of other redeclarations from this module file.
+ ModuleFile *M = getOwningModuleFile(FirstLocal);
+ assert(M && "imported decl from no module file");
+
+ llvm::BitstreamCursor &Cursor = M->DeclsCursor;
+ SavedStreamPosition SavedPosition(Cursor);
+ Cursor.JumpToBit(LocalOffset);
+
+ RecordData Record;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.readRecord(Code, Record);
+ (void)RecCode;
+ assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!");
+
+ // FIXME: We have several different dispatches on decl kind here; maybe
// we should instead generate one loop per kind and dispatch up-front?
- Decl *CanonDecl = FirstLocal->getCanonicalDecl();
- Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
- if (!MostRecent)
- MostRecent = CanonDecl;
- for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
- auto *D = Chain[N - I - 1];
- if (D == CanonDecl)
- continue;
+ Decl *MostRecent = FirstLocal;
+ for (unsigned I = 0, N = Record.size(); I != N; ++I) {
+ auto *D = GetLocalDecl(*M, Record[N - I - 1]);
ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl);
MostRecent = D;
}
RECORD(PPD_ENTITIES_OFFSETS);
RECORD(REFERENCED_SELECTOR_POOL);
RECORD(TU_UPDATE_LEXICAL);
- RECORD(LOCAL_REDECLARATIONS_MAP);
RECORD(SEMA_DECL_REFS);
RECORD(WEAK_UNDECLARED_IDENTIFIERS);
RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
RECORD(OBJC_CATEGORIES_MAP);
RECORD(FILE_SORTED_DECLS);
RECORD(IMPORTED_MODULES);
- RECORD(LOCAL_REDECLARATIONS);
RECORD(OBJC_CATEGORIES);
RECORD(MACRO_OFFSET);
RECORD(LATE_PARSED_TEMPLATE);
RECORD(TYPE_ATOMIC);
RECORD(TYPE_DECAYED);
RECORD(TYPE_ADJUSTED);
+ RECORD(LOCAL_REDECLARATIONS);
RECORD(DECL_TYPEDEF);
RECORD(DECL_TYPEALIAS);
RECORD(DECL_ENUM);
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
}
-void ASTWriter::WriteRedeclarations() {
- RecordData LocalRedeclChains;
- SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap;
-
- for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
- const Decl *FirstLocal = Redeclarations[I];
- assert(!FirstLocal->isFromASTFile() &&
- (!FirstLocal->getPreviousDecl() ||
- FirstLocal->getPreviousDecl()->isFromASTFile() ||
- getDeclID(FirstLocal->getPreviousDecl()) < NUM_PREDEF_DECL_IDS) &&
- "not the first local declaration");
- assert(getDeclID(FirstLocal) >= NUM_PREDEF_DECL_IDS &&
- "should not have predefined decl as first decl");
-
- unsigned Offset = LocalRedeclChains.size();
- unsigned Size = 0;
- LocalRedeclChains.push_back(0); // Placeholder for the size.
-
- // Collect the set of local redeclarations of this declaration, from newest
- // to oldest.
- for (const Decl *Prev = FirstLocal->getMostRecentDecl(); Prev != FirstLocal;
- Prev = Prev->getPreviousDecl()) {
- if (!Prev->isFromASTFile()) {
- AddDeclRef(Prev, LocalRedeclChains);
- ++Size;
- }
- }
-
- // If we only have a single local declaration, there is no point in storing
- // a redeclaration chain.
- if (LocalRedeclChains.size() == 1)
- continue;
-
- LocalRedeclChains[Offset] = Size;
-
- // Add the mapping from the first ID from the AST to the set of local
- // declarations.
- LocalRedeclarationsInfo Info = { getDeclID(FirstLocal), Offset };
- LocalRedeclsMap.push_back(Info);
-
- assert(N == Redeclarations.size() &&
- "Deserialized a declaration we shouldn't have");
- }
-
- if (LocalRedeclChains.empty())
- return;
-
- // Sort the local redeclarations map by the first declaration ID,
- // since the reader will be performing binary searches on this information.
- llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end());
-
- // Emit the local redeclarations map.
- using namespace llvm;
- llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS_MAP));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
- unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
-
- RecordData Record;
- Record.push_back(LOCAL_REDECLARATIONS_MAP);
- Record.push_back(LocalRedeclsMap.size());
- Stream.EmitRecordWithBlob(AbbrevID, Record,
- reinterpret_cast<char*>(LocalRedeclsMap.data()),
- LocalRedeclsMap.size() * sizeof(LocalRedeclarationsInfo));
-
- // Emit the redeclaration chains.
- Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains);
-}
-
void ASTWriter::WriteObjCCategories() {
SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
RecordData Categories;
}
WriteDeclReplacementsBlock();
- WriteRedeclarations();
WriteObjCCategories();
if(!WritingModule)
WriteOptimizePragmaOptions(SemaRef);
// first local declaration in the chain.
const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT);
if (DAsT == FirstLocal) {
- Writer.Redeclarations.push_back(DAsT);
-
// Emit a list of all imported first declarations so that we can be sure
// that all redeclarations visible to this module are before D in the
// redecl chain.
AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false);
// This is the number of imported first declarations + 1.
Record[I] = Record.size() - I;
+
+ // Collect the set of local redeclarations of this declaration, from
+ // newest to oldest.
+ RecordData LocalRedecls;
+ for (const Decl *Prev = FirstLocal->getMostRecentDecl();
+ Prev != FirstLocal; Prev = Prev->getPreviousDecl())
+ if (!Prev->isFromASTFile())
+ Writer.AddDeclRef(Prev, LocalRedecls);
+
+ // If we have any redecls, write them now as a separate record preceding
+ // the declaration itself.
+ if (LocalRedecls.empty())
+ Record.push_back(0);
+ else {
+ Record.push_back(Writer.Stream.GetCurrentBitNo());
+ Writer.Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedecls);
+ }
} else {
Record.push_back(0);
Writer.AddDeclRef(FirstLocal, Record);
VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
}
+ // Build a record for this declaration
+ Record.clear();
+ W.Code = (serialization::DeclCode)0;
+ W.AbbrevToUse = 0;
+ W.Visit(D);
+ if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
+
if (isReplacingADecl) {
// We're replacing a decl in a previous file.
ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(),
DeclOffsets[Index].setLocation(Loc);
DeclOffsets[Index].BitOffset = Stream.GetCurrentBitNo();
}
-
+
SourceManager &SM = Context.getSourceManager();
if (Loc.isValid() && SM.isLocalSourceLocation(Loc))
associateDeclWithFile(D, ID);
}
- // Build and emit a record for this declaration
- Record.clear();
- W.Code = (serialization::DeclCode)0;
- W.AbbrevToUse = 0;
- W.Visit(D);
- if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
-
if (!W.Code)
llvm::report_fatal_error(StringRef("unexpected declaration kind '") +
D->getDeclKindName() + "'");
LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr),
LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr),
FileSortedDecls(nullptr), NumFileSortedDecls(0),
- RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0),
ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0),
LocalNumTypes(0), TypeOffsets(nullptr), BaseTypeIndex(0)
{}