[cfe-commits] r146667 - in /cfe/trunk: include/clang/AST/DeclObjC.h lib/AST/DeclBase.cpp lib/AST/DeclObjC.cpp lib/Serialization/ASTCommon.h lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp lib/Serialization/ASTWriterDecl.cpp

Douglas Gregor dgregor at apple.com
Thu Dec 15 10:03:10 PST 2011


Author: dgregor
Date: Thu Dec 15 12:03:09 2011
New Revision: 146667

URL: http://llvm.org/viewvc/llvm-project?rev=146667&view=rev
Log:
Introduce the core infrastructure needed to model a complete
redeclaration chain for Objective-C classes, including:
  - Using the first declaration as the canonical declaration.
  - Using the definition as the primary DeclContext
  - Making sure that all declarations have a pointer to the definition
  data, and the definition knows that it is the definition.
  - Serialization support for when a definition gets added to a
  declaration that comes from an AST file.

However, note that we're not taking advantage of much of this code
yet, because we're still re-using ObjCInterfaceDecls.


Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Serialization/ASTCommon.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=146667&r1=146666&r2=146667&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Dec 15 12:03:09 2011
@@ -540,7 +540,8 @@
 ///   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> {
   /// TypeForDecl - This indicates the Type object that represents this
   /// TypeDecl.  It is a cache maintained by ASTContext::getObjCInterfaceType
   mutable const Type *TypeForDecl;
@@ -584,7 +585,10 @@
 
   /// \brief Contains a pointer to the data associated with this class,
   /// which will be NULL if this class has not yet been defined.
-  DefinitionData *Definition;
+  ///
+  /// The boolean value indicates whether this particular declaration is 
+  /// also the definition.
+  llvm::PointerIntPair<DefinitionData *, 1, bool> Definition;
 
   /// \brief The location of the last location in this declaration, e.g.,
   /// the '>', '}', or identifier.
@@ -598,13 +602,18 @@
   bool InitiallyForwardDecl : 1;
 
   DefinitionData &data() const {
-    assert(Definition != 0 && "Declaration is not a definition!");
-    return *Definition;
+    assert(Definition.getPointer() != 0 && "Declaration is not a definition!");
+    return *Definition.getPointer();
   }
 
   /// \brief Allocate the definition data for this class.
   void allocateDefinitionData();
   
+  typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
+  virtual ObjCInterfaceDecl *getNextRedeclaration() { 
+    return RedeclLink.getNext(); 
+  }
+
 public:
   static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
                                    SourceLocation atLoc,
@@ -771,11 +780,15 @@
 
   /// \brief Determine whether this declaration is a forward declaration of
   /// the class.
-  bool isForwardDecl() const { return Definition == 0; }
+  bool isForwardDecl() const { return !Definition.getInt(); }
 
+  /// \brief Determine whether this particular declaration of this class is
+  /// actually also a definition.
+  bool isThisDeclarationADefinition() const { return Definition.getInt(); }
+                          
   /// \brief Determine whether this class has been defined.
-  bool hasDefinition() const { return Definition != 0; }
-  
+  bool hasDefinition() const { return Definition.getPointer() != 0; }
+                        
   /// \brief Retrieve the definition of this class, or NULL if this class 
   /// has been forward-declared (with @class) but not yet defined (with 
   /// @interface).
@@ -896,6 +909,22 @@
                                bool lookupCategory,
                                bool RHSIsQualifiedID = false);
 
+  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();
+  }
+
+  /// Retrieves the canonical declaration of this Objective-C class.
+  ObjCInterfaceDecl *getCanonicalDecl() {
+    return getFirstDeclaration();
+  }
+  const ObjCInterfaceDecl *getCanonicalDecl() const {
+    return getFirstDeclaration();
+  }
+
   // Low-level accessor
   const Type *getTypeForDecl() const { return TypeForDecl; }
   void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; }

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=146667&r1=146666&r2=146667&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Dec 15 12:03:09 2011
@@ -779,9 +779,16 @@
     return this;
 
   case Decl::ObjCInterface:
+    if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(this)->getDefinition())
+      return Def;
+      
+    return this;
+      
   case Decl::ObjCProtocol:
+    // FIXME: Update when protocols properly model forward declarations.
+    // For now, it's fine to fall through
+      
   case Decl::ObjCCategory:
