aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-11-12 21:07:46 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-11-12 21:07:46 +0000
commitad834d534e9a5db3d3baa09593775f83ceaff1f2 (patch)
treed32e3e0b772dbce67ebb80c1f5d33a8b53feda7d /lib
parent5bbe816cd08bd28a87e8dadedf2cafb19ebf3b0b (diff)
[PCH] When completing an objc forward reference, do not serialize the chain of its categories because
it is going to be rewritten (and the chain will be serialized again), otherwise we may form a cycle in its categories list when deserializing. Also introduce ASTMutationListener::CompletedObjCForwardRef to notify that a forward reference was completed; using Decl's isChangedSinceDeserialization/setChangedSinceDeserialization is bug inducing and kinda gross, we should phase it out. Fixes infinite loop in rdar://10418538. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144465 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTImporter.cpp8
-rw-r--r--lib/AST/DeclObjC.cpp14
-rw-r--r--lib/Sema/SemaDeclObjC.cpp16
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp4
-rw-r--r--lib/Serialization/ASTWriter.cpp31
5 files changed, 42 insertions, 31 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index f7a55a1474..318f6f2897 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -3111,9 +3111,10 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
Name.getAsIdentifierInfo(), Loc,
Importer.Import(D->getAtStartLoc()),
D->isInitiallyForwardDecl());
- ToProto->setForwardDecl(D->isForwardDecl());
ToProto->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToProto);
+ if (D->isInitiallyForwardDecl() && !D->isForwardDecl())
+ ToProto->completedForwardDecl();
}
Importer.Imported(D, ToProto);
@@ -3172,11 +3173,12 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getAtStartLoc()),
Name.getAsIdentifierInfo(), Loc,
- D->isForwardDecl(),
+ D->isInitiallyForwardDecl(),
D->isImplicitInterfaceDecl());
- ToIface->setForwardDecl(D->isForwardDecl());
ToIface->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToIface);
+ if (D->isInitiallyForwardDecl() && !D->isForwardDecl())
+ ToIface->completedForwardDecl();
}
Importer.Imported(D, ToIface);
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 5c4d25fd02..35ee7c6ccd 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -217,6 +217,13 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
}
+void ObjCInterfaceDecl::completedForwardDecl() {
+ assert(isForwardDecl() && "Only valid to call for forward refs");
+ ForwardDecl = false;
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->CompletedObjCForwardRef(this);
+}
+
/// getFirstClassExtension - Find first class extension of the given class.
ObjCCategoryDecl* ObjCInterfaceDecl::getFirstClassExtension() const {
for (ObjCCategoryDecl *CDecl = getCategoryList(); CDecl;
@@ -913,6 +920,13 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
return NULL;
}
+void ObjCProtocolDecl::completedForwardDecl() {
+ assert(isForwardDecl() && "Only valid to call for forward refs");
+ isForwardProtoDecl = false;
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->CompletedObjCForwardRef(this);
+}
+
//===----------------------------------------------------------------------===//
// ObjCClassDecl
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 1632e092e3..3d1f5bd064 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -377,18 +377,16 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
return ActOnObjCContainerStartDefinition(IDecl);
} else {
IDecl->setLocation(ClassLoc);
- IDecl->setForwardDecl(false);
IDecl->setAtStartLoc(AtInterfaceLoc);
- // If the forward decl was in a PCH, we need to write it again in a
- // dependent AST file.
- IDecl->setChangedSinceDeserialization(true);
// Since this ObjCInterfaceDecl was created by a forward declaration,
// we now add it to the DeclContext since it wasn't added before
// (see ActOnForwardClassDeclaration).
IDecl->setLexicalDeclContext(CurContext);
CurContext->addDecl(IDecl);
-
+
+ IDecl->completedForwardDecl();
+
if (AttrList)
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
}
@@ -588,19 +586,16 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
// Make sure the cached decl gets a valid start location.
PDecl->setAtStartLoc(AtProtoInterfaceLoc);
PDecl->setLocation(ProtocolLoc);
- PDecl->setForwardDecl(false);
// Since this ObjCProtocolDecl was created by a forward declaration,
// we now add it to the DeclContext since it wasn't added before
PDecl->setLexicalDeclContext(CurContext);
CurContext->addDecl(PDecl);
- // Repeat in dependent AST files.
- PDecl->setChangedSinceDeserialization(true);
+ PDecl->completedForwardDecl();
} else {
PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName,
ProtocolLoc, AtProtoInterfaceLoc,
/*isForwardDecl=*/false);
PushOnScopeChains(PDecl, TUScope);
- PDecl->setForwardDecl(false);
}
if (AttrList)
ProcessDeclAttributeList(TUScope, PDecl, AttrList);
@@ -925,7 +920,8 @@ Decl *Sema::ActOnStartClassImplementation(
// Mark the interface as being completed, even if it was just as
// @class ....;
// declaration; the user cannot reopen it.
- IDecl->setForwardDecl(false);
+ if (IDecl->isForwardDecl())
+ IDecl->completedForwardDecl();
}
ObjCImplementationDecl* IMPDecl =
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index d414c07290..729cde0abf 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -558,7 +558,7 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
// We will rebuild this list lazily.
ID->setIvarList(0);
ID->InitiallyForwardDecl = Record[Idx++];
- ID->setForwardDecl(Record[Idx++]);
+ ID->ForwardDecl = Record[Idx++];
ID->setImplicitInterfaceDecl(Record[Idx++]);
ID->setSuperClassLoc(ReadSourceLocation(Record, Idx));
ID->setLocEnd(ReadSourceLocation(Record, Idx));
@@ -576,7 +576,7 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
VisitObjCContainerDecl(PD);
PD->InitiallyForwardDecl = Record[Idx++];
- PD->setForwardDecl(Record[Idx++]);
+ PD->isForwardProtoDecl = Record[Idx++];
PD->setLocEnd(ReadSourceLocation(Record, Idx));
unsigned NumProtoRefs = Record[Idx++];
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index deaec02271..a98c4cc82b 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -2995,7 +2995,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
// 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;
@@ -3183,7 +3182,7 @@ void ASTWriter::ResolveDeclUpdatesBlocks() {
const Decl *D = I->first;
UpdateRecord &URec = I->second;
- if (DeclsToRewrite.count(D))
+ if (isRewritten(D))
continue; // The decl will be written completely
unsigned Idx = 0, N = URec.size();
@@ -3216,7 +3215,7 @@ void ASTWriter::WriteDeclUpdatesBlocks() {
const Decl *D = I->first;
UpdateRecord &URec = I->second;
- if (DeclsToRewrite.count(D))
+ if (isRewritten(D))
continue; // The decl will be written completely,no need to store updates.
uint64_t Offset = Stream.GetCurrentBitNo();
@@ -3243,17 +3242,6 @@ void ASTWriter::WriteDeclReplacementsBlock() {
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;
@@ -3263,13 +3251,16 @@ void ASTWriter::WriteChainedObjCCategories() {
I = LocalChainedObjCCategories.begin(),
E = LocalChainedObjCCategories.end(); I != E; ++I) {
ChainedObjCCategoriesData &Data = *I;
+ if (isRewritten(Data.Interface))
+ continue;
+
serialization::DeclID
HeadCatID = getDeclID(Data.Interface->getCategoryList());
assert(HeadCatID != 0 && "Category not written ?");
- Record.push_back(Data.InterfaceID);
+ Record.push_back(GetDeclRef(Data.Interface));
Record.push_back(HeadCatID);
- Record.push_back(Data.TailCategoryID);
+ Record.push_back(GetDeclRef(Data.TailCategory));
}
Stream.EmitRecord(OBJC_CHAINED_CATEGORIES, Record);
}
@@ -4136,3 +4127,11 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
ChainedObjCCategoriesData Data = { IFD, CatD, 0, 0 };
LocalChainedObjCCategories.push_back(Data);
}
+
+void ASTWriter::CompletedObjCForwardRef(const ObjCContainerDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+ if (!D->isFromASTFile())
+ return; // Declaration not imported from PCH.
+
+ RewriteDecl(D);
+}