diff options
-rw-r--r-- | include/clang/AST/DeclObjC.h | 204 | ||||
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 6 | ||||
-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 | ||||
-rw-r--r-- | tools/libclang/IndexingContext.cpp | 5 |
11 files changed, 434 insertions, 233 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 597eb45672..06fa4cb11e 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -545,45 +545,63 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType mutable const Type *TypeForDecl; friend class ASTContext; + + struct DefinitionData { + /// Class's super class. + ObjCInterfaceDecl *SuperClass; - /// Class's super class. - ObjCInterfaceDecl *SuperClass; + /// Protocols referenced in the @interface declaration + ObjCProtocolList ReferencedProtocols; - /// Protocols referenced in the @interface declaration - ObjCProtocolList ReferencedProtocols; + /// Protocols reference in both the @interface and class extensions. + ObjCList<ObjCProtocolDecl> AllReferencedProtocols; - /// Protocols reference in both the @interface and class extensions. - ObjCList<ObjCProtocolDecl> AllReferencedProtocols; + /// \brief List of categories and class extensions defined for this class. + /// + /// Categories are stored as a linked list in the AST, since the categories + /// and class extensions come long after the initial interface declaration, + /// and we avoid dynamically-resized arrays in the AST wherever possible. + ObjCCategoryDecl *CategoryList; - /// \brief List of categories and class extensions defined for this class. - /// - /// Categories are stored as a linked list in the AST, since the categories - /// and class extensions come long after the initial interface declaration, - /// and we avoid dynamically-resized arrays in the AST wherever possible. - ObjCCategoryDecl *CategoryList; + /// IvarList - List of all ivars defined by this class; including class + /// extensions and implementation. This list is built lazily. + ObjCIvarDecl *IvarList; + + /// \brief Indicates that the contents of this Objective-C class will be + /// completed by the external AST source when required. + mutable bool ExternallyCompleted : 1; + + SourceLocation SuperClassLoc; // location of the super class identifier. + }; + + ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, + SourceLocation CLoc, bool FD, bool isInternal); + + void LoadExternalDefinition() const; + + /// \brief Contains a pointer to the data associated with this class, + /// which will be NULL if this class has not yet been defined. + DefinitionData *Definition; - /// IvarList - List of all ivars defined by this class; including class - /// extensions and implementation. This list is built lazily. - ObjCIvarDecl *IvarList; + /// \brief The location of the last location in this declaration, e.g., + /// the '>', '}', or identifier. + /// FIXME: This seems like the wrong location to care about. + SourceLocation EndLoc; /// \brief True if it was initially declared with @class. /// Differs with \see ForwardDecl in that \see ForwardDecl will change to /// false when we see the @interface, but InitiallyForwardDecl will remain /// true. bool InitiallyForwardDecl : 1; - bool ForwardDecl:1; // declared with @class. - - /// \brief Indicates that the contents of this Objective-C class will be - /// completed by the external AST source when required. - mutable bool ExternallyCompleted : 1; - SourceLocation SuperClassLoc; // location of the super class identifier. - SourceLocation EndLoc; // marks the '>', '}', or identifier. - - ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal); + DefinitionData &data() const { + assert(Definition != 0 && "Declaration is not a definition!"); + return *Definition; + } - void LoadExternalDefinition() const; + /// \brief Allocate the definition data for this class. + void allocateDefinitionData(); + public: static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, @@ -604,10 +622,10 @@ public: void setExternallyCompleted(); const ObjCProtocolList &getReferencedProtocols() const { - if (ExternallyCompleted) + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols; + return data().ReferencedProtocols; } ObjCImplementationDecl *getImplementation() const; @@ -626,55 +644,93 @@ public: typedef ObjCProtocolList::iterator protocol_iterator; protocol_iterator protocol_begin() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.begin(); + return data().ReferencedProtocols.begin(); } protocol_iterator protocol_end() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.end(); + return data().ReferencedProtocols.end(); } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; protocol_loc_iterator protocol_loc_begin() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_loc_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.loc_begin(); + return data().ReferencedProtocols.loc_begin(); } protocol_loc_iterator protocol_loc_end() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return protocol_loc_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return ReferencedProtocols.loc_end(); + return data().ReferencedProtocols.loc_end(); } typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator; all_protocol_iterator all_referenced_protocol_begin() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return all_protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return AllReferencedProtocols.empty() ? protocol_begin() - : AllReferencedProtocols.begin(); + return data().AllReferencedProtocols.empty() + ? protocol_begin() + : data().AllReferencedProtocols.begin(); } all_protocol_iterator all_referenced_protocol_end() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return all_protocol_iterator(); + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return AllReferencedProtocols.empty() ? protocol_end() - : AllReferencedProtocols.end(); + return data().AllReferencedProtocols.empty() + ? protocol_end() + : data().AllReferencedProtocols.end(); } typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } - ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } + ivar_iterator ivar_begin() const { + if (const ObjCInterfaceDecl *Def = getDefinition()) + return ivar_iterator(Def->decls_begin()); + + // FIXME: Should make sure no callers ever do this. + return ivar_iterator(); + } + ivar_iterator ivar_end() const { + if (const ObjCInterfaceDecl *Def = getDefinition()) + return ivar_iterator(Def->decls_end()); + + // FIXME: Should make sure no callers ever do this. + return ivar_iterator(); + } unsigned ivar_size() const { return std::distance(ivar_begin(), ivar_end()); @@ -688,13 +744,13 @@ public: // the ivar chain is essentially a cached property of ObjCInterfaceDecl. return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin(); } - void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; } + void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; } /// setProtocolList - Set the list of protocols that this interface /// implements. void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, const SourceLocation *Locs, ASTContext &C) { - ReferencedProtocols.set(List, Num, Locs, C); + data().ReferencedProtocols.set(List, Num, Locs, C); } /// mergeClassExtensionProtocolList - Merge class extension's protocol list @@ -706,30 +762,63 @@ public: /// \brief True if it was initially declared with @class. /// Differs with \see isForwardDecl in that \see isForwardDecl will change to /// false when we see the @interface, but this will remain true. - bool isInitiallyForwardDecl() const { return InitiallyForwardDecl; } + bool isInitiallyForwardDecl() const { + return InitiallyForwardDecl; + } - bool isForwardDecl() const { return ForwardDecl; } + /// \brief Determine whether this declaration is a forward declaration of + /// the class. + bool isForwardDecl() const { return Definition == 0; } - void completedForwardDecl(); + /// \brief Determine whether this class has been defined. + bool hasDefinition() const { return Definition != 0; } + + /// \brief Retrieve the definition of this class, or NULL if this class + /// has been forward-declared (with @class) but not yet defined (with + /// @interface). + ObjCInterfaceDecl *getDefinition() { + return hasDefinition()? this : 0; + } + + /// \brief Retrieve the definition of this class, or NULL if this class + /// has been forward-declared (with @class) but not yet defined (with + /// @interface). + const ObjCInterfaceDecl *getDefinition() const { + return hasDefinition()? this : 0; + } + /// \brief Starts the definition of this Objective-C class, taking it from + /// a forward declaration (@class) to a definition (@interface). + void startDefinition(); + ObjCInterfaceDecl *getSuperClass() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return SuperClass; + return data().SuperClass; } - void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } + void setSuperClass(ObjCInterfaceDecl * superCls) { + data().SuperClass = superCls; + } ObjCCategoryDecl* getCategoryList() const { - if (ExternallyCompleted) + // FIXME: Should make sure no callers ever do this. + if (!hasDefinition()) + return 0; + + if (data().ExternallyCompleted) LoadExternalDefinition(); - return CategoryList; + return data().CategoryList; } void setCategoryList(ObjCCategoryDecl *category) { - CategoryList = category; + data().CategoryList = category; } ObjCCategoryDecl* getFirstClassExtension() const; @@ -744,6 +833,7 @@ public: while (I != NULL) { if (declaresSameEntity(this, I)) return true; + I = I->getSuperClass(); } return false; @@ -787,8 +877,8 @@ public: SourceLocation getLocEnd() const { return EndLoc; } void setLocEnd(SourceLocation LE) { EndLoc = LE; } - void setSuperClassLoc(SourceLocation Loc) { SuperClassLoc = Loc; } - SourceLocation getSuperClassLoc() const { return SuperClassLoc; } + void setSuperClassLoc(SourceLocation Loc) { data().SuperClassLoc = Loc; } + SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; } /// isImplicitInterfaceDecl - check that this is an implicitly declared /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 5e9da51b97..e145cb74b2 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -329,14 +329,16 @@ private: /// haven't been loaded yet. DeclContextVisibleUpdatesPending PendingVisibleUpdates; - typedef SmallVector<CXXRecordDecl *, 4> ForwardRefs; - typedef llvm::DenseMap<const CXXRecordDecl *, ForwardRefs> + typedef SmallVector<Decl *, 4> ForwardRefs; + typedef llvm::DenseMap<const Decl *, ForwardRefs> PendingForwardRefsMap; + /// \brief Forward references that have a definition but the definition decl /// is still initializing. When the definition gets read it will update /// the DefinitionData pointer of all pending references. PendingForwardRefsMap PendingForwardRefs; + typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID> FirstLatestDeclIDMap; /// \brief Map of first declarations from a chained PCH that point to the 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, |