]> granicus.if.org Git - clang/commitdiff
Lazily deserialize Sema::VTableUses. Plus, fix the utterly and
authorDouglas Gregor <dgregor@apple.com>
Thu, 28 Jul 2011 19:11:31 +0000 (19:11 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 28 Jul 2011 19:11:31 +0000 (19:11 +0000)
completely broken deserialization mapping code we had for VTableUses,
which would have broken horribly as soon as our local-to-global ID
mapping became interesting.

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

include/clang/Sema/ExternalSemaSource.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTReader.h
lib/Sema/SemaDeclCXX.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp

index 41bc4e3536b02fe7b30a4357a5840a3b016aeb79..00494641ba7002e2a853c1c30e735c413a347278 100644 (file)
@@ -29,6 +29,14 @@ class Sema;
 class TypedefNameDecl;
 class VarDecl;
   
+/// \brief A simple structure that captures a vtable use for the purposes of
+/// the \c ExternalSemaSource.
+struct ExternalVTableUse {
+  CXXRecordDecl *Record;
+  SourceLocation Location;
+  bool DefinitionRequired;
+};
+  
 /// \brief An abstract interface that should be implemented by
 /// external AST sources that also provide information for semantic
 /// analysis.
@@ -147,6 +155,13 @@ public:
   virtual void ReadWeakUndeclaredIdentifiers(
                  SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) {}
 
+  /// \brief Read the set of used vtables known to the external Sema source.
+  ///
+  /// The external source should append its own used vtables to the given
+  /// vector. Note that this routine may be invoked multiple times; the external
+  /// source should take care not to introduce the same vtables repeatedly.
+  virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {}
+
   // isa/cast/dyn_cast support
   static bool classof(const ExternalASTSource *Source) {
     return Source->SemaSource;
index adc6e2ba6df5cf7e666e735d2b201ce191d28f4c..81d93115e383cc98e1da6636b0950c23bddc5bb8 100644 (file)
@@ -3365,6 +3365,9 @@ public:
   /// by code generation).
   llvm::DenseMap<CXXRecordDecl *, bool> VTablesUsed;
 
+  /// \brief Load any externally-stored vtable uses.
+  void LoadExternalVTableUses();
+  
   typedef LazyVector<CXXRecordDecl *, ExternalSemaSource, 
                      &ExternalSemaSource::ReadDynamicClasses, 2, 2>
     DynamicClassesType;
index 8bb11cc57543cfd4c3a8e6383bfff3e0f5e7d607..f3bdcc8c2f7c4fe6e46775a39a9d01551bf65fc2 100644 (file)
@@ -1404,6 +1404,8 @@ public:
   virtual void ReadWeakUndeclaredIdentifiers(
                  SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI);
 
+  virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables);
+
   /// \brief Load a selector from disk, registering its ID if it exists.
   void LoadSelector(Selector Sel);
 
index ba00944156403df8879888986247001df0ef6a90..5d81205137988c143ad97cd670fe25e0a5548c63 100644 (file)
@@ -8935,6 +8935,30 @@ DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
   return Dcl;
 }
 
