v.g.vassilev updated this revision to Diff 98445.
v.g.vassilev marked 2 inline comments as done.
v.g.vassilev added a comment.

Reduce the amount of calls to AddLazySpecializations. Remove assert.

In order to create a reasonable test I need to use 
`-error-on-deserialized-decl` and I hit a bug: 
https://bugs.llvm.org/show_bug.cgi?id=32988

Richard, could you help me out with the test? Maybe we could trigger this 
avoiding the abovementioned bug...


https://reviews.llvm.org/D29951

Files:
  include/clang/Serialization/ASTReader.h
  lib/Serialization/ASTReaderDecl.cpp
  test/Modules/Inputs/lazy-template-specializations/A.h
  test/Modules/Inputs/lazy-template-specializations/B.h
  test/Modules/Inputs/lazy-template-specializations/module.modulemap
  test/Modules/lazy-template-specializations.cpp

Index: test/Modules/lazy-template-specializations.cpp
===================================================================
--- /dev/null
+++ test/Modules/lazy-template-specializations.cpp
@@ -0,0 +1,10 @@
+// RUN: rm -fr %t
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t \
+// RUN:             -I %S/Inputs/lazy-template-specializations -std=c++11      \
+// RUN:             -error-on-deserialized-decl S -Rmodule-build %s
+
+
+#include "A.h"
+
+namespace N {
+}
Index: test/Modules/Inputs/lazy-template-specializations/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/lazy-template-specializations/module.modulemap
@@ -0,0 +1,9 @@
+module A {
+  header "A.h"
+  export *
+}
+
+module B {
+  header "B.h"
+  export *
+}
Index: test/Modules/Inputs/lazy-template-specializations/B.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/lazy-template-specializations/B.h
@@ -0,0 +1,4 @@
+namespace N {
+  template <typename T> struct S { int a; };
+  template <> struct S<int> { double b; };
+}
Index: test/Modules/Inputs/lazy-template-specializations/A.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/lazy-template-specializations/A.h
@@ -0,0 +1,3 @@
+#include "B.h"
+int i;
+
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -1951,35 +1951,15 @@
   return Redecl;
 }
 
-static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old,
-                             SmallVectorImpl<DeclID> &IDs) {
-  assert(!IDs.empty() && "no IDs to add to list");
-  if (Old) {
-    IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
-    std::sort(IDs.begin(), IDs.end());
-    IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
-  }
-
-  auto *Result = new (Context) DeclID[1 + IDs.size()];
-  *Result = IDs.size();
-  std::copy(IDs.begin(), IDs.end(), Result + 1);
-  return Result;
-}
-
 void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
   RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
 
   if (ThisDeclID == Redecl.getFirstID()) {
     // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
     // the specializations.
     SmallVector<serialization::DeclID, 32> SpecIDs;
     ReadDeclIDList(SpecIDs);
-
-    if (!SpecIDs.empty()) {
-      auto *CommonPtr = D->getCommonPtr();
-      CommonPtr->LazySpecializations = newDeclIDList(
-          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
-    }
+    Reader.AddLazySpecializations(D, SpecIDs);
   }
 
   if (D->getTemplatedDecl()->TemplateOrInstantiation) {
@@ -2006,12 +1986,7 @@
     // the specializations.
     SmallVector<serialization::DeclID, 32> SpecIDs;
     ReadDeclIDList(SpecIDs);
-
-    if (!SpecIDs.empty()) {
-      auto *CommonPtr = D->getCommonPtr();
-      CommonPtr->LazySpecializations = newDeclIDList(
-          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
-    }
+    Reader.AddLazySpecializations(D, SpecIDs);
   }
 }
 
@@ -2117,12 +2092,7 @@
     // This FunctionTemplateDecl owns a CommonPtr; read it.
     SmallVector<serialization::DeclID, 32> SpecIDs;
     ReadDeclIDList(SpecIDs);
-
-    if (!SpecIDs.empty()) {
-      auto *CommonPtr = D->getCommonPtr();
-      CommonPtr->LazySpecializations = newDeclIDList(
-          Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs);
-    }
+    Reader.AddLazySpecializations(D, SpecIDs);
   }
 }
 
@@ -3697,6 +3667,17 @@
       }
     }
   }
+  // Add the lazy specializations to the template.
+  assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) ||
+          isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) &&
+         "Must not have pending specializations");
+  if (auto *CTD = dyn_cast<ClassTemplateDecl>(D))
+    AddLazySpecializations(CTD, PendingLazySpecializationIDs);
+  else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
+    AddLazySpecializations(FTD, PendingLazySpecializationIDs);
+  else if (auto *VTD = dyn_cast<VarTemplateDecl>(D))
+    AddLazySpecializations(VTD, PendingLazySpecializationIDs);
+  PendingLazySpecializationIDs.clear();
 
   // Load the pending visible updates for this decl context, if it has any.
   auto I = PendingVisibleUpdates.find(ID);
@@ -3909,8 +3890,8 @@
     }
 
     case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
-      // It will be added to the template's specializations set when loaded.
-      (void)Record.readDecl();
+      // It will be added to the template's lazy specialization set.
+      Reader.PendingLazySpecializationIDs.push_back(ReadDeclID());
       break;
 
     case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -16,6 +16,7 @@
 
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/FileSystemOptions.h"
@@ -547,6 +548,9 @@
   llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
       PendingVisibleUpdates;
 
+  llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs;
+
+
   /// \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;
@@ -1280,6 +1284,37 @@
   RecordLocation DeclCursorForID(serialization::DeclID ID,
                                  SourceLocation &Location);
   void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
+  template <typename T>
+  void AddLazySpecializations(T *D,
+                              SmallVectorImpl<serialization::DeclID>& IDs) {
+    if (IDs.empty())
+      return;
+
+    // FIXME: A hack to access the protected getCommonPtr. This is because
+    // AddLazySpecializations should be called in the ASTReader which is not a
+    // friend of Class,Function,VarTemplateDecl.
+    struct CommonPtrAccessor : public T {
+      static uint32_t *&getLazySpecializations(T *D) {
+        return ((CommonPtrAccessor*)D)->getCommonPtr()->LazySpecializations;
+      }
+    };
+    ASTContext &C = getContext();
+
+    auto *&LazySpecializations = CommonPtrAccessor::getLazySpecializations(D);
+
+    if (auto &Old = LazySpecializations) {
+      IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
+      std::sort(IDs.begin(), IDs.end());
+      IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
+    }
+
+    auto *Result = new (C) serialization::DeclID[1 + IDs.size()];
+    *Result = IDs.size();
+    std::copy(IDs.begin(), IDs.end(), Result + 1);
+
+    LazySpecializations = Result;
+  }
+
   void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
   void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,
                           unsigned PreviousGeneration = 0);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to