]> granicus.if.org Git - clang/commitdiff
Once we have fully deserialized a redeclaration chain for something
authorDouglas Gregor <dgregor@apple.com>
Mon, 19 Dec 2011 19:00:47 +0000 (19:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 19 Dec 2011 19:00:47 +0000 (19:00 +0000)
with a definition pointer (e.g., C++ and Objective-C classes), zip
through the redeclaration chain to make sure that all of the
declarations point to the definition data.

As part of this, realized again why the first redeclaration of an
entity in a file is important, and brought back that idea.

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

include/clang/AST/DeclObjC.h
include/clang/Serialization/ASTReader.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/Modules/redecl-merge.m

index 7a5a715eab6d6ffdf6b9e30ea77509ac1b152fcc..6a0b6acc87dd55015e1552fc0a12dd0dd96ef2fe 100644 (file)
@@ -928,6 +928,7 @@ public:
   static bool classof(const ObjCInterfaceDecl *D) { return true; }
   static bool classofKind(Kind K) { return K == ObjCInterface; }
 
+  friend class ASTReader;
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
 };
index 10ed5dceea5fe82a7a5b2d926e1f3ca36e28fbbf..507b75f33cee31a5b34d765a93d63111766c7d9a 100644 (file)
@@ -338,7 +338,10 @@ private:
   /// the DefinitionData pointer of all pending references.
   PendingForwardRefsMap PendingForwardRefs;
 
-
+  /// \brief The set of C++ or Objective-C classes that have forward 
+  /// declarations that have not yet been linked to their definitions.
+  llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
+  
   typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
       FirstLatestDeclIDMap;
   /// \brief Map of first declarations from a chained PCH that point to the
index fc49e88a50adb97741f02c6b6066d1ebf9fae2bd..2b417522bccb07dfa5e26aa0815a6d9d75362efa 100644 (file)
@@ -6095,6 +6095,29 @@ void ASTReader::finishPendingActions() {
     }
     PendingChainedObjCCategories.clear();
   }
+  
+  // If we deserialized any C++ or Objective-C class definitions, make sure
+  // that all redeclarations point to the definitions. Note that this can only 
+  // happen now, after the redeclaration chains have been fully wired.
+  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;
+      
+      continue;
+    }
+    
+    ObjCInterfaceDecl *ID = cast<ObjCInterfaceDecl>(*D);
+    for (ObjCInterfaceDecl::redecl_iterator R = ID->redecls_begin(),
+                                         REnd = ID->redecls_end();
+         R != REnd; ++R)
+      R->Data = ID->Data;
+  }
+  PendingDefinitions.clear();
 }
 
 void ASTReader::FinishedDeserializing() {
index 35cd8478d5be2725249a66e954675cd6b4f34667..bd6a5a5e06d3965c38f83d0b9dfe874ec6f4c7a9 100644 (file)
@@ -630,6 +630,9 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
       // pending references were linked.
       Reader.PendingForwardRefs.erase(ID);
 #endif
+      
+      // Note that we have deserialized a definition.
+      Reader.PendingDefinitions.insert(ID);
     }
   } else if (Def) {
     if (Def->Data) {
@@ -1030,6 +1033,9 @@ void ASTDeclReader::InitializeCXXDefinitionData(CXXRecordDecl *D,
       Reader.PendingForwardRefs.erase(D);
 #endif
     }
+    
+    // Note that we have deserialized a definition.
+    Reader.PendingDefinitions.insert(D);
   } else if (DefinitionDecl) {
     if (DefinitionDecl->DefinitionData) {
       D->DefinitionData = DefinitionDecl->DefinitionData;
@@ -1162,7 +1168,7 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
 void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
   // Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
   // can be used while this is still initializing.
-  enum RedeclKind { FirstDeclaration, PointsToPrevious };
+  enum RedeclKind { FirstDeclaration, FirstInFile, PointsToPrevious };
   RedeclKind Kind = (RedeclKind)Record[Idx++];
   
   // Determine the first declaration ID.
@@ -1190,7 +1196,8 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
     }
     break;
   }
-      
+   
+  case FirstInFile:
   case PointsToPrevious: {
     FirstDeclID = ReadDeclID(Record, Idx);
     DeclID PrevDeclID = ReadDeclID(Record, Idx);
@@ -1204,9 +1211,13 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
     // loaded and attached later on.
     D->CommonOrPrev = FirstDecl;
     
-    // Make a note that we need to wire up this declaration to its
-    // previous declaration, later.
-    Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
+    if (Kind == PointsToPrevious) {
+      // Make a note that we need to wire up this declaration to its
+      // previous declaration, later. We don't need to do this for the first
+      // declaration in any given module file, because those will be wired 
+      // together later.
+      Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
+    }
     break;
   }
   }
