diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-12-15 05:27:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-12-15 05:27:12 +0000 |
commit | 2e5c15be82f362611c5928ce853d0685ff98c766 (patch) | |
tree | 8b23e367ea5a70ddf92adc54293271df5f5c1d08 /lib | |
parent | fa39f5b76bafdf536c5e305f821eb1b7f11079bd (diff) |
Move the definition-specific data of ObjCInterfaceDecl into a
separately-allocated DefinitionData structure, which we manage the
same way as CXXRecordDecl::DefinitionData. This prepares the way for
making ObjCInterfaceDecls redeclarable, to more accurately model
forward declarations of Objective-C classes and eliminate the mutation
of ObjCInterfaceDecl that causes us serious trouble in the AST reader.
Note that ObjCInterfaceDecl's accessors are fairly robust against
being applied to forward declarations, because Clang (and Sema in
particular) doesn't perform RequireCompleteType/hasDefinition() checks
everywhere it has to. Each of these overly-robust cases is marked with
a FIXME, which we can tackle over time.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146644 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTImporter.cpp | 140 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 108 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 11 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 103 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 62 |
8 files changed, 279 insertions, 173 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index e409f0a1d3..949db7972a 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3178,7 +3178,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { } ObjCInterfaceDecl *ToIface = MergeWithIface; - if (!ToIface || ToIface->isForwardDecl()) { + if (!ToIface || !ToIface->hasDefinition()) { if (!ToIface) { ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), @@ -3187,88 +3187,98 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { D->isImplicitInterfaceDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); - if (D->isInitiallyForwardDecl() && !D->isForwardDecl()) - ToIface->completedForwardDecl(); } Importer.Imported(D, ToIface); - if (D->getSuperClass()) { - ObjCInterfaceDecl *Super - = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass())); - if (!Super) - return 0; + if (D->hasDefinition()) { + if (!ToIface->hasDefinition()) + ToIface->startDefinition(); - ToIface->setSuperClass(Super); - ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc())); - } - - // Import protocols - SmallVector<ObjCProtocolDecl *, 4> Protocols; - SmallVector<SourceLocation, 4> ProtocolLocs; - ObjCInterfaceDecl::protocol_loc_iterator - FromProtoLoc = D->protocol_loc_begin(); - - // FIXME: Should we be usng all_referenced_protocol_begin() here? - for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(), - FromProtoEnd = D->protocol_end(); - FromProto != FromProtoEnd; - ++FromProto, ++FromProtoLoc) { - ObjCProtocolDecl *ToProto - = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); - if (!ToProto) - return 0; - Protocols.push_back(ToProto); - ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + if (D->getSuperClass()) { + ObjCInterfaceDecl *Super + = cast_or_null<ObjCInterfaceDecl>( + Importer.Import(D->getSuperClass())); + if (!Super) + return 0; + + ToIface->setSuperClass(Super); + ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc())); + } + + // Import protocols + SmallVector<ObjCProtocolDecl *, 4> Protocols; + SmallVector<SourceLocation, 4> ProtocolLocs; + ObjCInterfaceDecl::protocol_loc_iterator + FromProtoLoc = D->protocol_loc_begin(); + + for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(), + FromProtoEnd = D->protocol_end(); + FromProto != FromProtoEnd; + ++FromProto, ++FromProtoLoc) { + ObjCProtocolDecl *ToProto + = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); + if (!ToProto) + return 0; + Protocols.push_back(ToProto); + ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); + } + + // FIXME: If we're merging, make sure that the protocol list is the same. + ToIface->setProtocolList(Protocols.data(), Protocols.size(), + ProtocolLocs.data(), Importer.getToContext()); } - // FIXME: If we're merging, make sure that the protocol list is the same. - ToIface->setProtocolList(Protocols.data(), Protocols.size(), - ProtocolLocs.data(), Importer.getToContext()); - // Import @end range ToIface->setAtEndRange(Importer.Import(D->getAtEndRange())); } else { Importer.Imported(D, ToIface); - // Check for consistency of superclasses. - DeclarationName FromSuperName, ToSuperName; - - // If the superclass hasn't been imported yet, do so before checking. - ObjCInterfaceDecl *DSuperClass = D->getSuperClass(); - ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass(); - - if (DSuperClass && !ToIfaceSuperClass) { - Decl *ImportedSuperClass = Importer.Import(DSuperClass); - ObjCInterfaceDecl *ImportedSuperIface = cast<ObjCInterfaceDecl>(ImportedSuperClass); - ToIface->setSuperClass(ImportedSuperIface); - } + if (D->hasDefinition()) { + // Check for consistency of superclasses. + DeclarationName FromSuperName, ToSuperName; + + // If the superclass hasn't been imported yet, do so before checking. + ObjCInterfaceDecl *DSuperClass = D->getSuperClass(); + ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass(); + + if (DSuperClass && !ToIfaceSuperClass) { + Decl *ImportedSuperClass = Importer.Import(DSuperClass); + ObjCInterfaceDecl *ImportedSuperIface + = cast<ObjCInterfaceDecl>(ImportedSuperClass); + + ToIface->setSuperClass(ImportedSuperIface); + } - if (D->getSuperClass()) - FromSuperName = Importer.Import(D->getSuperClass()->getDeclName()); - if (ToIface->getSuperClass()) - ToSuperName = ToIface->getSuperClass()->getDeclName(); - if (FromSuperName != ToSuperName) { - Importer.ToDiag(ToIface->getLocation(), - diag::err_odr_objc_superclass_inconsistent) - << ToIface->getDeclName(); + if (D->getSuperClass()) + FromSuperName = Importer.Import(D->getSuperClass()->getDeclName()); if (ToIface->getSuperClass()) - Importer.ToDiag(ToIface->getSuperClassLoc(), - diag::note_odr_objc_superclass) - << ToIface->getSuperClass()->getDeclName(); - else + ToSuperName = ToIface->getSuperClass()->getDeclName(); + if (FromSuperName != ToSuperName) { Importer.ToDiag(ToIface->getLocation(), - diag::note_odr_objc_missing_superclass); - if (D->getSuperClass()) - Importer.FromDiag(D->getSuperClassLoc(), + diag::err_odr_objc_superclass_inconsistent) + << ToIface->getDeclName(); + if (ToIface->getSuperClass()) + Importer.ToDiag(ToIface->getSuperClassLoc(), diag::note_odr_objc_superclass) - << D->getSuperClass()->getDeclName(); - else - Importer.FromDiag(D->getLocation(), + << ToIface->getSuperClass()->getDeclName(); + else + Importer.ToDiag(ToIface->getLocation(), diag::note_odr_objc_missing_superclass); - return 0; + if (D->getSuperClass()) + Importer.FromDiag(D->getSuperClassLoc(), + diag::note_odr_objc_superclass) + << D->getSuperClass()->getDeclName(); + else + Importer.FromDiag(D->getLocation(), + diag::note_odr_objc_missing_superclass); + return 0; + } } } + if (!D->hasDefinition()) + return ToIface; + // Import categories. When the categories themselves are imported, they'll // hook themselves into this interface. for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat; @@ -3279,7 +3289,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ImportDeclContext(D); // If we have an @implementation, import it as well. - if (D->getImplementation()) { + if ( D->getImplementation()) { ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>( Importer.Import(D->getImplementation())); if (!Impl) diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 38efadf3b5..decbd54c6d 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -154,7 +154,11 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( IdentifierInfo *PropertyId) const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); if (ObjCPropertyDecl *PD = @@ -175,11 +179,12 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ObjCProtocolDecl *const* ExtList, unsigned ExtNum, ASTContext &C) { - if (ExternallyCompleted) + if (data().ExternallyCompleted) LoadExternalDefinition(); - if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) { - AllReferencedProtocols.set(ExtList, ExtNum, C); + if (data().AllReferencedProtocols.empty() && + data().ReferencedProtocols.empty()) { + data().AllReferencedProtocols.set(ExtList, ExtNum, C); return; } @@ -214,12 +219,16 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ProtocolRefs.push_back(*p); } - AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C); + data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C); } -void ObjCInterfaceDecl::completedForwardDecl() { - assert(isForwardDecl() && "Only valid to call for forward refs"); - ForwardDecl = false; +void ObjCInterfaceDecl::allocateDefinitionData() { + assert(!hasDefinition() && "ObjC class already has a definition"); + Definition = new (getASTContext()) DefinitionData(); +} + +void ObjCInterfaceDecl::startDefinition() { + allocateDefinitionData(); if (ASTMutationListener *L = getASTContext().getASTMutationListener()) L->CompletedObjCForwardRef(this); } @@ -244,7 +253,11 @@ const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const { ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); ObjCInterfaceDecl* ClassDecl = this; @@ -271,7 +284,11 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, /// the it returns NULL. ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( const IdentifierInfo*ICName) { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); ObjCInterfaceDecl* ClassDecl = this; @@ -287,10 +304,14 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( /// the class, its categories, and its super classes (using a linear search). ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, bool isInstance) const { + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + const ObjCInterfaceDecl* ClassDecl = this; ObjCMethodDecl *MethodDecl = 0; - if (ExternallyCompleted) + if (data().ExternallyCompleted) LoadExternalDefinition(); while (ClassDecl != NULL) { @@ -328,7 +349,11 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( const Selector &Sel, bool Instance) { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); ObjCMethodDecl *Method = 0; @@ -651,16 +676,14 @@ ObjCInterfaceDecl:: ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation CLoc, bool FD, bool isInternal) : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc), - TypeForDecl(0), SuperClass(0), - CategoryList(0), IvarList(0), - InitiallyForwardDecl(FD), ForwardDecl(FD), - ExternallyCompleted(false) { + TypeForDecl(0), Definition(), InitiallyForwardDecl(FD) +{ setImplicit(isInternal); } void ObjCInterfaceDecl::LoadExternalDefinition() const { - assert(ExternallyCompleted && "Class is not externally completed"); - ExternallyCompleted = false; + assert(data().ExternallyCompleted && "Class is not externally completed"); + data().ExternallyCompleted = false; getASTContext().getExternalSource()->CompleteType( const_cast<ObjCInterfaceDecl *>(this)); } @@ -668,13 +691,17 @@ void ObjCInterfaceDecl::LoadExternalDefinition() const { void ObjCInterfaceDecl::setExternallyCompleted() { assert(getASTContext().getExternalSource() && "Class can't be externally completed without an external source"); - assert(!ForwardDecl && + assert(hasDefinition() && "Forward declarations can't be externally completed"); - ExternallyCompleted = true; + data().ExternallyCompleted = true; } ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); return getASTContext().getObjCImplementation( @@ -689,14 +716,18 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { /// its extensions and its implementation. Lazily build the list on first /// access. ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { - if (IvarList) - return IvarList; + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().IvarList) + return data().IvarList; ObjCIvarDecl *curIvar = 0; if (!ivar_empty()) { ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); - IvarList = (*I); ++I; - for (curIvar = IvarList; I != E; curIvar = *I, ++I) + data().IvarList = (*I); ++I; + for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); } @@ -705,9 +736,9 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { if (!CDecl->ivar_empty()) { ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), E = CDecl->ivar_end(); - if (!IvarList) { - IvarList = (*I); ++I; - curIvar = IvarList; + if (!data().IvarList) { + data().IvarList = (*I); ++I; + curIvar = data().IvarList; } for ( ;I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); @@ -718,15 +749,15 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { if (!ImplDecl->ivar_empty()) { ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), E = ImplDecl->ivar_end(); - if (!IvarList) { - IvarList = (*I); ++I; - curIvar = IvarList; + if (!data().IvarList) { + data().IvarList = (*I); ++I; + curIvar = data().IvarList; } for ( ;I != E; curIvar = *I, ++I) curIvar->setNextIvar(*I); } } - return IvarList; + return data().IvarList; } /// FindCategoryDeclaration - Finds category declaration in the list of @@ -735,7 +766,7 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { /// ObjCCategoryDecl * ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { - if (ExternallyCompleted) + if (data().ExternallyCompleted) LoadExternalDefinition(); for (ObjCCategoryDecl *Category = getCategoryList(); @@ -770,6 +801,9 @@ ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const { bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, bool lookupCategory, bool RHSIsQualifiedID) { + if (!hasDefinition()) + return false; + ObjCInterfaceDecl *IDecl = this; // 1st, look up the class. const ObjCList<ObjCProtocolDecl> &Protocols = @@ -997,9 +1031,11 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC, if (IDecl) { // Link this category into its class's category list. CatDecl->NextClassCategory = IDecl->getCategoryList(); - IDecl->setCategoryList(CatDecl); - if (ASTMutationListener *L = C.getASTMutationListener()) - L->AddedObjCCategoryToInterface(CatDecl, IDecl); + if (IDecl->hasDefinition()) { + IDecl->setCategoryList(CatDecl); + if (ASTMutationListener *L = C.getASTMutationListener()) + L->AddedObjCCategoryToInterface(CatDecl, IDecl); + } } return CatDecl; diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 91b011fbda..ec7d6de71a 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -905,6 +905,11 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { else Out << "@interface " << I; + if (OID->isForwardDecl()) { + Out << "@end"; + return; + } + // Protocols? const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); if (!Protocols.empty()) { diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3d2d0930d8..7e7e87a065 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -4558,7 +4558,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, } ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); - if (!IFace) + if (!IFace || !IFace->hasDefinition()) return; // Add methods in protocols. @@ -5783,6 +5783,9 @@ static void FindImplementableMethods(ASTContext &Context, bool InOriginalClass = true) { if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) { // Recurse into protocols. + if (!IFace->hasDefinition()) + return; + const ObjCList<ObjCProtocolDecl> &Protocols = IFace->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index b70c982955..6947d7e211 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -368,10 +368,10 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); if (IDecl) { // Class already seen. Is it a forward declaration? - if (!IDecl->isForwardDecl()) { + if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) { IDecl->setInvalidDecl(); Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName(); - Diag(IDecl->getLocation(), diag::note_previous_definition); + Diag(Def->getLocation(), diag::note_previous_definition); // Create a new one; the other may be in a different DeclContex, (e.g. // this one may be in a LinkageSpecDecl while the other is not) which @@ -392,8 +392,6 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IDecl->setLexicalDeclContext(CurContext); CurContext->addDecl(IDecl); - IDecl->completedForwardDecl(); - if (AttrList) ProcessDeclAttributeList(TUScope, IDecl, AttrList); } @@ -406,6 +404,9 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, PushOnScopeChains(IDecl, TUScope); } + if (!IDecl->hasDefinition()) + IDecl->startDefinition(); + if (SuperName) { // Check if a different kind of symbol declared in this scope. PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, @@ -942,6 +943,7 @@ Decl *Sema::ActOnStartClassImplementation( // copy them over. IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, ClassName, ClassLoc, false, true); + IDecl->startDefinition(); IDecl->setSuperClass(SDecl); IDecl->setLocEnd(ClassLoc); @@ -950,8 +952,8 @@ Decl *Sema::ActOnStartClassImplementation( // Mark the interface as being completed, even if it was just as // @class ....; // declaration; the user cannot reopen it. - if (IDecl->isForwardDecl()) - IDecl->completedForwardDecl(); + if (!IDecl->hasDefinition()) + IDecl->startDefinition(); } ObjCImplementationDecl* IMPDecl = @@ -2540,7 +2542,9 @@ private: void searchFrom(ObjCInterfaceDecl *iface) { // A method in a class declaration overrides declarations from - + if (!iface->hasDefinition()) + return; + // - categories, for (ObjCCategoryDecl *category = iface->getCategoryList(); category; category = category->getNextClassCategory()) diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index fbae96071e..20c3b75431 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -512,6 +512,9 @@ ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel, ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, ObjCInterfaceDecl *ClassDecl) { + if (!ClassDecl->hasDefinition()) + return 0; + ObjCMethodDecl *Method = 0; while (ClassDecl && !Method) { // If we have implementations in scope, check "private" methods. @@ -1339,12 +1342,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, return ExprError(); forwardClass = OCIType->getInterfaceDecl(); + Method = 0; + } else { + Method = ClassDecl->lookupInstanceMethod(Sel); } - - // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be - // faster than the following method (which can do *many* linear searches). - // The idea is to add class info to MethodPool. - Method = ClassDecl->lookupInstanceMethod(Sel); if (!Method) // Search protocol qualifiers. diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index bdedf8ac7e..f7f93af9ce 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -556,43 +556,80 @@ void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { VisitObjCContainerDecl(ID); ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull()); - ID->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx)); - // Read the directly referenced protocols and their SourceLocations. - unsigned NumProtocols = Record[Idx++]; - SmallVector<ObjCProtocolDecl *, 16> Protocols; - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); - ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), - Reader.getContext()); + ObjCInterfaceDecl *Def = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); + if (ID == Def) { + // Read the definition. + ID->allocateDefinitionData(); + + ObjCInterfaceDecl::DefinitionData &Data = ID->data(); + + // Read the superclass. + Data.SuperClass = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx); + Data.SuperClassLoc = ReadSourceLocation(Record, Idx); + + // Read the directly referenced protocols and their SourceLocations. + unsigned NumProtocols = Record[Idx++]; + SmallVector<ObjCProtocolDecl *, 16> Protocols; + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; + ProtoLocs.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); + ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), + Reader.getContext()); - // Read the transitive closure of protocols referenced by this class. - NumProtocols = Record[Idx++]; - Protocols.clear(); - Protocols.reserve(NumProtocols); - for (unsigned I = 0; I != NumProtocols; ++I) - Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols, - Reader.getContext()); + // Read the transitive closure of protocols referenced by this class. + NumProtocols = Record[Idx++]; + Protocols.clear(); + Protocols.reserve(NumProtocols); + for (unsigned I = 0; I != NumProtocols; ++I) + Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols, + Reader.getContext()); - // Read the ivars. - unsigned NumIvars = Record[Idx++]; - SmallVector<ObjCIvarDecl *, 16> IVars; - IVars.reserve(NumIvars); - for (unsigned I = 0; I != NumIvars; ++I) - IVars.push_back(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); - ID->setCategoryList(ReadDeclAs<ObjCCategoryDecl>(Record, Idx)); + // Read the ivars. + unsigned NumIvars = Record[Idx++]; + SmallVector<ObjCIvarDecl *, 16> IVars; + IVars.reserve(NumIvars); + for (unsigned I = 0; I != NumIvars; ++I) + IVars.push_back(ReadDeclAs<ObjCIvarDecl>(Record, Idx)); + + // Read the categories. + ID->setCategoryList(ReadDeclAs<ObjCCategoryDecl>(Record, Idx)); + + // We will rebuild this list lazily. + ID->setIvarList(0); + + // If there are any pending forward references, make their definition data + // pointers point at the newly-allocated data. + ASTReader::PendingForwardRefsMap::iterator + FindI = Reader.PendingForwardRefs.find(ID); + if (FindI != Reader.PendingForwardRefs.end()) { + ASTReader::ForwardRefs &Refs = FindI->second; + for (ASTReader::ForwardRefs::iterator I = Refs.begin(), + E = Refs.end(); + I != E; ++I) + cast<ObjCInterfaceDecl>(*I)->Definition = ID->Definition; +#ifndef NDEBUG + // We later check whether PendingForwardRefs is empty to make sure all + // pending references were linked. + Reader.PendingForwardRefs.erase(ID); +#endif + + } else if (Def) { + if (Def->Definition) { + ID->Definition = Def->Definition; + } else { + // The definition is still initializing. + Reader.PendingForwardRefs[Def].push_back(ID); + } + } + } - // We will rebuild this list lazily. - ID->setIvarList(0); ID->InitiallyForwardDecl = Record[Idx++]; - ID->ForwardDecl = Record[Idx++]; - ID->setSuperClassLoc(ReadSourceLocation(Record, Idx)); ID->setLocEnd(ReadSourceLocation(Record, Idx)); } @@ -972,7 +1009,7 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D, ASTReader::ForwardRefs &Refs = FindI->second; for (ASTReader::ForwardRefs::iterator I = Refs.begin(), E = Refs.end(); I != E; ++I) - (*I)->DefinitionData = D->DefinitionData; + cast<CXXRecordDecl>(*I)->DefinitionData = D->DefinitionData; #ifndef NDEBUG // We later check whether PendingForwardRefs is empty to make sure all // pending references were linked. diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 1448e59fb6..9396958659 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -449,36 +449,46 @@ void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { VisitObjCContainerDecl(D); Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); - Writer.AddDeclRef(D->getSuperClass(), Record); - // Write out the protocols that are directly referenced by the @interface. - Record.push_back(D->ReferencedProtocols.size()); - for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), - PEnd = D->protocol_end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); - for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), + ObjCInterfaceDecl *Def = D->getDefinition(); + Writer.AddDeclRef(Def, Record); + + if (D == Def) { + // Write the DefinitionData + ObjCInterfaceDecl::DefinitionData &Data = D->data(); + + Writer.AddDeclRef(D->getSuperClass(), Record); + Writer.AddSourceLocation(D->getSuperClassLoc(), Record); + + // Write out the protocols that are directly referenced by the @interface. + Record.push_back(Data.ReferencedProtocols.size()); + for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(), + PEnd = D->protocol_end(); + P != PEnd; ++P) + Writer.AddDeclRef(*P, Record); + for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); - - // Write out the protocols that are transitively referenced. - Record.push_back(D->AllReferencedProtocols.size()); - for (ObjCList<ObjCProtocolDecl>::iterator - P = D->AllReferencedProtocols.begin(), - PEnd = D->AllReferencedProtocols.end(); - P != PEnd; ++P) - Writer.AddDeclRef(*P, Record); + PL != PLEnd; ++PL) + Writer.AddSourceLocation(*PL, Record); + + // Write out the protocols that are transitively referenced. + Record.push_back(Data.AllReferencedProtocols.size()); + for (ObjCList<ObjCProtocolDecl>::iterator + P = Data.AllReferencedProtocols.begin(), + PEnd = Data.AllReferencedProtocols.end(); + P != PEnd; ++P) + Writer.AddDeclRef(*P, Record); + + // Write out the ivars. + Record.push_back(D->ivar_size()); + for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), + IEnd = D->ivar_end(); I != IEnd; ++I) + Writer.AddDeclRef(*I, Record); + + Writer.AddDeclRef(D->getCategoryList(), Record); + } - // Write out the ivars. - Record.push_back(D->ivar_size()); - for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(), - IEnd = D->ivar_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - Writer.AddDeclRef(D->getCategoryList(), Record); Record.push_back(D->isInitiallyForwardDecl()); - Record.push_back(D->isForwardDecl()); - Writer.AddSourceLocation(D->getSuperClassLoc(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); Code = serialization::DECL_OBJC_INTERFACE; } |