Fix chaining of ObjCInterfaceDecl redeclarations
authorDouglas Gregor <dgregor@apple.com>
Fri, 16 Dec 2011 03:12:41 +0000 (03:12 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 16 Dec 2011 03:12:41 +0000 (03:12 +0000)
llvm-svn: 146722

clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/DeclObjC.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/DeclObjC.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaDeclObjC.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/test/Modules/Inputs/decl2.h [new file with mode: 0644]
clang/test/Modules/Inputs/module.map
clang/test/SemaObjC/forward-class-1.m

index 9f20782..c272580 100644 (file)
@@ -853,7 +853,8 @@ public:
   QualType getPackExpansionType(QualType Pattern,
                                 llvm::Optional<unsigned> NumExpansions);
 
-  QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const;
+  QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+                                ObjCInterfaceDecl *PrevDecl = 0) const;
 
   QualType getObjCObjectType(QualType Base,
                              ObjCProtocolDecl * const *Protocols,
index d333522..c13e1ba 100644 (file)
@@ -614,9 +614,12 @@ public:
   static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
                                    SourceLocation atLoc,
                                    IdentifierInfo *Id,
+                                   ObjCInterfaceDecl *PrevDecl,
                                    SourceLocation ClassLoc = SourceLocation(),
                                    bool isInternal = false);
 
+  static ObjCInterfaceDecl *CreateEmpty(ASTContext &C);
+
   virtual SourceRange getSourceRange() const {
     if (isThisDeclarationADefinition())
       return ObjCContainerDecl::getSourceRange();
@@ -916,8 +919,6 @@ public:
     return getFirstDeclaration();
   }
 
-  void setPreviousDeclaration(ObjCInterfaceDecl *PrevDecl);
-
   // Low-level accessor
   const Type *getTypeForDecl() const { return TypeForDecl; }
   void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }
index f65888f..de0250c 100644 (file)
@@ -2808,11 +2808,17 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const {
 
 /// 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) const {
+QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+                                          ObjCInterfaceDecl *PrevDecl) const {
   if (Decl->TypeForDecl)
     return QualType(Decl->TypeForDecl, 0);
 
-  // FIXME: redeclarations?
+  if (PrevDecl) {
+    assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl");
+    Decl->TypeForDecl = PrevDecl->TypeForDecl;
+    return QualType(PrevDecl->TypeForDecl, 0);
+  }
+
   void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
   ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
   Decl->TypeForDecl = T;
index ac3b536..963643e 100644 (file)
@@ -3182,7 +3182,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
     if (!ToIface) {
       ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
                                           Importer.Import(D->getAtStartLoc()),
-                                          Name.getAsIdentifierInfo(), Loc,
+                                          Name.getAsIdentifierInfo(), 
+                                          /*PrevDecl=*/0,Loc,
                                           D->isImplicitInterfaceDecl());
       ToIface->setLexicalDeclContext(LexicalDC);
       LexicalDC->addDeclInternal(ToIface);
index d420b2b..317dc95 100644 (file)
@@ -225,18 +225,19 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
 void ObjCInterfaceDecl::allocateDefinitionData() {
   assert(!hasDefinition() && "ObjC class already has a definition");
   Data = new (getASTContext()) DefinitionData();
-  Data->Definition = this;
-  
+  Data->Definition = this;  
+}
+
+void ObjCInterfaceDecl::startDefinition() {
+  allocateDefinitionData();
+
   // Update all of the declarations with a pointer to the definition.
   for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
        RD != RDEnd; ++RD) {
     if (*RD != this)
       RD->Data = Data;
   }
-}
 
-void ObjCInterfaceDecl::startDefinition() {
-  allocateDefinitionData();
   if (ASTMutationListener *L = getASTContext().getASTMutationListener())
     L->CompletedObjCForwardRef(this);
 }
@@ -674,9 +675,24 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
                                              DeclContext *DC,
                                              SourceLocation atLoc,
                                              IdentifierInfo *Id,
+                                             ObjCInterfaceDecl *PrevDecl,
                                              SourceLocation ClassLoc,
                                              bool isInternal){
-  return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, isInternal);
+  ObjCInterfaceDecl *Result = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, 
+                                                        isInternal);
+  C.getObjCInterfaceType(Result, PrevDecl);
+  
+  if (PrevDecl) {
+    Result->Data = PrevDecl->Data;
+    Result->setPreviousDeclaration(PrevDecl);
+  }
+
+  return Result;
+}
+
+ObjCInterfaceDecl *ObjCInterfaceDecl::CreateEmpty(ASTContext &C) {
+  return new (C) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(),
+                                   false);
 }
 
 ObjCInterfaceDecl::
@@ -851,14 +867,6 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
   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
 //===----------------------------------------------------------------------===//
index 2b7be7e..c95cf22 100644 (file)
@@ -82,6 +82,7 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
       ObjCInterfaceDecl *ProtocolDecl =
         ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
                                   &Context.Idents.get("Protocol"),
+                                  /*PrevDecl=*/0,
                                   SourceLocation(), true);
       Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
       PushOnScopeChains(ProtocolDecl, TUScope, false);
