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?"



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146679 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 949db79..ac3b536 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -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);
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index e088c66..d420b2b 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -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
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index ec7d6de..03a69a0 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -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()) {
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 2568ada..e0ea612 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -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) {
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 3e413be..a47bd4a 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -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 =
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index e01346c..d375e7c 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -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();
   }
 }