+void Sema::LoadExternalVTableUses() {
+  if (!ExternalSource)
+    return;
+  
+  SmallVector<ExternalVTableUse, 4> VTables;
+  ExternalSource->ReadUsedVTables(VTables);
+  SmallVector<VTableUse, 4> NewUses;
+  for (unsigned I = 0, N = VTables.size(); I != N; ++I) {
+    llvm::DenseMap<CXXRecordDecl *, bool>::iterator Pos
+      = VTablesUsed.find(VTables[I].Record);
+    // Even if a definition wasn't required before, it may be required now.
+    if (Pos != VTablesUsed.end()) {
+      if (!Pos->second && VTables[I].DefinitionRequired)
+        Pos->second = true;
+      continue;
+    }
+    
+    VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired;
+    NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location));
+  }
+  
+  VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end());
+}
+
 void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
                           bool DefinitionRequired) {
   // Ignore any vtable uses in unevaluated operands or for classes that do
@@ -8945,6 +8969,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
     return;
 
   // Try to insert this class into the map.
+  LoadExternalVTableUses();
   Class = cast<CXXRecordDecl>(Class->getCanonicalDecl());
   std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
     Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
@@ -8970,6 +8995,7 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
 }
 
 bool Sema::DefineUsedVTables() {
+  LoadExternalVTableUses();
   if (VTableUses.empty())
     return false;
 
index ff87c2389714b1acd255897e7119a57f2cf9d210..288e50df744afa5446ac1967c9f810b556f8002f 100644 (file)
@@ -2310,11 +2310,22 @@ ASTReader::ReadASTBlock(Module &F) {
       break;
 
     case VTABLE_USES:
+      if (Record.size() % 3 != 0) {
+        Error("Invalid VTABLE_USES record");
+        return Failure;
+      }
+        
       // Later tables overwrite earlier ones.
-      // FIXME: Modules will have some trouble with this.
+      // FIXME: Modules will have some trouble with this. This is clearly not
+      // the right way to do this.
       VTableUses.clear();
-      for (unsigned I = 0, N = Record.size(); I != N; ++I)
-        VTableUses.push_back(getGlobalDeclID(F, Record[I]));
+        
+      for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) {
+        VTableUses.push_back(getGlobalDeclID(F, Record[Idx++]));
+        VTableUses.push_back(
+          ReadSourceLocation(F, Record, Idx).getRawEncoding());
+        VTableUses.push_back(Record[Idx++]);
+      }
       break;
 
     case DYNAMIC_CLASSES:
@@ -4397,19 +4408,6 @@ void ASTReader::InitializeSema(Sema &S) {
     SemaObj->PendingInstantiations.push_back(std::make_pair(D, Loc));
   }
 
-  // If there were any VTable uses, deserialize the information and add it
-  // to Sema's vector and map of VTable uses.
-  if (!VTableUses.empty()) {
-    unsigned Idx = 0;
-    for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) {
-      CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
-      SourceLocation Loc = ReadSourceLocation(F, VTableUses, Idx);
-      bool DefinitionRequired = VTableUses[Idx++];
-      SemaObj->VTableUses.push_back(std::make_pair(Class, Loc));
-      SemaObj->VTablesUsed[Class] = DefinitionRequired;
-    }
-  }
-
   if (!FPPragmaOptions.empty()) {
     assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS");
     SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
@@ -4644,6 +4642,18 @@ void ASTReader::ReadWeakUndeclaredIdentifiers(
   WeakUndeclaredIdentifiers.clear();
 }
 
+void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {
+  for (unsigned Idx = 0, N = VTableUses.size(); Idx < N; /* In loop */) {
+    ExternalVTableUse VT;
+    VT.Record = dyn_cast_or_null<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
+    VT.Location = SourceLocation::getFromRawEncoding(VTableUses[Idx++]);
+    VT.DefinitionRequired = VTableUses[Idx++];
+    VTables.push_back(VT);
+  }
+  
+  VTableUses.clear();
+}
+
 void ASTReader::LoadSelector(Selector Sel) {
   // It would be complicated to avoid reading the methods anyway. So don't.
   ReadMethodPool(Sel);
index fb29f6970fadc02910494c34efa63052e32be3b6..e506bba8a2566cce2f4f94d9b4a4ef22b251df1d 100644 (file)
@@ -2886,7 +2886,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   // Build a record containing all of the VTable uses information.
   RecordData VTableUses;
   if (!SemaRef.VTableUses.empty()) {
-    VTableUses.push_back(SemaRef.VTableUses.size());
     for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
       AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
       AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
@@ -3153,7 +3152,6 @@ void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
   // a use is new to this part.
   RecordData VTableUses;
   if (!SemaRef.VTableUses.empty()) {
-    VTableUses.push_back(SemaRef.VTableUses.size());
     for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
       AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
       AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);