llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID>
MacroDefinitions;
- typedef SmallVector<uint64_t, 2> UpdateRecord;
+ /// An update to a Decl.
+ class DeclUpdate {
+ /// A DeclUpdateKind.
+ unsigned Kind;
+ union {
+ const Decl *Dcl;
+ void *Type;
+ unsigned Loc;
+ };
+
+ public:
+ DeclUpdate(unsigned Kind) : Kind(Kind), Dcl(0) {}
+ DeclUpdate(unsigned Kind, const Decl *Dcl) : Kind(Kind), Dcl(Dcl) {}
+ DeclUpdate(unsigned Kind, QualType Type)
+ : Kind(Kind), Type(Type.getAsOpaquePtr()) {}
+ DeclUpdate(unsigned Kind, SourceLocation Loc)
+ : Kind(Kind), Loc(Loc.getRawEncoding()) {}
+
+ unsigned getKind() const { return Kind; }
+ const Decl *getDecl() const { return Dcl; }
+ QualType getType() const { return QualType::getFromOpaquePtr(Type); }
+ SourceLocation getLoc() const {
+ return SourceLocation::getFromRawEncoding(Loc);
+ }
+ };
+
+ typedef SmallVector<DeclUpdate, 1> UpdateRecord;
typedef llvm::DenseMap<const Decl *, UpdateRecord> DeclUpdateMap;
/// \brief Mapping from declarations that came from a chained PCH to the
/// record containing modifications to them.
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
bool IsModule);
void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record);
- void ResolveDeclUpdatesBlocks();
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
void WriteDeclReplacementsBlock();
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
// If the translation unit has an anonymous namespace, and we don't already
// have an update block for it, write it as an update block.
+ // FIXME: Why do we not do this if there's already an update block?
if (NamespaceDecl *NS = TU->getAnonymousNamespace()) {
ASTWriter::UpdateRecord &Record = DeclUpdates[TU];
- if (Record.empty()) {
- Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE);
- Record.push_back(reinterpret_cast<uint64_t>(NS));
- }
+ if (Record.empty())
+ Record.push_back({UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS});
}
// Make sure visible decls, added to DeclContexts previously loaded from
Buffer.data(), Buffer.size());
}
- // Resolve any declaration pointers within the declaration updates block.
- // FIXME: Fold this into WriteDeclUpdatesBlocks.
- ResolveDeclUpdatesBlocks();
-
RecordData DeclUpdatesOffsetsRecord;
// Keep writing types, declarations, and declaration update records
Stream.ExitBlock();
}
-/// \brief Go through the declaration update blocks and resolve declaration
-/// pointers into declaration IDs.
-void ASTWriter::ResolveDeclUpdatesBlocks() {
- for (DeclUpdateMap::iterator
- I = DeclUpdates.begin(), E = DeclUpdates.end(); I != E; ++I) {
- const Decl *D = I->first;
- UpdateRecord &URec = I->second;
-
+void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
+ if (DeclUpdates.empty())
+ return;
+
+ DeclUpdateMap LocalUpdates;
+ LocalUpdates.swap(DeclUpdates);
+
+ for (auto &DeclUpdate : LocalUpdates) {
+ const Decl *D = DeclUpdate.first;
if (isRewritten(D))
- continue; // The decl will be written completely
+ continue; // The decl will be written completely,no need to store updates.
+
+ OffsetsRecord.push_back(GetDeclRef(D));
+ OffsetsRecord.push_back(Stream.GetCurrentBitNo());
- unsigned Idx = 0, N = URec.size();
- while (Idx < N) {
- switch ((DeclUpdateKind)URec[Idx++]) {
+ RecordData Record;
+ for (auto &Update : DeclUpdate.second) {
+ DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind();
+
+ Record.push_back(Kind);
+ switch (Kind) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER:
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
- URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
- ++Idx;
+ Record.push_back(GetDeclRef(Update.getDecl()));
break;
case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
- case UPD_DECL_MARKED_USED:
- ++Idx;
+ AddSourceLocation(Update.getLoc(), Record);
break;
case UPD_CXX_DEDUCED_RETURN_TYPE:
- URec[Idx] = GetOrCreateTypeID(
- QualType::getFromOpaquePtr(reinterpret_cast<void *>(URec[Idx])));
- ++Idx;
+ Record.push_back(GetOrCreateTypeID(Update.getType()));
+ break;
+
+ case UPD_DECL_MARKED_USED:
break;
}
}
- }
-}
-void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
- if (DeclUpdates.empty())
- return;
-
- DeclUpdateMap LocalUpdates;
- LocalUpdates.swap(DeclUpdates);
-
- for (auto &Update : LocalUpdates) {
- const Decl *D = Update.first;
- UpdateRecord &URec = Update.second;
-
- if (isRewritten(D))
- continue; // The decl will be written completely,no need to store updates.
-
- uint64_t Offset = Stream.GetCurrentBitNo();
- Stream.EmitRecord(DECL_UPDATES, URec);
+ Stream.EmitRecord(DECL_UPDATES, Record);
// Flush any statements that were written as part of this update record.
FlushStmts();
-
- OffsetsRecord.push_back(GetDeclRef(D));
- OffsetsRecord.push_back(Offset);
}
}
// A decl coming from PCH was modified.
assert(RD->isCompleteDefinition());
- UpdateRecord &Record = DeclUpdates[RD];
- Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[RD].push_back({UPD_CXX_ADDED_IMPLICIT_MEMBER, D});
}
void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back({UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D});
}
void ASTWriter::AddedCXXTemplateSpecialization(
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back({UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D});
}
void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
if (!(!D->isFromASTFile() && TD->isFromASTFile()))
return; // Not a source specialization added to a template from PCH.
- UpdateRecord &Record = DeclUpdates[TD];
- Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
- Record.push_back(reinterpret_cast<uint64_t>(D));
+ DeclUpdates[TD].push_back({UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, D});
}
void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
if (!FD->isFromASTFile())
return; // Not a function declared in PCH and defined outside.
- UpdateRecord &Record = DeclUpdates[FD];
- Record.push_back(UPD_CXX_DEDUCED_RETURN_TYPE);
- Record.push_back(reinterpret_cast<uint64_t>(ReturnType.getAsOpaquePtr()));
+ DeclUpdates[FD].push_back({UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType});
}
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
// Since the actual instantiation is delayed, this really means that we need
// to update the instantiation location.
- UpdateRecord &Record = DeclUpdates[D];
- Record.push_back(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER);
- AddSourceLocation(
- D->getMemberSpecializationInfo()->getPointOfInstantiation(), Record);
+ DeclUpdates[D].push_back(
+ {UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+ D->getMemberSpecializationInfo()->getPointOfInstantiation()});
}
void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
if (!D->isFromASTFile())
return;
- UpdateRecord &Record = DeclUpdates[D];
- Record.push_back(UPD_DECL_MARKED_USED);
+ DeclUpdates[D].push_back({UPD_DECL_MARKED_USED});
}