aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/ASTWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r--lib/Serialization/ASTWriter.cpp90
1 files changed, 58 insertions, 32 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index c5f9b2dc88..838ec35173 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -798,11 +798,12 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(KNOWN_NAMESPACES);
RECORD(MODULE_OFFSET_MAP);
RECORD(SOURCE_MANAGER_LINE_TABLE);
- RECORD(OBJC_CHAINED_CATEGORIES);
+ RECORD(OBJC_CATEGORIES_MAP);
RECORD(FILE_SORTED_DECLS);
RECORD(IMPORTED_MODULES);
RECORD(MERGED_DECLARATIONS);
RECORD(LOCAL_REDECLARATIONS);
+ RECORD(OBJC_CATEGORIES);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -2975,6 +2976,57 @@ void ASTWriter::WriteRedeclarations() {
Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains);
}
+void ASTWriter::WriteObjCCategories() {
+ llvm::SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
+ RecordData Categories;
+
+ for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) {
+ unsigned Size = 0;
+ unsigned StartIndex = Categories.size();
+
+ ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I];
+
+ // Allocate space for the size.
+ Categories.push_back(0);
+
+ // Add the categories.
+ for (ObjCCategoryDecl *Cat = Class->getCategoryList();
+ Cat; Cat = Cat->getNextClassCategory(), ++Size) {
+ assert(getDeclID(Cat) != 0 && "Bogus category");
+ AddDeclRef(Cat, Categories);
+ }
+
+ // Update the size.
+ Categories[StartIndex] = Size;
+
+ // Record this interface -> category map.
+ ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex };
+ CategoriesMap.push_back(CatInfo);
+ }
+
+ // Sort the categories map by the definition ID, since the reader will be
+ // performing binary searches on this information.
+ llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end());
+
+ // Emit the categories map.
+ using namespace llvm;
+ llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
+
+ RecordData Record;
+ Record.push_back(OBJC_CATEGORIES_MAP);
+ Record.push_back(CategoriesMap.size());
+ Stream.EmitRecordWithBlob(AbbrevID, Record,
+ reinterpret_cast<char*>(CategoriesMap.data()),
+ CategoriesMap.size() * sizeof(ObjCCategoriesInfo));
+
+ // Emit the category lists.
+ Stream.EmitRecord(OBJC_CATEGORIES, Categories);
+}
+
void ASTWriter::WriteMergedDecls() {
if (!Chain || Chain->MergedDecls.empty())
return;
@@ -3492,9 +3544,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
WriteDeclUpdatesBlocks();
WriteDeclReplacementsBlock();
- WriteChainedObjCCategories();
WriteMergedDecls();
WriteRedeclarations();
+ WriteObjCCategories();
// Some simple statistics
Record.clear();
@@ -3573,29 +3625,6 @@ void ASTWriter::WriteDeclReplacementsBlock() {
Stream.EmitRecord(DECL_REPLACEMENTS, Record);
}
-void ASTWriter::WriteChainedObjCCategories() {
- if (LocalChainedObjCCategories.empty())
- return;
-
- RecordData Record;
- for (SmallVector<ChainedObjCCategoriesData, 16>::iterator
- I = LocalChainedObjCCategories.begin(),
- E = LocalChainedObjCCategories.end(); I != E; ++I) {
- ChainedObjCCategoriesData &Data = *I;
- if (isRewritten(Data.Interface))
- continue;
-
- assert(Data.Interface->getCategoryList());
- serialization::DeclID
- HeadCatID = getDeclID(Data.Interface->getCategoryList());
-
- Record.push_back(getDeclID(Data.Interface));
- Record.push_back(HeadCatID);
- Record.push_back(getDeclID(Data.TailCategory));
- }
- Stream.EmitRecord(OBJC_CHAINED_CATEGORIES, Record);
-}
-
void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) {
Record.push_back(Loc.getRawEncoding());
}
@@ -4447,13 +4476,10 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
assert(!WritingAST && "Already writing the AST!");
if (!IFD->isFromASTFile())
return; // Declaration not imported from PCH.
- if (CatD->getNextClassCategory() &&
- !CatD->getNextClassCategory()->isFromASTFile())
- return; // We already recorded that the tail of a category chain should be
- // attached to an interface.
-
- ChainedObjCCategoriesData Data = { IFD, CatD };
- LocalChainedObjCCategories.push_back(Data);
+
+ assert(IFD->getDefinition() && "Category on a class without a definition?");
+ ObjCClassesWithCategories.insert(
+ const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));
}