]> granicus.if.org Git - clang/commitdiff
Add SourceLocations to ObjCClassDecl for the class identifiers referenced by @class.
authorTed Kremenek <kremenek@apple.com>
Wed, 18 Nov 2009 00:28:11 +0000 (00:28 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 18 Nov 2009 00:28:11 +0000 (00:28 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89170 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclObjC.h
lib/AST/DeclBase.cpp
lib/AST/DeclObjC.cpp
lib/AST/DeclPrinter.cpp
lib/Frontend/PCHReaderDecl.cpp
lib/Frontend/PCHWriterDecl.cpp
lib/Frontend/RewriteObjC.cpp
lib/Sema/SemaDeclObjC.cpp

index bcd28eab039fe775b6f63d1da720632ef9aa8a4c..0d4089623d206f6e5845329ebfecbcafd9ff6b81 100644 (file)
@@ -718,10 +718,22 @@ public:
 /// @class NSCursor, NSImage, NSPasteboard, NSWindow;
 ///
 class ObjCClassDecl : public Decl {
-  ObjCList<ObjCInterfaceDecl> 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<ObjCInterfaceDecl>::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; }
index c3c506e5ba198b999c0da385f74c0708694cb8ca..abcffed4050285db8f54866bf5450de21ebcd072 100644 (file)
@@ -678,7 +678,7 @@ void DeclContext::buildLookup(DeclContext *DCtx) {
       if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*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).
index 7b48b724c0eb670799f08716264eeb019bcffc0e..9d43c7cca0a8e6ff95bd44d563a37041d4d7b8ce 100644 (file)
@@ -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<ObjCClassRef>());
+  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);
 }
 
index 199ed356d6d3838b73056f81ae4b7fcf88355b5b..645133b4da4393e8a80b96dae335b0939d7ab7cb 100644 (file)
@@ -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();
   }
 }
 
index 775ce76c92d87e0b16f45f71df17d9a7b8bbfd12..6a92a2db51a8705d0ec937e6c72d6ca38e3aaa9d 100644 (file)
@@ -264,7 +264,12 @@ void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
   ClassRefs.reserve(NumClassRefs);
   for (unsigned I = 0; I != NumClassRefs; ++I)
     ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
-  CD->setClassList(*Reader.getContext(), ClassRefs.data(), NumClassRefs);
+  llvm::SmallVector<SourceLocation, 16> 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) {
index 8997e661a5a1d20b1c07fe6d1eb12cd0a7c26f25..c7bfee2c8bcd6d4bf2d7c2de6b06c9c6bf7ff239 100644 (file)
@@ -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;
 }
 
index 24ad69e3e0d386e4897d63573971547487847d62..06955e5c30b6b3b2e2040c6859c833d8d794de98 100644 (file)
@@ -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";
index 8961cf165ac0c67169b5e81c189302c447bdb825..0c5569caff008708d9797f0cef9e5fc2869288ef 100644 (file)
@@ -1197,10 +1197,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
     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],
-                                        // 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);