Move the definition-specific data of ObjCInterfaceDecl into a
separately-allocated DefinitionData structure, which we manage the
same way as CXXRecordDecl::DefinitionData. This prepares the way for
making ObjCInterfaceDecls redeclarable, to more accurately model
forward declarations of Objective-C classes and eliminate the mutation
of ObjCInterfaceDecl that causes us serious trouble in the AST reader.

Note that ObjCInterfaceDecl's accessors are fairly robust against
being applied to forward declarations, because Clang (and Sema in
particular) doesn't perform RequireCompleteType/hasDefinition() checks
everywhere it has to. Each of these overly-robust cases is marked with
a FIXME, which we can tackle over time.




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146644 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index e409f0a..949db79 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -3178,7 +3178,7 @@
   }
   
   ObjCInterfaceDecl *ToIface = MergeWithIface;
-  if (!ToIface || ToIface->isForwardDecl()) {
+  if (!ToIface || !ToIface->hasDefinition()) {
     if (!ToIface) {
       ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
                                           Importer.Import(D->getAtStartLoc()),
@@ -3187,88 +3187,98 @@
                                           D->isImplicitInterfaceDecl());
       ToIface->setLexicalDeclContext(LexicalDC);
       LexicalDC->addDeclInternal(ToIface);
-      if (D->isInitiallyForwardDecl() && !D->isForwardDecl())
-        ToIface->completedForwardDecl();
     }
     Importer.Imported(D, ToIface);
 
-    if (D->getSuperClass()) {
-      ObjCInterfaceDecl *Super
-        = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass()));
-      if (!Super)
-        return 0;
+    if (D->hasDefinition()) {
+      if (!ToIface->hasDefinition())
+        ToIface->startDefinition();
       
-      ToIface->setSuperClass(Super);
-      ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
+      if (D->getSuperClass()) {
+        ObjCInterfaceDecl *Super
+          = cast_or_null<ObjCInterfaceDecl>(
+              Importer.Import(D->getSuperClass()));
+        if (!Super)
+          return 0;
+        
+        ToIface->setSuperClass(Super);
+        ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
+      }
+      
+      // Import protocols
+      SmallVector<ObjCProtocolDecl *, 4> Protocols;
+      SmallVector<SourceLocation, 4> ProtocolLocs;
+      ObjCInterfaceDecl::protocol_loc_iterator 
+        FromProtoLoc = D->protocol_loc_begin();
+      
+      for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
+                                             FromProtoEnd = D->protocol_end();
+         FromProto != FromProtoEnd;
+         ++FromProto, ++FromProtoLoc) {
+        ObjCProtocolDecl *ToProto
+          = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+        if (!ToProto)
+          return 0;
+        Protocols.push_back(ToProto);
+        ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+      }
+      
+      // FIXME: If we're merging, make sure that the protocol list is the same.
+      ToIface->setProtocolList(Protocols.data(), Protocols.size(),
+                               ProtocolLocs.data(), Importer.getToContext());
     }
     
