[cfe-commits] r139974 - in /cfe/trunk: include/clang/Serialization/ASTWriter.h lib/Serialization/ASTWriter.cpp test/Modules/objc-categories.m
Douglas Gregor
dgregor at apple.com
Fri Sep 16 17:05:03 PDT 2011
Author: dgregor
Date: Fri Sep 16 19:05:03 2011
New Revision: 139974
URL: http://llvm.org/viewvc/llvm-project?rev=139974&view=rev
Log:
With modules, we can end up loading a new module after we've seen an
arbitrary amount of code. This forces us to stage the AST writer more
strictly, ensuring that we don't assign a declaration ID to a
declaration until after we're certain that no more modules will get
loaded.
Modified:
cfe/trunk/include/clang/Serialization/ASTWriter.h
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/Modules/objc-categories.m
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=139974&r1=139973&r2=139974&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Fri Sep 16 19:05:03 2011
@@ -97,6 +97,10 @@
/// \brief A listener object that receives notifications when certain
/// entities are serialized.
ASTSerializationListener *SerializationListener;
+
+ /// \brief Indicates when the AST writing is actively performing
+ /// serialization, rather than just queueing updates.
+ bool WritingAST;
/// \brief Stores a declaration or a type to be written to the AST file.
class DeclOrType {
@@ -251,11 +255,15 @@
struct ChainedObjCCategoriesData {
/// \brief The interface in the imported module.
const ObjCInterfaceDecl *Interface;
- /// \brief ID of the interface.
+ /// \brief The local tail category ID that got chained to the imported
+ /// interface.
+ const ObjCCategoryDecl *TailCategory;
+
+ /// \brief ID corresponding to \c Interface.
serialization::DeclID InterfaceID;
- /// \brief ID of the locally tail category ID that got chained to the
- /// imported interface.
- serialization::DeclID TailCatID;
+
+ /// \brief ID corresponding to TailCategoryID.
+ serialization::DeclID TailCategoryID;
};
/// \brief ObjC categories that got chained to an interface imported from
/// another module.
@@ -351,8 +359,10 @@
void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP, bool IsModule);
void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record);
+ void ResolveDeclUpdatesBlocks();
void WriteDeclUpdatesBlocks();
void WriteDeclReplacementsBlock();
+ void ResolveChainedObjCCategories();
void WriteChainedObjCCategories();
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
void WriteFPPragmaOptions(const FPOptions &Opts);
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=139974&r1=139973&r2=139974&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Sep 16 19:05:03 2011
@@ -2719,6 +2719,7 @@
ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
: Stream(Stream), Context(0), Chain(0), SerializationListener(0),
+ WritingAST(false),
FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID),
FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID),
@@ -2740,6 +2741,8 @@
void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const std::string &OutputFile,
bool IsModule, StringRef isysroot) {
+ WritingAST = true;
+
// Emit the file header.
Stream.Emit((unsigned)'C', 8);
Stream.Emit((unsigned)'P', 8);
@@ -2751,6 +2754,8 @@
Context = &SemaRef.Context;
WriteASTCore(SemaRef, StatCalls, isysroot, OutputFile, IsModule);
Context = 0;
+
+ WritingAST = false;
}
template<typename Vector>
@@ -2983,10 +2988,15 @@
ASTWriter::UpdateRecord &Record = DeclUpdates[TU];
if (Record.empty()) {
Record.push_back(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE);
- AddDeclRef(NS, Record);
+ Record.push_back(reinterpret_cast<uint64_t>(NS));
}
}
+ // Resolve any declaration pointers within the declaration updates block and
+ // chained Objective-C categories block to declaration IDs.
+ ResolveDeclUpdatesBlocks();
+ ResolveChainedObjCCategories();
+
// Form the record of special types.
RecordData SpecialTypes;
AddTypeRef(Context.getBuiltinVaListType(), SpecialTypes);
@@ -3120,6 +3130,36 @@
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;
+
+ if (DeclsToRewrite.count(D))
+ continue; // The decl will be written completely
+
+ unsigned Idx = 0, N = URec.size();
+ while (Idx < N) {
+ switch ((DeclUpdateKind)URec[Idx++]) {
+ case UPD_CXX_SET_DEFINITIONDATA:
+ 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;
+ break;
+
+ case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
+ ++Idx;
+ break;
+ }
+ }
+ }
+}
+
void ASTWriter::WriteDeclUpdatesBlocks() {
if (DeclUpdates.empty())
return;
@@ -3157,6 +3197,17 @@
Stream.EmitRecord(DECL_REPLACEMENTS, Record);
}
+void ASTWriter::ResolveChainedObjCCategories() {
+ for (SmallVector<ChainedObjCCategoriesData, 16>::iterator
+ I = LocalChainedObjCCategories.begin(),
+ E = LocalChainedObjCCategories.end(); I != E; ++I) {
+ ChainedObjCCategoriesData &Data = *I;
+ Data.InterfaceID = GetDeclRef(Data.Interface);
+ Data.TailCategoryID = GetDeclRef(Data.TailCategory);
+ }
+
+}
+
void ASTWriter::WriteChainedObjCCategories() {
if (LocalChainedObjCCategories.empty())
return;
@@ -3172,7 +3223,7 @@
Record.push_back(Data.InterfaceID);
Record.push_back(HeadCatID);
- Record.push_back(Data.TailCatID);
+ Record.push_back(Data.TailCategoryID);
}
Stream.EmitRecord(OBJC_CHAINED_CATEGORIES, Record);
}
@@ -3354,6 +3405,8 @@
}
DeclID ASTWriter::GetDeclRef(const Decl *D) {
+ assert(WritingAST && "Cannot request a declaration ID before AST writing");
+
if (D == 0) {
return 0;
}
@@ -3874,6 +3927,7 @@
void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
assert(D->isDefinition());
+ assert(!WritingAST && "Already writing the AST!");
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
// We are interested when a PCH decl is modified.
if (RD->isFromASTFile()) {
@@ -3895,12 +3949,14 @@
Record.push_back(UPD_CXX_SET_DEFINITIONDATA);
assert(Redecl->DefinitionData);
assert(Redecl->DefinitionData->Definition == D);
- AddDeclRef(D, Record); // the DefinitionDecl
+ Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl
}
}
}
}
void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+
// TU and namespaces are handled elsewhere.
if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC))
return;
@@ -3912,6 +3968,7 @@
}
void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
+ assert(!WritingAST && "Already writing the AST!");
assert(D->isImplicit());
if (!(!D->isFromASTFile() && RD->isFromASTFile()))
return; // Not a source member added to a class from PCH.
@@ -3922,34 +3979,37 @@
assert(RD->isDefinition());
UpdateRecord &Record = DeclUpdates[RD];
Record.push_back(UPD_CXX_ADDED_IMPLICIT_MEMBER);
- AddDeclRef(D, Record);
+ Record.push_back(reinterpret_cast<uint64_t>(D));
}
void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
const ClassTemplateSpecializationDecl *D) {
// The specializations set is kept in the canonical template.
+ assert(!WritingAST && "Already writing the AST!");
TD = TD->getCanonicalDecl();
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);
- AddDeclRef(D, Record);
+ Record.push_back(reinterpret_cast<uint64_t>(D));
}
void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {
// The specializations set is kept in the canonical template.
+ assert(!WritingAST && "Already writing the AST!");
TD = TD->getCanonicalDecl();
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);
- AddDeclRef(D, Record);
+ Record.push_back(reinterpret_cast<uint64_t>(D));
}
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
return; // Declaration not imported from PCH.
@@ -3959,6 +4019,7 @@
}
void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
return;
@@ -3972,6 +4033,7 @@
void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {
+ assert(!WritingAST && "Already writing the AST!");
if (!IFD->isFromASTFile())
return; // Declaration not imported from PCH.
if (CatD->getNextClassCategory() &&
@@ -3979,7 +4041,7 @@
return; // We already recorded that the tail of a category chain should be
// attached to an interface.
- ChainedObjCCategoriesData Data = { IFD, GetDeclRef(IFD), GetDeclRef(CatD) };
+ ChainedObjCCategoriesData Data = { IFD, CatD, 0, 0 };
LocalChainedObjCCategories.push_back(Data);
}
Modified: cfe/trunk/test/Modules/objc-categories.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/objc-categories.m?rev=139974&r1=139973&r2=139974&view=diff
==============================================================================
--- cfe/trunk/test/Modules/objc-categories.m (original)
+++ cfe/trunk/test/Modules/objc-categories.m Fri Sep 16 19:05:03 2011
@@ -54,12 +54,13 @@
#elif defined(MODULE_BOTTOM)
__import_module__ diamond_left;
-__import_module__ diamond_right;
@interface Foo(Bottom)
-(void)bottom;
@end
+__import_module__ diamond_right;
+
@interface LeftFoo(Bottom)
-(void)bottom;
@end
More information about the cfe-commits
mailing list