[cfe-commits] r110610 - in /cfe/trunk: include/clang/AST/ lib/AST/ lib/Frontend/ lib/Sema/ test/Index/

Sebastian Redl sebastian.redl at getdesigned.at
Mon Aug 9 14:55:29 PDT 2010


Author: cornedbee
Date: Mon Aug  9 16:55:28 2010
New Revision: 110610

URL: http://llvm.org/viewvc/llvm-project?rev=110610&view=rev
Log:
- Make ObjCInterfaceDecl redeclarable, and create separate decl nodes for forward declarations and the definition.
- Eagerly create ObjCInterfaceTypes for declarations.
- The two above changes lead to a 0.5% increase in memory use and no speed regression when parsing Cocoa.h. On the other hand, now chained PCH works when there's a forward declaration in one PCH and the interface definition in another.
- Add HandleInterestingDecl to ASTConsumer. PCHReader passes the "interesting" decls it finds to this function instead of HandleTopLevelDecl. The default implementation forwards to HandleTopLevelDecl, but ASTUnit's handler for example ignores them. This fixes a potential crash when lazy loading of PCH data would cause ASTUnit's "top level" declaration collection to change while being iterated.

Modified:
    cfe/trunk/include/clang/AST/ASTConsumer.h
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTConsumer.cpp
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/test/Index/TestClassDecl.m

Modified: cfe/trunk/include/clang/AST/ASTConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTConsumer.h?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTConsumer.h (original)
+++ cfe/trunk/include/clang/AST/ASTConsumer.h Mon Aug  9 16:55:28 2010
@@ -49,6 +49,11 @@
   /// 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) {}

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug  9 16:55:28 2010
@@ -668,7 +668,10 @@
                                                   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,

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Mon Aug  9 16:55:28 2010
@@ -450,7 +450,10 @@
 ///   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 @@
   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 @@
                                        ASTContext &C);
 
   bool isForwardDecl() const { return ForwardDecl; }
+  bool isDefinition() const { return !ForwardDecl; }
   void setForwardDecl(bool val) { ForwardDecl = val; }
 
   ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Aug  9 16:55:28 2010
@@ -3038,7 +3038,7 @@
   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); }

Modified: cfe/trunk/lib/AST/ASTConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTConsumer.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTConsumer.cpp (original)
+++ cfe/trunk/lib/AST/ASTConsumer.cpp Mon Aug  9 16:55:28 2010
@@ -17,3 +17,6 @@
 
 void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
 
+void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
+  HandleTopLevelDecl(D);
+}

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug  9 16:55:28 2010
@@ -872,7 +872,7 @@
 /// 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 @@
   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);
-
-  // 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);
+QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+                                          const ObjCInterfaceDecl *PrevDecl) {
+  assert(Decl && "Passed null for Decl param");
+
+  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

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Aug  9 16:55:28 2010
@@ -2467,6 +2467,18 @@
 }
 
 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 @@
       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());

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Mon Aug  9 16:55:28 2010
@@ -45,6 +45,14 @@
 // 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 @@
                                              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 {

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Mon Aug  9 16:55:28 2010
@@ -727,12 +727,19 @@
 
 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();

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Aug  9 16:55:28 2010
@@ -360,6 +360,17 @@
   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>())

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Mon Aug  9 16:55:28 2010
@@ -320,6 +320,9 @@
       Unit.addTopLevelDecl(D);
     }
   }
+
+  // We're not interested in "interesting" decls.
+  void HandleInterestingDecl(DeclGroupRef) {}
 };
 
 class TopLevelDeclTrackerAction : public ASTFrontendAction {

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Mon Aug  9 16:55:28 2010
@@ -2262,7 +2262,7 @@
   SavedStreamPosition SavedPosition(DeclsCursor);
 
   ReadingKindTracker ReadingKind(Read_Type, *this);
-  
+
   // Note that we are loading a type record.
   Deserializing AType(this);
 
@@ -3027,7 +3027,7 @@
   while (!InterestingDecls.empty()) {
     DeclGroupRef DG(InterestingDecls.front());
     InterestingDecls.pop_front();
-    Consumer->HandleTopLevelDecl(DG);
+    Consumer->HandleInterestingDecl(DG);
   }
 }
 

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Mon Aug  9 16:55:28 2010
@@ -34,7 +34,7 @@
     const pch::DeclID ThisDeclID;
     const PCHReader::RecordData &Record;
     unsigned &Idx;
