diff options
-rw-r--r-- | include/clang/AST/DeclObjC.h | 78 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 7 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 12 | ||||
-rw-r--r-- | lib/AST/DumpXML.cpp | 1 | ||||
-rw-r--r-- | lib/Rewrite/RewriteObjC.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 39 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 25 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 34 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 25 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 4 | ||||
-rw-r--r-- | tools/libclang/IndexDecl.cpp | 2 | ||||
-rw-r--r-- | tools/libclang/IndexingContext.cpp | 11 |
12 files changed, 173 insertions, 67 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index f475350e8f..9a594a68db 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1066,22 +1066,34 @@ public: class ObjCProtocolDecl : public ObjCContainerDecl { virtual void anchor(); - /// Referenced protocols - ObjCProtocolList ReferencedProtocols; + struct DefinitionData { + /// Referenced protocols + ObjCProtocolList ReferencedProtocols; + }; + + DefinitionData *Data; bool InitiallyForwardDecl : 1; bool isForwardProtoDecl : 1; // declared with @protocol. SourceLocation EndLoc; // marks the '>' or identifier. + DefinitionData &data() const { + assert(Data && "Objective-C protocol has no definition!"); + return *Data; + } + ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id, SourceLocation nameLoc, SourceLocation atStartLoc, bool isForwardDecl) : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), + Data(0), InitiallyForwardDecl(isForwardDecl), isForwardProtoDecl(isForwardDecl) { } + void allocateDefinitionData(); + public: static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, @@ -1090,25 +1102,48 @@ public: bool isForwardDecl); const ObjCProtocolList &getReferencedProtocols() const { - return ReferencedProtocols; + assert(hasDefinition() && "No definition available!"); + return data().ReferencedProtocols; } typedef ObjCProtocolList::iterator protocol_iterator; - protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} - protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } + protocol_iterator protocol_begin() const { + if (!hasDefinition()) + return protocol_iterator(); + + return data().ReferencedProtocols.begin(); + } + protocol_iterator protocol_end() const { + if (!hasDefinition()) + return protocol_iterator(); + + return data().ReferencedProtocols.end(); + } typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; protocol_loc_iterator protocol_loc_begin() const { - return ReferencedProtocols.loc_begin(); + if (!hasDefinition()) + return protocol_loc_iterator(); + + return data().ReferencedProtocols.loc_begin(); } protocol_loc_iterator protocol_loc_end() const { - return ReferencedProtocols.loc_end(); + if (!hasDefinition()) + return protocol_loc_iterator(); + + return data().ReferencedProtocols.loc_end(); + } + unsigned protocol_size() const { + if (!hasDefinition()) + return 0; + + return data().ReferencedProtocols.size(); } - unsigned protocol_size() const { return ReferencedProtocols.size(); } /// 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); + assert(Data && "Protocol is not defined"); + data().ReferencedProtocols.set(List, Num, Locs, C); } ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName); @@ -1123,13 +1158,33 @@ public: return lookupMethod(Sel, false/*isInstance*/); } + /// \brief Determine whether this protocol has a definition. + bool hasDefinition() const { return Data != 0; } + + /// \brief Retrieve the definition of this protocol, if any. + ObjCProtocolDecl *getDefinition() { + return hasDefinition()? this : 0; + } + + /// \brief Retrieve the definition of this protocol, if any. + const ObjCProtocolDecl *getDefinition() const { + return hasDefinition()? this : 0; + } + + /// \brief Determine whether this particular declaration is also the + /// definition. + bool isThisDeclarationADefinition() const { + return getDefinition() == this; + } + + /// \brief Starts the definition of this Objective-C protocol. + void startDefinition(); + /// \brief True if it was initially a forward reference. /// Differs with \see isForwardDecl in that \see isForwardDecl will change to /// false when we see the definition, but this will remain true. bool isInitiallyForwardDecl() const { return InitiallyForwardDecl; } - bool isForwardDecl() const { return isForwardProtoDecl; } - void completedForwardDecl(); // Location information, modeled after the Stmt API. @@ -1149,6 +1204,7 @@ public: static bool classof(const ObjCProtocolDecl *D) { return true; } static bool classofKind(Kind K) { return K == ObjCProtocol; } + friend class ASTReader; friend class ASTDeclReader; friend class ASTDeclWriter; }; diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 67045059cf..fe7049492f 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3119,7 +3119,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { } ObjCProtocolDecl *ToProto = MergeWithProtocol; - if (!ToProto || ToProto->isForwardDecl()) { + if (!ToProto || !ToProto->hasDefinition()) { if (!ToProto) { ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, Name.getAsIdentifierInfo(), Loc, @@ -3127,9 +3127,12 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { D->isInitiallyForwardDecl()); ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProto); - if (D->isInitiallyForwardDecl() && !D->isForwardDecl()) + if (D->isInitiallyForwardDecl() && D->hasDefinition()) ToProto->completedForwardDecl(); } + if (!ToProto->hasDefinition()) + ToProto->startDefinition(); + Importer.Imported(D, ToProto); // Import protocols diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 75100ecb3c..f5828fcb4c 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -1003,9 +1003,19 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, return NULL; } +void ObjCProtocolDecl::allocateDefinitionData() { + assert(!Data && "Protocol already has a definition!"); + Data = new (getASTContext()) DefinitionData; +} + +void ObjCProtocolDecl::startDefinition() { + allocateDefinitionData(); +} + void ObjCProtocolDecl::completedForwardDecl() { - assert(isForwardDecl() && "Only valid to call for forward refs"); + assert(!hasDefinition() && "Only valid to call for forward refs"); isForwardProtoDecl = false; + startDefinition(); if (ASTMutationListener *L = getASTContext().getASTMutationListener()) L->CompletedObjCForwardRef(this); } diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index 959bbcbb17..561fb8f372 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -819,7 +819,6 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, // ObjCProtocolDecl void visitObjCProtocolDeclAttrs(ObjCProtocolDecl *D) { - setFlag("forward_decl", D->isForwardDecl()); } void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) { if (D->protocol_begin() != D->protocol_end()) { diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index 1b39061d50..a126e8524e 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -5171,7 +5171,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData( static bool objc_protocol_methods = false; // Output struct protocol_methods holder of method selector and type. - if (!objc_protocol_methods && !PDecl->isForwardDecl()) { + if (!objc_protocol_methods && PDecl->hasDefinition()) { /* struct protocol_methods { SEL _cmd; char *method_types; diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 72cc37ccdd..6843ca7e6c 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -4554,13 +4554,16 @@ static void AddObjCMethods(ObjCContainerDecl *Container, // Visit the protocols of protocols. if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); - I != E; ++I) - AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, - CurContext, Selectors, AllowSameLength, Results, false); + if (Protocol->hasDefinition()) { + const ObjCList<ObjCProtocolDecl> &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, false); + } } ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); @@ -5417,7 +5420,7 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, D != DEnd; ++D) { // Record any protocols we find. if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D)) - if (!OnlyForwardDeclarations || Proto->isForwardDecl()) + if (!OnlyForwardDeclarations || !Proto->hasDefinition()) Results.AddResult(Result(Proto, 0), CurContext, 0, false); // Record any forward-declared protocols we find. @@ -5427,7 +5430,7 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, P = Forward->protocol_begin(), PEnd = Forward->protocol_end(); P != PEnd; ++P) - if (!OnlyForwardDeclarations || (*P)->isForwardDecl()) + if (!OnlyForwardDeclarations || !(*P)->hasDefinition()) Results.AddResult(Result(*P, 0), CurContext, 0, false); } } @@ -5823,14 +5826,16 @@ static void FindImplementableMethods(ASTContext &Context, } if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { - // Recurse into protocols. - const ObjCList<ObjCProtocolDecl> &Protocols - = Protocol->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); - I != E; ++I) - FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - KnownMethods, false); + if (Protocol->hasDefinition()) { + // Recurse into protocols. + const ObjCList<ObjCProtocolDecl> &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, false); + } } // Add methods in this container. This operation occurs last because diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 168ccfc3f5..eb178612c8 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -545,6 +545,10 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency( Diag(PrevLoc, diag::note_previous_definition); res = true; } + + if (!PDecl->hasDefinition()) + continue; + if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, PDecl->getLocation(), PDecl->getReferencedProtocols())) res = true; @@ -568,18 +572,18 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc); if (PDecl) { // Protocol already seen. Better be a forward protocol declaration - if (!PDecl->isForwardDecl()) { + if (ObjCProtocolDecl *Def = PDecl->getDefinition()) { Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; - Diag(PDecl->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 - // will break invariants. - // We will not add it to scope chains to ignore it as the warning says. + // Create a new protocol that is completely distinct from previous + // declarations, and do not make this protocol available for name lookup. + // That way, we'll end up completely ignoring the duplicate. + // FIXME: Can we turn this into an error? PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, ProtocolLoc, AtProtoInterfaceLoc, /*isForwardDecl=*/false); - + PDecl->startDefinition(); } else { ObjCList<ObjCProtocolDecl> PList; PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); @@ -600,7 +604,9 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, ProtocolLoc, AtProtoInterfaceLoc, /*isForwardDecl=*/false); PushOnScopeChains(PDecl, TUScope); + PDecl->startDefinition(); } + if (AttrList) ProcessDeclAttributeList(TUScope, PDecl, AttrList); if (!err && NumProtoRefs ) { @@ -647,7 +653,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, // If this is a forward declaration and we are supposed to warn in this // case, do it. - if (WarnOnDeclarations && PDecl->isForwardDecl()) + if (WarnOnDeclarations && !PDecl->hasDefinition()) Diag(ProtocolId[i].second, diag::warn_undef_protocolref) << ProtocolId[i].first; Protocols.push_back(PDecl); @@ -2497,6 +2503,9 @@ private: } void searchFrom(ObjCProtocolDecl *protocol) { + if (!protocol->hasDefinition()) + return; + // A method in a protocol declaration overrides declarations from // referenced ("parent") protocols. search(protocol->getReferencedProtocols()); diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 476f8b5c02..f88a394e90 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -764,17 +764,29 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { PD->InitiallyForwardDecl = Record[Idx++]; PD->isForwardProtoDecl = Record[Idx++]; PD->setLocEnd(ReadSourceLocation(Record, Idx)); - unsigned NumProtoRefs = Record[Idx++]; - SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; - ProtoRefs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); - SmallVector<SourceLocation, 16> ProtoLocs; - ProtoLocs.reserve(NumProtoRefs); - for (unsigned I = 0; I != NumProtoRefs; ++I) - ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); - PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - Reader.getContext()); + + ObjCProtocolDecl *Def = ReadDeclAs<ObjCProtocolDecl>(Record, Idx); + if (PD == Def) { + // Read the definition. + PD->allocateDefinitionData(); + + unsigned NumProtoRefs = Record[Idx++]; + SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; + ProtoRefs.reserve(NumProtoRefs); + for (unsigned I = 0; I != NumProtoRefs; ++I) + ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx)); + SmallVector<SourceLocation, 16> ProtoLocs; + ProtoLocs.reserve(NumProtoRefs); + for (unsigned I = 0; I != NumProtoRefs; ++I) + ProtoLocs.push_back(ReadSourceLocation(Record, Idx)); + PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), + Reader.getContext()); + + // FIXME: Note that we have deserialized a definition. + // Reader.PendingDefinitions.insert(PD); + } else if (Def && Def->Data) { + PD->Data = Def->Data; + } } void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 0692c023e4..f1394850ed 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -519,16 +519,23 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { VisitObjCContainerDecl(D); Record.push_back(D->isInitiallyForwardDecl()); - Record.push_back(D->isForwardDecl()); + Record.push_back(D->isForwardProtoDecl); Writer.AddSourceLocation(D->getLocEnd(), Record); - Record.push_back(D->protocol_size()); - for (ObjCProtocolDecl::protocol_iterator - I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); - for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), - PLEnd = D->protocol_loc_end(); - PL != PLEnd; ++PL) - Writer.AddSourceLocation(*PL, Record); + + ObjCProtocolDecl *Def = D->getDefinition(); + Writer.AddDeclRef(Def, Record); + + if (D == Def) { + Record.push_back(D->protocol_size()); + for (ObjCProtocolDecl::protocol_iterator + I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I) + Writer.AddDeclRef(*I, Record); + for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(), + PLEnd = D->protocol_loc_end(); + PL != PLEnd; ++PL) + Writer.AddSourceLocation(*PL, Record); + } + Code = serialization::DECL_OBJC_PROTOCOL; } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 33feadfdf1..f2e6b01329 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -4126,8 +4126,8 @@ CXCursor clang_getCursorDefinition(CXCursor C) { return clang_getNullCursor(); case Decl::ObjCProtocol: - if (!cast<ObjCProtocolDecl>(D)->isForwardDecl()) - return C; + if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(D)->getDefinition()) + return MakeCXCursor(Def, TU); return clang_getNullCursor(); case Decl::ObjCInterface: { diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp index 38868138cf..ee37bba942 100644 --- a/tools/libclang/IndexDecl.cpp +++ b/tools/libclang/IndexDecl.cpp @@ -102,7 +102,7 @@ public: bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { // Forward decls are handled at VisitObjCForwardProtocolDecl. - if (D->isForwardDecl()) + if (!D->isThisDeclarationADefinition()) return true; IndexCtx.handleObjCProtocol(D); diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp index 49dfa05cf1..28efe3fd56 100644 --- a/tools/libclang/IndexingContext.cpp +++ b/tools/libclang/IndexingContext.cpp @@ -368,8 +368,9 @@ bool IndexingContext::handleObjCInterface(const ObjCInterfaceDecl *D) { } ObjCProtocolList EmptyProtoList; - ObjCProtocolListInfo ProtInfo(D->hasDefinition() ? D->getReferencedProtocols() - : EmptyProtoList, + ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition() + ? D->getReferencedProtocols() + : EmptyProtoList, *this, SA); ObjCInterfaceDeclInfo InterInfo(D); @@ -401,7 +402,11 @@ bool IndexingContext::handleObjCForwardProtocol(const ObjCProtocolDecl *D, bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) { ScratchAlloc SA(*this); - ObjCProtocolListInfo ProtListInfo(D->getReferencedProtocols(), *this, SA); + ObjCProtocolList EmptyProtoList; + ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition() + ? D->getReferencedProtocols() + : EmptyProtoList, + *this, SA); ObjCProtocolDeclInfo ProtInfo(D); ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo(); |