diff options
-rw-r--r-- | include/clang/AST/DeclObjC.h | 30 | ||||
-rw-r--r-- | lib/ARCMigrate/Transforms.cpp | 2 | ||||
-rw-r--r-- | lib/AST/ASTImporter.cpp | 1 | ||||
-rw-r--r-- | lib/AST/DeclObjC.cpp | 36 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 10 | ||||
-rw-r--r-- | lib/AST/DumpXML.cpp | 2 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 2 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/CocoaConventions.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 2 | ||||
-rw-r--r-- | lib/Rewrite/RewriteObjC.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/IdentifierResolver.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 91 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 1 | ||||
-rw-r--r-- | test/Index/TestClassDecl.m | 2 | ||||
-rw-r--r-- | test/SemaObjC/forward-class-1.m | 2 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 24 | ||||
-rw-r--r-- | tools/libclang/IndexDecl.cpp | 2 | ||||
-rw-r--r-- | tools/libclang/IndexingContext.h | 2 |
21 files changed, 117 insertions, 132 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 8fbee1f520..6215fb0b4d 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -583,7 +583,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl }; ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, - SourceLocation CLoc, bool FD, bool isInternal); + SourceLocation CLoc, bool isInternal); void LoadExternalDefinition() const; @@ -596,12 +596,6 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// 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 @@ public: 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 @@ public: 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 @@ public: return getFirstDeclaration(); } + void setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl); + // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index e208e8471b..21df257872 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -80,7 +80,7 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type, 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; diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 949db7972a..ac3b536ace 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3183,7 +3183,6 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), Loc, - D->isInitiallyForwardDecl(), D->isImplicitInterfaceDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index e088c66229..d420b2be49 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -675,16 +675,15 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C, 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 @@ void ObjCInterfaceDecl::setExternallyCompleted() { } 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 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto, 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 //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index ec7d6de71a..03a69a0418 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -900,16 +900,16 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { 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()) { diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index 2568adaa5a..e0ea612dc2 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -755,7 +755,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, } 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) { diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 3e413befd8..a47bd4afb4 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -2161,7 +2161,7 @@ const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { 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 = diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index e01346cdb6..d375e7c59d 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -927,7 +927,7 @@ bool Type::isIncompleteType() const { ->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(); } } diff --git a/lib/Analysis/CocoaConventions.cpp b/lib/Analysis/CocoaConventions.cpp index 8acd1892f9..9dc5ef4906 100644 --- a/lib/Analysis/CocoaConventions.cpp +++ b/lib/Analysis/CocoaConventions.cpp @@ -115,7 +115,7 @@ bool cocoa::isCocoaObjectRef(QualType Ty) { // 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()) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 922b725d9d..2b67c2e5e4 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1211,7 +1211,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // 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, diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index 8635ed41be..b8b1497435 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -653,8 +653,9 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { 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 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { 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::RewriteImplementationDecl(Decl *OID) { 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 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 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 @@ void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, // 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 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe // 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); } diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 812f5d64fa..a80f23f58e 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -318,15 +318,6 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) { 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; } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 7e7e87a065..79985e8b32 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -5487,14 +5487,14 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, 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); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 6947d7e211..3d1f01fec3 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -60,7 +60,7 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method, // 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 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, 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 @@ Decl *Sema::ActOnStartClassImplementation( // 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 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, 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); } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 4dc960bdff..12b61b0cdd 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -629,7 +629,6 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { } } - ID->InitiallyForwardDecl = Record[Idx++]; ID->setLocEnd(ReadSourceLocation(Record, Idx)); } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index e641c101a1..7a194a8d18 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -489,7 +489,6 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Writer.AddDeclRef(D->getCategoryList(), Record); } - Record.push_back(D->isInitiallyForwardDecl()); Writer.AddSourceLocation(D->getLocEnd(), Record); Code = serialization::DECL_OBJC_INTERFACE; } diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m index e94a5c12fa..bc4f2afb73 100644 --- a/test/Index/TestClassDecl.m +++ b/test/Index/TestClassDecl.m @@ -16,7 +16,7 @@ void function(Foo * arg) } // 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 diff --git a/test/SemaObjC/forward-class-1.m b/test/SemaObjC/forward-class-1.m index 3a9a8ac82d..f5ce8892d3 100644 --- a/test/SemaObjC/forward-class-1.m +++ b/test/SemaObjC/forward-class-1.m @@ -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 diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f74953fee6..a5b390a53a 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -299,12 +299,7 @@ void CursorVisitor::visitDeclsFromFileRegion(FileID File, // 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 @@ CXCursor clang_getCursorReferenced(CXCursor C) { 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 @@ CXCursor clang_getCursorDefinition(CXCursor C) { // 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 @@ CXCursor clang_getCursorDefinition(CXCursor C) { 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(); diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp index 0d6dacb775..96a21d8486 100644 --- a/tools/libclang/IndexDecl.cpp +++ b/tools/libclang/IndexDecl.cpp @@ -97,7 +97,7 @@ public: bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // Forward decls are handled at VisitObjCClassDecl. - if (D->isForwardDecl()) + if (!D->isThisDeclarationADefinition()) return true; IndexCtx.handleObjCInterface(D); diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h index f5498e5292..206e322337 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/IndexingContext.h @@ -128,7 +128,7 @@ struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo { ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D) : ObjCContainerDeclInfo(Info_ObjCInterface, /*isForwardRef=*/false, - /*isRedeclaration=*/D->isInitiallyForwardDecl(), + /*isRedeclaration=*/D->getPreviousDeclaration() != 0, /*isImplementation=*/false) { } static bool classof(const DeclInfo *D) { |