[Lldb-commits] [clang] [lldb] [Serialization] Support load lazy specialization lazily (PR #119333)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Dec 9 22:47:29 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Chuanqi Xu (ChuanqiXu9)
<details>
<summary>Changes</summary>
Reland https://github.com/llvm/llvm-project/pull/83237
---
Currently all the specializations of a template (including instantiation, specialization and partial specializations) will be loaded at once if we want to instantiate another instance for the template, or find instantiation for the template, or just want to complete the redecl chain.
This means basically we need to load every specializations for the template once the template declaration got loaded. This is bad since when we load a specialization, we need to load all of its template arguments. Then we have to deserialize a lot of unnecessary declarations.
For example,
```
// M.cppm
export module M;
export template <class T>
class A {};
export class ShouldNotBeLoaded {};
export class Temp {
A<ShouldNotBeLoaded> AS;
};
// use.cpp
import M;
A<int> a;
```
We should a specialization ` A<ShouldNotBeLoaded>` in `M.cppm` and we instantiate the template `A` in `use.cpp`. Then we will deserialize `ShouldNotBeLoaded` surprisingly when compiling `use.cpp`. And this patch tries to avoid that.
Given that the templates are heavily used in C++, this is a pain point for the performance.
This patch adds MultiOnDiskHashTable for specializations in the ASTReader. Then we will only deserialize the specializations with the same template arguments. We made that by using ODRHash for the template arguments as the key of the hash table.
To review this patch, I think `ASTReaderDecl::AddLazySpecializations` may be a good entry point.
---
Patch is 95.25 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/119333.diff
29 Files Affected:
- (modified) clang/include/clang/AST/DeclTemplate.h (+13-10)
- (modified) clang/include/clang/AST/ExternalASTSource.h (+15)
- (modified) clang/include/clang/Sema/MultiplexExternalSemaSource.h (+6)
- (modified) clang/include/clang/Serialization/ASTBitCodes.h (+13)
- (modified) clang/include/clang/Serialization/ASTReader.h (+45-3)
- (modified) clang/include/clang/Serialization/ASTWriter.h (+17)
- (modified) clang/lib/AST/DeclTemplate.cpp (+77-31)
- (modified) clang/lib/AST/ExternalASTSource.cpp (+9)
- (modified) clang/lib/AST/ODRHash.cpp (+14-9)
- (modified) clang/lib/Sema/MultiplexExternalSemaSource.cpp (+17)
- (modified) clang/lib/Serialization/ASTCommon.h (-1)
- (modified) clang/lib/Serialization/ASTReader.cpp (+228-9)
- (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+43-61)
- (modified) clang/lib/Serialization/ASTReaderInternals.h (+82)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+206-3)
- (modified) clang/lib/Serialization/ASTWriterDecl.cpp (+79-31)
- (modified) clang/lib/Serialization/CMakeLists.txt (+1)
- (added) clang/lib/Serialization/TemplateArgumentHasher.cpp (+409)
- (added) clang/lib/Serialization/TemplateArgumentHasher.h (+34)
- (modified) clang/test/Modules/cxx-templates.cpp (+4-4)
- (modified) clang/test/Modules/odr_hash.cpp (+2-2)
- (added) clang/test/Modules/recursive-instantiations.cppm (+40)
- (modified) clang/test/OpenMP/target_parallel_ast_print.cpp (-4)
- (modified) clang/test/OpenMP/target_teams_ast_print.cpp (-4)
- (modified) clang/test/OpenMP/task_ast_print.cpp (-4)
- (modified) clang/test/OpenMP/teams_ast_print.cpp (-4)
- (modified) clang/unittests/Serialization/CMakeLists.txt (+1)
- (added) clang/unittests/Serialization/LoadSpecLazilyTest.cpp (+262)
- (modified) lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h (+28)
``````````diff
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index e4bf54c3d77b7f..dd92d40b804232 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -735,6 +735,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
}
void anchor() override;
+
protected:
template <typename EntryType> struct SpecEntryTraits {
using DeclType = EntryType;
@@ -775,13 +776,22 @@ class RedeclarableTemplateDecl : public TemplateDecl,
return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
}
- void loadLazySpecializationsImpl() const;
+ void loadLazySpecializationsImpl(bool OnlyPartial = false) const;
+
+ bool loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args,
+ TemplateParameterList *TPL = nullptr) const;
template <class EntryType, typename ...ProfileArguments>
typename SpecEntryTraits<EntryType>::DeclType*
findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
void *&InsertPos, ProfileArguments &&...ProfileArgs);
+ template <class EntryType, typename... ProfileArguments>
+ typename SpecEntryTraits<EntryType>::DeclType *
+ findSpecializationLocally(llvm::FoldingSetVector<EntryType> &Specs,
+ void *&InsertPos,
+ ProfileArguments &&...ProfileArgs);
+
template <class Derived, class EntryType>
void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
EntryType *Entry, void *InsertPos);
@@ -796,13 +806,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// was explicitly specialized.
llvm::PointerIntPair<RedeclarableTemplateDecl *, 1, bool>
InstantiatedFromMember;
-
- /// If non-null, points to an array of specializations (including
- /// partial specializations) known only by their external declaration IDs.
- ///
- /// The first value in the array is the number of specializations/partial
- /// specializations that follow.
- GlobalDeclID *LazySpecializations = nullptr;
};
/// Pointer to the common data shared by all declarations of this
@@ -2283,7 +2286,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 {
@@ -3033,7 +3036,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/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h
index 582ed7c65f58ca..9f968ba05b4466 100644
--- a/clang/include/clang/AST/ExternalASTSource.h
+++ b/clang/include/clang/AST/ExternalASTSource.h
@@ -152,6 +152,21 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
virtual bool
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
+ /// Load all the external specializations for the Decl \param D if \param
+ /// OnlyPartial is false. Otherwise, load all the external **partial**
+ /// specializations for the \param D.
+ ///
+ /// Return true if any new specializations get loaded. Return false otherwise.
+ virtual bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial);
+
+ /// Load all the specializations for the Decl \param D with the same template
+ /// args specified by \param TemplateArgs.
+ ///
+ /// Return true if any new specializations get loaded. Return false otherwise.
+ virtual bool
+ LoadExternalSpecializations(const Decl *D,
+ ArrayRef<TemplateArgument> TemplateArgs);
+
/// Ensures that the table of all visible declarations inside this
/// context is up to date.
///
diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
index 3d1906d8699265..0c92c52854c9e7 100644
--- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -97,6 +97,12 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) override;
+ bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;
+
+ bool
+ LoadExternalSpecializations(const Decl *D,
+ ArrayRef<TemplateArgument> TemplateArgs) override;
+
/// Ensures that the table of all visible declarations inside this
/// context is up to date.
void completeVisibleDeclsMap(const DeclContext *DC) override;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index fd834c14ce790f..af0e08d800bf28 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -733,6 +733,13 @@ enum ASTRecordTypes {
/// Record code for Sema's vector of functions/blocks with effects to
/// be verified.
DECLS_WITH_EFFECTS_TO_VERIFY = 72,
+
+ /// Record code for updated specialization
+ UPDATE_SPECIALIZATION = 73,
+
+ CXX_ADDED_TEMPLATE_SPECIALIZATION = 74,
+
+ CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION = 75,
};
/// Record types used within a source manager block.
@@ -1502,6 +1509,12 @@ enum DeclCode {
/// An ImplicitConceptSpecializationDecl record.
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,
+ // A decls specilization record.
+ DECL_SPECIALIZATIONS,
+
+ // A decls specilization record.
+ DECL_PARTIAL_SPECIALIZATIONS,
+
DECL_LAST = DECL_IMPLICIT_CONCEPT_SPECIALIZATION
};
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index f739fe688c110d..f91052be5e1291 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -354,6 +354,9 @@ class ASTIdentifierLookupTrait;
/// The on-disk hash table(s) used for DeclContext name lookup.
struct DeclContextLookupTable;
+/// The on-disk hash table(s) used for specialization decls.
+struct LazySpecializationInfoLookupTable;
+
} // namespace reader
} // namespace serialization
@@ -632,20 +635,40 @@ class ASTReader
llvm::DenseMap<const DeclContext *,
serialization::reader::DeclContextLookupTable> Lookups;
+ using SpecLookupTableTy =
+ llvm::DenseMap<const Decl *,
+ serialization::reader::LazySpecializationInfoLookupTable>;
+ /// Map from decls to specialized decls.
+ SpecLookupTableTy SpecializationsLookups;
+ /// Split partial specialization from specialization to speed up lookups.
+ SpecLookupTableTy PartialSpecializationsLookups;
+
+ bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups,
+ const Decl *D);
+ bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups,
+ const Decl *D,
+ ArrayRef<TemplateArgument> TemplateArgs);
+
// Updates for visible decls can occur for other contexts than just the
// TU, and when we read those update records, the actual context may not
// be available yet, so have this pending map using the ID as a key. It
- // will be realized when the context is actually loaded.
- struct PendingVisibleUpdate {
+ // will be realized when the data is actually loaded.
+ struct UpdateData {
ModuleFile *Mod;
const unsigned char *Data;
};
- using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>;
+ using DeclContextVisibleUpdates = SmallVector<UpdateData, 1>;
/// Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet.
llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingVisibleUpdates;
+ using SpecializationsUpdate = SmallVector<UpdateData, 1>;
+ using SpecializationsUpdateMap =
+ llvm::DenseMap<GlobalDeclID, SpecializationsUpdate>;
+ SpecializationsUpdateMap PendingSpecializationsUpdates;
+ SpecializationsUpdateMap PendingPartialSpecializationsUpdates;
+
/// 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;
@@ -678,6 +701,11 @@ class ASTReader
llvm::BitstreamCursor &Cursor,
uint64_t Offset, GlobalDeclID ID);
+ bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor,
+ uint64_t Offset, Decl *D, bool IsPartial);
+ void AddSpecializations(const Decl *D, const unsigned char *Data,
+ ModuleFile &M, bool IsPartial);
+
/// A vector containing identifiers that have already been
/// loaded.
///
@@ -1419,6 +1447,14 @@ class ASTReader
const serialization::reader::DeclContextLookupTable *
getLoadedLookupTables(DeclContext *Primary) const;
+ /// Get the loaded specializations lookup tables for \p D,
+ /// if any.
+ serialization::reader::LazySpecializationInfoLookupTable *
+ getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial);
+
+ /// If we have any unloaded specialization for \p D
+ bool haveUnloadedSpecializations(const Decl *D) const;
+
private:
struct ImportedModule {
ModuleFile *Mod;
@@ -2076,6 +2112,12 @@ class ASTReader
unsigned BlockID,
uint64_t *StartOfBlockOffset = nullptr);
+ bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;
+
+ bool
+ LoadExternalSpecializations(const Decl *D,
+ ArrayRef<TemplateArgument> TemplateArgs) override;
+
/// Finds all the visible declarations with a given name.
/// The current implementation of this method just loads the entire
/// lookup table as unmaterialized references.
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index e418fdea44a0a9..d98d23decbdc0d 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -423,6 +423,13 @@ class ASTWriter : public ASTDeserializationListener,
/// Only meaningful for reduced BMI.
DeclUpdateMap DeclUpdatesFromGMF;
+ /// Mapping from decl templates and its new specialization in the
+ /// current TU.
+ using SpecializationUpdateMap =
+ llvm::MapVector<const NamedDecl *, SmallVector<const Decl *>>;
+ SpecializationUpdateMap SpecializationsUpdates;
+ SpecializationUpdateMap PartialSpecializationsUpdates;
+
using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;
/// Map of first declarations from a chained PCH that point to the
@@ -575,6 +582,12 @@ class ASTWriter : public ASTDeserializationListener,
bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
+ void GenerateSpecializationInfoLookupTable(
+ const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
+ llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial);
+ uint64_t WriteSpecializationInfoLookupTable(
+ const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
+ bool IsPartial);
void GenerateNameLookupTable(ASTContext &Context, const DeclContext *DC,
llvm::SmallVectorImpl<char> &LookupTable);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context,
@@ -590,6 +603,7 @@ class ASTWriter : public ASTDeserializationListener,
void WriteDeclAndTypes(ASTContext &Context);
void PrepareWritingSpecialDecls(Sema &SemaRef);
void WriteSpecialDeclRecords(Sema &SemaRef);
+ void WriteSpecializationsUpdates(bool IsPartial);
void WriteDeclUpdatesBlocks(ASTContext &Context,
RecordDataImpl &OffsetsRecord);
void WriteDeclContextVisibleUpdate(ASTContext &Context,
@@ -619,6 +633,9 @@ class ASTWriter : public ASTDeserializationListener,
unsigned DeclEnumAbbrev = 0;
unsigned DeclObjCIvarAbbrev = 0;
unsigned DeclCXXMethodAbbrev = 0;
+ unsigned DeclSpecializationsAbbrev = 0;
+ unsigned DeclPartialSpecializationsAbbrev = 0;
+
unsigned DeclDependentNonTemplateCXXMethodAbbrev = 0;
unsigned DeclTemplateCXXMethodAbbrev = 0;
unsigned DeclMemberSpecializedCXXMethodAbbrev = 0;
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 1da3f26bf23cd5..40ee3753c24227 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -16,7 +16,9 @@
#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"
@@ -348,26 +350,39 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
return Common;
}
-void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
- // Grab the most recent declaration to ensure we've loaded any lazy
- // redeclarations of this template.
- CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
- if (CommonBasePtr->LazySpecializations) {
- ASTContext &Context = getASTContext();
- GlobalDeclID *Specs = CommonBasePtr->LazySpecializations;
- CommonBasePtr->LazySpecializations = nullptr;
- unsigned SpecSize = (*Specs++).getRawValue();
- for (unsigned I = 0; I != SpecSize; ++I)
- (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
- }
+void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
+ bool OnlyPartial /*=false*/) const {
+ auto *ExternalSource = getASTContext().getExternalSource();
+ if (!ExternalSource)
+ return;
+
+ ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
+ OnlyPartial);
+ return;
}
-template<class EntryType, typename... ProfileArguments>
+bool RedeclarableTemplateDecl::loadLazySpecializationsImpl(
+ ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
+ auto *ExternalSource = getASTContext().getExternalSource();
+ if (!ExternalSource)
+ return false;
+
+ // If TPL is not null, it implies that we're loading specializations for
+ // partial templates. We need to load all specializations in such cases.
+ if (TPL)
+ return ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
+ /*OnlyPartial=*/false);
+
+ return ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
+ Args);
+}
+
+template <class EntryType, typename... ProfileArguments>
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
-RedeclarableTemplateDecl::findSpecializationImpl(
+RedeclarableTemplateDecl::findSpecializationLocally(
llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos,
- ProfileArguments&&... ProfileArgs) {
- using SETraits = SpecEntryTraits<EntryType>;
+ ProfileArguments &&...ProfileArgs) {
+ using SETraits = RedeclarableTemplateDecl::SpecEntryTraits<EntryType>;
llvm::FoldingSetNodeID ID;
EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)...,
@@ -376,6 +391,24 @@ RedeclarableTemplateDecl::findSpecializationImpl(
return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
}
+template <class EntryType, typename... ProfileArguments>
+typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
+RedeclarableTemplateDecl::findSpecializationImpl(
+ llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos,
+ ProfileArguments &&...ProfileArgs) {
+
+ if (auto *Found = findSpecializationLocally(
+ Specs, InsertPos, std::forward<ProfileArguments>(ProfileArgs)...))
+ return Found;
+
+ if (!loadLazySpecializationsImpl(
+ std::forward<ProfileArguments>(ProfileArgs)...))
+ return nullptr;
+
+ return findSpecializationLocally(
+ Specs, InsertPos, std::forward<ProfileArguments>(ProfileArgs)...);
+}
+
template<class Derived, class EntryType>
void RedeclarableTemplateDecl::addSpecializationImpl(
llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
@@ -384,10 +417,14 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
if (InsertPos) {
#ifndef NDEBUG
+ auto Args = SETraits::getTemplateArgs(Entry);
+ // Due to hash collisions, it can happen that we load another template
+ // specialization with the same hash. This is fine, as long as the next
+ // call to findSpecializationImpl does not find a matching Decl for the
+ // template arguments.
+ loadLazySpecializationsImpl(Args);
void *CorrectInsertPos;
- assert(!findSpecializationImpl(Specializations,
- CorrectInsertPos,
- SETraits::getTemplateArgs(Entry)) &&
+ assert(!findSpecializationImpl(Specializations, CorrectInsertPos, Args) &&
InsertPos == CorrectInsertPos &&
"given incorrect InsertPos for specialization");
#endif
@@ -445,12 +482,14 @@ FunctionTemplateDecl::getSpecializations() const {
FunctionDecl *
FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void *&InsertPos) {
- return findSpecializationImpl(getSpecializations(), InsertPos, Args);
+ auto *Common = getCommonPtr();
+ return findSpecializationImpl(Common->Specializations, InsertPos, Args);
}
void FunctionTemplateDecl::addSpecialization(
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
- addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info,
+ auto *Common = getCommonPtr();
+ addSpecializationImpl<FunctionTemplateDecl>(Common->Specializations, Info,
InsertPos);
}
@@ -510,8 +549,9 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
DeclarationName(), nullptr, nullptr);
}
-void ClassTemplateDecl::LoadLazySpecializations() const {
- loadLazySpecializationsImpl();
+void ClassTemplateDecl::LoadLazySpecializations(
+ bool OnlyPartial /*=false*/) const {
+ loadLazySpecializationsImpl(OnlyPartial);
}
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
@@ -522,7 +562,7 @@ ClassTemplateDecl::getSpecializations() const {
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
ClassTemplateDecl::getPartialSpecializations() const {
- LoadLazySpecializations();
+ LoadLazySpecializations(/*PartialOnly = */ true);
return getCommonPtr()->PartialSpecializations;
}
@@ -536,12 +576,15 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {
ClassTemplateSpecializationDecl *
ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void *&InsertPos) {
- return findSpecializationImpl(getSpecializations(), InsertPos, Args);
+ auto *Common = getCommonPtr();
+ return findSpecializationImpl(Common->Specializations, InsertPos, Args);
}
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
void *InsertPos) {
- addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos);
+ auto *Common = getCommonPtr();
+ addSpecializationImpl<ClassTemplateDecl>(Common->Specializations, D,
+ InsertPos);
}
ClassTemplatePartialSpecializationDecl *
@@ -1259,8 +1302,9 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
DeclarationName(), nullptr, nullptr);
}
-void VarTemplateDecl::LoadLaz...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/119333
More information about the lldb-commits
mailing list