From: Ted Kremenek Date: Wed, 18 Nov 2009 00:28:11 +0000 (+0000) Subject: Add SourceLocations to ObjCClassDecl for the class identifiers referenced by @class. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=321c22f1c4271c3d9a3d4d3fc18847f948ab595b;p=clang Add SourceLocations to ObjCClassDecl for the class identifiers referenced by @class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89170 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index bcd28eab03..0d4089623d 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -718,10 +718,22 @@ public: /// @class NSCursor, NSImage, NSPasteboard, NSWindow; /// class ObjCClassDecl : public Decl { - ObjCList ForwardDecls; +public: + class ObjCClassRef { + ObjCInterfaceDecl *ID; + SourceLocation L; + public: + ObjCClassRef(ObjCInterfaceDecl *d, SourceLocation l) : ID(d), L(l) {} + SourceLocation getLocation() const { return L; } + ObjCInterfaceDecl *getInterface() const { return ID; } + }; +private: + ObjCClassRef *ForwardDecls; + unsigned NumDecls; ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts, unsigned nElts, ASTContext &C); + ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs, + unsigned nElts, ASTContext &C); virtual ~ObjCClassDecl() {} public: @@ -730,17 +742,17 @@ public: static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts = 0, + const SourceLocation *Locs = 0, unsigned nElts = 0); - typedef ObjCList::iterator iterator; - iterator begin() const { return ForwardDecls.begin(); } - iterator end() const { return ForwardDecls.end(); } - unsigned size() const { return ForwardDecls.size(); } + typedef const ObjCClassRef* iterator; + iterator begin() const { return ForwardDecls; } + iterator end() const { return ForwardDecls + NumDecls; } + unsigned size() const { return NumDecls; } /// setClassList - Set the list of forward classes. - void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, unsigned Num) { - ForwardDecls.set(List, Num, C); - } + void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, + const SourceLocation *Locs, unsigned Num); static bool classof(const Decl *D) { return D->getKind() == ObjCClass; } static bool classof(const ObjCClassDecl *D) { return true; } diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index c3c506e5ba..abcffed405 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -678,7 +678,7 @@ void DeclContext::buildLookup(DeclContext *DCtx) { if (ObjCClassDecl *Class = dyn_cast(*D)) for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end(); I != IEnd; ++I) - makeDeclVisibleInContextImpl(*I); + makeDeclVisibleInContextImpl(I->getInterface()); // If this declaration is itself a transparent declaration context, // add its members (recursively). diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 7b48b724c0..9d43c7cca0 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -571,31 +571,46 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel, //===----------------------------------------------------------------------===// ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts, unsigned nElts, + ObjCInterfaceDecl *const *Elts, + const SourceLocation *Locs, + unsigned nElts, ASTContext &C) : Decl(ObjCClass, DC, L) { - ForwardDecls.set(Elts, nElts, C); + setClassList(C, Elts, Locs, nElts); } +void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, + const SourceLocation *Locs, unsigned Num) { + ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num, + llvm::alignof()); + for (unsigned i = 0; i < Num; ++i) + new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]); + + NumDecls = Num; +} ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts, + const SourceLocation *Locs, unsigned nElts) { - return new (C) ObjCClassDecl(DC, L, Elts, nElts, C); + return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C); } void ObjCClassDecl::Destroy(ASTContext &C) { - - // FIXME: There is no clear ownership policy now for referenced - // ObjCInterfaceDecls. Some of them can be forward declarations that - // are never later defined (in which case the ObjCClassDecl owns them) - // or the ObjCInterfaceDecl later becomes a real definition later. Ideally - // we should have separate objects for forward declarations and definitions, - // obviating this problem. Because of this situation, referenced - // ObjCInterfaceDecls are destroyed in ~TranslationUnit. - - ForwardDecls.Destroy(C); + // ObjCInterfaceDecls registered with a DeclContext will get destroyed + // when the DeclContext is destroyed. For those created only by a forward + // declaration, the first @class that created the ObjCInterfaceDecl gets + // to destroy it. + // FIXME: Note that this ownership role is very brittle; a better + // polict is surely need in the future. + for (iterator I = begin(), E = end(); I !=E ; ++I) { + ObjCInterfaceDecl *ID = I->getInterface(); + if (ID->isForwardDecl() && ID->getLocStart() == getLocStart()) + ID->Destroy(C); + } + + C.Deallocate(ForwardDecls); Decl::Destroy(C); } diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 199ed356d6..645133b4da 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -624,7 +624,7 @@ void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) { for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I) { if (I != D->begin()) Out << ", "; - Out << (*I)->getNameAsString(); + Out << I->getInterface()->getNameAsString(); } } diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 775ce76c92..6a92a2db51 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -264,7 +264,12 @@ void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) { ClassRefs.reserve(NumClassRefs); for (unsigned I = 0; I != NumClassRefs; ++I) ClassRefs.push_back(cast(Reader.GetDecl(Record[Idx++]))); - CD->setClassList(*Reader.getContext(), ClassRefs.data(), NumClassRefs); + llvm::SmallVector SLocs; + SLocs.reserve(NumClassRefs); + for (unsigned I = 0; I != NumClassRefs; ++I) + SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); + CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(), + NumClassRefs); } void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) { diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 8997e661a5..c7bfee2c8b 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -260,7 +260,9 @@ void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) { VisitDecl(D); Record.push_back(D->size()); for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) - Writer.AddDeclRef(*I, Record); + Writer.AddDeclRef(I->getInterface(), Record); + for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I) + Writer.AddSourceLocation(I->getLocation(), Record); Code = pch::DECL_OBJC_CLASS; } diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index 24ad69e3e0..06955e5c30 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -744,7 +744,7 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { typedefString += "\n"; for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end(); I != E; ++I) { - ObjCInterfaceDecl *ForwardDecl = *I; + ObjCInterfaceDecl *ForwardDecl = I->getInterface(); typedefString += "#ifndef _REWRITER_typedef_"; typedefString += ForwardDecl->getNameAsString(); typedefString += "\n"; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 8961cf165a..0c5569caff 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1197,10 +1197,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, ObjCInterfaceDecl *IDecl = dyn_cast_or_null(PrevDecl); if (!IDecl) { // Not already seen? Make a forward decl. IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, - IdentList[i], - // FIXME: need to get the 'real' - // identifier loc from the parser. - AtClassLoc, true); + 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 @@ -1214,8 +1211,9 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, Interfaces.push_back(IDecl); } + assert(Interfaces.size() == NumElts); ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc, - &Interfaces[0], + Interfaces.data(), IdentLocs, Interfaces.size()); CurContext->addDecl(CDecl); CheckObjCDeclScope(CDecl);