-    // Import protocols
-    SmallVector<ObjCProtocolDecl *, 4> Protocols;
-    SmallVector<SourceLocation, 4> ProtocolLocs;
-    ObjCInterfaceDecl::protocol_loc_iterator 
-      FromProtoLoc = D->protocol_loc_begin();
-    
-    // FIXME: Should we be usng all_referenced_protocol_begin() here?
-    for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
-                                           FromProtoEnd = D->protocol_end();
-       FromProto != FromProtoEnd;
-       ++FromProto, ++FromProtoLoc) {
-      ObjCProtocolDecl *ToProto
-        = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
-      if (!ToProto)
-        return 0;
-      Protocols.push_back(ToProto);
-      ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
-    }
-    
-    // FIXME: If we're merging, make sure that the protocol list is the same.
-    ToIface->setProtocolList(Protocols.data(), Protocols.size(),
-                             ProtocolLocs.data(), Importer.getToContext());
-    
     // Import @end range
     ToIface->setAtEndRange(Importer.Import(D->getAtEndRange()));
   } else {
     Importer.Imported(D, ToIface);
 
-    // Check for consistency of superclasses.
-    DeclarationName FromSuperName, ToSuperName;
-    
-    // If the superclass hasn't been imported yet, do so before checking.
-    ObjCInterfaceDecl *DSuperClass = D->getSuperClass();
-    ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass();
-    
-    if (DSuperClass && !ToIfaceSuperClass) {
-      Decl *ImportedSuperClass = Importer.Import(DSuperClass);
-      ObjCInterfaceDecl *ImportedSuperIface = cast<ObjCInterfaceDecl>(ImportedSuperClass);
-      ToIface->setSuperClass(ImportedSuperIface);
-    }
+    if (D->hasDefinition()) {
+      // Check for consistency of superclasses.
+      DeclarationName FromSuperName, ToSuperName;
+      
+      // If the superclass hasn't been imported yet, do so before checking.
+      ObjCInterfaceDecl *DSuperClass = D->getSuperClass();
+      ObjCInterfaceDecl *ToIfaceSuperClass = ToIface->getSuperClass();
+      
+      if (DSuperClass && !ToIfaceSuperClass) {
+        Decl *ImportedSuperClass = Importer.Import(DSuperClass);
+        ObjCInterfaceDecl *ImportedSuperIface
+          = cast<ObjCInterfaceDecl>(ImportedSuperClass);
+        
+        ToIface->setSuperClass(ImportedSuperIface);
+      }
 
-    if (D->getSuperClass())
-      FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
-    if (ToIface->getSuperClass())
-      ToSuperName = ToIface->getSuperClass()->getDeclName();
-    if (FromSuperName != ToSuperName) {
-      Importer.ToDiag(ToIface->getLocation(), 
-                      diag::err_odr_objc_superclass_inconsistent)
-        << ToIface->getDeclName();
-      if (ToIface->getSuperClass())
-        Importer.ToDiag(ToIface->getSuperClassLoc(), 
-                        diag::note_odr_objc_superclass)
-          << ToIface->getSuperClass()->getDeclName();
-      else
-        Importer.ToDiag(ToIface->getLocation(), 
-                        diag::note_odr_objc_missing_superclass);
       if (D->getSuperClass())
-        Importer.FromDiag(D->getSuperClassLoc(), 
+        FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
+      if (ToIface->getSuperClass())
+        ToSuperName = ToIface->getSuperClass()->getDeclName();
+      if (FromSuperName != ToSuperName) {
+        Importer.ToDiag(ToIface->getLocation(), 
+                        diag::err_odr_objc_superclass_inconsistent)
+          << ToIface->getDeclName();
+        if (ToIface->getSuperClass())
+          Importer.ToDiag(ToIface->getSuperClassLoc(), 
                           diag::note_odr_objc_superclass)
-          << D->getSuperClass()->getDeclName();
-      else
-        Importer.FromDiag(D->getLocation(), 
+            << ToIface->getSuperClass()->getDeclName();
+        else
+          Importer.ToDiag(ToIface->getLocation(), 
                           diag::note_odr_objc_missing_superclass);
-      return 0;
+        if (D->getSuperClass())
+          Importer.FromDiag(D->getSuperClassLoc(), 
+                            diag::note_odr_objc_superclass)
+            << D->getSuperClass()->getDeclName();
+        else
+          Importer.FromDiag(D->getLocation(), 
+                            diag::note_odr_objc_missing_superclass);
+        return 0;
+      }
     }
   }
   
+  if (!D->hasDefinition())
+    return ToIface;
+  
   // Import categories. When the categories themselves are imported, they'll
   // hook themselves into this interface.
   for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat;
@@ -3279,7 +3289,7 @@
   ImportDeclContext(D);
   
   // If we have an @implementation, import it as well.
-  if (D->getImplementation()) {
+  if ( D->getImplementation()) {
     ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
                                        Importer.Import(D->getImplementation()));
     if (!Impl)