-    // FIXME: Can Objective-C interfaces be forward-declared?
     return this;
 
   case Decl::ObjCImplementation:

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=146667&r1=146666&r2=146667&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Thu Dec 15 12:03:09 2011
@@ -224,7 +224,15 @@
 
 void ObjCInterfaceDecl::allocateDefinitionData() {
   assert(!hasDefinition() && "ObjC class already has a definition");
-  Definition = new (getASTContext()) DefinitionData();  
+  Definition.setPointer(new (getASTContext()) DefinitionData());
+  Definition.setInt(true);
+  
+  // 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->Definition.setPointer(Definition.getPointer());
+  }
 }
 
 void ObjCInterfaceDecl::startDefinition() {

Modified: cfe/trunk/lib/Serialization/ASTCommon.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.h?rev=146667&r1=146666&r2=146667&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.h (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.h Thu Dec 15 12:03:09 2011
@@ -26,7 +26,8 @@
   UPD_CXX_ADDED_IMPLICIT_MEMBER,
   UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
   UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
-  UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER
+  UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+  UPD_OBJC_SET_CLASS_DEFINITIONDATA
 };
 
 TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=146667&r1=146666&r2=146667&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Dec 15 12:03:09 2011
@@ -554,6 +554,7 @@
 }
 
 void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
+  VisitRedeclarable(ID);
   VisitObjCContainerDecl(ID);
   ID->setTypeForDecl(Reader.readType(F, Record, Idx).getTypePtrOrNull());
   
@@ -618,10 +619,9 @@
       // pending references were linked.
       Reader.PendingForwardRefs.erase(ID);
 #endif
-    
     } else if (Def) {
-      if (Def->Definition) {
-        ID->Definition = Def->Definition;
+      if (Def->Definition.getPointer()) {
+        ID->Definition.setPointer(Def->Definition.getPointer());
       } else {
         // The definition is still initializing.
         Reader.PendingForwardRefs[Def].push_back(ID);
@@ -2067,6 +2067,19 @@
       cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation(
           Reader.ReadSourceLocation(ModuleFile, Record, Idx));
       break;
+    
+    case UPD_OBJC_SET_CLASS_DEFINITIONDATA: {
+      ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(D);
+      ObjCInterfaceDecl *Def
+        = Reader.ReadDeclAs<ObjCInterfaceDecl>(ModuleFile, Record, Idx);
+      if (Def->Definition.getPointer()) {
+        ID->Definition.setPointer(Def->Definition.getPointer());
+      } else {
+        // The definition is still initializing.
+        Reader.PendingForwardRefs[Def].push_back(ID);
+      }
+      break;
+    }
     }
   }
 }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=146667&r1=146666&r2=146667&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Dec 15 12:03:09 2011
@@ -3439,6 +3439,7 @@
       case UPD_CXX_ADDED_IMPLICIT_MEMBER:
       case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
       case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:
+      case UPD_OBJC_SET_CLASS_DEFINITIONDATA:
         URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
         ++Idx;
         break;
@@ -4379,10 +4380,26 @@
 
 void ASTWriter::CompletedObjCForwardRef(const ObjCContainerDecl *D) {
   assert(!WritingAST && "Already writing the AST!");
-  if (!D->isFromASTFile())
-    return; // Declaration not imported from PCH.
+  if (D->isFromASTFile())
+    RewriteDecl(D);
 
-  RewriteDecl(D);
+  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+    for (ObjCInterfaceDecl::redecl_iterator I = ID->redecls_begin(), 
+                                            E = ID->redecls_end(); 
+         I != E; ++I) {
+      if (*I == ID)
+        continue;
+      
+      // We are interested when a PCH decl is modified.
+      if (I->isFromASTFile()) {
+        UpdateRecord &Record = DeclUpdates[*I];
+        Record.push_back(UPD_OBJC_SET_CLASS_DEFINITIONDATA);
+        assert((*I)->hasDefinition());
+        assert((*I)->getDefinition() == D);
+        Record.push_back(reinterpret_cast<uint64_t>(D)); // the DefinitionDecl
+      }
+    }
+  }
 }
 
 void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=146667&r1=146666&r2=146667&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Dec 15 12:03:09 2011
@@ -447,6 +447,7 @@
 }
 
 void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+  VisitRedeclarable(D);
   VisitObjCContainerDecl(D);
   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
 





More information about the cfe-commits mailing list