@@ -1412,7 +1423,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) {
 
 template <typename T>
 void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
-  enum RedeclKind { FirstDeclaration = 0, PointsToPrevious };
+  enum RedeclKind { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
   RedeclKind Kind = (RedeclKind)Record[Idx++];
   
   DeclID FirstDeclID;
@@ -1420,7 +1431,8 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
   case FirstDeclaration:
     FirstDeclID = ThisDeclID;
     break;
-      
+    
+  case FirstInFile:
   case PointsToPrevious: {
     FirstDeclID = ReadDeclID(Record, Idx);
     DeclID PrevDeclID = ReadDeclID(Record, Idx);
@@ -1433,10 +1445,14 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
     // loaded & attached later on.
     D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(FirstDecl);
     
-    // Make a note that we need to wire up this declaration to its
-    // previous declaration, later.
-    Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
-                                                         PrevDeclID));
+    if (Kind == PointsToPrevious) {
+      // Make a note that we need to wire up this declaration to its
+      // previous declaration, later. We don't need to do this for the first
+      // declaration in any given module file, because those will be wired 
+      // together later.
+      Reader.PendingPreviousDecls.push_back(std::make_pair(static_cast<T*>(D),
+                                                           PrevDeclID));
+    }
     break;
   }
   }
index cb1c6f0476ea9f6a1697ba25ba2532f02ede25e3..7ae601810b92c729b43d3d51cd5c5e1ae1f2a1ce 100644 (file)
@@ -1051,7 +1051,7 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
 void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
   // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
   // getCommonPtr() can be used while this is still initializing.
-  enum { FirstDeclaration, PointsToPrevious };
+  enum { FirstDeclaration, FirstInFile, PointsToPrevious };
   RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
   RedeclarableTemplateDecl *First = 0;
   if (!Prev) {
@@ -1063,7 +1063,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
       Record.push_back(D->isMemberSpecialization());
   } else {
     First = D->getFirstDeclaration();
-    Record.push_back(PointsToPrevious);
+    Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
     Writer.AddDeclRef(First, Record);
     Writer.AddDeclRef(Prev, Record);    
   }
@@ -1276,14 +1276,14 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
 
 template <typename T>
 void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
-  enum { FirstDeclaration = 0, PointsToPrevious };
+  enum { FirstDeclaration = 0, FirstInFile, PointsToPrevious };
   T *Prev = D->getPreviousDeclaration();
   T *First = D->getFirstDeclaration();
   
   if (!Prev) {
     Record.push_back(FirstDeclaration);
   } else {  
-    Record.push_back(PointsToPrevious);
+    Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
     Writer.AddDeclRef(First, Record);
     Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   }
index c5da754dfe0f153a2a03b0d402075907cbdcfc93..6497268c3840acda1112d89a46337297a5255d17 100644 (file)
@@ -32,7 +32,7 @@ void g(A *a) {
 
 #ifdef __cplusplus
 void testVector() {
-  Vector<int> *vec_int;
-  // FIXME:  vec_int.push_back(0);
+  Vector<int> vec_int;
+  vec_int.push_back(0);
 }
 #endif