-    pch::TypeID TypeIDForTypeDecl;
+    pch::TypeID TypeIDForDecl;
 
     uint64_t GetCurrentCursorOffset();
 
@@ -43,7 +43,7 @@
                   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 @@
 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::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::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 @@
     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 @@
                                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,

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Mon Aug  9 16:55:28 2010
@@ -305,7 +305,9 @@
 }
 
 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;
 }
 

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Mon Aug  9 16:55:28 2010
@@ -340,6 +340,9 @@
 
 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 @@
                                      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);

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Aug  9 16:55:28 2010
@@ -89,7 +89,7 @@
     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);
   }

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Mon Aug  9 16:55:28 2010
@@ -3748,20 +3748,28 @@
   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);
+      }
     }
   }
 }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug  9 16:55:28 2010
@@ -606,45 +606,6 @@
   }
 }
 
-/// \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

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Aug  9 16:55:28 2010
@@ -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 @@
                          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 @@
   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 @@
       }
     }
 
+    // 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 @@
       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 @@
         }
       }
 
+      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 @@
                       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,
@@ -538,11 +584,10 @@
   if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
     Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
     Diag(PrevDecl->getLocation(), diag::note_previous_definition);
-  } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
-    // If this is a forward declaration of an interface, warn.
-    if (IDecl->isForwardDecl()) {
+  } else if ((ODecl = cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
+    // If we can't find a definition of the interface, warn.
+    if (!(IDecl = ODecl->getDefinition())) {
       Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
-      IDecl = 0;
     }
   } else {
     // We did not find anything with the name ClassName; try to correct for 
@@ -552,7 +597,7 @@
         (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {
       // Suggest the (potentially) correct interface name. However, put the
       // fix-it hint itself in a separate note, since changing the name in 
-      // the warning would make the fix-it change semantics.However, don't
+      // the warning would make the fix-it change semantics. Also, don't
       // provide a code-modification hint or use the typo name for recovery,
       // because this is just a warning. The program may actually be correct.
       Diag(ClassLoc, diag::warn_undef_interface_suggest)
@@ -599,16 +644,11 @@
     // 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, ODecl, false, true);
     IDecl->setSuperClass(SDecl);
     IDecl->setLocEnd(ClassLoc);
 
     PushOnScopeChains(IDecl, TUScope);
-  } else {
-    // Mark the interface as being completed, even if it was just as
-    //   @class ....;
-    // declaration; the user cannot reopen it.
-    IDecl->setForwardDecl(false);
   }
 
   ObjCImplementationDecl* IMPDecl =
@@ -619,15 +659,15 @@
     return DeclPtrTy::make(IMPDecl);
 
   // Check that there is no duplicate implementation of this class.
-  if (IDecl->getImplementation()) {
-    // FIXME: Don't leak everything!
+  if (IDecl && IDecl->getImplementation()) {
     Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
     Diag(IDecl->getImplementation()->getLocation(),
          diag::note_previous_definition);
-  } else { // add it to the list.
+  } else {
     IDecl->setImplementation(IMPDecl);
     PushOnScopeChains(IMPDecl, TUScope);
   }
+
   return DeclPtrTy::make(IMPDecl);
 }
 
@@ -1029,19 +1069,18 @@
           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);
-    }
+    ObjCInterfaceDecl *ODecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
+    ObjCInterfaceDecl *IDecl =
+        ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
+                                  IdentList[i], IdentLocs[i], ODecl, 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);
 
     Interfaces.push_back(IDecl);
   }

Modified: cfe/trunk/test/Index/TestClassDecl.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/TestClassDecl.m?rev=110610&r1=110609&r2=110610&view=diff
==============================================================================
--- cfe/trunk/test/Index/TestClassDecl.m (original)
+++ cfe/trunk/test/Index/TestClassDecl.m Mon Aug  9 16:55:28 2010
@@ -17,7 +17,7 @@
 
 // CHECK-scan: [1:1 - 8:1] Invalid Cursor => NoDeclFound
 // CHECK-scan: [8:1 - 8:8] UnexposedDecl=:8:1
-// CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:10:12
+// CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:8:8
 // CHECK-scan: [8:11 - 10:1] Invalid Cursor => NoDeclFound
 // CHECK-scan: [10:1 - 11:5] ObjCInterfaceDecl=Foo:10:12
 // CHECK-scan: [11:5 - 13:6] Invalid Cursor => NoDeclFound





More information about the cfe-commits mailing list