Author: dgregor Date: Thu Dec 15 14:29:51 2011 New Revision: 146679 URL: http://llvm.org/viewvc/llvm-project?rev=146679&view=rev Log: Keep track of all declarations of an Objective-C class (both forward declarations and definitions) as ObjCInterfaceDecls within the same redeclaration chain. This new representation matches what we do for C/C++ variables/functions/classes/templates/etc., and makes it possible to answer the query "where are all of the declarations of this class?"
Modified: cfe/trunk/include/clang/AST/DeclObjC.h cfe/trunk/lib/ARCMigrate/Transforms.cpp cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/lib/AST/DeclObjC.cpp cfe/trunk/lib/AST/DeclPrinter.cpp cfe/trunk/lib/AST/DumpXML.cpp cfe/trunk/lib/AST/RecordLayoutBuilder.cpp cfe/trunk/lib/AST/Type.cpp cfe/trunk/lib/Analysis/CocoaConventions.cpp cfe/trunk/lib/CodeGen/CGDebugInfo.cpp cfe/trunk/lib/Rewrite/RewriteObjC.cpp cfe/trunk/lib/Sema/IdentifierResolver.cpp cfe/trunk/lib/Sema/SemaCodeComplete.cpp cfe/trunk/lib/Sema/SemaDeclObjC.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/test/Index/TestClassDecl.m cfe/trunk/test/SemaObjC/forward-class-1.m cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/tools/libclang/IndexDecl.cpp cfe/trunk/tools/libclang/IndexingContext.h Modified: cfe/trunk/include/clang/AST/DeclObjC.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclObjC.h (original) +++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Dec 15 14:29:51 2011 @@ -583,7 +583,7 @@ }; ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal); + SourceLocation CLoc, bool isInternal); void LoadExternalDefinition() const; @@ -596,12 +596,6 @@ /// 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; - DefinitionData &data() const { assert(Data != 0 && "Declaration has no definition!"); return *Data; @@ -620,13 +614,13 @@ SourceLocation atLoc, IdentifierInfo *Id, SourceLocation ClassLoc = SourceLocation(), - bool ForwardDecl = false, bool isInternal = false); virtual SourceRange getSourceRange() const { - if (isForwardDecl()) - return SourceRange(getAtStartLoc(), getLocation()); - return ObjCContainerDecl::getSourceRange(); + if (isThisDeclarationADefinition()) + return ObjCContainerDecl::getSourceRange(); + + return SourceRange(getAtStartLoc(), getLocation()); } /// \brief Indicate that this Objective-C class is complete, but that @@ -772,20 +766,10 @@ unsigned Num, ASTContext &C); - /// \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; - } - - /// \brief Determine whether this class has only ever been forward-declared. - bool isForwardDecl() const { return Data == 0; } - /// \brief Determine whether this particular declaration of this class is /// actually also a definition. bool isThisDeclarationADefinition() const { - return Data == 0 || Data->Definition != this; + return Data && Data->Definition == this; } /// \brief Determine whether this class has been defined. @@ -927,6 +911,8 @@ return getFirstDeclaration(); } + void setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl); + // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original) +++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Thu Dec 15 14:29:51 2011 @@ -80,7 +80,7 @@ ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl(); if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject")) return false; // id/NSObject is not safe for weak. - if (!AllowOnUnknownClass && Class->isForwardDecl()) + if (!AllowOnUnknownClass && !Class->hasDefinition()) return false; // forward classes are not verifiable, therefore not safe. if (Class->isArcWeakrefUnavailable()) return false; Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Dec 15 14:29:51 2011 @@ -3183,7 +3183,6 @@ ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), Loc, - D->isInitiallyForwardDecl(), D->isImplicitInterfaceDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); Modified: cfe/trunk/lib/AST/DeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclObjC.cpp (original) +++ cfe/trunk/lib/AST/DeclObjC.cpp Thu Dec 15 14:29:51 2011 @@ -675,16 +675,15 @@ SourceLocation atLoc, IdentifierInfo *Id, SourceLocation ClassLoc, - bool ForwardDecl, bool isInternal){ - return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl, - isInternal); + bool isInternal){ + return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, isInternal); } ObjCInterfaceDecl:: ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal) + SourceLocation CLoc, bool isInternal) : ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc), - TypeForDecl(0), Data(), InitiallyForwardDecl(FD) + TypeForDecl(0), Data() { setImplicit(isInternal); } @@ -705,19 +704,20 @@ } ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { + if (const ObjCInterfaceDecl *Def = getDefinition()) { + if (data().ExternallyCompleted) + LoadExternalDefinition(); + + return getASTContext().getObjCImplementation( + const_cast<ObjCInterfaceDecl*>(Def)); + } + // FIXME: Should make sure no callers ever do this. - if (!hasDefinition()) - return 0; - - if (data().ExternallyCompleted) - LoadExternalDefinition(); - - return getASTContext().getObjCImplementation( - const_cast<ObjCInterfaceDecl*>(this)); + return 0; } void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) { - getASTContext().setObjCImplementation(this, ImplD); + getASTContext().setObjCImplementation(getDefinition(), ImplD); } /// all_declared_ivar_begin - return first ivar declared in this class, @@ -851,6 +851,14 @@ return false; } +void ObjCInterfaceDecl::setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl) { + redeclarable_base::setPreviousDeclaration(PrevDecl); + + // Inherit the 'Data' pointer from the previous declaration. + if (PrevDecl) + Data = PrevDecl->Data; +} + //===----------------------------------------------------------------------===// // ObjCIvarDecl //===----------------------------------------------------------------------===// Modified: cfe/trunk/lib/AST/DeclPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclPrinter.cpp (original) +++ cfe/trunk/lib/AST/DeclPrinter.cpp Thu Dec 15 14:29:51 2011 @@ -900,16 +900,16 @@ std::string I = OID->getNameAsString(); ObjCInterfaceDecl *SID = OID->getSuperClass(); + if (!OID->isThisDeclarationADefinition()) { + Out << "@class " << I << ";"; + return; + } + if (SID) Out << "@interface " << I << " : " << *SID; else Out << "@interface " << I; - if (OID->isForwardDecl()) { - Out << "@end"; - return; - } - // Protocols? const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); if (!Protocols.empty()) { Modified: cfe/trunk/lib/AST/DumpXML.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DumpXML.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/AST/DumpXML.cpp (original) +++ cfe/trunk/lib/AST/DumpXML.cpp Thu Dec 15 14:29:51 2011 @@ -755,7 +755,7 @@ } void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { setPointer("typeptr", D->getTypeForDecl()); - setFlag("forward_decl", D->isForwardDecl()); + setFlag("forward_decl", !D->isThisDeclarationADefinition()); setFlag("implicit_interface", D->isImplicitInterfaceDecl()); } void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) { Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original) +++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Thu Dec 15 14:29:51 2011 @@ -2161,7 +2161,7 @@ const ASTRecordLayout & ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const { - assert(!D->isForwardDecl() && "Invalid interface decl!"); + assert(D->isThisDeclarationADefinition() && "Invalid interface decl!"); // Look up this layout, if already laid out, return what we have. ObjCContainerDecl *Key = Modified: cfe/trunk/lib/AST/Type.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/AST/Type.cpp (original) +++ cfe/trunk/lib/AST/Type.cpp Thu Dec 15 14:29:51 2011 @@ -927,7 +927,7 @@ ->isIncompleteType(); case ObjCInterface: // ObjC interfaces are incomplete if they are @class, not @interface. - return cast<ObjCInterfaceType>(CanonicalType)->getDecl()->isForwardDecl(); + return !cast<ObjCInterfaceType>(CanonicalType)->getDecl()->hasDefinition(); } } Modified: cfe/trunk/lib/Analysis/CocoaConventions.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CocoaConventions.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/CocoaConventions.cpp (original) +++ cfe/trunk/lib/Analysis/CocoaConventions.cpp Thu Dec 15 14:29:51 2011 @@ -115,7 +115,7 @@ // Assume that anything declared with a forward declaration and no // @interface subclasses NSObject. - if (ID->isForwardDecl()) + if (!ID->hasDefinition()) return true; for ( ; ID ; ID = ID->getSuperClass()) Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Dec 15 14:29:51 2011 @@ -1211,7 +1211,7 @@ // If this is just a forward declaration return a special forward-declaration // debug type since we won't be able to lay out the entire type. - if (ID->isForwardDecl()) { + if (!ID->isThisDeclarationADefinition()) { llvm::DIType FwdDecl = DBuilder.createStructType(Unit, ID->getName(), DefUnit, Line, 0, 0, Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original) +++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Thu Dec 15 14:29:51 2011 @@ -653,8 +653,9 @@ ConstantStringClassReference = FVD; return; } - } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) { - RewriteInterfaceDecl(MD); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + if (ID->isThisDeclarationADefinition()) + RewriteInterfaceDecl(ID); } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { RewriteCategoryDecl(CD); } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { @@ -673,9 +674,18 @@ SourceLocation Loc = D->getLocation(); while (DI != DIEnd && isa<ObjCClassDecl>(D) && D->getLocation() == Loc) { + ObjCClassDecl *Class = cast<ObjCClassDecl>(D); DG.push_back(D); ++DI; D = (*DI); + + // Following the ObjCClassDecl, we should have the corresponding + // ObjCInterfaceDecl. Skip over it. + if (DI != DIEnd && isa<ObjCInterfaceDecl>(D) && + Class->getForwardInterfaceDecl() == D) { + ++DI; + D = (*DI); + } } RewriteForwardClassDecl(DG); continue; @@ -1179,7 +1189,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { std::string ResultStr; - if (!ObjCForwardDecls.count(ClassDecl)) { + if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) { // we haven't seen a forward decl - generate a typedef. ResultStr = "#ifndef _REWRITER_typedef_"; ResultStr += ClassDecl->getNameAsString(); @@ -1191,7 +1201,7 @@ ResultStr += ClassDecl->getNameAsString(); ResultStr += ";\n#endif\n"; // Mark this typedef as having been generated. - ObjCForwardDecls.insert(ClassDecl); + ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl()); } RewriteObjCInternalStruct(ClassDecl, ResultStr); @@ -3130,7 +3140,7 @@ // If no ivars and no root or if its root, directly or indirectly, // have no ivars (thus not synthesized) then no need to synthesize this class. - if ((CDecl->isForwardDecl() || NumIvars == 0) && + if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) && (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); ReplaceText(LocStart, endBuf-startBuf, Result); @@ -5357,7 +5367,7 @@ // Explicitly declared @interface's are already synthesized. if (CDecl->isImplicitInterfaceDecl()) { - // FIXME: Implementation of a class with no @interface (legacy) doese not + // FIXME: Implementation of a class with no @interface (legacy) does not // produce correct synthesis as yet. RewriteObjCInternalStruct(CDecl, Result); } Modified: cfe/trunk/lib/Sema/IdentifierResolver.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/Sema/IdentifierResolver.cpp (original) +++ cfe/trunk/lib/Sema/IdentifierResolver.cpp Thu Dec 15 14:29:51 2011 @@ -318,15 +318,6 @@ return DMK_Ignore; } - // If the declarations are both Objective-C classes, and one is a forward - // declaration and the other is not, take the full definition. - // FIXME: At some point, we'll actually have to detect collisions better. - // This logic, however, belongs in the AST reader, not here. - if (ObjCInterfaceDecl *ExistingIFace = dyn_cast<ObjCInterfaceDecl>(Existing)) - if (ObjCInterfaceDecl *NewIFace = dyn_cast<ObjCInterfaceDecl>(New)) - if (ExistingIFace->isForwardDecl() != NewIFace->isForwardDecl()) - return ExistingIFace->isForwardDecl()? DMK_Replace : DMK_Ignore; - return DMK_Different; } Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original) +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Dec 15 14:29:51 2011 @@ -5487,14 +5487,14 @@ D != DEnd; ++D) { // Record any interfaces we find. if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) - if ((!OnlyForwardDeclarations || Class->isForwardDecl()) && + if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && (!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)) { ObjCInterfaceDecl *IDecl = Forward->getForwardInterfaceDecl(); - if ((!OnlyForwardDeclarations || IDecl->isForwardDecl()) && + if ((!OnlyForwardDeclarations || !IDecl->hasDefinition()) && (!OnlyUnimplemented || !IDecl->getImplementation())) Results.AddResult(Result(IDecl, 0), CurContext, 0, false); Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Thu Dec 15 14:29:51 2011 @@ -60,7 +60,7 @@ // It's okay for the result type to still be a forward declaration // if we're checking an interface declaration. - if (resultClass->isForwardDecl()) { + if (!resultClass->hasDefinition()) { if (receiverTypeIfCall.isNull() && !isa<ObjCImplementationDecl>(method->getDeclContext())) return false; @@ -365,45 +365,31 @@ Diag(PrevDecl->getLocation(), diag::note_previous_definition); } - ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); - if (IDecl) { - // Class already seen. Is it a forward declaration? - if (ObjCInterfaceDecl *Def = IDecl->getDefinition()) { - IDecl->setInvalidDecl(); - Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName(); + // Create a declaration to describe this @interface. + ObjCInterfaceDecl *IDecl + = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, + ClassLoc); + + ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + if (PrevIDecl) { + // Class already seen. Was it a definition? + if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { + Diag(AtInterfaceLoc, diag::err_duplicate_class_def) + << PrevIDecl->getDeclName(); 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. - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, - ClassName, ClassLoc); - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); - PushOnScopeChains(IDecl, TUScope); - - } else { - IDecl->setLocation(ClassLoc); - IDecl->setAtStartLoc(AtInterfaceLoc); - - // 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); + IDecl->setInvalidDecl(); } - } else { - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, - ClassName, ClassLoc); - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); - PushOnScopeChains(IDecl, TUScope); + // Link to the previous declaration. + IDecl->setPreviousDeclaration(PrevIDecl); } + + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); + PushOnScopeChains(IDecl, TUScope); + // Start the definition of this class. If we're in a redefinition case, there + // may already be a definition, so we'll end up adding to it. if (!IDecl->hasDefinition()) IDecl->startDefinition(); @@ -942,7 +928,7 @@ // FIXME: Do we support attributes on the @implementation? If so we should // copy them over. IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, - ClassName, ClassLoc, false, true); + ClassName, ClassLoc, true); IDecl->startDefinition(); IDecl->setSuperClass(SDecl); IDecl->setLocEnd(ClassLoc); @@ -1781,22 +1767,29 @@ PrevDecl = OI->getInterface(); } } - ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); - if (!IDecl) { // Not already seen? Make a forward decl. - IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], IdentLocs[i], true); - - // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to - // the current DeclContext. This prevents clients that walk DeclContext - // from seeing the imaginary ObjCInterfaceDecl until it is actually - // declared later (if at all). We also take care to explicitly make - // sure this declaration is visible for name lookup. - PushOnScopeChains(IDecl, TUScope, false); - CurContext->makeDeclVisibleInContext(IDecl, true); - } + + // Create a declaration to describe this forward declaration. + ObjCInterfaceDecl *IDecl + = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, + IdentList[i], IdentLocs[i], true); + IDecl->setAtEndRange(IdentLocs[i]); + IDecl->setLocEnd(IdentLocs[i]); + + // If there was a previous declaration, link to it. + if (ObjCInterfaceDecl *PrevIDecl + = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl)) + IDecl->setPreviousDeclaration(PrevIDecl); + + // Create the forward declaration. Note that we intentionally do this + // before we add the ObjCInterfaceDecl we just created, so that the + // rewriter sees the ObjCClassDecl first. + // FIXME: ObjCClassDecl should probably just go away. ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc, IDecl, IdentLocs[i]); CurContext->addDecl(CDecl); + + PushOnScopeChains(IDecl, TUScope); + CheckObjCDeclScope(CDecl); DeclsInGroup.push_back(CDecl); } Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Dec 15 14:29:51 2011 @@ -629,7 +629,6 @@ } } - ID->InitiallyForwardDecl = Record[Idx++]; ID->setLocEnd(ReadSourceLocation(Record, Idx)); } Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Dec 15 14:29:51 2011 @@ -489,7 +489,6 @@ Writer.AddDeclRef(D->getCategoryList(), Record); } - Record.push_back(D->isInitiallyForwardDecl()); Writer.AddSourceLocation(D->getLocEnd(), Record); Code = serialization::DECL_OBJC_INTERFACE; } Modified: cfe/trunk/test/Index/TestClassDecl.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/TestClassDecl.m?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/test/Index/TestClassDecl.m (original) +++ cfe/trunk/test/Index/TestClassDecl.m Thu Dec 15 14:29:51 2011 @@ -16,7 +16,7 @@ } // CHECK-scan: [1:1 - 8:1] Invalid Cursor => NoDeclFound -// CHECK-scan: [8:1 - 8:8] UnexposedDecl=[10:12] +// CHECK-scan: [8:1 - 8:8] UnexposedDecl=[8:8] // CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:10:12 // CHECK-scan: [8:11 - 10:1] Invalid Cursor => NoDeclFound // CHECK-scan: [10:1 - 11:5] ObjCInterfaceDecl=Foo:10:12 Modified: cfe/trunk/test/SemaObjC/forward-class-1.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/forward-class-1.m?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/test/SemaObjC/forward-class-1.m (original) +++ cfe/trunk/test/SemaObjC/forward-class-1.m Thu Dec 15 14:29:51 2011 @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +@class FOO, BAR; @class FOO, BAR; // expected-note {{forward declaration of class here}} -@class FOO, BAR; @interface INTF : FOO // expected-error {{attempting to use the forward class 'FOO' as superclass of 'INTF'}} @end Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Thu Dec 15 14:29:51 2011 @@ -299,12 +299,7 @@ // We handle forward decls via ObjCClassDecl. if (ObjCInterfaceDecl *InterD = dyn_cast<ObjCInterfaceDecl>(D)) { - if (InterD->isForwardDecl()) - continue; - // An interface that started as a forward decl may have changed location - // because its @interface was parsed. - if (InterD->isInitiallyForwardDecl() && - !SM.isInFileID(SM.getFileLoc(InterD->getLocation()), File)) + if (!InterD->isThisDeclarationADefinition()) continue; } @@ -3948,8 +3943,13 @@ case CXCursor_ObjCProtocolRef: { return MakeCXCursor(getCursorObjCProtocolRef(C).first, tu); - case CXCursor_ObjCClassRef: - return MakeCXCursor(getCursorObjCClassRef(C).first, tu ); + case CXCursor_ObjCClassRef: { + ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first; + if (ObjCInterfaceDecl *Def = Class->getDefinition()) + return MakeCXCursor(Def, tu); + + return MakeCXCursor(Class, tu); + } case CXCursor_TypeRef: return MakeCXCursor(getCursorTypeRef(C).first, tu ); @@ -4147,8 +4147,8 @@ // the definition; when we were provided with the interface, // produce the @implementation as the definition. if (WasReference) { - if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl()) - return C; + if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(D)->getDefinition()) + return MakeCXCursor(Def, TU); } else if (ObjCImplementationDecl *Impl = cast<ObjCInterfaceDecl>(D)->getImplementation()) return MakeCXCursor(Impl, TU); @@ -4162,8 +4162,8 @@ case Decl::ObjCCompatibleAlias: if (ObjCInterfaceDecl *Class = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface()) - if (!Class->isForwardDecl()) - return MakeCXCursor(Class, TU); + if (ObjCInterfaceDecl *Def = Class->getDefinition()) + return MakeCXCursor(Def, TU); return clang_getNullCursor(); Modified: cfe/trunk/tools/libclang/IndexDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexDecl.cpp?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/tools/libclang/IndexDecl.cpp (original) +++ cfe/trunk/tools/libclang/IndexDecl.cpp Thu Dec 15 14:29:51 2011 @@ -97,7 +97,7 @@ bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Forward decls are handled at VisitObjCClassDecl. - if (D->isForwardDecl()) + if (!D->isThisDeclarationADefinition()) return true; IndexCtx.handleObjCInterface(D); Modified: cfe/trunk/tools/libclang/IndexingContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/IndexingContext.h?rev=146679&r1=146678&r2=146679&view=diff ============================================================================== --- cfe/trunk/tools/libclang/IndexingContext.h (original) +++ cfe/trunk/tools/libclang/IndexingContext.h Thu Dec 15 14:29:51 2011 @@ -128,7 +128,7 @@ ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D) : ObjCContainerDeclInfo(Info_ObjCInterface, /*isForwardRef=*/false, - /*isRedeclaration=*/D->isInitiallyForwardDecl(), + /*isRedeclaration=*/D->getPreviousDeclaration() != 0, /*isImplementation=*/false) { } static bool classof(const DeclInfo *D) { _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits