[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-07-10 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/83108

>From 1f7c6650f739092a1b8908de3793aa8bbdc7de34 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev 
Date: Sun, 7 Jan 2018 15:16:11 +0200
Subject: [PATCH 1/2] D41416: [modules] [pch] Do not deserialize all lazy
 template specializations when looking for one.

---
 clang/include/clang/AST/DeclTemplate.h|  36 +++-
 clang/lib/AST/DeclTemplate.cpp| 100 +-
 clang/lib/AST/ODRHash.cpp |  15 
 clang/lib/Serialization/ASTReader.cpp |  25 --
 clang/lib/Serialization/ASTReaderDecl.cpp |  46 ++
 clang/lib/Serialization/ASTWriter.cpp |  21 -
 clang/lib/Serialization/ASTWriterDecl.cpp |  76 +---
 clang/test/Modules/cxx-templates.cpp  |   8 +-
 clang/test/Modules/odr_hash.cpp   |   4 +-
 9 files changed, 255 insertions(+), 76 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index 5b6a6b40b28ef..d76c293706369 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -256,6 +256,9 @@ class TemplateArgumentList final
   TemplateArgumentList(const TemplateArgumentList &) = delete;
   TemplateArgumentList =(const TemplateArgumentList &) = delete;
 
+  /// Create hash for the given arguments.
+  static unsigned ComputeODRHash(ArrayRef Args);
+
   /// Create a new template argument list that copies the given set of
   /// template arguments.
   static TemplateArgumentList *CreateCopy(ASTContext ,
@@ -729,6 +732,26 @@ class RedeclarableTemplateDecl : public TemplateDecl,
   }
 
   void anchor() override;
+  struct LazySpecializationInfo {
+GlobalDeclID DeclID = GlobalDeclID();
+unsigned ODRHash = ~0U;
+bool IsPartial = false;
+LazySpecializationInfo(GlobalDeclID ID, unsigned Hash = ~0U,
+   bool Partial = false)
+  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
+LazySpecializationInfo() { }
+bool operator<(const LazySpecializationInfo ) const {
+  return DeclID < Other.DeclID;
+}
+bool operator==(const LazySpecializationInfo ) const {
+  assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
+ "Hashes differ!");
+  assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
+ "Both must be the same kinds!");
+  return DeclID == Other.DeclID;
+}
+  };
+
 protected:
   template  struct SpecEntryTraits {
 using DeclType = EntryType;
@@ -769,7 +792,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 return SpecIterator(isEnd ? Specs.end() : Specs.begin());
   }
 
-  void loadLazySpecializationsImpl() const;
+  void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+  void loadLazySpecializationsImpl(llvm::ArrayRef Args,
+   TemplateParameterList *TPL = nullptr) const;
+
+  Decl *loadLazySpecializationImpl(LazySpecializationInfo ) const;
 
   template 
   typename SpecEntryTraits::DeclType*
@@ -796,7 +824,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 ///
 /// The first value in the array is the number of specializations/partial
 /// specializations that follow.
-GlobalDeclID *LazySpecializations = nullptr;
+LazySpecializationInfo *LazySpecializations = nullptr;
 
 /// The set of "injected" template arguments used within this
 /// template.
@@ -2279,7 +2307,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl 
{
   friend class TemplateDeclInstantiator;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying class declarations of the template.
   CXXRecordDecl *getTemplatedDecl() const {
@@ -3023,7 +3051,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
   friend class ASTDeclWriter;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying variable declarations of the template.
   VarDecl *getTemplatedDecl() const {
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 722c7fcf0b0df..021454c770741 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -20,6 +20,8 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/ODRHash.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LLVM.h"
@@ -331,17 +333,46 @@ RedeclarableTemplateDecl::CommonBase 
*RedeclarableTemplateDecl::getCommonPtr() c
   return Common;
 }
 
-void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
+void 

[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-07-05 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/83108

>From 270cdac974482a9852fa8c1bff517d444a5f51f2 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev 
Date: Sun, 7 Jan 2018 15:16:11 +0200
Subject: [PATCH 1/2] D41416: [modules] [pch] Do not deserialize all lazy
 template specializations when looking for one.

---
 clang/include/clang/AST/DeclTemplate.h|  36 +++-
 clang/lib/AST/DeclTemplate.cpp| 100 +-
 clang/lib/AST/ODRHash.cpp |  15 
 clang/lib/Serialization/ASTReader.cpp |  25 --
 clang/lib/Serialization/ASTReaderDecl.cpp |  46 ++
 clang/lib/Serialization/ASTWriter.cpp |  21 -
 clang/lib/Serialization/ASTWriterDecl.cpp |  76 +---
 clang/test/Modules/cxx-templates.cpp  |   8 +-
 clang/test/Modules/odr_hash.cpp   |   4 +-
 9 files changed, 255 insertions(+), 76 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index 5b6a6b40b28ef8..d76c2937063696 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -256,6 +256,9 @@ class TemplateArgumentList final
   TemplateArgumentList(const TemplateArgumentList &) = delete;
   TemplateArgumentList =(const TemplateArgumentList &) = delete;
 
+  /// Create hash for the given arguments.
+  static unsigned ComputeODRHash(ArrayRef Args);
+
   /// Create a new template argument list that copies the given set of
   /// template arguments.
   static TemplateArgumentList *CreateCopy(ASTContext ,
@@ -729,6 +732,26 @@ class RedeclarableTemplateDecl : public TemplateDecl,
   }
 
   void anchor() override;
+  struct LazySpecializationInfo {
+GlobalDeclID DeclID = GlobalDeclID();
+unsigned ODRHash = ~0U;
+bool IsPartial = false;
+LazySpecializationInfo(GlobalDeclID ID, unsigned Hash = ~0U,
+   bool Partial = false)
+  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
+LazySpecializationInfo() { }
+bool operator<(const LazySpecializationInfo ) const {
+  return DeclID < Other.DeclID;
+}
+bool operator==(const LazySpecializationInfo ) const {
+  assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
+ "Hashes differ!");
+  assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
+ "Both must be the same kinds!");
+  return DeclID == Other.DeclID;
+}
+  };
+
 protected:
   template  struct SpecEntryTraits {
 using DeclType = EntryType;
@@ -769,7 +792,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 return SpecIterator(isEnd ? Specs.end() : Specs.begin());
   }
 
-  void loadLazySpecializationsImpl() const;
+  void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+  void loadLazySpecializationsImpl(llvm::ArrayRef Args,
+   TemplateParameterList *TPL = nullptr) const;
+
+  Decl *loadLazySpecializationImpl(LazySpecializationInfo ) const;
 
   template 
   typename SpecEntryTraits::DeclType*
@@ -796,7 +824,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 ///
 /// The first value in the array is the number of specializations/partial
 /// specializations that follow.
-GlobalDeclID *LazySpecializations = nullptr;
+LazySpecializationInfo *LazySpecializations = nullptr;
 
 /// The set of "injected" template arguments used within this
 /// template.
@@ -2279,7 +2307,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl 
{
   friend class TemplateDeclInstantiator;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying class declarations of the template.
   CXXRecordDecl *getTemplatedDecl() const {
@@ -3023,7 +3051,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
   friend class ASTDeclWriter;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying variable declarations of the template.
   VarDecl *getTemplatedDecl() const {
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 722c7fcf0b0df7..021454c7707413 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -20,6 +20,8 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/ODRHash.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LLVM.h"
@@ -331,17 +333,46 @@ RedeclarableTemplateDecl::CommonBase 
*RedeclarableTemplateDecl::getCommonPtr() c
   return Common;
 }
 
-void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
+void 

[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-04-25 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Rebased with main.

https://github.com/llvm/llvm-project/pull/83108
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-04-25 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/83108

>From be1c83fb885536c3e65657c6549bd20dd29d9649 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev 
Date: Sun, 7 Jan 2018 15:16:11 +0200
Subject: [PATCH 1/3] D41416: [modules] [pch] Do not deserialize all lazy
 template specializations when looking for one.

---
 clang/include/clang/AST/DeclTemplate.h|  36 +++-
 clang/lib/AST/DeclTemplate.cpp| 100 +-
 clang/lib/AST/ODRHash.cpp |  15 
 clang/lib/Serialization/ASTReader.cpp |  25 --
 clang/lib/Serialization/ASTReaderDecl.cpp |  46 ++
 clang/lib/Serialization/ASTWriter.cpp |  21 -
 clang/lib/Serialization/ASTWriterDecl.cpp |  76 +---
 7 files changed, 249 insertions(+), 70 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index 3ee03eebdb8ca4..24578cfdaa7c7c 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -256,6 +256,9 @@ class TemplateArgumentList final
   TemplateArgumentList(const TemplateArgumentList &) = delete;
   TemplateArgumentList =(const TemplateArgumentList &) = delete;
 
+  /// Create hash for the given arguments.
+  static unsigned ComputeODRHash(ArrayRef Args);
+
   /// Create a new template argument list that copies the given set of
   /// template arguments.
   static TemplateArgumentList *CreateCopy(ASTContext ,
@@ -730,6 +733,26 @@ class RedeclarableTemplateDecl : public TemplateDecl,
   }
 
   void anchor() override;
+  struct LazySpecializationInfo {
+GlobalDeclID DeclID = GlobalDeclID();
+unsigned ODRHash = ~0U;
+bool IsPartial = false;
+LazySpecializationInfo(GlobalDeclID ID, unsigned Hash = ~0U,
+   bool Partial = false)
+  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
+LazySpecializationInfo() { }
+bool operator<(const LazySpecializationInfo ) const {
+  return DeclID < Other.DeclID;
+}
+bool operator==(const LazySpecializationInfo ) const {
+  assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
+ "Hashes differ!");
+  assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
+ "Both must be the same kinds!");
+  return DeclID == Other.DeclID;
+}
+  };
+
 protected:
   template  struct SpecEntryTraits {
 using DeclType = EntryType;
@@ -770,7 +793,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 return SpecIterator(isEnd ? Specs.end() : Specs.begin());
   }
 
-  void loadLazySpecializationsImpl() const;
+  void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+  void loadLazySpecializationsImpl(llvm::ArrayRef Args,
+   TemplateParameterList *TPL = nullptr) const;
+
+  Decl *loadLazySpecializationImpl(LazySpecializationInfo ) const;
 
   template 
   typename SpecEntryTraits::DeclType*
@@ -797,7 +825,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 ///
 /// The first value in the array is the number of specializations/partial
 /// specializations that follow.
-GlobalDeclID *LazySpecializations = nullptr;
+LazySpecializationInfo *LazySpecializations = nullptr;
 
 /// The set of "injected" template arguments used within this
 /// template.
@@ -2284,7 +2312,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl 
{
   friend class TemplateDeclInstantiator;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying class declarations of the template.
   CXXRecordDecl *getTemplatedDecl() const {
@@ -3056,7 +3084,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
   friend class ASTDeclWriter;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying variable declarations of the template.
   VarDecl *getTemplatedDecl() const {
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index d27a30e0c5fce1..1afd7b4550c917 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -20,6 +20,8 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/ODRHash.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LLVM.h"
@@ -331,17 +333,46 @@ RedeclarableTemplateDecl::CommonBase 
*RedeclarableTemplateDecl::getCommonPtr() c
   return Common;
 }
 
-void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
+void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
+ bool 

[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-04-07 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/83108

>From 2a9dfdab30467bef5361cea743be0dc215011685 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev 
Date: Sun, 7 Jan 2018 15:16:11 +0200
Subject: [PATCH 1/3] D41416: [modules] [pch] Do not deserialize all lazy
 template specializations when looking for one.

---
 clang/include/clang/AST/DeclTemplate.h| 36 -
 clang/lib/AST/DeclTemplate.cpp| 96 +--
 clang/lib/AST/ODRHash.cpp | 15 
 clang/lib/Serialization/ASTReader.cpp | 25 --
 clang/lib/Serialization/ASTReaderDecl.cpp | 36 ++---
 clang/lib/Serialization/ASTWriter.cpp | 21 -
 clang/lib/Serialization/ASTWriterDecl.cpp | 74 ++---
 7 files changed, 242 insertions(+), 61 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index e3b6a7efb1127a..4ed9b58d4ff609 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -256,6 +256,9 @@ class TemplateArgumentList final
   TemplateArgumentList(const TemplateArgumentList &) = delete;
   TemplateArgumentList =(const TemplateArgumentList &) = delete;
 
+  /// Create hash for the given arguments.
+  static unsigned ComputeODRHash(ArrayRef Args);
+
   /// Create a new template argument list that copies the given set of
   /// template arguments.
   static TemplateArgumentList *CreateCopy(ASTContext ,
@@ -730,6 +733,26 @@ class RedeclarableTemplateDecl : public TemplateDecl,
   }
 
   void anchor() override;
+  struct LazySpecializationInfo {
+uint32_t DeclID = ~0U;
+unsigned ODRHash = ~0U;
+bool IsPartial = false;
+LazySpecializationInfo(uint32_t ID, unsigned Hash = ~0U,
+   bool Partial = false)
+  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
+LazySpecializationInfo() { }
+bool operator<(const LazySpecializationInfo ) const {
+  return DeclID < Other.DeclID;
+}
+bool operator==(const LazySpecializationInfo ) const {
+  assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
+ "Hashes differ!");
+  assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
+ "Both must be the same kinds!");
+  return DeclID == Other.DeclID;
+}
+  };
+
 protected:
   template  struct SpecEntryTraits {
 using DeclType = EntryType;
@@ -770,7 +793,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 return SpecIterator(isEnd ? Specs.end() : Specs.begin());
   }
 
-  void loadLazySpecializationsImpl() const;
+  void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+  void loadLazySpecializationsImpl(llvm::ArrayRef Args,
+   TemplateParameterList *TPL = nullptr) const;
+
+  Decl *loadLazySpecializationImpl(LazySpecializationInfo ) const;
 
   template 
   typename SpecEntryTraits::DeclType*
@@ -797,7 +825,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 ///
 /// The first value in the array is the number of specializations/partial
 /// specializations that follow.
-uint32_t *LazySpecializations = nullptr;
+LazySpecializationInfo *LazySpecializations = nullptr;
 
 /// The set of "injected" template arguments used within this
 /// template.
@@ -2268,7 +2296,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl 
{
   friend class TemplateDeclInstantiator;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying class declarations of the template.
   CXXRecordDecl *getTemplatedDecl() const {
@@ -3039,7 +3067,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
   friend class ASTDeclWriter;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying variable declarations of the template.
   VarDecl *getTemplatedDecl() const {
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 3c217d6a6a5ae3..1babe39ee2a7e5 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -20,6 +20,8 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/ODRHash.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LLVM.h"
@@ -331,16 +333,43 @@ RedeclarableTemplateDecl::CommonBase 
*RedeclarableTemplateDecl::getCommonPtr() c
   return Common;
 }
 
-void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
+void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
+ bool OnlyPartial/*=false*/) const 
{
   // Grab 

[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/83108

>From 59e1880df74434e3c446705788d92b5949d99536 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev 
Date: Sun, 7 Jan 2018 15:16:11 +0200
Subject: [PATCH 1/3] D41416: [modules] [pch] Do not deserialize all lazy
 template specializations when looking for one.

---
 clang/include/clang/AST/DeclTemplate.h| 36 -
 clang/lib/AST/DeclTemplate.cpp| 96 +--
 clang/lib/AST/ODRHash.cpp | 15 
 clang/lib/Serialization/ASTReader.cpp | 25 --
 clang/lib/Serialization/ASTReaderDecl.cpp | 36 ++---
 clang/lib/Serialization/ASTWriter.cpp | 21 -
 clang/lib/Serialization/ASTWriterDecl.cpp | 74 ++---
 7 files changed, 242 insertions(+), 61 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index e3b6a7efb1127a..4ed9b58d4ff609 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -256,6 +256,9 @@ class TemplateArgumentList final
   TemplateArgumentList(const TemplateArgumentList &) = delete;
   TemplateArgumentList =(const TemplateArgumentList &) = delete;
 
+  /// Create hash for the given arguments.
+  static unsigned ComputeODRHash(ArrayRef Args);
+
   /// Create a new template argument list that copies the given set of
   /// template arguments.
   static TemplateArgumentList *CreateCopy(ASTContext ,
@@ -730,6 +733,26 @@ class RedeclarableTemplateDecl : public TemplateDecl,
   }
 
   void anchor() override;
+  struct LazySpecializationInfo {
+uint32_t DeclID = ~0U;
+unsigned ODRHash = ~0U;
+bool IsPartial = false;
+LazySpecializationInfo(uint32_t ID, unsigned Hash = ~0U,
+   bool Partial = false)
+  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
+LazySpecializationInfo() { }
+bool operator<(const LazySpecializationInfo ) const {
+  return DeclID < Other.DeclID;
+}
+bool operator==(const LazySpecializationInfo ) const {
+  assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
+ "Hashes differ!");
+  assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
+ "Both must be the same kinds!");
+  return DeclID == Other.DeclID;
+}
+  };
+
 protected:
   template  struct SpecEntryTraits {
 using DeclType = EntryType;
@@ -770,7 +793,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 return SpecIterator(isEnd ? Specs.end() : Specs.begin());
   }
 
-  void loadLazySpecializationsImpl() const;
+  void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+  void loadLazySpecializationsImpl(llvm::ArrayRef Args,
+   TemplateParameterList *TPL = nullptr) const;
+
+  Decl *loadLazySpecializationImpl(LazySpecializationInfo ) const;
 
   template 
   typename SpecEntryTraits::DeclType*
@@ -797,7 +825,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 ///
 /// The first value in the array is the number of specializations/partial
 /// specializations that follow.
-uint32_t *LazySpecializations = nullptr;
+LazySpecializationInfo *LazySpecializations = nullptr;
 
 /// The set of "injected" template arguments used within this
 /// template.
@@ -2268,7 +2296,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl 
{
   friend class TemplateDeclInstantiator;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying class declarations of the template.
   CXXRecordDecl *getTemplatedDecl() const {
@@ -3039,7 +3067,7 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
   friend class ASTDeclWriter;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying variable declarations of the template.
   VarDecl *getTemplatedDecl() const {
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 3c217d6a6a5ae3..1babe39ee2a7e5 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -20,6 +20,8 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/ODRHash.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LLVM.h"
@@ -331,16 +333,43 @@ RedeclarableTemplateDecl::CommonBase 
*RedeclarableTemplateDecl::getCommonPtr() c
   return Common;
 }
 
-void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
+void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
+ bool OnlyPartial/*=false*/) const 
{
   // Grab 

[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread Vassil Vassilev via cfe-commits

vgvassilev wrote:

> Weird. I only see two failures in my local environment:
> 
> ```
> Failed Tests (2):
>   Clang :: Modules/cxx-templates.cpp
>   Clang :: Modules/odr_hash.cpp
> ```
> 
> And I saw both of them in my patch. It is simply order mismatches.

Ha, ok. I know that my system constantly have some tests that fail even fro the 
master but I thought these were real. If we don't see them in the bots then 
that's probably a problem only on my side...

https://github.com/llvm/llvm-project/pull/83108
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Weird. I only see two failures in my local environment:

```
Failed Tests (2):
  Clang :: Modules/cxx-templates.cpp
  Clang :: Modules/odr_hash.cpp
```

And I saw both of them in my patch. It is simply order mismatches.

https://github.com/llvm/llvm-project/pull/83108
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread Vassil Vassilev via cfe-commits

vgvassilev wrote:

> Personally I feel this patch is good and the testing result from our workload 
> shows it is good too. But it looks like the performance testing results from 
> google @zygoloid @ilya-biryukov is not good. So maybe we need to wait for 
> landing this. (It will be great if @ilya-biryukov would like to test again)

Thanks for putting this up. I was planning to do so, however, locally I got:

```
  Clang :: CXX/module/basic/basic.link/p2.cppm
  Clang :: Driver/clang_f_opts.c
  Clang :: Driver/darwin-header-search-libcxx.cpp
  Clang :: Index/crash-recovery-modules.m
  Clang :: Modules/ExtDebugInfo.cpp
  Clang :: Modules/cxx-templates.cpp
  Clang :: Modules/odr_hash.cpp
  Clang :: Modules/using-directive-redecl.cpp
  Clang :: Modules/using-directive.cpp
  Clang :: PCH/chain-late-anonymous-namespace.cpp
  Clang :: PCH/cxx-namespaces.cpp
  Clang :: PCH/namespaces.cpp
```

I believe some tests require just adjusting the reference files, but others may 
need some debugging.

https://github.com/llvm/llvm-project/pull/83108
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 1ecbab56dcbb78268c8d19af34a50591f90b12a0 
59e1880df74434e3c446705788d92b5949d99536 -- 
clang/include/clang/AST/DeclTemplate.h clang/lib/AST/DeclTemplate.cpp 
clang/lib/AST/ODRHash.cpp clang/lib/Serialization/ASTReader.cpp 
clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTWriter.cpp 
clang/lib/Serialization/ASTWriterDecl.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index 4ed9b58d4f..51caef54ba 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -739,8 +739,8 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 bool IsPartial = false;
 LazySpecializationInfo(uint32_t ID, unsigned Hash = ~0U,
bool Partial = false)
-  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
-LazySpecializationInfo() { }
+: DeclID(ID), ODRHash(Hash), IsPartial(Partial) {}
+LazySpecializationInfo() {}
 bool operator<(const LazySpecializationInfo ) const {
   return DeclID < Other.DeclID;
 }
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 1babe39ee2..aa2368783d 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -16,12 +16,12 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/ODRHash.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
-#include "clang/AST/ODRHash.h"
-#include "clang/AST/ExprCXX.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LLVM.h"
@@ -334,7 +334,7 @@ RedeclarableTemplateDecl::CommonBase 
*RedeclarableTemplateDecl::getCommonPtr() c
 }
 
 void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
- bool OnlyPartial/*=false*/) const 
{
+bool OnlyPartial /*=false*/) const {
   // Grab the most recent declaration to ensure we've loaded any lazy
   // redeclarations of this template.
   CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
@@ -343,16 +343,16 @@ void 
RedeclarableTemplateDecl::loadLazySpecializationsImpl(
   CommonBasePtr->LazySpecializations = nullptr;
 for (uint32_t I = 0, N = Specs[0].DeclID; I != N; ++I) {
   // Skip over already loaded specializations.
-  if (!Specs[I+1].ODRHash)
+  if (!Specs[I + 1].ODRHash)
 continue;
-  if (!OnlyPartial || Specs[I+1].IsPartial)
-(void)loadLazySpecializationImpl(Specs[I+1]);
+  if (!OnlyPartial || Specs[I + 1].IsPartial)
+(void)loadLazySpecializationImpl(Specs[I + 1]);
 }
   }
 }
 
 Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl(
-   LazySpecializationInfo ) const 
{
+LazySpecializationInfo ) const {
   uint32_t ID = LazySpecInfo.DeclID;
   assert(ID && "Loading already loaded specialization!");
   // Note that we loaded the specialization.
@@ -360,16 +360,14 @@ Decl 
*RedeclarableTemplateDecl::loadLazySpecializationImpl(
   return getASTContext().getExternalSource()->GetExternalDecl(ID);
 }
 
-void
-RedeclarableTemplateDecl::loadLazySpecializationsImpl(ArrayRef
-  Args,
-  TemplateParameterList 
*TPL) const {
+void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
+ArrayRef Args, TemplateParameterList *TPL) const {
   CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
   if (auto *Specs = CommonBasePtr->LazySpecializations) {
 unsigned Hash = TemplateArgumentList::ComputeODRHash(Args);
 for (uint32_t I = 0, N = Specs[0].DeclID; I != N; ++I)
-  if (Specs[I+1].ODRHash && Specs[I+1].ODRHash == Hash)
-(void)loadLazySpecializationImpl(Specs[I+1]);
+  if (Specs[I + 1].ODRHash && Specs[I + 1].ODRHash == Hash)
+(void)loadLazySpecializationImpl(Specs[I + 1]);
   }
 }
 
@@ -546,7 +544,7 @@ ClassTemplateDecl 
*ClassTemplateDecl::CreateDeserialized(ASTContext ,
 }
 
 void ClassTemplateDecl::LoadLazySpecializations(
- bool OnlyPartial/*=false*/) const 
{
+bool OnlyPartial /*=false*/) const {
   loadLazySpecializationsImpl(OnlyPartial);
 }
 
@@ -1275,7 +1273,7 @@ VarTemplateDecl 
*VarTemplateDecl::CreateDeserialized(ASTContext ,
 }
 
 void VarTemplateDecl::LoadLazySpecializations(
- bool OnlyPartial/*=false*/) const 
{
+bool OnlyPartial /*=false*/) const {
   

[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Personally I feel this patch is good and the testing result from our workload 
shows it is good too. But it looks like the performance testing results from 
google @zygoloid @ilya-biryukov is not good. So maybe we need to wait for 
landing this. (It will be great if @ilya-biryukov would like to test again)

https://github.com/llvm/llvm-project/pull/83108
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Chuanqi Xu (ChuanqiXu9)


Changes

This from https://reviews.llvm.org/D41416. And we plan to introduce on disk 
hash table based on this. See https://github.com/llvm/llvm-project/pull/76774.

Following off are cited from https://reviews.llvm.org/D41416:

Currently, we load all lazy template specializations when we search whether 
there is a suitable template specialization for a template. This is especially 
suboptimal with modules. If module B specializes a template from module A the 
ASTReader would only read the specialization DeclID. This is observed to be 
especially pathological when module B is stl. However, the template 
instantiator (almost immediately after) will call findSpecialization. In turn, 
findSpecialization will load all lazy specializations to give an answer.

This patch teaches findSpecialization to work with lazy specializations without 
having to deserialize their full content. It provides along with the DeclID an 
cross-TU stable ODRHash of the template arguments which is enough to decide if 
we have already specialization and which are the exact ones (we load all decls 
with the same hash to avoid potential collisions) to deserialize.

While we make finding a template specialization more memory-efficient we are 
far from being done. There are still a few places which trigger eager 
deserialization of template specializations: the places where we require 
completion of the redeclaration chain.



---

Patch is 26.57 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/83108.diff


7 Files Affected:

- (modified) clang/include/clang/AST/DeclTemplate.h (+32-4) 
- (modified) clang/lib/AST/DeclTemplate.cpp (+74-22) 
- (modified) clang/lib/AST/ODRHash.cpp (+15) 
- (modified) clang/lib/Serialization/ASTReader.cpp (+17-8) 
- (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+23-13) 
- (modified) clang/lib/Serialization/ASTWriter.cpp (+19-2) 
- (modified) clang/lib/Serialization/ASTWriterDecl.cpp (+62-12) 


``diff
diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index e3b6a7efb1127a..4ed9b58d4ff609 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -256,6 +256,9 @@ class TemplateArgumentList final
   TemplateArgumentList(const TemplateArgumentList &) = delete;
   TemplateArgumentList =(const TemplateArgumentList &) = delete;
 
+  /// Create hash for the given arguments.
+  static unsigned ComputeODRHash(ArrayRef Args);
+
   /// Create a new template argument list that copies the given set of
   /// template arguments.
   static TemplateArgumentList *CreateCopy(ASTContext ,
@@ -730,6 +733,26 @@ class RedeclarableTemplateDecl : public TemplateDecl,
   }
 
   void anchor() override;
+  struct LazySpecializationInfo {
+uint32_t DeclID = ~0U;
+unsigned ODRHash = ~0U;
+bool IsPartial = false;
+LazySpecializationInfo(uint32_t ID, unsigned Hash = ~0U,
+   bool Partial = false)
+  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
+LazySpecializationInfo() { }
+bool operator<(const LazySpecializationInfo ) const {
+  return DeclID < Other.DeclID;
+}
+bool operator==(const LazySpecializationInfo ) const {
+  assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
+ "Hashes differ!");
+  assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
+ "Both must be the same kinds!");
+  return DeclID == Other.DeclID;
+}
+  };
+
 protected:
   template  struct SpecEntryTraits {
 using DeclType = EntryType;
@@ -770,7 +793,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 return SpecIterator(isEnd ? Specs.end() : Specs.begin());
   }
 
-  void loadLazySpecializationsImpl() const;
+  void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+  void loadLazySpecializationsImpl(llvm::ArrayRef Args,
+   TemplateParameterList *TPL = nullptr) const;
+
+  Decl *loadLazySpecializationImpl(LazySpecializationInfo ) const;
 
   template 
   typename SpecEntryTraits::DeclType*
@@ -797,7 +825,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 ///
 /// The first value in the array is the number of specializations/partial
 /// specializations that follow.
-uint32_t *LazySpecializations = nullptr;
+LazySpecializationInfo *LazySpecializations = nullptr;
 
 /// The set of "injected" template arguments used within this
 /// template.
@@ -2268,7 +2296,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl 
{
   friend class TemplateDeclInstantiator;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations() const;
+  void LoadLazySpecializations(bool OnlyPartial = false) const;
 
   /// Get the underlying class declarations of the template.
   CXXRecordDecl 

[clang] D41416: [modules] [pch] Do not deserialize all lazy template specializations when looking for one. (PR #83108)

2024-02-26 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 created 
https://github.com/llvm/llvm-project/pull/83108

This from https://reviews.llvm.org/D41416. And we plan to introduce on disk 
hash table based on this. See https://github.com/llvm/llvm-project/pull/76774.

Following off are cited from https://reviews.llvm.org/D41416:

Currently, we load all lazy template specializations when we search whether 
there is a suitable template specialization for a template. This is especially 
suboptimal with modules. If module B specializes a template from module A the 
ASTReader would only read the specialization DeclID. This is observed to be 
especially pathological when module B is stl. However, the template 
instantiator (almost immediately after) will call findSpecialization. In turn, 
findSpecialization will load all lazy specializations to give an answer.

This patch teaches findSpecialization to work with lazy specializations without 
having to deserialize their full content. It provides along with the DeclID an 
cross-TU stable ODRHash of the template arguments which is enough to decide if 
we have already specialization and which are the exact ones (we load all decls 
with the same hash to avoid potential collisions) to deserialize.

While we make finding a template specialization more memory-efficient we are 
far from being done. There are still a few places which trigger eager 
deserialization of template specializations: the places where we require 
completion of the redeclaration chain.



>From 59e1880df74434e3c446705788d92b5949d99536 Mon Sep 17 00:00:00 2001
From: Vassil Vassilev 
Date: Sun, 7 Jan 2018 15:16:11 +0200
Subject: [PATCH] D41416: [modules] [pch] Do not deserialize all lazy template
 specializations when looking for one.

---
 clang/include/clang/AST/DeclTemplate.h| 36 -
 clang/lib/AST/DeclTemplate.cpp| 96 +--
 clang/lib/AST/ODRHash.cpp | 15 
 clang/lib/Serialization/ASTReader.cpp | 25 --
 clang/lib/Serialization/ASTReaderDecl.cpp | 36 ++---
 clang/lib/Serialization/ASTWriter.cpp | 21 -
 clang/lib/Serialization/ASTWriterDecl.cpp | 74 ++---
 7 files changed, 242 insertions(+), 61 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index e3b6a7efb1127a..4ed9b58d4ff609 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -256,6 +256,9 @@ class TemplateArgumentList final
   TemplateArgumentList(const TemplateArgumentList &) = delete;
   TemplateArgumentList =(const TemplateArgumentList &) = delete;
 
+  /// Create hash for the given arguments.
+  static unsigned ComputeODRHash(ArrayRef Args);
+
   /// Create a new template argument list that copies the given set of
   /// template arguments.
   static TemplateArgumentList *CreateCopy(ASTContext ,
@@ -730,6 +733,26 @@ class RedeclarableTemplateDecl : public TemplateDecl,
   }
 
   void anchor() override;
+  struct LazySpecializationInfo {
+uint32_t DeclID = ~0U;
+unsigned ODRHash = ~0U;
+bool IsPartial = false;
+LazySpecializationInfo(uint32_t ID, unsigned Hash = ~0U,
+   bool Partial = false)
+  : DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
+LazySpecializationInfo() { }
+bool operator<(const LazySpecializationInfo ) const {
+  return DeclID < Other.DeclID;
+}
+bool operator==(const LazySpecializationInfo ) const {
+  assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
+ "Hashes differ!");
+  assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
+ "Both must be the same kinds!");
+  return DeclID == Other.DeclID;
+}
+  };
+
 protected:
   template  struct SpecEntryTraits {
 using DeclType = EntryType;
@@ -770,7 +793,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 return SpecIterator(isEnd ? Specs.end() : Specs.begin());
   }
 
-  void loadLazySpecializationsImpl() const;
+  void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+  void loadLazySpecializationsImpl(llvm::ArrayRef Args,
+   TemplateParameterList *TPL = nullptr) const;
+
+  Decl *loadLazySpecializationImpl(LazySpecializationInfo ) const;
 
   template 
   typename SpecEntryTraits::DeclType*
@@ -797,7 +825,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
 ///
 /// The first value in the array is the number of specializations/partial
 /// specializations that follow.
-uint32_t *LazySpecializations = nullptr;
+LazySpecializationInfo *LazySpecializations = nullptr;
 
 /// The set of "injected" template arguments used within this
 /// template.
@@ -2268,7 +2296,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl 
{
   friend class TemplateDeclInstantiator;
 
   /// Load any lazily-loaded specializations from the external source.
-  void LoadLazySpecializations()