]> granicus.if.org Git - clang/commitdiff
Rework the way in which we (de-)serialize the declarations
authorDouglas Gregor <dgregor@apple.com>
Tue, 17 Jan 2012 19:21:53 +0000 (19:21 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 17 Jan 2012 19:21:53 +0000 (19:21 +0000)
corresponding to TagType and ObjCInterfaceType. Previously, we would
serialize the definition (if available) or the canonical declaration
(if no definition was available). However, this can end up forcing the
deserialization of the definition even through we might not want to
yet.

Instead, always serialize the canonical declaration reference in the
TagType/ObjCInterfaceType entry, and as part of loading a pending
definition, update the "decl" pointer within the type node to point at
the definition. This is more robust in hard-to-isolate cases
where the *Type gets built and filled in before we see the definition.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148323 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/AST/Type.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp

index 4016c2085f3b7ceb21822d97b56c55f8531cdbb8..01177fa2773eea8d957e40f4686b5b366cceed77 100644 (file)
@@ -2225,6 +2225,7 @@ class TypeDecl : public NamedDecl {
   friend class TagDecl;
   friend class TemplateTypeParmDecl;
   friend class TagType;
+  friend class ASTReader;
 
 protected:
   TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
index 436c02cd9199e5cedbc739937ddc8d3e6c8cbfaf..ed2e83763febe8f265b58aeccebdb8200cc5b7e1 100644 (file)
@@ -3070,6 +3070,8 @@ class TagType : public Type {
   /// TagDecl that declares the entity.
   TagDecl * decl;
 
+  friend class ASTReader;
+  
 protected:
   TagType(TypeClass TC, const TagDecl *D, QualType can);
 
@@ -4160,6 +4162,7 @@ class ObjCInterfaceType : public ObjCObjectType {
     : ObjCObjectType(Nonce_ObjCInterface),
       Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
   friend class ASTContext;  // ASTContext creates these.
+  friend class ASTReader;
   friend class ObjCInterfaceDecl;
 
 public:
index 57cd0212b3c98e0b27f9d316b4721b1d912d5a4e..245e8b1b18392712dc6d5a48606b830330df8752 100644 (file)
@@ -3901,8 +3901,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
     }
     unsigned Idx = 0;
     bool IsDependent = Record[Idx++];
-    QualType T
-      = Context.getRecordType(ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx));
+    RecordDecl *RD = ReadDeclAs<RecordDecl>(*Loc.F, Record, Idx);
+    RD = cast_or_null<RecordDecl>(RD->getCanonicalDecl());
+    QualType T = Context.getRecordType(RD);
     const_cast<Type*>(T.getTypePtr())->setDependent(IsDependent);
     return T;
   }
@@ -3966,7 +3967,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
     unsigned Idx = 0;
     ObjCInterfaceDecl *ItfD
       = ReadDeclAs<ObjCInterfaceDecl>(*Loc.F, Record, Idx);
-    return Context.getObjCInterfaceType(ItfD);
+    return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
   }
 
   case TYPE_OBJC_OBJECT: {
@@ -6124,6 +6125,7 @@ void ASTReader::finishPendingActions() {
     // Load pending declaration chains.
     for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
       loadPendingDeclChain(PendingDeclChains[I]);
+      PendingDeclChainsKnown.erase(PendingDeclChains[I]);
     }
     PendingDeclChains.clear();
     
@@ -6143,16 +6145,28 @@ void ASTReader::finishPendingActions() {
   for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
                                            DEnd = PendingDefinitions.end();
        D != DEnd; ++D) {
-    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
-      for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
-                                       REnd = RD->redecls_end();
-           R != REnd; ++R)
-        cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+    if (TagDecl *TD = dyn_cast<TagDecl>(*D)) {
+      if (const TagType *TagT = dyn_cast<TagType>(TD->TypeForDecl)) {
+        // Make sure that the TagType points at the definition.
+        const_cast<TagType*>(TagT)->decl = TD;
+      }
       
+      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(*D)) {
+        for (CXXRecordDecl::redecl_iterator R = RD->redecls_begin(),
+                                         REnd = RD->redecls_end();
+             R != REnd; ++R)
+          cast<CXXRecordDecl>(*R)->DefinitionData = RD->DefinitionData;
+        
+      }
+
       continue;
     }
     
     if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(*D)) {
+      // Make sure that the ObjCInterfaceType points at the definition.
+      const_cast<ObjCInterfaceType *>(cast<ObjCInterfaceType>(ID->TypeForDecl))
+        ->Decl = ID;
+      
       for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
                                            REnd = ID->redecls_end();
            R != REnd; ++R)
index 7a09b32ac1032d5fbb45ad70fe615e135b71e8e3..c5f9b2dc88a719ac1f79c9fe62285ec6a37c7b6b 100644 (file)
@@ -239,7 +239,7 @@ void ASTTypeWriter::VisitAutoType(const AutoType *T) {
 
 void ASTTypeWriter::VisitTagType(const TagType *T) {
   Record.push_back(T->isDependentType());
-  Writer.AddDeclRef(T->getDecl(), Record);
+  Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record);
   assert(!T->isBeingDefined() &&
          "Cannot serialize in the middle of a type definition");
 }
@@ -369,7 +369,7 @@ void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
 }
 
 void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
-  Writer.AddDeclRef(T->getDecl(), Record);
+  Writer.AddDeclRef(T->getDecl()->getCanonicalDecl(), Record);
   Code = TYPE_OBJC_INTERFACE;
 }