diff options
-rw-r--r-- | include/clang/AST/ASTConsumer.h | 5 | ||||
-rw-r--r-- | include/clang/AST/ASTContext.h | 5 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 47 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 2 | ||||
-rw-r--r-- | lib/AST/ASTConsumer.cpp | 3 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 30 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 14 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 26 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 13 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 11 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHReaderDecl.cpp | 22 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 26 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 39 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 159 | ||||
-rw-r--r-- | test/Index/TestClassDecl.m | 2 |
20 files changed, 274 insertions, 148 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index b01f6c6001..3f964ad0e9 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -49,6 +49,11 @@ public: /// elements). Use Decl::getNextDeclarator() to walk the chain. virtual void HandleTopLevelDecl(DeclGroupRef D); + /// HandleInterestingDecl - Handle the specified interesting declaration. This + /// is called by the PCH reader when deserializing things that might interest + /// the consumer. The default implementation forwards to HandleTopLevelDecl. + virtual void HandleInterestingDecl(DeclGroupRef D); + /// HandleTranslationUnit - This method is called when the ASTs for entire /// translation unit have been parsed. virtual void HandleTranslationUnit(ASTContext &Ctx) {} diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index aa1985a888..31686d89c2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -668,7 +668,10 @@ public: unsigned NumArgs, const TemplateArgument *Args); - QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); + /// getObjCInterfaceType - Return the unique reference to the type for the + /// specified ObjC interface decl. + QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, + const ObjCInterfaceDecl *PrevDecl = 0); QualType getObjCObjectType(QualType Base, ObjCProtocolDecl * const *Protocols, diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 8484216521..1fe1cf7cb4 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -450,7 +450,10 @@ public: /// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes /// typically inherit from NSObject (an exception is NSProxy). /// -class ObjCInterfaceDecl : public ObjCContainerDecl { +class ObjCInterfaceDecl : public ObjCContainerDecl, + public Redeclarable<ObjCInterfaceDecl> { + typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base; + /// TypeForDecl - This indicates the Type object that represents this /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType mutable Type *TypeForDecl; @@ -474,15 +477,52 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { SourceLocation EndLoc; // marks the '>', '}', or identifier. ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal); + SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, + bool FD, bool isInternal); + +protected: + virtual ObjCInterfaceDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } public: + typedef redeclarable_base::redecl_iterator redecl_iterator; + redecl_iterator redecls_begin() const { + return redeclarable_base::redecls_begin(); + } + redecl_iterator redecls_end() const { + return redeclarable_base::redecls_end(); + } + static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation ClassLoc = SourceLocation(), + SourceLocation ClassLoc, + ObjCInterfaceDecl *PrevDecl, bool ForwardDecl = false, bool isInternal = false); + + static ObjCInterfaceDecl *Create(ASTContext &C, EmptyShell Empty); + + void setPreviousDeclaration(ObjCInterfaceDecl *Prev) { + // Adopt a type pointer if it exists. + TypeForDecl = Prev->TypeForDecl; + redeclarable_base::setPreviousDeclaration(Prev); + } + + virtual ObjCInterfaceDecl *getCanonicalDecl() { + return getFirstDeclaration(); + } + const ObjCInterfaceDecl *getCanonicalDecl() const { + return const_cast<ObjCInterfaceDecl*>(this)->getCanonicalDecl(); + } + + /// Get the interface declaration that is a definition, if there is one. + ObjCInterfaceDecl *getDefinition(); + const ObjCInterfaceDecl *getDefinition() const { + return const_cast<ObjCInterfaceDecl*>(this)->getDefinition(); + } + const ObjCProtocolList &getReferencedProtocols() const { return ReferencedProtocols; } @@ -535,6 +575,7 @@ public: ASTContext &C); bool isForwardDecl() const { return ForwardDecl; } + bool isDefinition() const { return !ForwardDecl; } void setForwardDecl(bool val) { ForwardDecl = val; } ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 7a522f42fa..6c4ad893b4 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -3038,7 +3038,7 @@ class ObjCInterfaceType : public ObjCObjectType { friend class ASTContext; // ASTContext creates these. public: /// getDecl - Get the declaration of this interface. - ObjCInterfaceDecl *getDecl() const { return Decl; } + ObjCInterfaceDecl *getDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp index f37cbdea54..04a084a06a 100644 --- a/lib/AST/ASTConsumer.cpp +++ b/lib/AST/ASTConsumer.cpp @@ -17,3 +17,6 @@ using namespace clang; void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {} +void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) { + HandleTopLevelDecl(D); +} diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7d159269c1..83cee5cc78 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -872,7 +872,7 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, /// CollectNonClassIvars - /// This routine collects all other ivars which are not declared in the class. /// This includes synthesized ivars (via @synthesize) and those in -// class's @implementation. +/// class's @implementation. /// void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { @@ -2212,18 +2212,24 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) { return QualType(QType, 0); } -/// getObjCInterfaceType - Return the unique reference to the type for the -/// specified ObjC interface decl. The list of protocols is optional. -QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) { - if (Decl->TypeForDecl) - return QualType(Decl->TypeForDecl, 0); +QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, + const ObjCInterfaceDecl *PrevDecl) { + assert(Decl && "Passed null for Decl param"); - // FIXME: redeclarations? - void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment); - ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl); - Decl->TypeForDecl = T; - Types.push_back(T); - return QualType(T, 0); + if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); + + if (PrevDecl) { + assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl"); + Decl->TypeForDecl = PrevDecl->TypeForDecl; + return QualType(PrevDecl->TypeForDecl, 0); + } + + assert(!Decl->getPreviousDeclaration() && + "interface has previous declaration"); + + Decl->TypeForDecl = new (*this, TypeAlignment) ObjCInterfaceType(Decl); + Types.push_back(Decl->TypeForDecl); + return QualType(Decl->TypeForDecl, 0); } /// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 5e8586f2a0..6242d40041 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -2467,6 +2467,18 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { } Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + // If this interface has a definition in the translation unit we're coming + // from, but this particular declaration is not that definition, import the + // definition and map to that. + ObjCInterfaceDecl *Definition = D->getDefinition(); + if (Definition && Definition != D) { + Decl *ImportedDef = Importer.Import(Definition); + if (!ImportedDef) + return 0; + + return Importer.Imported(D, ImportedDef); + } + // Import the major distinguishing characteristics of an @interface. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2491,7 +2503,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), - Importer.Import(D->getClassLoc()), + Importer.Import(D->getClassLoc()), 0, D->isForwardDecl(), D->isImplicitInterfaceDecl()); ToIface->setForwardDecl(D->isForwardDecl()); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 32f9433d9a..0720b203d6 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -45,6 +45,14 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, // ObjCInterfaceDecl //===----------------------------------------------------------------------===// +ObjCInterfaceDecl *ObjCInterfaceDecl::getDefinition() { + for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + if (I->isDefinition()) + return *I; + } + return 0; +} + /// getIvarDecl - This method looks up an ivar in this ContextDecl. /// ObjCIvarDecl * @@ -432,18 +440,30 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C, SourceLocation atLoc, IdentifierInfo *Id, SourceLocation ClassLoc, + ObjCInterfaceDecl *PrevDecl, bool ForwardDecl, bool isInternal){ - return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl, - isInternal); + ObjCInterfaceDecl *D = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, + PrevDecl, ForwardDecl, + isInternal); + C.getObjCInterfaceType(D, PrevDecl); + return D; +} + +ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C, EmptyShell) { + return new (C) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(), + 0, false, false); } ObjCInterfaceDecl:: ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal) + SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, + bool FD, bool isInternal) : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id), TypeForDecl(0), SuperClass(0), CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal), ClassLoc(CLoc) { + if (PrevDecl) + setPreviousDeclaration(PrevDecl); } ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index fae1e724a1..d3ebc8f508 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -727,12 +727,19 @@ void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) { void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { std::string I = OID->getNameAsString(); + + if (OID->isForwardDecl()) { + // These shouldn't be directly visited, but in case they are, write them + // as an @class declaration. + Out << "@class " << I; + return; + } + ObjCInterfaceDecl *SID = OID->getSuperClass(); + Out << "@interface " << I; if (SID) - Out << "@interface " << I << " : " << SID; - else - Out << "@interface " << I; + Out << " : " << SID; // Protocols? const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 31af6fb661..4f884989ae 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -360,6 +360,17 @@ const ObjCObjectPointerType *Type::getAsObjCInterfacePointerType() const { return 0; } +ObjCInterfaceDecl *ObjCInterfaceType::getDecl() const { + for (ObjCInterfaceDecl::redecl_iterator I = Decl->redecls_begin(), + E = Decl->redecls_end(); + I != E; ++I) { + if (I->isDefinition()) + return *I; + } + // If we can't find a definition, return whatever we have. + return Decl; +} + const CXXRecordDecl *Type::getCXXRecordDeclForPointerType() const { if (const PointerType *PT = getAs<PointerType>()) if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index b287522806..cd78abdaeb 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -320,6 +320,9 @@ public: Unit.addTopLevelDecl(D); } } + + // We're not interested in "interesting" decls. + void HandleInterestingDecl(DeclGroupRef) {} }; class TopLevelDeclTrackerAction : public ASTFrontendAction { diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 1bfc138d4f..68acbb2faf 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2262,7 +2262,7 @@ QualType PCHReader::ReadTypeRecord(unsigned Index) { SavedStreamPosition SavedPosition(DeclsCursor); ReadingKindTracker ReadingKind(Read_Type, *this); - + // Note that we are loading a type record. Deserializing AType(this); @@ -3027,7 +3027,7 @@ void PCHReader::PassInterestingDeclsToConsumer() { while (!InterestingDecls.empty()) { DeclGroupRef DG(InterestingDecls.front()); InterestingDecls.pop_front(); - Consumer->HandleTopLevelDecl(DG); + Consumer->HandleInterestingDecl(DG); } } diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 7aab7b7557..2930ca73b9 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -34,7 +34,7 @@ namespace clang { const pch::DeclID ThisDeclID; const PCHReader::RecordData &Record; unsigned &Idx; - pch::TypeID TypeIDForTypeDecl; + pch::TypeID TypeIDForDecl; uint64_t GetCurrentCursorOffset(); @@ -43,7 +43,7 @@ namespace clang { pch::DeclID thisDeclID, const PCHReader::RecordData &Record, unsigned &Idx) : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record), - Idx(Idx), TypeIDForTypeDecl(0) { } + Idx(Idx), TypeIDForDecl(0) { } void Visit(Decl *D); @@ -132,9 +132,11 @@ uint64_t PCHDeclReader::GetCurrentCursorOffset() { void PCHDeclReader::Visit(Decl *D) { DeclVisitor<PCHDeclReader, void>::Visit(D); + // if we have a fully initialized Decl, we can safely read its type now. if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { - // if we have a fully initialized TypeDecl, we can safely read its type now. - TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr()); + TD->setTypeForDecl(Reader.GetType(TypeIDForDecl).getTypePtr()); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + ID->setTypeForDecl(Reader.GetType(TypeIDForDecl).getTypePtr()); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // FunctionDecl's body was written last after all other Stmts/Exprs. if (Record[Idx++]) @@ -170,7 +172,7 @@ void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) { void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); // Delay type reading until after we have fully initialized the decl. - TypeIDForTypeDecl = Record[Idx++]; + TypeIDForDecl = Record[Idx++]; } void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) { @@ -367,7 +369,11 @@ void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { VisitObjCContainerDecl(ID); - ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr()); + ID->setForwardDecl(Record[Idx++]); + ID->setImplicitInterfaceDecl(Record[Idx++]); + VisitRedeclarable(ID); + // Must delay type reading until the redecl chain is complete. + TypeIDForDecl = Record[Idx++]; ID->setSuperClass(cast_or_null<ObjCInterfaceDecl> (Reader.GetDecl(Record[Idx++]))); unsigned NumProtocols = Record[Idx++]; @@ -388,8 +394,6 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); ID->setCategoryList( cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); - ID->setForwardDecl(Record[Idx++]); - ID->setImplicitInterfaceDecl(Record[Idx++]); ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); @@ -1459,7 +1463,7 @@ Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) { Selector(), QualType(), 0, 0); break; case pch::DECL_OBJC_INTERFACE: - D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); + D = ObjCInterfaceDecl::Create(*Context, Decl::EmptyShell()); break; case pch::DECL_OBJC_IVAR: D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 0eed4ccd71..990641294a 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -305,7 +305,9 @@ void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) { } void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { - Writer.AddDeclRef(T->getDecl(), Record); + // The stored declaration must be the first, but getDecl() returns the + // definition. + Writer.AddDeclRef(T->getDecl()->getFirstDeclaration(), Record); Code = pch::TYPE_OBJC_INTERFACE; } diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index a509ed1dce..9917ad6419 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -340,6 +340,9 @@ void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { VisitObjCContainerDecl(D); + Record.push_back(D->isForwardDecl()); + Record.push_back(D->isImplicitInterfaceDecl()); + VisitRedeclarable(D); Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record); Writer.AddDeclRef(D->getSuperClass(), Record); Record.push_back(D->protocol_size()); @@ -356,8 +359,6 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { IEnd = D->ivar_end(); I != IEnd; ++I) Writer.AddDeclRef(*I, Record); Writer.AddDeclRef(D->getCategoryList(), Record); - Record.push_back(D->isForwardDecl()); - Record.push_back(D->isImplicitInterfaceDecl()); Writer.AddSourceLocation(D->getClassLoc(), Record); Writer.AddSourceLocation(D->getSuperClassLoc(), Record); Writer.AddSourceLocation(D->getLocEnd(), Record); diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index aeb4db987d..11d7a9191f 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -89,7 +89,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { ObjCInterfaceDecl *ProtocolDecl = ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("Protocol"), - SourceLocation(), true); + SourceLocation(), 0, true); Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); PushOnScopeChains(ProtocolDecl, TUScope, false); } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 52ac8dd649..f12e1839e5 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3748,20 +3748,28 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, for (DeclContext::decl_iterator D = Ctx->decls_begin(), DEnd = Ctx->decls_end(); D != DEnd; ++D) { - // Record any interfaces we find. - if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) - if ((!OnlyForwardDeclarations || Class->isForwardDecl()) && - (!OnlyUnimplemented || !Class->getImplementation())) - Results.AddResult(Result(Class, 0), CurContext, 0, false); + // Record any interfaces we find. Forward declarations are never registered + // in the lexical contest, so if we're only looking for those, don't bother. + if (!OnlyForwardDeclarations) + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) + if (!OnlyUnimplemented || !Class->getImplementation()) + Results.AddResult(Result(Class, 0), CurContext, 0, false); // Record any forward-declared interfaces we find. if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) { for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end(); - C != CEnd; ++C) - if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) && - (!OnlyUnimplemented || !C->getInterface()->getImplementation())) - Results.AddResult(Result(C->getInterface(), 0), CurContext, + C != CEnd; ++C) { + ObjCInterfaceDecl *IDecl = C->getInterface(); + ObjCInterfaceDecl *IDef = IDecl->getDefinition(); + // If there's a definition, and we're looking for everything, then we + // already added the decl in question above. + if (!OnlyForwardDeclarations && !OnlyUnimplemented && IDef) + continue; + if ((!OnlyForwardDeclarations || !IDef) && + (!OnlyUnimplemented || !IDef || !IDef->getImplementation())) + Results.AddResult(Result(IDecl, 0), CurContext, 0, false); + } } } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 200b8fd681..e6c5170357 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -606,45 +606,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } -/// \brief Look for an Objective-C class in the translation unit. -/// -/// \param Id The name of the Objective-C class we're looking for. If -/// typo-correction fixes this name, the Id will be updated -/// to the fixed name. -/// -/// \param IdLoc The location of the name in the translation unit. -/// -/// \param TypoCorrection If true, this routine will attempt typo correction -/// if there is no class with the given name. -/// -/// \returns The declaration of the named Objective-C class, or NULL if the -/// class could not be found. -ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, - SourceLocation IdLoc, - bool TypoCorrection) { - // The third "scope" argument is 0 since we aren't enabling lazy built-in - // creation from this context. - NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); - - if (!IDecl && TypoCorrection) { - // Perform typo correction at the given location, but only if we - // find an Objective-C class name. - LookupResult R(*this, Id, IdLoc, LookupOrdinaryName); - if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && - (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { - Diag(IdLoc, diag::err_undef_interface_suggest) - << Id << IDecl->getDeclName() - << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); - Diag(IDecl->getLocation(), diag::note_previous_decl) - << IDecl->getDeclName(); - - Id = IDecl->getIdentifier(); - } - } - - return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); -} - /// getNonFieldDeclScope - Retrieves the innermost scope, starting /// from S, where a non-field would be declared. This routine copes /// with the difference between C and C++ scoping rules in structs and diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 9e0d250536..283376bfde 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -20,6 +20,50 @@ #include "clang/Parse/DeclSpec.h" using namespace clang; +/// \brief Look for an Objective-C class in the translation unit. +/// +/// \param Id The name of the Objective-C class we're looking for. If +/// typo-correction fixes this name, the Id will be updated +/// to the fixed name. +/// +/// \param IdLoc The location of the name in the translation unit. +/// +/// \param TypoCorrection If true, this routine will attempt typo correction +/// if there is no class with the given name. +/// +/// \returns The declaration of the named Objective-C class, which is also the +/// definition if one is available, or NULL if the class could not be found. +ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, + SourceLocation IdLoc, + bool TypoCorrection) { + // The third "scope" argument is 0 since we aren't enabling lazy built-in + // creation from this context. + NamedDecl *Decl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); + + if (!Decl && TypoCorrection) { + // Perform typo correction at the given location, but only if we + // find an Objective-C class name. + LookupResult R(*this, Id, IdLoc, LookupOrdinaryName); + if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && + (Decl = R.getAsSingle<ObjCInterfaceDecl>())) { + Diag(IdLoc, diag::err_undef_interface_suggest) + << Id << Decl->getDeclName() + << FixItHint::CreateReplacement(IdLoc, Decl->getNameAsString()); + Diag(Decl->getLocation(), diag::note_previous_decl) + << Decl->getDeclName(); + + Id = Decl->getIdentifier(); + } + } + + ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(Decl); + if (IDecl) { + if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) + IDecl = Def; + } + return IDecl; +} + /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible /// and user declared, in the method definition's AST. void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { @@ -65,6 +109,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, SourceLocation EndProtoLoc, AttributeList *AttrList) { assert(ClassName && "Missing class identifier"); + bool Invalid = false; + // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, ForRedeclaration); @@ -72,42 +118,35 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); + // Set the new decl invalid and ignore the old. + Invalid = true; + PrevDecl = 0; } - ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); - if (IDecl) { + ObjCInterfaceDecl *ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl); + if (ODecl) { // Class already seen. Is it a forward declaration? - if (!IDecl->isForwardDecl()) { - IDecl->setInvalidDecl(); - Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName(); - Diag(IDecl->getLocation(), diag::note_previous_definition); + if (ObjCInterfaceDecl *Def = ODecl->getDefinition()) { + Invalid = true; + Diag(AtInterfaceLoc, diag::err_duplicate_class_def) << Def->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); - // Return the previous class interface. - // FIXME: don't leak the objects passed in! - return DeclPtrTy::make(IDecl); - } else { - IDecl->setLocation(AtInterfaceLoc); - IDecl->setForwardDecl(false); - IDecl->setClassLoc(ClassLoc); - - // 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); - - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); + // Return the previous class interface and ignore the new one. + return DeclPtrTy::make(ODecl); } - } else { - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, - ClassName, ClassLoc); - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); - - PushOnScopeChains(IDecl, TUScope); } + ObjCInterfaceDecl *IDecl = + ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassName, ClassLoc, ODecl); + if (Invalid) + IDecl->setInvalidDecl(); + + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); + + PushOnScopeChains(IDecl, TUScope); + if (SuperName) { // Check if a different kind of symbol declared in this scope. PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, @@ -125,6 +164,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } + // Since we just pushed IDecl on the scope chain, if PrevDecl is the same + // class, it will be the same declaration. if (PrevDecl == IDecl) { Diag(SuperLoc, diag::err_recursive_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); @@ -140,11 +181,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (PrevDecl && SuperClassDecl == 0) { // The previous declaration was not a class decl. Check if we have a // typedef. If we do, get the underlying class type. - if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)) { + if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(PrevDecl)){ QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { - if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) - SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl); + if (NamedDecl *NDecl = T->getAs<ObjCObjectType>()->getInterface()) + SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(NDecl); } } @@ -159,6 +200,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } + if (SuperClassDecl) { + if (ObjCInterfaceDecl *Def = SuperClassDecl->getDefinition()) + SuperClassDecl = Def; + } + if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) { if (!SuperClassDecl) Diag(SuperLoc, diag::err_undef_superclass) @@ -530,7 +576,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation( IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperClassname, SourceLocation SuperClassLoc) { - ObjCInterfaceDecl* IDecl = 0; + ObjCInterfaceDecl *IDecl = 0, *ODecl = 0; // Check for another declaration kind with the same name. NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, |