index 02a83e5..4f87db4 100644 (file)
@@ -366,11 +366,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
   }
 
   // Create a declaration to describe this @interface.
+  ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
   ObjCInterfaceDecl *IDecl
     = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName,
-                                ClassLoc);
+                                PrevIDecl, ClassLoc);
   
-  ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
   if (PrevIDecl) {
     // Class already seen. Was it a definition?
     if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
@@ -379,9 +379,6 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
       Diag(Def->getLocation(), diag::note_previous_definition);
       IDecl->setInvalidDecl();
     }
-
-    // Link to the previous declaration.
-    IDecl->setPreviousDeclaration(PrevIDecl);
   }
   
   if (AttrList)
@@ -870,9 +867,8 @@ Decl *Sema::ActOnStartClassImplementation(
     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 (RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
-                            diag::warn_undef_interface))
-      IDecl = 0;
+    RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
+                        diag::warn_undef_interface);
   } else {
     // We did not find anything with the name ClassName; try to correct for 
     // typos in the class name.
@@ -928,7 +924,8 @@ Decl *Sema::ActOnStartClassImplementation(
     // FIXME: Do we support attributes on the @implementation? If so we should
     // copy them over.
     IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc,
-                                      ClassName, ClassLoc, true);
+                                      ClassName, /*PrevDecl=*/0, ClassLoc, 
+                                      true);
     IDecl->startDefinition();
     if (SDecl) {
       IDecl->setSuperClass(SDecl);
@@ -1774,16 +1771,13 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
     }
     
     // Create a declaration to describe this forward declaration.
+    ObjCInterfaceDecl *PrevIDecl
+      = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
     ObjCInterfaceDecl *IDecl
       = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc,
-                                  IdentList[i], IdentLocs[i], true);
+                                  IdentList[i], PrevIDecl, IdentLocs[i], true);
     IDecl->setAtEndRange(IdentLocs[i]);
     
-    // If there was a previous declaration, link to it.
-    if (ObjCInterfaceDecl *PrevIDecl
-        = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))
-      IDecl->setPreviousDeclaration(PrevIDecl);
-
     // Create the forward declaration. Note that we intentionally do this 
     // before we add the ObjCInterfaceDecl we just created, so that the
     // rewriter sees the ObjCClassDecl first.
index cacacd2..5e5f1cb 100644 (file)
@@ -223,6 +223,9 @@ void ASTDeclReader::Visit(Decl *D) {
   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).getTypePtrOrNull());
+  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+    // if we have a fully initialized TypeDecl, we can safely read its type now.
+    ID->TypeForDecl = Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull();
   } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     // FunctionDecl's body was written last after all other Stmts/Exprs.
     if (Record[Idx++])
@@ -556,7 +559,7 @@ void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
 void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
   VisitRedeclarable(ID);
   VisitObjCContainerDecl(ID);
-  ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull());
+  TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
   
   ObjCInterfaceDecl *Def = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
   if (ID == Def) {
@@ -621,13 +624,13 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
       // pending references were linked.
       Reader.PendingForwardRefs.erase(ID);
 #endif
-    } else if (Def) {
-      if (Def->Data) {
-        ID->Data = Def->Data;
-      } else {
-        // The definition is still initializing.
-        Reader.PendingForwardRefs[Def].push_back(ID);
-      }
+    }
+  } else if (Def) {
+    if (Def->Data) {
+      ID->Data = Def->Data;
+    } else {
+      // The definition is still initializing.
+      Reader.PendingForwardRefs[Def].push_back(ID);
     }
   }
 }
@@ -1561,6 +1564,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
     FD->RedeclLink.setPointer(cast<FunctionDecl>(previous));
   } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
     VD->RedeclLink.setPointer(cast<VarDecl>(previous));
+  } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(previous)) {
+    ID->RedeclLink.setPointer(cast<ObjCInterfaceDecl>(previous));
   } else {
     RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
     TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous);
@@ -1736,7 +1741,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
                                Selector(), QualType(), 0, 0);
     break;
   case DECL_OBJC_INTERFACE:
-    D = ObjCInterfaceDecl::Create(Context, 0, SourceLocation(), 0);
+    D = ObjCInterfaceDecl::CreateEmpty(Context);
     break;
   case DECL_OBJC_IVAR:
     D = ObjCIvarDecl::Create(Context, 0, SourceLocation(), SourceLocation(),
diff --git a/clang/test/Modules/Inputs/decl2.h b/clang/test/Modules/Inputs/decl2.h
new file mode 100644 (file)
index 0000000..decf6e0
--- /dev/null
@@ -0,0 +1 @@
+@class A;
index 6b93a6a..f7cc7d4 100644 (file)
@@ -39,5 +39,6 @@ module load_failure { header "load_failure.h" }
 
 module decldef {
   explicit module Decl { header "decl.h" }
+  explicit module Decl2 { header "decl2.h" }
   explicit module Def { header "def.h" }
 }
\ No newline at end of file
index f5ce889..e8c3695 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-@class FOO, BAR; 
 @class FOO, BAR; // expected-note {{forward declaration of class here}}
+@class FOO, BAR; 
 
 @interface INTF : FOO  // expected-error {{attempting to use the forward class 'FOO' as superclass of 'INTF'}}
 @end