[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 20 07:24:11 PDT 2024
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/106585
>From 2cca9d25091c49b9a412af1d7585574c77754752 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Thu, 1 Aug 2024 13:13:57 -0400
Subject: [PATCH 01/29] [WIP] set isMemberSpecialization early
---
clang/include/clang/AST/DeclTemplate.h | 30 ++++----------
clang/include/clang/Sema/Sema.h | 7 ++--
clang/lib/AST/DeclTemplate.cpp | 28 ++++++-------
clang/lib/Sema/SemaDecl.cpp | 23 +++++------
clang/lib/Sema/SemaDeclCXX.cpp | 3 +-
clang/lib/Sema/SemaTemplate.cpp | 48 +++++++++++-----------
clang/lib/Sema/SemaTemplateInstantiate.cpp | 18 ++++++++
clang/lib/Serialization/ASTReaderDecl.cpp | 14 +++----
clang/lib/Serialization/ASTWriterDecl.cpp | 9 ++--
clang/test/PCH/cxx-templates.cpp | 6 +--
10 files changed, 94 insertions(+), 92 deletions(-)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 687715a22e9fd3..3ad31243d5e559 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -809,8 +809,8 @@ class RedeclarableTemplateDecl : public TemplateDecl,
};
/// Pointer to the common data shared by all declarations of this
- /// template.
- mutable CommonBase *Common = nullptr;
+ /// template, and a flag indicating if the template is a member specialization.
+ mutable llvm::PointerIntPair<CommonBase *, 1, bool> Common;
/// Retrieves the "common" pointer shared by all (re-)declarations of
/// the same template. Calling this routine may implicitly allocate memory
@@ -858,14 +858,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// struct X<int>::Inner { /* ... */ };
/// \endcode
bool isMemberSpecialization() const {
- return getCommonPtr()->InstantiatedFromMember.getInt();
+ return Common.getInt();
}
/// Note that this member template is a specialization.
void setMemberSpecialization() {
- assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- getCommonPtr()->InstantiatedFromMember.setInt(true);
+ Common.setInt(true);
}
/// Retrieve the member template from which this template was
@@ -2187,17 +2185,12 @@ class ClassTemplatePartialSpecializationDecl
/// struct X<int>::Inner<T*> { /* ... */ };
/// \endcode
bool isMemberSpecialization() const {
- const auto *First =
- cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
- return First->InstantiatedFromMember.getInt();
+ return InstantiatedFromMember.getInt();
}
/// Note that this member template is a specialization.
void setMemberSpecialization() {
- auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
- assert(First->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- return First->InstantiatedFromMember.setInt(true);
+ return InstantiatedFromMember.setInt(true);
}
/// Retrieves the injected specialization type for this partial
@@ -2269,7 +2262,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
}
void setCommonPtr(Common *C) {
- RedeclarableTemplateDecl::Common = C;
+ RedeclarableTemplateDecl::Common.setPointer(C);
}
public:
@@ -2949,17 +2942,12 @@ class VarTemplatePartialSpecializationDecl
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
/// \endcode
bool isMemberSpecialization() const {
- const auto *First =
- cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
- return First->InstantiatedFromMember.getInt();
+ return InstantiatedFromMember.getInt();
}
/// Note that this member template is a specialization.
void setMemberSpecialization() {
- auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
- assert(First->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- return First->InstantiatedFromMember.setInt(true);
+ return InstantiatedFromMember.setInt(true);
}
SourceRange getSourceRange() const override LLVM_READONLY;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0358259945c796..99b8b17c2b0578 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11392,9 +11392,8 @@ class Sema final : public SemaBase {
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
- SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
- TemplateParameterList **OuterTemplateParamLists,
- SkipBodyInfo *SkipBody = nullptr);
+ SourceLocation FriendLoc, ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
+ bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr);
/// Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
@@ -11433,7 +11432,7 @@ class Sema final : public SemaBase {
DeclResult ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
- StorageClass SC, bool IsPartialSpecialization);
+ StorageClass SC, bool IsPartialSpecialization, bool IsMemberSpecialization);
/// Get the specialization of the given variable template corresponding to
/// the specified argument list, or a null-but-valid result if the arguments
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 976b3a3e1ecedb..58ce956f4b916a 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -309,16 +309,16 @@ bool TemplateDecl::isTypeAlias() const {
void RedeclarableTemplateDecl::anchor() {}
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
- if (Common)
- return Common;
+ if (CommonBase *C = Common.getPointer())
+ return C;
// Walk the previous-declaration chain until we either find a declaration
// with a common pointer or we run out of previous declarations.
SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
Prev = Prev->getPreviousDecl()) {
- if (Prev->Common) {
- Common = Prev->Common;
+ if (CommonBase *C = Prev->Common.getPointer()) {
+ Common.setPointer(C);
break;
}
@@ -326,18 +326,18 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
}
// If we never found a common pointer, allocate one now.
- if (!Common) {
+ if (!Common.getPointer()) {
// FIXME: If any of the declarations is from an AST file, we probably
// need an update record to add the common data.
- Common = newCommon(getASTContext());
+ Common.setPointer(newCommon(getASTContext()));
}
// Update any previous declarations we saw with the common pointer.
for (const RedeclarableTemplateDecl *Prev : PrevDecls)
- Prev->Common = Common;
+ Prev->Common.setPointer(Common.getPointer());
- return Common;
+ return Common.getPointer();
}
void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
@@ -467,15 +467,15 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
// If we haven't created a common pointer yet, then it can just be created
// with the usual method.
- if (!Base::Common)
+ if (!Base::Common.getPointer())
return;
- Common *ThisCommon = static_cast<Common *>(Base::Common);
+ Common *ThisCommon = static_cast<Common *>(Base::Common.getPointer());
Common *PrevCommon = nullptr;
SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
for (; Prev; Prev = Prev->getPreviousDecl()) {
- if (Prev->Base::Common) {
- PrevCommon = static_cast<Common *>(Prev->Base::Common);
+ if (CommonBase *C = Prev->Base::Common.getPointer()) {
+ PrevCommon = static_cast<Common *>(C);
break;
}
PreviousDecls.push_back(Prev);
@@ -485,7 +485,7 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
// use this common pointer.
if (!PrevCommon) {
for (auto *D : PreviousDecls)
- D->Base::Common = ThisCommon;
+ D->Base::Common.setPointer(ThisCommon);
return;
}
@@ -493,7 +493,7 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
assert(ThisCommon->Specializations.size() == 0 &&
"Can't merge incompatible declarations!");
- Base::Common = PrevCommon;
+ Base::Common.setPointer(PrevCommon);
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0f63c764536ecb..9d1927680146b5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -7655,7 +7655,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
: SourceLocation();
DeclResult Res = ActOnVarTemplateSpecialization(
S, D, TInfo, Previous, TemplateKWLoc, TemplateParams, SC,
- IsPartialSpecialization);
+ IsPartialSpecialization, IsMemberSpecialization);
if (Res.isInvalid())
return nullptr;
NewVD = cast<VarDecl>(Res.get());
@@ -7674,6 +7674,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
TemplateParams, NewVD);
NewVD->setDescribedVarTemplate(NewTemplate);
+ // If we are providing an explicit specialization of a static variable
+ // template, make a note of that.
+ if (IsMemberSpecialization)
+ NewTemplate->setMemberSpecialization();
}
// If this decl has an auto type in need of deduction, make a note of the
@@ -8049,12 +8053,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
? TPC_ClassTemplateMember
: TPC_VarTemplate))
NewVD->setInvalidDecl();
-
- // If we are providing an explicit specialization of a static variable
- // template, make a note of that.
- if (PrevVarTemplate &&
- PrevVarTemplate->getInstantiatedFromMemberTemplate())
- PrevVarTemplate->setMemberSpecialization();
}
}
@@ -9858,6 +9856,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD);
FunctionTemplate->setLexicalDeclContext(CurContext);
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+ if (isMemberSpecialization)
+ FunctionTemplate->setMemberSpecialization();
// For source fidelity, store the other template param lists.
if (TemplateParamLists.size() > 1) {
@@ -12004,10 +12004,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// If this is an explicit specialization of a member that is a function
// template, mark it as a member specialization.
- if (IsMemberSpecialization &&
- NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
+ if (IsMemberSpecialization) {
NewTemplateDecl->setMemberSpecialization();
- assert(OldTemplateDecl->isMemberSpecialization());
+ // assert(OldTemplateDecl->isMemberSpecialization());
// Explicit specializations of a member template do not inherit deleted
// status from the parent member template that they are specializing.
if (OldFD->isDeleted()) {
@@ -17066,8 +17065,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
DeclResult Result = CheckClassTemplate(
S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams,
AS, ModulePrivateLoc,
- /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1,
- TemplateParameterLists.data(), SkipBody);
+ /*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(),
+ isMemberSpecialization, SkipBody);
return Result.get();
} else {
// The "template<>" header is extraneous.
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3044f1218f5b23..8d0dfa4da33e4f 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17411,8 +17411,7 @@ DeclResult Sema::ActOnTemplatedFriendTag(
return CheckClassTemplate(S, TagSpec, TagUseKind::Friend, TagLoc, SS,
Name, NameLoc, Attr, TemplateParams, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
- FriendLoc, TempParamLists.size() - 1,
- TempParamLists.data())
+ FriendLoc, TempParamLists.drop_back(), IsMemberSpecialization)
.get();
} else {
// The "template<>" header is extraneous.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index bf6b53700d90eb..7bdc87b8c7439f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1793,8 +1793,8 @@ DeclResult Sema::CheckClassTemplate(
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
- SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
- TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) {
+ SourceLocation FriendLoc, ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
+ bool IsMemberSpecialization, SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TagUseKind::Reference &&
@@ -2087,10 +2087,9 @@ DeclResult Sema::CheckClassTemplate(
PrevClassTemplate->getTemplatedDecl() : nullptr,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(*this, NewClass, SS);
- if (NumOuterTemplateParamLists > 0)
+ if (!OuterTemplateParamLists.empty())
NewClass->setTemplateParameterListsInfo(
- Context,
- llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists));
+ Context, OuterTemplateParamLists);
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
@@ -2103,7 +2102,10 @@ DeclResult Sema::CheckClassTemplate(
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
NewClass);
-
+ // If we are providing an explicit specialization of a member that is a
+ // class template, make a note of that.
+ if (IsMemberSpecialization)
+ NewTemplate->setMemberSpecialization();
if (ShouldAddRedecl)
NewTemplate->setPreviousDecl(PrevClassTemplate);
@@ -2118,12 +2120,6 @@ DeclResult Sema::CheckClassTemplate(
assert(T->isDependentType() && "Class template type is not dependent?");
(void)T;
- // If we are providing an explicit specialization of a member that is a
- // class template, make a note of that.
- if (PrevClassTemplate &&
- PrevClassTemplate->getInstantiatedFromMemberTemplate())
- PrevClassTemplate->setMemberSpecialization();
-
// Set the access specifier.
if (!Invalid && TUK != TagUseKind::Friend &&
NewTemplate->getDeclContext()->isRecord())
@@ -3970,7 +3966,7 @@ void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) {
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
- StorageClass SC, bool IsPartialSpecialization) {
+ StorageClass SC, bool IsPartialSpecialization, bool IsMemberSpecialization) {
// D must be variable template id.
assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
"Variable template specialization is declared with a template id.");
@@ -4087,16 +4083,18 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
Context, VarTemplate->getDeclContext(), TemplateKWLoc,
TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
CanonicalConverted);
+ // If we are providing an explicit specialization of a member variable
+ // template specialization, make a note of that.
+ if (IsMemberSpecialization)
+ Partial->setMemberSpecialization();
Partial->setTemplateArgsAsWritten(TemplateArgs);
if (!PrevPartial)
VarTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;
- // If we are providing an explicit specialization of a member variable
- // template specialization, make a note of that.
- if (PrevPartial && PrevPartial->getInstantiatedFromMember())
- PrevPartial->setMemberSpecialization();
+ //if (PrevPartial && PrevPartial->getInstantiatedFromMember())
+ // PrevPartial->setMemberSpecialization();
CheckTemplatePartialSpecialization(Partial);
} else {
@@ -8304,8 +8302,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
TemplateParams,
AS_none, /*ModulePrivateLoc=*/SourceLocation(),
/*FriendLoc*/SourceLocation(),
- TemplateParameterLists.size() - 1,
- TemplateParameterLists.data());
+ TemplateParameterLists.drop_back(),
+ isMemberSpecialization);
}
// Create a new class template partial specialization declaration node.
@@ -8315,6 +8313,11 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplatePartialSpecializationDecl::Create(
Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams,
ClassTemplate, CanonicalConverted, CanonType, PrevPartial);
+
+ // If we are providing an explicit specialization of a member class
+ // template specialization, make a note of that.
+ if (isMemberSpecialization)
+ Partial->setMemberSpecialization();
Partial->setTemplateArgsAsWritten(TemplateArgs);
SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
@@ -8326,11 +8329,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;
- // If we are providing an explicit specialization of a member class
- // template specialization, make a note of that.
- if (PrevPartial && PrevPartial->getInstantiatedFromMember())
- PrevPartial->setMemberSpecialization();
-
CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
@@ -11127,7 +11125,7 @@ class ExplicitSpecializationVisibilityChecker {
template<typename TemplDecl>
void checkTemplate(TemplDecl *TD) {
- if (TD->isMemberSpecialization()) {
+ if (TD->getMostRecentDecl()->isMemberSpecialization()) {
if (!CheckMemberSpecialization(TD))
diagnose(TD->getMostRecentDecl(), false);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c42cc250bb904a..c27bc4690d10e8 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -332,12 +332,15 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
MultiLevelTemplateArgumentList &Result) {
+ #if 0
if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
Result.addOuterTemplateArguments(
const_cast<FunctionTemplateDecl *>(FTD),
const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
/*Final=*/false);
+
+
NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
@@ -381,6 +384,21 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
}
return Response::ChangeDecl(FTD->getLexicalDeclContext());
+ #else
+ if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
+ Result.addOuterTemplateArguments(
+ const_cast<FunctionTemplateDecl *>(FTD),
+ const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
+ /*Final=*/false);
+ }
+
+ if (FTD->isMemberSpecialization())
+ return Response::Done();
+
+ if (FTD->getFriendObjectKind())
+ return Response::ChangeDecl(FTD->getLexicalDeclContext());
+ return Response::UseNextDecl(FTD);
+ #endif
}
Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec,
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 9272e23c7da3fc..d9556dc4ce731a 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2416,11 +2416,13 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Make sure we've allocated the Common pointer first. We do this before
// VisitTemplateDecl so that getCommonPtr() can be used during initialization.
RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
- if (!CanonD->Common) {
- CanonD->Common = CanonD->newCommon(Reader.getContext());
+ if (!CanonD->Common.getPointer()) {
+ CanonD->Common.setPointer(CanonD->newCommon(Reader.getContext()));
Reader.PendingDefinitions.insert(CanonD);
}
- D->Common = CanonD->Common;
+ D->Common.setPointer(CanonD->Common.getPointer());
+ if (Record.readInt())
+ D->setMemberSpecialization();
// If this is the first declaration of the template, fill in the information
// for the 'common' pointer.
@@ -2429,8 +2431,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
assert(RTD->getKind() == D->getKind() &&
"InstantiatedFromMemberTemplate kind mismatch");
D->setInstantiatedFromMemberTemplate(RTD);
- if (Record.readInt())
- D->setMemberSpecialization();
}
}
@@ -2562,12 +2562,12 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
D->TemplateParams = Params;
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
+ D->InstantiatedFromMember.setInt(Record.readInt());
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
readDeclAs<ClassTemplatePartialSpecializationDecl>());
- D->InstantiatedFromMember.setInt(Record.readInt());
}
}
@@ -2660,12 +2660,12 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
D->TemplateParams = Params;
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
+ D->InstantiatedFromMember.setInt(Record.readInt());
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
readDeclAs<VarTemplatePartialSpecializationDecl>());
- D->InstantiatedFromMember.setInt(Record.readInt());
}
}
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 555f6325da646b..eb45124f911475 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1707,13 +1707,14 @@ void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitRedeclarable(D);
+ // if (D->getInstantiatedFromMemberTemplate())
+ Record.push_back(D->isMemberSpecialization());
+
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
// getCommonPtr() can be used while this is still initializing.
if (D->isFirstDecl()) {
// This declaration owns the 'common' pointer, so serialize that data now.
Record.AddDeclRef(D->getInstantiatedFromMemberTemplate());
- if (D->getInstantiatedFromMemberTemplate())
- Record.push_back(D->isMemberSpecialization());
}
VisitTemplateDecl(D);
@@ -1788,10 +1789,10 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
VisitClassTemplateSpecializationDecl(D);
+ Record.push_back(D->isMemberSpecialization());
// These are read/set from/to the first declaration.
if (D->getPreviousDecl() == nullptr) {
Record.AddDeclRef(D->getInstantiatedFromMember());
- Record.push_back(D->isMemberSpecialization());
}
Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
@@ -1856,11 +1857,11 @@ void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
Record.AddTemplateParameterList(D->getTemplateParameters());
VisitVarTemplateSpecializationDecl(D);
+ Record.push_back(D->isMemberSpecialization());
// These are read/set from/to the first declaration.
if (D->getPreviousDecl() == nullptr) {
Record.AddDeclRef(D->getInstantiatedFromMember());
- Record.push_back(D->isMemberSpecialization());
}
Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION;
diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp
index 11ad401de23a8c..bbe8c79bec374c 100644
--- a/clang/test/PCH/cxx-templates.cpp
+++ b/clang/test/PCH/cxx-templates.cpp
@@ -34,15 +34,15 @@ struct A {
void test(const int (&a6)[17]) {
int x = templ_f<int, 5>(3);
-
+
S<char, float>::templ();
S<int, char>::partial();
S<int, float>::explicit_special();
-
+
Dep<A>::Ty ty;
Dep<A> a;
a.f();
-
+
S3<int> s3;
s3.m();
>From 4d696213bfb23e36d6d71e2dd1b70ad37bf6f3eb Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Thu, 8 Aug 2024 09:58:22 -0400
Subject: [PATCH 02/29] [WIP] set isMemberSpecialization before comparing
template parameter lists of class templates
---
clang/lib/Sema/SemaTemplate.cpp | 45 +++++++++++--------
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 11 ++++-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 30 ++++++++++---
clang/lib/Serialization/ASTReaderDecl.cpp | 2 +-
4 files changed, 61 insertions(+), 27 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7bdc87b8c7439f..1d06d75ab6a076 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1982,6 +1982,7 @@ DeclResult Sema::CheckClassTemplate(
}
if (PrevClassTemplate) {
+ #if 0
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
// could be dependent.
@@ -1994,6 +1995,7 @@ DeclResult Sema::CheckClassTemplate(
PrevClassTemplate->getTemplateParameters(), /*Complain=*/true,
TPL_TemplateMatch))
return true;
+ #endif
// C++ [temp.class]p4:
// In a redeclaration, partial specialization, explicit
@@ -2044,23 +2046,6 @@ DeclResult Sema::CheckClassTemplate(
return true;
}
- // Check the template parameter list of this declaration, possibly
- // merging in the template parameter list from the previous class
- // template declaration. Skip this check for a friend in a dependent
- // context, because the template parameter list might be dependent.
- if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) &&
- CheckTemplateParameterList(
- TemplateParams,
- PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate)
- : nullptr,
- (SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
- SemanticContext->isDependentContext())
- ? TPC_ClassTemplateMember
- : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate
- : TPC_ClassTemplate,
- SkipBody))
- Invalid = true;
-
if (SS.isSet()) {
// If the name of the template was qualified, we must be defining the
// template out-of-line.
@@ -2129,6 +2114,30 @@ DeclResult Sema::CheckClassTemplate(
NewClass->setLexicalDeclContext(CurContext);
NewTemplate->setLexicalDeclContext(CurContext);
+
+ if (ShouldAddRedecl && PrevClassTemplate && !TemplateParameterListsAreEqual(
+ NewTemplate, TemplateParams,
+ PrevClassTemplate, PrevClassTemplate->getTemplateParameters(),
+ /*Complain=*/true, TPL_TemplateMatch))
+ return true;
+
+
+ // Check the template parameter list of this declaration, possibly
+ // merging in the template parameter list from the previous class
+ // template declaration. Skip this check for a friend in a dependent
+ // context, because the template parameter list might be dependent.
+ if (ShouldAddRedecl && CheckTemplateParameterList(
+ TemplateParams,
+ PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate)
+ : nullptr,
+ (SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
+ SemanticContext->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate
+ : TPC_ClassTemplate,
+ SkipBody))
+ Invalid = true;
+
if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
NewClass->startDefinition();
@@ -11126,7 +11135,7 @@ class ExplicitSpecializationVisibilityChecker {
template<typename TemplDecl>
void checkTemplate(TemplDecl *TD) {
if (TD->getMostRecentDecl()->isMemberSpecialization()) {
- if (!CheckMemberSpecialization(TD))
+ if (!CheckMemberSpecialization(TD->getMostRecentDecl()))
diagnose(TD->getMostRecentDecl(), false);
}
}
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 545da21183c3c4..d09b7a807f700f 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -802,8 +802,15 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
// A list of template arguments for transforming the require-clause of F.
// It must contain the entire set of template argument lists.
- MultiLevelTemplateArgumentList ArgsForBuildingRC;
+ MultiLevelTemplateArgumentList ArgsForBuildingRC =
+ SemaRef.getTemplateInstantiationArgs(
+ F, F->getLexicalDeclContext(),
+ /*Final=*/false, /*Innermost=*/TemplateArgsForBuildingRC,
+ /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr,
+ /*ForConstraintInstantiation=*/true);;
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
+ #if 0
ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC);
// For 2), if the underlying deduction guide F is nested in a class template,
// we need the entire template argument list, as the constraint AST in the
@@ -846,6 +853,8 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
for (auto It : OuterLevelArgs)
ArgsForBuildingRC.addOuterTemplateArguments(It.Args);
}
+ #endif
+
ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
if (E.isInvalid())
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c27bc4690d10e8..095dfebafe076e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -385,12 +385,10 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
return Response::ChangeDecl(FTD->getLexicalDeclContext());
#else
- if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
- Result.addOuterTemplateArguments(
- const_cast<FunctionTemplateDecl *>(FTD),
- const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
- /*Final=*/false);
- }
+ Result.addOuterTemplateArguments(
+ const_cast<FunctionTemplateDecl *>(FTD),
+ const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
+ /*Final=*/false);
if (FTD->isMemberSpecialization())
return Response::Done();
@@ -401,6 +399,24 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
#endif
}
+Response HandleClassTemplateDecl(const ClassTemplateDecl *CTD,
+ MultiLevelTemplateArgumentList &Result) {
+ #if 0
+ Result.addOuterTemplateArguments(
+ const_cast<ClassTemplateDecl *>(CTD),
+ const_cast<ClassTemplateDecl *>(CTD)->getInjectedTemplateArgs(),
+ /*Final=*/false);
+
+ if (CTD->isMemberSpecialization())
+ return Response::Done();
+
+ if (CTD->getFriendObjectKind())
+ return Response::ChangeDecl(CTD->getLexicalDeclContext());
+ return Response::UseNextDecl(CTD);
+ #endif
+ return Response::ChangeDecl(CTD->getLexicalDeclContext());
+}
+
Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec,
MultiLevelTemplateArgumentList &Result,
ASTContext &Context,
@@ -539,7 +555,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
} else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CurDecl)) {
R = HandleFunctionTemplateDecl(FTD, Result);
} else if (const auto *CTD = dyn_cast<ClassTemplateDecl>(CurDecl)) {
- R = Response::ChangeDecl(CTD->getLexicalDeclContext());
+ R = HandleClassTemplateDecl(CTD, Result);
} else if (!isa<DeclContext>(CurDecl)) {
R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl);
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) {
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index d9556dc4ce731a..5a893515de9cc6 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2888,7 +2888,7 @@ void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
// If we merged the template with a prior declaration chain, merge the
// common pointer.
// FIXME: Actually merge here, don't just overwrite.
- D->Common = D->getCanonicalDecl()->Common;
+ D->Common.setPointer(D->getCanonicalDecl()->Common.getPointer());
}
/// "Cast" to type T, asserting if we don't have an implicit conversion.
>From b04d89f1e46d34cbd70b2c47a653eaa2a014b61b Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Thu, 8 Aug 2024 15:00:23 -0400
Subject: [PATCH 03/29] [FOLD]
---
clang/lib/Sema/SemaTemplate.cpp | 2 +-
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 2 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 73 +++++++++++++++----
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 ++
4 files changed, 66 insertions(+), 16 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 1d06d75ab6a076..e09e1f854fb590 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2128,7 +2128,7 @@ DeclResult Sema::CheckClassTemplate(
// context, because the template parameter list might be dependent.
if (ShouldAddRedecl && CheckTemplateParameterList(
TemplateParams,
- PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate)
+ PrevClassTemplate ? PrevClassTemplate->getTemplateParameters()
: nullptr,
(SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
SemanticContext->isDependentContext())
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index d09b7a807f700f..ea02e979c4270f 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -317,7 +317,7 @@ struct ConvertConstructorToDeductionGuideTransform {
}
if (NestedPattern)
- OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template);
+ OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(/*D=*/nullptr, Template->getDeclContext());
}
Sema &SemaRef;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 095dfebafe076e..92b2c2d2337279 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -52,7 +52,6 @@ using namespace sema;
//===----------------------------------------------------------------------===/
namespace {
-namespace TemplateInstArgsHelpers {
struct Response {
const Decl *NextDecl = nullptr;
bool IsDone = false;
@@ -84,6 +83,7 @@ struct Response {
}
};
+namespace TemplateInstArgsHelpers {
// Retrieve the primary template for a lambda call operator. It's
// unfortunate that we only have the mappings of call operators rather
// than lambda classes.
@@ -331,7 +331,8 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
}
Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
- MultiLevelTemplateArgumentList &Result) {
+ MultiLevelTemplateArgumentList &Result,
+ bool ForConstraintInstantiation) {
#if 0
if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
Result.addOuterTemplateArguments(
@@ -385,10 +386,11 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
return Response::ChangeDecl(FTD->getLexicalDeclContext());
#else
- Result.addOuterTemplateArguments(
- const_cast<FunctionTemplateDecl *>(FTD),
- const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
- /*Final=*/false);
+ if (ForConstraintInstantiation)
+ Result.addOuterTemplateArguments(
+ const_cast<FunctionTemplateDecl *>(FTD),
+ const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
+ /*Final=*/false);
if (FTD->isMemberSpecialization())
return Response::Done();
@@ -400,12 +402,15 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
}
Response HandleClassTemplateDecl(const ClassTemplateDecl *CTD,
- MultiLevelTemplateArgumentList &Result) {
- #if 0
- Result.addOuterTemplateArguments(
- const_cast<ClassTemplateDecl *>(CTD),
- const_cast<ClassTemplateDecl *>(CTD)->getInjectedTemplateArgs(),
- /*Final=*/false);
+ MultiLevelTemplateArgumentList &Result,
+ bool ForConstraintInstantiation,
+ bool SkipForSpecialization) {
+ #if 1
+ if (!SkipForSpecialization && ForConstraintInstantiation)
+ Result.addOuterTemplateArguments(
+ const_cast<ClassTemplateDecl *>(CTD),
+ const_cast<ClassTemplateDecl *>(CTD)->getInjectedTemplateArgs(),
+ /*Final=*/false);
if (CTD->isMemberSpecialization())
return Response::Done();
@@ -496,6 +501,38 @@ Response HandleGenericDeclContext(const Decl *CurDecl) {
return Response::UseNextDecl(CurDecl);
}
} // namespace TemplateInstArgsHelpers
+
+
+struct TemplateInstantiationArgumentCollecter
+ : DeclVisitor<TemplateInstantiationArgumentCollecter, Decl*> {
+ MultiLevelTemplateArgumentList &Result;
+ bool RelativeToPrimary;
+ bool ForConstraintInstantiation;
+ bool SkipForSpecialization;
+
+ TemplateInstantiationArgumentCollecter(
+ MultiLevelTemplateArgumentList &Result,
+ bool RelativeToPrimary,
+ bool ForConstraintInstantiation,
+ bool SkipForSpecialization) :
+ Result(Result), RelativeToPrimary(RelativeToPrimary),
+ ForConstraintInstantiation(ForConstraintInstantiation),
+ SkipForSpecialization(SkipForSpecialization) { }
+ //using inherited = DeclVisitor<TemplateInstantiationArgumentCollecter>;
+
+
+
+ Decl *VisitDecl(Decl *D) {
+ if (D->isFileContextDecl())
+ return nullptr;
+
+ if (isa<DeclContext>(D))
+ RelativeToPrimary = false;
+
+ return Decl::castFromDeclContext(D->getDeclContext());
+ }
+};
+
} // namespace
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
@@ -529,6 +566,14 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
CurDecl = Response::UseNextDecl(CurDecl).NextDecl;
}
+ TemplateInstantiationArgumentCollecter Collecter(
+ Result, RelativeToPrimary,
+ ForConstraintInstantiation,
+ SkipForSpecialization);
+ do {
+ CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
+ } while (CurDecl);
+
while (!CurDecl->isFileContextDecl()) {
Response R;
if (const auto *VarTemplSpec =
@@ -553,9 +598,9 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
dyn_cast<ImplicitConceptSpecializationDecl>(CurDecl)) {
R = HandleImplicitConceptSpecializationDecl(CSD, Result);
} else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CurDecl)) {
- R = HandleFunctionTemplateDecl(FTD, Result);
+ R = HandleFunctionTemplateDecl(FTD, Result, ForConstraintInstantiation);
} else if (const auto *CTD = dyn_cast<ClassTemplateDecl>(CurDecl)) {
- R = HandleClassTemplateDecl(CTD, Result);
+ R = HandleClassTemplateDecl(CTD, Result, ForConstraintInstantiation, SkipForSpecialization);
} else if (!isa<DeclContext>(CurDecl)) {
R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl);
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 51109b092d7568..97c240d58c0709 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5183,9 +5183,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
RebuildTypeSourceInfoForDefaultSpecialMembers();
SetDeclDefaulted(Function, PatternDecl->getLocation());
} else {
+ #if 0
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
Function, Function->getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt, false, PatternDecl);
+ #else
+ MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
+ Function, Function->getLexicalDeclContext());
+ #endif
// Substitute into the qualifier; we can get a substitution failure here
// through evil use of alias templates.
>From 8d099394ca7e2ec1d258aa41da6822441deea693 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 12 Aug 2024 08:30:01 -0400
Subject: [PATCH 04/29] [FOLD] pass old and new declarations to
TemplateParameterListsAreEqual when comparing variable templates
---
clang/lib/Sema/SemaDecl.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9d1927680146b5..0eb58eb4339bc7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4506,8 +4506,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// Ensure the template parameters are compatible.
if (NewTemplate &&
- !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
- OldTemplate->getTemplateParameters(),
+ !TemplateParameterListsAreEqual(NewTemplate, NewTemplate->getTemplateParameters(),
+ OldTemplate, OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
return New->setInvalidDecl();
>From 3861eab6df1382277b8b106f907c9412addc6159 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 12 Aug 2024 08:30:36 -0400
Subject: [PATCH 05/29] [FOLD] implement TemplateInstantiationArgumentCollecter
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 320 +++++++++++++++++++--
1 file changed, 299 insertions(+), 21 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 92b2c2d2337279..481d32a310e260 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -82,8 +82,6 @@ struct Response {
return R;
}
};
-
-namespace TemplateInstArgsHelpers {
// Retrieve the primary template for a lambda call operator. It's
// unfortunate that we only have the mappings of call operators rather
// than lambda classes.
@@ -171,6 +169,23 @@ bool isLambdaEnclosedByTypeAliasDecl(
.TraverseType(Underlying);
}
+namespace TemplateInstArgsHelpers {
+
+// If we have a template template parameter with translation unit context,
+// then we're performing substitution into a default template argument of
+// this template template parameter before we've constructed the template
+// that will own this template template parameter. In this case, we
+// use empty template parameter lists for all of the outer templates
+// to avoid performing any substitutions.
+Response
+HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP,
+ MultiLevelTemplateArgumentList &Result) {
+ for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
+ Result.addOuterTemplateArguments(std::nullopt);
+ return Response::Done();
+}
+
+#if 0
// Add template arguments from a variable template instantiation.
Response
HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
@@ -211,20 +226,6 @@ HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec);
}
-// If we have a template template parameter with translation unit context,
-// then we're performing substitution into a default template argument of
-// this template template parameter before we've constructed the template
-// that will own this template template parameter. In this case, we
-// use empty template parameter lists for all of the outer templates
-// to avoid performing any substitutions.
-Response
-HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP,
- MultiLevelTemplateArgumentList &Result) {
- for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
- Result.addOuterTemplateArguments(std::nullopt);
- return Response::Done();
-}
-
Response HandlePartialClassTemplateSpec(
const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec,
MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) {
@@ -500,36 +501,310 @@ Response HandleImplicitConceptSpecializationDecl(
Response HandleGenericDeclContext(const Decl *CurDecl) {
return Response::UseNextDecl(CurDecl);
}
+#endif
} // namespace TemplateInstArgsHelpers
struct TemplateInstantiationArgumentCollecter
: DeclVisitor<TemplateInstantiationArgumentCollecter, Decl*> {
+ Sema &S;
MultiLevelTemplateArgumentList &Result;
bool RelativeToPrimary;
bool ForConstraintInstantiation;
bool SkipForSpecialization;
TemplateInstantiationArgumentCollecter(
+ Sema &S,
MultiLevelTemplateArgumentList &Result,
bool RelativeToPrimary,
bool ForConstraintInstantiation,
bool SkipForSpecialization) :
- Result(Result), RelativeToPrimary(RelativeToPrimary),
+ S(S), Result(Result), RelativeToPrimary(RelativeToPrimary),
ForConstraintInstantiation(ForConstraintInstantiation),
SkipForSpecialization(SkipForSpecialization) { }
- //using inherited = DeclVisitor<TemplateInstantiationArgumentCollecter>;
+ Decl *Done() {
+ return nullptr;
+ }
+
+ Decl *ChangeDecl(const Decl *D) {
+ RelativeToPrimary = false;
+ return const_cast<Decl *>(D);
+ }
+
+ Decl *ChangeDecl(const DeclContext *DC) {
+ return ChangeDecl(Decl::castFromDeclContext(DC));
+ }
+
+ Decl *UseNextDecl(const Decl *D) {
+ return ChangeDecl(D->getDeclContext());
+ }
+
+ Decl *DontClearRelativeToPrimaryNextDecl(const Decl* D) {
+ return const_cast<Decl *>(
+ Decl::castFromDeclContext(D->getDeclContext()));
+ }
+
+ Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) {
+ for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I)
+ Result.addOuterTemplateArguments(std::nullopt);
+ return Done();
+ }
+
+ Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) {
+ if (ForConstraintInstantiation)
+ Result.addOuterTemplateArguments(
+ FTD, FTD->getInjectedTemplateArgs(), /*Final=*/false);
+
+ if (FTD->isMemberSpecialization())
+ return Done();
+
+ if (FTD->getFriendObjectKind())
+ return ChangeDecl(FTD->getLexicalDeclContext());
+ return UseNextDecl(FTD);
+ }
+
+ Decl *VisitVarTemplateDecl(VarTemplateDecl *VTD) {
+ if (!SkipForSpecialization && ForConstraintInstantiation)
+ Result.addOuterTemplateArguments(
+ VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false);
+
+ if (VTD->isMemberSpecialization())
+ return Done();
+
+ return UseNextDecl(VTD);
+ }
+
+ Decl *VisitClassTemplateDecl(ClassTemplateDecl *CTD) {
+ if (!SkipForSpecialization && ForConstraintInstantiation)
+ Result.addOuterTemplateArguments(
+ CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false);
+
+ if (CTD->isMemberSpecialization())
+ return Done();
+
+ if (CTD->getFriendObjectKind())
+ return ChangeDecl(CTD->getLexicalDeclContext());
+ return UseNextDecl(CTD);
+ }
+
+ Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) {
+ if (!SkipForSpecialization)
+ Result.addOuterRetainedLevels(CTPSD->getTemplateDepth());
+ return Done();
+ }
+
+ Decl *VisitFunctionDecl(FunctionDecl *FD) {
+ // Add template arguments from a function template specialization.
+ if (!RelativeToPrimary &&
+ FD->getTemplateSpecializationKindForInstantiation() ==
+ TSK_ExplicitSpecialization)
+ return Done();
+
+ if (!RelativeToPrimary &&
+ FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
+ // This is an implicit instantiation of an explicit specialization. We
+ // don't get any template arguments from this function but might get
+ // some from an enclosing template.
+ return UseNextDecl(FD);
+ } else if (const TemplateArgumentList *TemplateArgs =
+ FD->getTemplateSpecializationArgs()) {
+ // Add the template arguments for this specialization.
+ Result.addOuterTemplateArguments(
+ FD, TemplateArgs->asArray(), /*Final=*/false);
+
+ if (RelativeToPrimary &&
+ (FD->getTemplateSpecializationKind() ==
+ TSK_ExplicitSpecialization ||
+ (FD->getFriendObjectKind() &&
+ !FD->getPrimaryTemplate()->getFriendObjectKind())))
+ return UseNextDecl(FD);
+
+ // If this function was instantiated from a specialized member that is
+ // a function template, we're done.
+ assert(FD->getPrimaryTemplate() && "No function template?");
+ if (FD->getPrimaryTemplate()->isMemberSpecialization())
+ return Done();
+
+ // If this function is a generic lambda specialization, we are done.
+ if (!ForConstraintInstantiation &&
+ isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) {
+ // TypeAliasTemplateDecls should be taken into account, e.g.
+ // when we're deducing the return type of a lambda.
+ //
+ // template <class> int Value = 0;
+ // template <class T>
+ // using T = decltype([]<int U = 0>() { return Value<T>; }());
+ //
+ if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) {
+ if (isLambdaEnclosedByTypeAliasDecl(
+ /*PrimaryLambdaCallOperator=*/getPrimaryTemplateOfGenericLambda(FD),
+ /*PrimaryTypeAliasDecl=*/TypeAlias.PrimaryTypeAliasDecl))
+ return UseNextDecl(FD);
+ }
+ return Done();
+ }
+
+ } else if (FD->getDescribedFunctionTemplate()) {
+ assert(
+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "Outer template not instantiated?");
+ }
+ // If this is a friend or local declaration and it declares an entity at
+ // namespace scope, take arguments from its lexical parent
+ // instead of its semantic parent, unless of course the pattern we're
+ // instantiating actually comes from the file's context!
+ if ((FD->getFriendObjectKind() || FD->isLocalExternDecl()) &&
+ FD->getNonTransparentDeclContext()->isFileContext()) {
+ return ChangeDecl(FD->getLexicalDeclContext());
+ }
+
+ if (ForConstraintInstantiation && FD->getFriendObjectKind())
+ return ChangeDecl(FD->getLexicalDeclContext());
+ return UseNextDecl(FD);
+ }
+
+ Decl *VisitCXXRecordDecl(CXXRecordDecl *RD) {
+ if (ClassTemplateDecl *ClassTemplate = RD->getDescribedClassTemplate()) {
+ assert(
+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "Outer template not instantiated?");
+ if (ClassTemplate->isMemberSpecialization())
+ return Done();
+ if (ForConstraintInstantiation)
+ Result.addOuterTemplateArguments(
+ RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false);
+ }
+ if (const MemberSpecializationInfo *MSInfo =
+ RD->getMemberSpecializationInfo())
+ if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return Done();
+
+ bool IsFriend = RD->getFriendObjectKind() ||
+ (RD->getDescribedClassTemplate() &&
+ RD->getDescribedClassTemplate()->getFriendObjectKind());
+ if (ForConstraintInstantiation && IsFriend &&
+ RD->getNonTransparentDeclContext()->isFileContext()) {
+ return ChangeDecl(RD->getLexicalDeclContext());
+ }
+
+ // This is to make sure we pick up the VarTemplateSpecializationDecl or the
+ // TypeAliasTemplateDecl that this lambda is defined inside of.
+ if (RD->isLambda()) {
+ if (Decl *LCD = RD->getLambdaContextDecl())
+ return ChangeDecl(LCD);
+ // Retrieve the template arguments for a using alias declaration.
+ // This is necessary for constraint checking, since we always keep
+ // constraints relative to the primary template.
+ if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) {
+ const FunctionDecl *PrimaryLambdaCallOperator =
+ getPrimaryTemplateOfGenericLambda(RD->getLambdaCallOperator());
+ if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator,
+ TypeAlias.PrimaryTypeAliasDecl)) {
+ Result.addOuterTemplateArguments(TypeAlias.Template,
+ TypeAlias.AssociatedTemplateArguments,
+ /*Final=*/false);
+ // Visit the parent of the current type alias declaration rather than
+ // the lambda thereof.
+ // E.g., in the following example:
+ // struct S {
+ // template <class> using T = decltype([]<Concept> {} ());
+ // };
+ // void foo() {
+ // S::T var;
+ // }
+ // The instantiated lambda expression (which we're visiting at 'var')
+ // has a function DeclContext 'foo' rather than the Record DeclContext
+ // S. This seems to be an oversight to me that we may want to set a
+ // Sema Context from the CXXScopeSpec before substituting into T.
+ return ChangeDecl(TypeAlias.Template->getDeclContext());
+ }
+ }
+ }
+
+ return UseNextDecl(RD);
+ }
+
+ Decl *VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) {
+ if (!CTSD->isClassScopeExplicitSpecialization()) {
+ // We're done when we hit an explicit specialization.
+ if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization &&
+ !isa<ClassTemplatePartialSpecializationDecl>(CTSD))
+ return Done();
+
+ if (!SkipForSpecialization)
+ Result.addOuterTemplateArguments(
+ CTSD, CTSD->getTemplateInstantiationArgs().asArray(), /*Final=*/false);
+
+ // If this class template specialization was instantiated from a
+ // specialized member that is a class template, we're done.
+ assert(CTSD->getSpecializedTemplate() && "No class template?");
+ if (CTSD->getSpecializedTemplate()->isMemberSpecialization())
+ return Done();
+
+ // If this was instantiated from a partial template specialization, we need
+ // to get the next level of declaration context from the partial
+ // specialization, as the ClassTemplateSpecializationDecl's
+ // DeclContext/LexicalDeclContext will be for the primary template.
+ if (auto *CTPSD = CTSD->getSpecializedTemplateOrPartial()
+ .dyn_cast<ClassTemplatePartialSpecializationDecl *>())
+ return ChangeDecl(CTPSD->getLexicalDeclContext());
+ }
+ return UseNextDecl(CTSD);
+ }
+
+ Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
+ // For a class-scope explicit specialization, there are no template arguments
+ // at this level, but there may be enclosing template arguments.
+ if (VTSD->isClassScopeExplicitSpecialization())
+ return DontClearRelativeToPrimaryNextDecl(VTSD);
+
+ // We're done when we hit an explicit specialization.
+ if (VTSD->getSpecializationKind() == TSK_ExplicitSpecialization &&
+ !isa<VarTemplatePartialSpecializationDecl>(VTSD))
+ return Done();
+
+ // If this variable template specialization was instantiated from a
+ // specialized member that is a variable template, we're done.
+ assert(VTSD->getSpecializedTemplate() && "No variable template?");
+ llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ Specialized = VTSD->getSpecializedTemplateOrPartial();
+ if (VarTemplatePartialSpecializationDecl *VTPSD =
+ Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+ if (!SkipForSpecialization)
+ Result.addOuterTemplateArguments(
+ VTPSD, VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
+ if (VTPSD->isMemberSpecialization())
+ return Done();
+ } else {
+ VarTemplateDecl *VTD = Specialized.get<VarTemplateDecl *>();
+ if (!SkipForSpecialization)
+ Result.addOuterTemplateArguments(
+ VTD, VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
+ if (VTD->isMemberSpecialization())
+ return Done();
+ }
+ return DontClearRelativeToPrimaryNextDecl(VTSD);
+ }
+
+ Decl *VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl *ICSD) {
+ Result.addOuterTemplateArguments(
+ ICSD, ICSD->getTemplateArguments(),
+ /*Final=*/false);
+ return UseNextDecl(ICSD);
+ }
Decl *VisitDecl(Decl *D) {
if (D->isFileContextDecl())
- return nullptr;
+ return Done();
if (isa<DeclContext>(D))
RelativeToPrimary = false;
- return Decl::castFromDeclContext(D->getDeclContext());
+ return UseNextDecl(D);
}
};
@@ -567,13 +842,15 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
}
TemplateInstantiationArgumentCollecter Collecter(
- Result, RelativeToPrimary,
+ *this, Result, RelativeToPrimary,
ForConstraintInstantiation,
SkipForSpecialization);
do {
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
} while (CurDecl);
+ return Result;
+ #if 0
while (!CurDecl->isFileContextDecl()) {
Response R;
if (const auto *VarTemplSpec =
@@ -619,6 +896,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
}
return Result;
+ #endif
}
bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
>From b0da1f06c3bd80136015d0660f7bae04ebfbbc6d Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 12 Aug 2024 08:52:11 -0400
Subject: [PATCH 06/29] [FOLD] update test
---
.../class-template-partial-specializations.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp
index 7772eecc69be8b..3358869b95e370 100644
--- a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp
@@ -33,11 +33,12 @@ class D{}; // expected-note{{previous definition is here}}
template<typename T>
class D<T>{}; // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}} expected-error{{redefinition of 'D'}}
-template<typename T> requires C1<T> // expected-note{{previous template declaration is here}}
-class E{};
+template<typename T> requires C1<T>
+class E{}; // expected-note{{previous definition is here}}
-template<typename T> // expected-error{{requires clause differs in template redeclaration}}
+template<typename T>
class E<T>{}; // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
+ // expected-error at -1{{redefinition of 'E'}}
template<typename T>
struct F{ enum{ value = 1 }; };
>From 0c9e6c3d5b052b083948735f118f6bda14e4c636 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 12 Aug 2024 12:25:45 -0400
Subject: [PATCH 07/29] [FOLD] further simplify getTemplateInstantiationArgs
---
clang/lib/Sema/SemaTemplateDeduction.cpp | 30 +++++
clang/lib/Sema/SemaTemplateInstantiate.cpp | 107 ++++++++++++++++--
clang/test/SemaCXX/friend.cpp | 4 +-
.../SemaTemplate/default-expr-arguments.cpp | 26 ++---
4 files changed, 142 insertions(+), 25 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 01f18e5a325197..db1f7177f514f2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3170,6 +3170,8 @@ template<>
struct IsPartialSpecialization<VarTemplatePartialSpecializationDecl> {
static constexpr bool value = true;
};
+
+#if 0
template <typename TemplateDeclT>
static bool DeducedArgsNeedReplacement(TemplateDeclT *Template) {
return false;
@@ -3184,6 +3186,7 @@ bool DeducedArgsNeedReplacement<ClassTemplatePartialSpecializationDecl>(
ClassTemplatePartialSpecializationDecl *Spec) {
return !Spec->isClassScopeExplicitSpecialization();
}
+#endif
template <typename TemplateDeclT>
static TemplateDeductionResult
@@ -3194,6 +3197,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
Template->getAssociatedConstraints(AssociatedConstraints);
+ #if 0
std::optional<ArrayRef<TemplateArgument>> Innermost;
// If we don't need to replace the deduced template arguments,
// we can add them immediately as the inner-most argument list.
@@ -3211,6 +3215,32 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
// instead of adding to inner-most.
if (!Innermost)
MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
+ #endif
+ MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
+ Template, Template->getDeclContext(), /*Final=*/false,
+ /*Innermost=*/CanonicalDeducedArgs, /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
+
+ #if 0
+ if (DeducedArgsNeedReplacement(Template)) {
+ MultiLevelTemplateArgumentList WithReplacement = S.getTemplateInstantiationArgs(
+ Template, Template->getDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt,
+ /*RelativeToPrimary=*/true, /*Pattern=*/
+ nullptr, /*ForConstraintInstantiation=*/true);
+
+ WithReplacement.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
+
+ assert(MLTAL.getNumLevels() == WithReplacement.getNumLevels());
+ assert(MLTAL.getNumSubstitutedLevels() == WithReplacement.getNumSubstitutedLevels());
+ auto First0 = MLTAL.begin(), Last0 = MLTAL.end();
+ auto First1 = WithReplacement.begin(), Last1 = WithReplacement.end();
+
+ while (First0 != Last0) {
+ assert(First0->Args.data() == First1->Args.data());
+ ++First0, ++First1;
+ }
+ }
+ #endif
if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
Info.getLocation(),
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 481d32a310e260..74149273b06fd0 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -546,12 +546,21 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) {
+ #if 0
for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I)
Result.addOuterTemplateArguments(std::nullopt);
return Done();
+ #endif
+ if (ForConstraintInstantiation)
+ Result.addOuterTemplateArguments(std::nullopt);
+
+ return UseNextDecl(TTPD);
}
Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) {
+ assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
+
if (ForConstraintInstantiation)
Result.addOuterTemplateArguments(
FTD, FTD->getInjectedTemplateArgs(), /*Final=*/false);
@@ -565,6 +574,9 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitVarTemplateDecl(VarTemplateDecl *VTD) {
+ assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
+
if (!SkipForSpecialization && ForConstraintInstantiation)
Result.addOuterTemplateArguments(
VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false);
@@ -576,6 +588,9 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitClassTemplateDecl(ClassTemplateDecl *CTD) {
+ assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
+
if (!SkipForSpecialization && ForConstraintInstantiation)
Result.addOuterTemplateArguments(
CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false);
@@ -588,13 +603,24 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(CTD);
}
+ #if 0
Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) {
if (!SkipForSpecialization)
Result.addOuterRetainedLevels(CTPSD->getTemplateDepth());
return Done();
}
+ #endif
Decl *VisitFunctionDecl(FunctionDecl *FD) {
+ if (!RelativeToPrimary) {
+ if (const MemberSpecializationInfo *MSI = FD->getMemberSpecializationInfo();
+ MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return Done();
+
+ if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return UseNextDecl(FD);
+ }
+ #if 0
// Add template arguments from a function template specialization.
if (!RelativeToPrimary &&
FD->getTemplateSpecializationKindForInstantiation() ==
@@ -607,13 +633,15 @@ struct TemplateInstantiationArgumentCollecter
// don't get any template arguments from this function but might get
// some from an enclosing template.
return UseNextDecl(FD);
- } else if (const TemplateArgumentList *TemplateArgs =
+ } else
+ #endif
+ if (const TemplateArgumentList *TemplateArgs =
FD->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
Result.addOuterTemplateArguments(
FD, TemplateArgs->asArray(), /*Final=*/false);
- if (RelativeToPrimary &&
+ if ( // RelativeToPrimary &&
(FD->getTemplateSpecializationKind() ==
TSK_ExplicitSpecialization ||
(FD->getFriendObjectKind() &&
@@ -676,10 +704,9 @@ struct TemplateInstantiationArgumentCollecter
RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false);
}
- if (const MemberSpecializationInfo *MSInfo =
- RD->getMemberSpecializationInfo())
- if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
- return Done();
+ if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo();
+ MSI &&MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return Done();
bool IsFriend = RD->getFriendObjectKind() ||
(RD->getDescribedClassTemplate() &&
@@ -727,6 +754,7 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) {
+ #if 0
if (!CTSD->isClassScopeExplicitSpecialization()) {
// We're done when we hit an explicit specialization.
if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization &&
@@ -752,10 +780,60 @@ struct TemplateInstantiationArgumentCollecter
return ChangeDecl(CTPSD->getLexicalDeclContext());
}
return UseNextDecl(CTSD);
+ #else
+ // For a class-scope explicit specialization, there are no template arguments
+ // at this level, but there may be enclosing template arguments.
+ if (CTSD->isClassScopeExplicitSpecialization())
+ return DontClearRelativeToPrimaryNextDecl(CTSD);
+
+ // We're done when we hit an explicit specialization.
+ if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization &&
+ !isa<ClassTemplatePartialSpecializationDecl>(CTSD))
+ return Done();
+
+ // If this class template specialization was instantiated from a
+ // specialized member that is a class template, we're done.
+ assert(CTSD->getSpecializedTemplate() && "No class template?");
+ llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>
+ Specialized = CTSD->getSpecializedTemplateOrPartial();
+ #if 0
+ if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
+ if (!SkipForSpecialization)
+ Result.addOuterTemplateArguments(
+ CTPSD, CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
+ if (CTPSD->isMemberSpecialization())
+ return Done();
+ } else {
+ auto *CTD = Specialized.get<ClassTemplateDecl *>();
+ if (!SkipForSpecialization)
+ Result.addOuterTemplateArguments(
+ CTD, CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
+ if (CTD->isMemberSpecialization())
+ return Done();
+ }
+ #else
+ if (!SkipForSpecialization)
+ Result.addOuterTemplateArguments(
+ CTSD, CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
+ if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
+ if (CTPSD->isMemberSpecialization())
+ return Done();
+ } else {
+ auto *CTD = Specialized.get<ClassTemplateDecl *>();
+ if (CTD->isMemberSpecialization())
+ return Done();
+ }
+ #endif
+
+ return DontClearRelativeToPrimaryNextDecl(CTSD);
+ #endif
}
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
- // For a class-scope explicit specialization, there are no template arguments
+ // For a class-scope explicit specialization, there are no template arguments
// at this level, but there may be enclosing template arguments.
if (VTSD->isClassScopeExplicitSpecialization())
return DontClearRelativeToPrimaryNextDecl(VTSD);
@@ -770,8 +848,7 @@ struct TemplateInstantiationArgumentCollecter
assert(VTSD->getSpecializedTemplate() && "No variable template?");
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
Specialized = VTSD->getSpecializedTemplateOrPartial();
- if (VarTemplatePartialSpecializationDecl *VTPSD =
- Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+ if (auto *VTPSD = Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
if (!SkipForSpecialization)
Result.addOuterTemplateArguments(
VTPSD, VTSD->getTemplateInstantiationArgs().asArray(),
@@ -779,7 +856,7 @@ struct TemplateInstantiationArgumentCollecter
if (VTPSD->isMemberSpecialization())
return Done();
} else {
- VarTemplateDecl *VTD = Specialized.get<VarTemplateDecl *>();
+ auto *VTD = Specialized.get<VarTemplateDecl *>();
if (!SkipForSpecialization)
Result.addOuterTemplateArguments(
VTD, VTSD->getTemplateInstantiationArgs().asArray(),
@@ -806,6 +883,14 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(D);
}
+
+ Decl *Visit(Decl *D) {
+ #if 0
+ if (TemplateDecl *TD = D->getDescribedTemplate())
+ D = TD;
+ #endif
+ return DeclVisitor::Visit(D);
+ }
};
} // namespace
@@ -819,6 +904,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
+ SkipForSpecialization = false;
+
using namespace TemplateInstArgsHelpers;
const Decl *CurDecl = ND;
diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp
index 53e6bbfcf42a8e..0283fa1f7b2122 100644
--- a/clang/test/SemaCXX/friend.cpp
+++ b/clang/test/SemaCXX/friend.cpp
@@ -52,14 +52,14 @@ namespace test3 {
namespace test4 {
class T4A {
friend class T4B;
-
+
public:
T4A(class T4B *);
protected:
T4B *mB; // error here
};
-
+
class T4B {};
}
diff --git a/clang/test/SemaTemplate/default-expr-arguments.cpp b/clang/test/SemaTemplate/default-expr-arguments.cpp
index 438f5b1aa95f74..7570110caae81b 100644
--- a/clang/test/SemaTemplate/default-expr-arguments.cpp
+++ b/clang/test/SemaTemplate/default-expr-arguments.cpp
@@ -23,10 +23,10 @@ template<typename T> void f3(T a, T b = T() + T()); // expected-error{{invalid o
void g() {
f1(10);
f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1<S>' required here}}
-
+
f2(10);
f2(S());
-
+
f3(10);
f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3<S>' required here}}
}
@@ -48,7 +48,7 @@ void g2() {
void g3(F<int> f, F<struct S> s) {
f.f();
s.f(); // expected-note{{in instantiation of default function argument expression for 'f<S>' required here}}
-
+
F<int> f2;
F<S> s2; // expected-note{{in instantiation of default function argument expression for 'F<S>' required here}}
}
@@ -115,7 +115,7 @@ template<typename T> struct A {
// expected-note 3{{passing argument to parameter here}}
};
-struct B : A<int*> {
+struct B : A<int*> {
B();
};
B::B() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
@@ -127,7 +127,7 @@ C::C() { } // expected-note {{in instantiation of default function argument expr
struct D {
D();
-
+
A<int*> a;
};
D::D() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
@@ -162,12 +162,12 @@ namespace PR5810 {
struct allocator {
allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error2 {{array with a negative size}}
};
-
+
template<typename T>
struct vector {
vector(const allocator<T>& = allocator<T>()) {} // expected-note2 {{instantiation of}}
};
-
+
struct A { };
struct B { };
@@ -175,7 +175,7 @@ namespace PR5810 {
void FilterVTs() {
vector<A> Result;
}
-
+
void f() {
vector<A> Result;
}
@@ -229,8 +229,8 @@ namespace PR5810b {
namespace PR5810c {
template<typename T>
- struct X {
- X() {
+ struct X {
+ X() {
T t;
double *****p = t; // expected-error{{cannot initialize a variable of type 'double *****' with an lvalue of type 'int'}}
}
@@ -251,7 +251,7 @@ namespace PR8127 {
PointerClass( T * object_p ) : p_( object_p ) {
p_->acquire();
}
- private:
+ private:
T * p_;
};
@@ -285,8 +285,8 @@ namespace rdar8427926 {
}
namespace PR8401 {
- template<typename T>
- struct A {
+ template<typename T>
+ struct A {
A() { T* x = 1; } // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
};
>From f525cbd16c11713d8c5400d1bd636173f6fe8005 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 12 Aug 2024 14:17:08 -0400
Subject: [PATCH 08/29] [FOLD] add tests
---
.../temp/temp.constr/temp.constr.decl/p4.cpp | 108 ++++++++++++++++++
1 file changed, 108 insertions(+)
create mode 100644 clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
new file mode 100644
index 00000000000000..f6e0d45334c0f7
--- /dev/null
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+
+template<typename T>
+struct A {
+ template<typename U, bool V>
+ void f() requires V;
+
+ template<>
+ void f<short, true>();
+
+ template<typename U, bool V> requires V
+ struct B;
+
+ template<typename U, bool V> requires V
+ struct B<U*, V>;
+
+ template<>
+ struct B<short, true>;
+
+ template<typename U, bool V> requires V
+ static int x;
+
+ template<typename U, bool V> requires V
+ static int x<U*, V>;
+
+ template<>
+ int x<short, true>;
+};
+
+template<typename T>
+template<typename U, bool V>
+void A<T>::f() requires V { }
+
+template<typename T>
+template<typename U, bool V> requires V
+struct A<T>::B { };
+
+template<typename T>
+template<typename U, bool V> requires V
+struct A<T>::B<U*, V> { };
+
+template<typename T>
+template<typename U, bool V> requires V
+struct A<T>::B<U&, V> { };
+
+template<typename T>
+template<typename U, bool V> requires V
+int A<T>::x = 0;
+
+template<typename T>
+template<typename U, bool V> requires V
+int A<T>::x<U*, V> = 0;
+
+template<typename T>
+template<typename U, bool V> requires V
+int A<T>::x<U&, V> = 0;
+
+template<>
+template<typename U, bool V>
+void A<short>::f() requires V;
+
+template<>
+template<>
+void A<short>::f<int, true>();
+
+template<>
+template<>
+void A<void>::f<int, true>();
+
+template<>
+template<typename U, bool V> requires V
+struct A<int>::B;
+
+template<>
+template<>
+struct A<int>::B<int, true>;
+
+template<>
+template<>
+struct A<void>::B<int, true>;
+
+template<>
+template<typename U, bool V> requires V
+struct A<int>::B<U*, V>;
+
+template<>
+template<typename U, bool V> requires V
+struct A<int>::B<U&, V>;
+
+template<>
+template<typename U, bool V> requires V
+int A<long>::x;
+
+template<>
+template<>
+int A<long>::x<int, true>;
+
+template<>
+template<>
+int A<void>::x<int, true>;
+
+template<>
+template<typename U, bool V> requires V
+int A<long>::x<U*, V>;
+
+template<>
+template<typename U, bool V> requires V
+int A<long>::x<U&, V>;
>From 8e470b52d1e18f229987a42515a4486388ad1d02 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 12 Aug 2024 14:59:26 -0400
Subject: [PATCH 09/29] [FOLD]
---
clang/lib/Sema/SemaConcept.cpp | 12 ++++++++----
clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 ++++++++-
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 6a1b32598bb4a6..5fd2b998c7fc8c 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -585,7 +585,7 @@ static bool CheckConstraintSatisfaction(
ArrayRef<TemplateArgument> TemplateArgs =
TemplateArgsLists.getNumSubstitutedLevels() > 0
- ? TemplateArgsLists.getOutermost()
+ ? TemplateArgsLists.getInnermost()
: ArrayRef<TemplateArgument> {};
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{},
@@ -1063,16 +1063,20 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
assert(FD->getFriendObjectKind() && "Must be a friend!");
+ FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate();
// The logic for non-templates is handled in ASTContext::isSameEntity, so we
// don't have to bother checking 'DependsOnEnclosingTemplate' for a
// non-function-template.
- assert(FD->getDescribedFunctionTemplate() &&
- "Non-function templates don't need to be checked");
+ assert(FTD && "Non-function templates don't need to be checked");
SmallVector<const Expr *, 3> ACs;
- FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
+ FTD->getAssociatedConstraints(ACs);
+ #if 0
unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
+ #else
+ unsigned OldTemplateDepth = FTD->getTemplateParameters()->getDepth();
+ #endif
for (const Expr *Constraint : ACs)
if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
Constraint))
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 74149273b06fd0..83f87cc8b07ffa 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -705,7 +705,7 @@ struct TemplateInstantiationArgumentCollecter
}
if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo();
- MSI &&MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return Done();
bool IsFriend = RD->getFriendObjectKind() ||
@@ -912,6 +912,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
if (!CurDecl)
CurDecl = Decl::castFromDeclContext(DC);
+ #if 1
if (Innermost) {
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost,
Final);
@@ -927,6 +928,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
HandleDefaultTempArgIntoTempTempParam(TTP, Result);
CurDecl = Response::UseNextDecl(CurDecl).NextDecl;
}
+ #endif
TemplateInstantiationArgumentCollecter Collecter(
*this, Result, RelativeToPrimary,
@@ -935,6 +937,11 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
do {
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
} while (CurDecl);
+
+ #if 0
+ if (Innermost)
+ Result.replaceInnermostTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost);
+ #endif
return Result;
#if 0
>From 9a7be77f6ffeddff49e80315fbb035760bef1304 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 13 Aug 2024 09:27:34 -0400
Subject: [PATCH 10/29] [FOLD] remove SkipForSpecialization and Pattern
parameters from getTemplateInstantiationArgs
---
clang/include/clang/Sema/Sema.h | 5 +-
clang/lib/Sema/SemaConcept.cpp | 15 ++---
clang/lib/Sema/SemaTemplate.cpp | 4 +-
clang/lib/Sema/SemaTemplateDeduction.cpp | 2 +-
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 1 -
clang/lib/Sema/SemaTemplateInstantiate.cpp | 57 ++++++++-----------
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +-
7 files changed, 32 insertions(+), 54 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 99b8b17c2b0578..e8fea08a5783d5 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13087,10 +13087,7 @@ class Sema final : public SemaBase {
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
- bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
- bool ForConstraintInstantiation = false,
- bool SkipForSpecialization = false,
- bool ForDefaultArgumentSubstitution = false);
+ bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);
/// RAII object to handle the state changes required to synthesize
/// a function body.
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 5fd2b998c7fc8c..bff98e21564cdd 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -833,7 +833,6 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
return std::nullopt;
@@ -910,14 +909,12 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
// the purpose of seeing if they differ by constraints. This isn't the same as
// getTemplateDepth, because it includes already instantiated parents.
static unsigned
-CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
- bool SkipForSpecialization = false) {
+CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND) {
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
ND, ND->getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
- /*ForConstraintInstantiation=*/true, SkipForSpecialization);
+ /*ForConstraintInstantiation=*/true);
return MLTAL.getNumLevels();
}
@@ -956,8 +953,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
- /*SkipForSpecialization*/ false);
+ /*ForConstraintInstantiation=*/true);
if (MLTAL.getNumSubstitutedLevels() == 0)
return ConstrExpr;
@@ -1523,7 +1519,6 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
/*Final=*/false, CSE->getTemplateArguments(),
/*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
@@ -1804,8 +1799,8 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
return false;
}
- unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
- unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
+ unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1);
+ unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2);
for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
if (Depth2 > Depth1) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e09e1f854fb590..398c0dac45cb53 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5615,9 +5615,7 @@ bool Sema::CheckTemplateArgumentList(
MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
Template, NewContext, /*Final=*/false, CanonicalConverted,
- /*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
- /*ForConceptInstantiation=*/true);
+ /*RelativeToPrimary=*/true, /*ForConceptInstantiation=*/true);
if (EnsureTemplateArgumentListConstraints(
Template, MLTAL,
SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) {
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index db1f7177f514f2..4507a2204f78ce 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3219,7 +3219,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
Template, Template->getDeclContext(), /*Final=*/false,
/*Innermost=*/CanonicalDeducedArgs, /*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
+ /*ForConstraintInstantiation=*/true);
#if 0
if (DeducedArgsNeedReplacement(Template)) {
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index ea02e979c4270f..e74f9abb3ea413 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -807,7 +807,6 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
F, F->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/TemplateArgsForBuildingRC,
/*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);;
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
#if 0
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 83f87cc8b07ffa..a0159e369a248f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -511,17 +511,15 @@ struct TemplateInstantiationArgumentCollecter
MultiLevelTemplateArgumentList &Result;
bool RelativeToPrimary;
bool ForConstraintInstantiation;
- bool SkipForSpecialization;
TemplateInstantiationArgumentCollecter(
Sema &S,
MultiLevelTemplateArgumentList &Result,
bool RelativeToPrimary,
- bool ForConstraintInstantiation,
- bool SkipForSpecialization) :
+ bool ForConstraintInstantiation) :
S(S), Result(Result), RelativeToPrimary(RelativeToPrimary),
- ForConstraintInstantiation(ForConstraintInstantiation),
- SkipForSpecialization(SkipForSpecialization) { }
+ ForConstraintInstantiation(ForConstraintInstantiation) {
+ }
Decl *Done() {
return nullptr;
@@ -577,7 +575,7 @@ struct TemplateInstantiationArgumentCollecter
assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
"outer template not instantiated?");
- if (!SkipForSpecialization && ForConstraintInstantiation)
+ if (ForConstraintInstantiation)
Result.addOuterTemplateArguments(
VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false);
@@ -591,7 +589,7 @@ struct TemplateInstantiationArgumentCollecter
assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
"outer template not instantiated?");
- if (!SkipForSpecialization && ForConstraintInstantiation)
+ if (ForConstraintInstantiation)
Result.addOuterTemplateArguments(
CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false);
@@ -798,26 +796,23 @@ struct TemplateInstantiationArgumentCollecter
Specialized = CTSD->getSpecializedTemplateOrPartial();
#if 0
if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- CTPSD, CTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ Result.addOuterTemplateArguments(
+ CTPSD, CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (CTPSD->isMemberSpecialization())
return Done();
} else {
auto *CTD = Specialized.get<ClassTemplateDecl *>();
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- CTD, CTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ Result.addOuterTemplateArguments(
+ CTD, CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (CTD->isMemberSpecialization())
return Done();
}
#else
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- CTSD, CTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ Result.addOuterTemplateArguments(
+ CTSD, CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
if (CTPSD->isMemberSpecialization())
return Done();
@@ -849,18 +844,16 @@ struct TemplateInstantiationArgumentCollecter
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
Specialized = VTSD->getSpecializedTemplateOrPartial();
if (auto *VTPSD = Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- VTPSD, VTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ Result.addOuterTemplateArguments(
+ VTPSD, VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (VTPSD->isMemberSpecialization())
return Done();
} else {
auto *VTD = Specialized.get<VarTemplateDecl *>();
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- VTD, VTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ Result.addOuterTemplateArguments(
+ VTD, VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (VTD->isMemberSpecialization())
return Done();
}
@@ -897,15 +890,12 @@ struct TemplateInstantiationArgumentCollecter
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
const NamedDecl *ND, const DeclContext *DC, bool Final,
- std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
- const FunctionDecl *Pattern, bool ForConstraintInstantiation,
- bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
+ std::optional<ArrayRef<TemplateArgument>> Innermost,
+ bool RelativeToPrimary, bool ForConstraintInstantiation) {
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
- SkipForSpecialization = false;
-
using namespace TemplateInstArgsHelpers;
const Decl *CurDecl = ND;
@@ -932,8 +922,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
TemplateInstantiationArgumentCollecter Collecter(
*this, Result, RelativeToPrimary,
- ForConstraintInstantiation,
- SkipForSpecialization);
+ ForConstraintInstantiation);
do {
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
} while (CurDecl);
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 97c240d58c0709..8a609d6d23830f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4746,7 +4746,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Decl, Decl->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
- /*RelativeToPrimary*/ true);
+ /*RelativeToPrimary=*/true);
// FIXME: We can't use getTemplateInstantiationPattern(false) in general
// here, because for a non-defining friend declaration in a class template,
>From 63e2cf877dd5ead67dc940de60ecc6afa198ca2f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 14 Aug 2024 07:53:18 -0400
Subject: [PATCH 11/29] [FOLD] using the right next decl after adding innermost
template arguments
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 172 +++++++++++++-----
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 25 ++-
.../temp/temp.constr/temp.constr.decl/p4.cpp | 1 +
.../SemaTemplate/default-arguments-cxx0x.cpp | 2 +-
4 files changed, 147 insertions(+), 53 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a0159e369a248f..aeeb6d303e859c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -509,15 +509,17 @@ struct TemplateInstantiationArgumentCollecter
: DeclVisitor<TemplateInstantiationArgumentCollecter, Decl*> {
Sema &S;
MultiLevelTemplateArgumentList &Result;
+ std::optional<ArrayRef<TemplateArgument>> Innermost;
bool RelativeToPrimary;
bool ForConstraintInstantiation;
TemplateInstantiationArgumentCollecter(
Sema &S,
MultiLevelTemplateArgumentList &Result,
+ std::optional<ArrayRef<TemplateArgument>> Innermost,
bool RelativeToPrimary,
bool ForConstraintInstantiation) :
- S(S), Result(Result), RelativeToPrimary(RelativeToPrimary),
+ S(S), Result(Result), Innermost(Innermost), RelativeToPrimary(RelativeToPrimary),
ForConstraintInstantiation(ForConstraintInstantiation) {
}
@@ -543,14 +545,34 @@ struct TemplateInstantiationArgumentCollecter
Decl::castFromDeclContext(D->getDeclContext()));
}
+ void AddInnermostTemplateArguments(const Decl *D) {
+ assert(Innermost);
+ Result.addOuterTemplateArguments(const_cast<Decl*>(D), *Innermost, /*Final=*/false);
+ Innermost.reset();
+ }
+
+ void AddOuterTemplateArguments(const Decl *D, ArrayRef<TemplateArgument> Args, bool Final) {
+ #if 0
+ if (Innermost) {
+ Args = *Innermost;
+ Innermost.reset();
+ }
+ #endif
+ Result.addOuterTemplateArguments(const_cast<Decl*>(D), Args, Final);
+ }
+
Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) {
#if 0
for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I)
Result.addOuterTemplateArguments(std::nullopt);
return Done();
#endif
+ if (Innermost)
+ AddInnermostTemplateArguments(TTPD);
+
+ // else if (ForConstraintInstantiation)
if (ForConstraintInstantiation)
- Result.addOuterTemplateArguments(std::nullopt);
+ AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false);
return UseNextDecl(TTPD);
}
@@ -559,8 +581,10 @@ struct TemplateInstantiationArgumentCollecter
assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
"outer template not instantiated?");
- if (ForConstraintInstantiation)
- Result.addOuterTemplateArguments(
+ if (Innermost)
+ AddInnermostTemplateArguments(FTD);
+ else if (ForConstraintInstantiation)
+ AddOuterTemplateArguments(
FTD, FTD->getInjectedTemplateArgs(), /*Final=*/false);
if (FTD->isMemberSpecialization())
@@ -575,8 +599,10 @@ struct TemplateInstantiationArgumentCollecter
assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
"outer template not instantiated?");
- if (ForConstraintInstantiation)
- Result.addOuterTemplateArguments(
+ if (Innermost)
+ AddInnermostTemplateArguments(VTD);
+ else if (ForConstraintInstantiation)
+ AddOuterTemplateArguments(
VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false);
if (VTD->isMemberSpecialization())
@@ -589,8 +615,10 @@ struct TemplateInstantiationArgumentCollecter
assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
"outer template not instantiated?");
- if (ForConstraintInstantiation)
- Result.addOuterTemplateArguments(
+ if (Innermost)
+ AddInnermostTemplateArguments(CTD);
+ else if (ForConstraintInstantiation)
+ AddOuterTemplateArguments(
CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false);
if (CTD->isMemberSpecialization())
@@ -601,6 +629,27 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(CTD);
}
+ Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *TATD) {
+ assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
+ if (Innermost)
+ AddInnermostTemplateArguments(TATD);
+ else if (ForConstraintInstantiation)
+ AddOuterTemplateArguments(
+ TATD, TATD->getInjectedTemplateArgs(), /*Final=*/false);
+
+ return UseNextDecl(TATD);
+ }
+
+ Decl *VisitConceptDecl(ConceptDecl *CD) {
+ assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
+ if (Innermost)
+ AddInnermostTemplateArguments(CD);
+
+ return UseNextDecl(CD);
+ }
+
#if 0
Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) {
if (!SkipForSpecialization)
@@ -636,8 +685,11 @@ struct TemplateInstantiationArgumentCollecter
if (const TemplateArgumentList *TemplateArgs =
FD->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
- Result.addOuterTemplateArguments(
- FD, TemplateArgs->asArray(), /*Final=*/false);
+ if (Innermost)
+ AddInnermostTemplateArguments(FD);
+ else
+ AddOuterTemplateArguments(
+ FD, TemplateArgs->asArray(), /*Final=*/false);
if ( // RelativeToPrimary &&
(FD->getTemplateSpecializationKind() ==
@@ -698,7 +750,7 @@ struct TemplateInstantiationArgumentCollecter
if (ClassTemplate->isMemberSpecialization())
return Done();
if (ForConstraintInstantiation)
- Result.addOuterTemplateArguments(
+ AddOuterTemplateArguments(
RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false);
}
@@ -727,9 +779,9 @@ struct TemplateInstantiationArgumentCollecter
getPrimaryTemplateOfGenericLambda(RD->getLambdaCallOperator());
if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator,
TypeAlias.PrimaryTypeAliasDecl)) {
- Result.addOuterTemplateArguments(TypeAlias.Template,
- TypeAlias.AssociatedTemplateArguments,
- /*Final=*/false);
+ AddOuterTemplateArguments(TypeAlias.Template,
+ TypeAlias.AssociatedTemplateArguments,
+ /*Final=*/false);
// Visit the parent of the current type alias declaration rather than
// the lambda thereof.
// E.g., in the following example:
@@ -781,7 +833,8 @@ struct TemplateInstantiationArgumentCollecter
#else
// For a class-scope explicit specialization, there are no template arguments
// at this level, but there may be enclosing template arguments.
- if (CTSD->isClassScopeExplicitSpecialization())
+ if (CTSD->isClassScopeExplicitSpecialization() &&
+ !isa<ClassTemplatePartialSpecializationDecl>(CTSD))
return DontClearRelativeToPrimaryNextDecl(CTSD);
// We're done when we hit an explicit specialization.
@@ -810,9 +863,12 @@ struct TemplateInstantiationArgumentCollecter
return Done();
}
#else
- Result.addOuterTemplateArguments(
- CTSD, CTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ if (Innermost)
+ AddInnermostTemplateArguments(CTSD);
+ else
+ AddOuterTemplateArguments(
+ CTSD, CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
if (CTPSD->isMemberSpecialization())
return Done();
@@ -830,7 +886,8 @@ struct TemplateInstantiationArgumentCollecter
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
// For a class-scope explicit specialization, there are no template arguments
// at this level, but there may be enclosing template arguments.
- if (VTSD->isClassScopeExplicitSpecialization())
+ if (VTSD->isClassScopeExplicitSpecialization() &&
+ !isa<VarTemplatePartialSpecializationDecl>(VTSD))
return DontClearRelativeToPrimaryNextDecl(VTSD);
// We're done when we hit an explicit specialization.
@@ -844,16 +901,22 @@ struct TemplateInstantiationArgumentCollecter
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
Specialized = VTSD->getSpecializedTemplateOrPartial();
if (auto *VTPSD = Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
- Result.addOuterTemplateArguments(
- VTPSD, VTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ if (Innermost)
+ AddInnermostTemplateArguments(VTPSD);
+ else
+ AddOuterTemplateArguments(
+ VTPSD, VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (VTPSD->isMemberSpecialization())
return Done();
} else {
auto *VTD = Specialized.get<VarTemplateDecl *>();
- Result.addOuterTemplateArguments(
- VTD, VTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ if (Innermost)
+ AddInnermostTemplateArguments(VTD);
+ else
+ AddOuterTemplateArguments(
+ VTD, VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (VTD->isMemberSpecialization())
return Done();
}
@@ -861,7 +924,7 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl *ICSD) {
- Result.addOuterTemplateArguments(
+ AddOuterTemplateArguments(
ICSD, ICSD->getTemplateArguments(),
/*Final=*/false);
return UseNextDecl(ICSD);
@@ -877,13 +940,13 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(D);
}
- Decl *Visit(Decl *D) {
#if 0
+ Decl *Visit(Decl *D) {
if (TemplateDecl *TD = D->getDescribedTemplate())
D = TD;
- #endif
return DeclVisitor::Visit(D);
}
+ #endif
};
} // namespace
@@ -902,7 +965,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
if (!CurDecl)
CurDecl = Decl::castFromDeclContext(DC);
- #if 1
+ #if 0
if (Innermost) {
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost,
Final);
@@ -921,7 +984,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
#endif
TemplateInstantiationArgumentCollecter Collecter(
- *this, Result, RelativeToPrimary,
+ *this, Result, Innermost, RelativeToPrimary,
ForConstraintInstantiation);
do {
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
@@ -2121,25 +2184,42 @@ namespace {
ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
LambdaScopeInfo *LSI) {
+ #if 1
CXXMethodDecl *MD = LSI->CallOperator;
- for (ParmVarDecl *PVD : MD->parameters()) {
- assert(PVD && "null in a parameter list");
- if (!PVD->hasDefaultArg())
- continue;
- Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
- // FIXME: Obtain the source location for the '=' token.
- SourceLocation EqualLoc = UninstExpr->getBeginLoc();
- if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
- // If substitution fails, the default argument is set to a
- // RecoveryExpr that wraps the uninstantiated default argument so
- // that downstream diagnostics are omitted.
- ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
- UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(),
- { UninstExpr }, UninstExpr->getType());
- if (ErrorResult.isUsable())
- PVD->setDefaultArg(ErrorResult.get());
+ if (MD->getParentFunctionOrMethod()) {
+ #if 0
+ NamedDecl *Pattern = MD;
+ std::optional<ArrayRef<TemplateArgument>> Innermost;
+ if (FunctionTemplateDecl *FTD = MD->getDescribedFunctionTemplate()) {
+ Pattern = FTD;
+ Innermost = FTD->getInjectedTemplateArgs();
+ }
+ MultiLevelTemplateArgumentList MLTAL =
+ SemaRef.getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(),
+ /*Final=*/false, Innermost,
+ /*RelativeToPrimary=*/true);
+ #endif
+;
+ for (ParmVarDecl *PVD : MD->parameters()) {
+ assert(PVD && "null in a parameter list");
+ if (!PVD->hasDefaultArg())
+ continue;
+ Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
+ // FIXME: Obtain the source location for the '=' token.
+ SourceLocation EqualLoc = UninstExpr->getBeginLoc();
+ if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
+ // If substitution fails, the default argument is set to a
+ // RecoveryExpr that wraps the uninstantiated default argument so
+ // that downstream diagnostics are omitted.
+ ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
+ UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(),
+ { UninstExpr }, UninstExpr->getType());
+ if (ErrorResult.isUsable())
+ PVD->setDefaultArg(ErrorResult.get());
+ }
}
}
+ #endif
return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8a609d6d23830f..e70edd0ef66f9d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4683,6 +4683,21 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) {
assert(Param->hasUninstantiatedDefaultArg());
+ NamedDecl *Pattern = nullptr;
+ std::optional<ArrayRef<TemplateArgument>> Innermost;
+ #if 1
+ if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) {
+ Pattern = FTD->isCXXClassMember() ? FTD->getFirstDecl() : FTD;
+ Innermost = FD->getTemplateSpecializationArgs()->asArray();
+ } else if (FD->isCXXClassMember()) {
+ Pattern = FD->getFirstDecl();
+ } else {
+ Pattern = FD;
+ }
+ #else
+ Pattern = FD;
+ #endif
+
// Instantiate the expression.
//
// FIXME: Pass in a correct Pattern argument, otherwise
@@ -4700,12 +4715,10 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
//
// template<typename T>
// A<T> Foo(int a = A<T>::FooImpl());
- MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
- FD, FD->getLexicalDeclContext(),
- /*Final=*/false, /*Innermost=*/std::nullopt,
- /*RelativeToPrimary=*/true, /*Pattern=*/nullptr,
- /*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/false,
- /*ForDefaultArgumentSubstitution=*/true);
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(),
+ /*Final=*/false, Innermost,
+ /*RelativeToPrimary=*/true);
if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
return true;
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
index f6e0d45334c0f7..c39d13c47c8a15 100644
--- a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
template<typename T>
struct A {
diff --git a/clang/test/SemaTemplate/default-arguments-cxx0x.cpp b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp
index 4972c57a719229..bd9388eede316f 100644
--- a/clang/test/SemaTemplate/default-arguments-cxx0x.cpp
+++ b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp
@@ -12,7 +12,7 @@ void f0();
void g0() {
f0(); // okay!
-}
+}
template<typename T, int N = T::value>
int &f1(T);
>From e8c553f3cc0204b55ba18262861b4183d2756c64 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 20 Aug 2024 06:41:24 -0400
Subject: [PATCH 12/29] [FOLD] instantiate lambda default args correctly
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 3 ++-
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index aeeb6d303e859c..48efc064f4701e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2186,7 +2186,8 @@ namespace {
LambdaScopeInfo *LSI) {
#if 1
CXXMethodDecl *MD = LSI->CallOperator;
- if (MD->getParentFunctionOrMethod()) {
+ // if (MD->getParentFunctionOrMethod()) {
+ if (true) {
#if 0
NamedDecl *Pattern = MD;
std::optional<ArrayRef<TemplateArgument>> Innermost;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e70edd0ef66f9d..03cd9b5ffed303 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -12,6 +12,7 @@
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
@@ -4686,6 +4687,7 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
NamedDecl *Pattern = nullptr;
std::optional<ArrayRef<TemplateArgument>> Innermost;
#if 1
+
if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) {
Pattern = FTD->isCXXClassMember() ? FTD->getFirstDecl() : FTD;
Innermost = FD->getTemplateSpecializationArgs()->asArray();
@@ -4698,6 +4700,9 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
Pattern = FD;
#endif
+ if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD))
+ Pattern = FD;
+
// Instantiate the expression.
//
// FIXME: Pass in a correct Pattern argument, otherwise
>From 9f08b9bb37ba0d5ad1abad33d66a5e9a8e39b1bc Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 23 Aug 2024 11:51:49 -0400
Subject: [PATCH 13/29] [FOLD] handle template template params correctly and
switch to described template
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 422 +-----------------
.../namespace.udecl/p8-cxx0x.cpp | 4 +-
2 files changed, 20 insertions(+), 406 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 48efc064f4701e..2a956d488423d7 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -185,323 +185,6 @@ HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP,
return Response::Done();
}
-#if 0
-// Add template arguments from a variable template instantiation.
-Response
-HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
- MultiLevelTemplateArgumentList &Result,
- bool SkipForSpecialization) {
- // For a class-scope explicit specialization, there are no template arguments
- // at this level, but there may be enclosing template arguments.
- if (VarTemplSpec->isClassScopeExplicitSpecialization())
- return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec);
-
- // We're done when we hit an explicit specialization.
- if (VarTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization &&
- !isa<VarTemplatePartialSpecializationDecl>(VarTemplSpec))
- return Response::Done();
-
- // If this variable template specialization was instantiated from a
- // specialized member that is a variable template, we're done.
- assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?");
- llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
- Specialized = VarTemplSpec->getSpecializedTemplateOrPartial();
- if (VarTemplatePartialSpecializationDecl *Partial =
- Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
- if (Partial->isMemberSpecialization())
- return Response::Done();
- } else {
- VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
- if (Tmpl->isMemberSpecialization())
- return Response::Done();
- }
- return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec);
-}
-
-Response HandlePartialClassTemplateSpec(
- const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec,
- MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) {
- if (!SkipForSpecialization)
- Result.addOuterRetainedLevels(PartialClassTemplSpec->getTemplateDepth());
- return Response::Done();
-}
-
-// Add template arguments from a class template instantiation.
-Response
-HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
- MultiLevelTemplateArgumentList &Result,
- bool SkipForSpecialization) {
- if (!ClassTemplSpec->isClassScopeExplicitSpecialization()) {
- // We're done when we hit an explicit specialization.
- if (ClassTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization &&
- !isa<ClassTemplatePartialSpecializationDecl>(ClassTemplSpec))
- return Response::Done();
-
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- const_cast<ClassTemplateSpecializationDecl *>(ClassTemplSpec),
- ClassTemplSpec->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
-
- // If this class template specialization was instantiated from a
- // specialized member that is a class template, we're done.
- assert(ClassTemplSpec->getSpecializedTemplate() && "No class template?");
- if (ClassTemplSpec->getSpecializedTemplate()->isMemberSpecialization())
- return Response::Done();
-
- // If this was instantiated from a partial template specialization, we need
- // to get the next level of declaration context from the partial
- // specialization, as the ClassTemplateSpecializationDecl's
- // DeclContext/LexicalDeclContext will be for the primary template.
- if (auto *InstFromPartialTempl = ClassTemplSpec->getSpecializedTemplateOrPartial()
- .dyn_cast<ClassTemplatePartialSpecializationDecl *>())
- return Response::ChangeDecl(InstFromPartialTempl->getLexicalDeclContext());
- }
- return Response::UseNextDecl(ClassTemplSpec);
-}
-
-Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
- MultiLevelTemplateArgumentList &Result,
- const FunctionDecl *Pattern, bool RelativeToPrimary,
- bool ForConstraintInstantiation,
- bool ForDefaultArgumentSubstitution) {
- // Add template arguments from a function template specialization.
- if (!RelativeToPrimary &&
- Function->getTemplateSpecializationKindForInstantiation() ==
- TSK_ExplicitSpecialization)
- return Response::Done();
-
- if (!RelativeToPrimary &&
- Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
- // This is an implicit instantiation of an explicit specialization. We
- // don't get any template arguments from this function but might get
- // some from an enclosing template.
- return Response::UseNextDecl(Function);
- } else if (const TemplateArgumentList *TemplateArgs =
- Function->getTemplateSpecializationArgs()) {
- // Add the template arguments for this specialization.
- Result.addOuterTemplateArguments(const_cast<FunctionDecl *>(Function),
- TemplateArgs->asArray(),
- /*Final=*/false);
-
- if (RelativeToPrimary &&
- (Function->getTemplateSpecializationKind() ==
- TSK_ExplicitSpecialization ||
- (Function->getFriendObjectKind() &&
- !Function->getPrimaryTemplate()->getFriendObjectKind())))
- return Response::UseNextDecl(Function);
-
- // If this function was instantiated from a specialized member that is
- // a function template, we're done.
- assert(Function->getPrimaryTemplate() && "No function template?");
- if (!ForDefaultArgumentSubstitution &&
- Function->getPrimaryTemplate()->isMemberSpecialization())
- return Response::Done();
-
- // If this function is a generic lambda specialization, we are done.
- if (!ForConstraintInstantiation &&
- isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function))
- return Response::Done();
-
- } else if (Function->getDescribedFunctionTemplate()) {
- assert(
- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "Outer template not instantiated?");
- }
- // If this is a friend or local declaration and it declares an entity at
- // namespace scope, take arguments from its lexical parent
- // instead of its semantic parent, unless of course the pattern we're
- // instantiating actually comes from the file's context!
- if ((Function->getFriendObjectKind() || Function->isLocalExternDecl()) &&
- Function->getNonTransparentDeclContext()->isFileContext() &&
- (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
- return Response::ChangeDecl(Function->getLexicalDeclContext());
- }
-
- if (ForConstraintInstantiation && Function->getFriendObjectKind())
- return Response::ChangeDecl(Function->getLexicalDeclContext());
- return Response::UseNextDecl(Function);
-}
-
-Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
- MultiLevelTemplateArgumentList &Result,
- bool ForConstraintInstantiation) {
- #if 0
- if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
- Result.addOuterTemplateArguments(
- const_cast<FunctionTemplateDecl *>(FTD),
- const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
- /*Final=*/false);
-
-
-
- NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
-
- while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) {
- if (NNS->isInstantiationDependent()) {
- if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>()) {
- ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
- // Prefer template arguments from the injected-class-type if possible.
- // For example,
- // ```cpp
- // template <class... Pack> struct S {
- // template <class T> void foo();
- // };
- // template <class... Pack> template <class T>
- // ^^^^^^^^^^^^^ InjectedTemplateArgs
- // They're of kind TemplateArgument::Pack, not of
- // TemplateArgument::Type.
- // void S<Pack...>::foo() {}
- // ^^^^^^^
- // TSTy->template_arguments() (which are of PackExpansionType)
- // ```
- // This meets the contract in
- // TreeTransform::TryExpandParameterPacks that the template arguments
- // for unexpanded parameters should be of a Pack kind.
- if (TSTy->isCurrentInstantiation()) {
- auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
- if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
- Arguments = CTD->getInjectedTemplateArgs();
- else if (auto *Specialization =
- dyn_cast<ClassTemplateSpecializationDecl>(RD))
- Arguments =
- Specialization->getTemplateInstantiationArgs().asArray();
- }
- Result.addOuterTemplateArguments(
- const_cast<FunctionTemplateDecl *>(FTD), Arguments,
- /*Final=*/false);
- }
- }
-
- NNS = NNS->getPrefix();
- }
- }
-
- return Response::ChangeDecl(FTD->getLexicalDeclContext());
- #else
- if (ForConstraintInstantiation)
- Result.addOuterTemplateArguments(
- const_cast<FunctionTemplateDecl *>(FTD),
- const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(),
- /*Final=*/false);
-
- if (FTD->isMemberSpecialization())
- return Response::Done();
-
- if (FTD->getFriendObjectKind())
- return Response::ChangeDecl(FTD->getLexicalDeclContext());
- return Response::UseNextDecl(FTD);
- #endif
-}
-
-Response HandleClassTemplateDecl(const ClassTemplateDecl *CTD,
- MultiLevelTemplateArgumentList &Result,
- bool ForConstraintInstantiation,
- bool SkipForSpecialization) {
- #if 1
- if (!SkipForSpecialization && ForConstraintInstantiation)
- Result.addOuterTemplateArguments(
- const_cast<ClassTemplateDecl *>(CTD),
- const_cast<ClassTemplateDecl *>(CTD)->getInjectedTemplateArgs(),
- /*Final=*/false);
-
- if (CTD->isMemberSpecialization())
- return Response::Done();
-
- if (CTD->getFriendObjectKind())
- return Response::ChangeDecl(CTD->getLexicalDeclContext());
- return Response::UseNextDecl(CTD);
- #endif
- return Response::ChangeDecl(CTD->getLexicalDeclContext());
-}
-
-Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec,
- MultiLevelTemplateArgumentList &Result,
- ASTContext &Context,
- bool ForConstraintInstantiation) {
- if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
- assert(
- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "Outer template not instantiated?");
- if (ClassTemplate->isMemberSpecialization())
- return Response::Done();
- if (ForConstraintInstantiation)
- Result.addOuterTemplateArguments(const_cast<CXXRecordDecl *>(Rec),
- ClassTemplate->getInjectedTemplateArgs(),
- /*Final=*/false);
- }
-
- if (const MemberSpecializationInfo *MSInfo =
- Rec->getMemberSpecializationInfo())
- if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
- return Response::Done();
-
- bool IsFriend = Rec->getFriendObjectKind() ||
- (Rec->getDescribedClassTemplate() &&
- Rec->getDescribedClassTemplate()->getFriendObjectKind());
- if (ForConstraintInstantiation && IsFriend &&
- Rec->getNonTransparentDeclContext()->isFileContext()) {
- return Response::ChangeDecl(Rec->getLexicalDeclContext());
- }
-
- // This is to make sure we pick up the VarTemplateSpecializationDecl or the
- // TypeAliasTemplateDecl that this lambda is defined inside of.
- if (Rec->isLambda()) {
- if (const Decl *LCD = Rec->getLambdaContextDecl())
- return Response::ChangeDecl(LCD);
- // Retrieve the template arguments for a using alias declaration.
- // This is necessary for constraint checking, since we always keep
- // constraints relative to the primary template.
- if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef);
- ForConstraintInstantiation && TypeAlias) {
- if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(),
- TypeAlias.PrimaryTypeAliasDecl)) {
- Result.addOuterTemplateArguments(TypeAlias.Template,
- TypeAlias.AssociatedTemplateArguments,
- /*Final=*/false);
- // Visit the parent of the current type alias declaration rather than
- // the lambda thereof.
- // E.g., in the following example:
- // struct S {
- // template <class> using T = decltype([]<Concept> {} ());
- // };
- // void foo() {
- // S::T var;
- // }
- // The instantiated lambda expression (which we're visiting at 'var')
- // has a function DeclContext 'foo' rather than the Record DeclContext
- // S. This seems to be an oversight to me that we may want to set a
- // Sema Context from the CXXScopeSpec before substituting into T.
- return Response::ChangeDecl(TypeAlias.Template->getDeclContext());
- }
- }
- }
-
- return Response::UseNextDecl(Rec);
-}
-
-Response HandleImplicitConceptSpecializationDecl(
- const ImplicitConceptSpecializationDecl *CSD,
- MultiLevelTemplateArgumentList &Result) {
- Result.addOuterTemplateArguments(
- const_cast<ImplicitConceptSpecializationDecl *>(CSD),
- CSD->getTemplateArguments(),
- /*Final=*/false);
- return Response::UseNextDecl(CSD);
-}
-
-Response HandleGenericDeclContext(const Decl *CurDecl) {
- return Response::UseNextDecl(CurDecl);
-}
-#endif
} // namespace TemplateInstArgsHelpers
@@ -529,6 +212,8 @@ struct TemplateInstantiationArgumentCollecter
Decl *ChangeDecl(const Decl *D) {
RelativeToPrimary = false;
+ if (const TemplateDecl *TD = D->getDescribedTemplate())
+ D = TD;
return const_cast<Decl *>(D);
}
@@ -541,8 +226,10 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *DontClearRelativeToPrimaryNextDecl(const Decl* D) {
- return const_cast<Decl *>(
- Decl::castFromDeclContext(D->getDeclContext()));
+ D = Decl::castFromDeclContext(D->getDeclContext());
+ if (const TemplateDecl *TD = D->getDescribedTemplate())
+ D = TD;
+ return const_cast<Decl *>(D);
}
void AddInnermostTemplateArguments(const Decl *D) {
@@ -562,19 +249,15 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) {
- #if 0
- for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I)
- Result.addOuterTemplateArguments(std::nullopt);
- return Done();
- #endif
if (Innermost)
AddInnermostTemplateArguments(TTPD);
+ else if (ForConstraintInstantiation)
+ AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false);
- // else if (ForConstraintInstantiation)
- if (ForConstraintInstantiation)
+ for (unsigned Depth = TTPD->getDepth() + 1; Depth--;)
AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false);
- return UseNextDecl(TTPD);
+ return Done();
}
Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) {
@@ -706,22 +389,8 @@ struct TemplateInstantiationArgumentCollecter
// If this function is a generic lambda specialization, we are done.
if (!ForConstraintInstantiation &&
- isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) {
- // TypeAliasTemplateDecls should be taken into account, e.g.
- // when we're deducing the return type of a lambda.
- //
- // template <class> int Value = 0;
- // template <class T>
- // using T = decltype([]<int U = 0>() { return Value<T>; }());
- //
- if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) {
- if (isLambdaEnclosedByTypeAliasDecl(
- /*PrimaryLambdaCallOperator=*/getPrimaryTemplateOfGenericLambda(FD),
- /*PrimaryTypeAliasDecl=*/TypeAlias.PrimaryTypeAliasDecl))
- return UseNextDecl(FD);
- }
+ isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD))
return Done();
- }
} else if (FD->getDescribedFunctionTemplate()) {
assert(
@@ -747,6 +416,7 @@ struct TemplateInstantiationArgumentCollecter
assert(
(ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
"Outer template not instantiated?");
+ // llvm_unreachable("shouldn't get here");
if (ClassTemplate->isMemberSpecialization())
return Done();
if (ForConstraintInstantiation)
@@ -774,11 +444,10 @@ struct TemplateInstantiationArgumentCollecter
// Retrieve the template arguments for a using alias declaration.
// This is necessary for constraint checking, since we always keep
// constraints relative to the primary template.
- if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) {
- const FunctionDecl *PrimaryLambdaCallOperator =
- getPrimaryTemplateOfGenericLambda(RD->getLambdaCallOperator());
- if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator,
- TypeAlias.PrimaryTypeAliasDecl)) {
+ if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S);
+ ForConstraintInstantiation && TypeAlias) {
+ if (isLambdaEnclosedByTypeAliasDecl(RD->getLambdaCallOperator(),
+ TypeAlias.PrimaryTypeAliasDecl)) {
AddOuterTemplateArguments(TypeAlias.Template,
TypeAlias.AssociatedTemplateArguments,
/*Final=*/false);
@@ -989,60 +658,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
do {
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
} while (CurDecl);
-
- #if 0
- if (Innermost)
- Result.replaceInnermostTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost);
- #endif
return Result;
-
- #if 0
- while (!CurDecl->isFileContextDecl()) {
- Response R;
- if (const auto *VarTemplSpec =
- dyn_cast<VarTemplateSpecializationDecl>(CurDecl)) {
- R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization);
- } else if (const auto *PartialClassTemplSpec =
- dyn_cast<ClassTemplatePartialSpecializationDecl>(CurDecl)) {
- R = HandlePartialClassTemplateSpec(PartialClassTemplSpec, Result,
- SkipForSpecialization);
- } else if (const auto *ClassTemplSpec =
- dyn_cast<ClassTemplateSpecializationDecl>(CurDecl)) {
- R = HandleClassTemplateSpec(ClassTemplSpec, Result,
- SkipForSpecialization);
- } else if (const auto *Function = dyn_cast<FunctionDecl>(CurDecl)) {
- R = HandleFunction(*this, Function, Result, Pattern, RelativeToPrimary,
- ForConstraintInstantiation,
- ForDefaultArgumentSubstitution);
- } else if (const auto *Rec = dyn_cast<CXXRecordDecl>(CurDecl)) {
- R = HandleRecordDecl(*this, Rec, Result, Context,
- ForConstraintInstantiation);
- } else if (const auto *CSD =
- dyn_cast<ImplicitConceptSpecializationDecl>(CurDecl)) {
- R = HandleImplicitConceptSpecializationDecl(CSD, Result);
- } else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CurDecl)) {
- R = HandleFunctionTemplateDecl(FTD, Result, ForConstraintInstantiation);
- } else if (const auto *CTD = dyn_cast<ClassTemplateDecl>(CurDecl)) {
- R = HandleClassTemplateDecl(CTD, Result, ForConstraintInstantiation, SkipForSpecialization);
- } else if (!isa<DeclContext>(CurDecl)) {
- R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl);
- if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) {
- R = HandleDefaultTempArgIntoTempTempParam(TTP, Result);
- }
- } else {
- R = HandleGenericDeclContext(CurDecl);
- }
-
- if (R.IsDone)
- return Result;
- if (R.ClearRelativeToPrimary)
- RelativeToPrimary = false;
- assert(R.NextDecl);
- CurDecl = R.NextDecl;
- }
-
- return Result;
- #endif
}
bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
@@ -2160,10 +1776,8 @@ namespace {
CXXRecordDecl::LambdaDependencyKind
ComputeLambdaDependency(LambdaScopeInfo *LSI) {
- if (auto TypeAlias =
- TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl(
- getSema());
- TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl(
+ if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(getSema());
+ TypeAlias && isLambdaEnclosedByTypeAliasDecl(
LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) {
unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth();
if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
index 0ea4eeb1e9b08d..8361a35e96ec15 100644
--- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
+++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
@@ -61,14 +61,14 @@ namespace PR21933 {
}
};
template<typename T>
- struct Y : T {
+ struct Y : T {
static void StaticFun() {
using T::member; // expected-error 2{{class member}} expected-note {{use a reference instead}}
(void)member;
}
};
- void f() {
+ void f() {
X<A>::StaticFun(); // expected-note {{instantiation of}}
X<B>::StaticFun(); // expected-note {{instantiation of}}
X<C>::StaticFun();
>From f011c5a98ee0dc42c6d3a19776dcdce9630c55a4 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 23 Aug 2024 12:08:33 -0400
Subject: [PATCH 14/29] [FOLD] remove code for handling described templates
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 35 +++++-----------------
1 file changed, 7 insertions(+), 28 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 2a956d488423d7..9a30e42f132128 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -212,8 +212,6 @@ struct TemplateInstantiationArgumentCollecter
Decl *ChangeDecl(const Decl *D) {
RelativeToPrimary = false;
- if (const TemplateDecl *TD = D->getDescribedTemplate())
- D = TD;
return const_cast<Decl *>(D);
}
@@ -226,10 +224,8 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *DontClearRelativeToPrimaryNextDecl(const Decl* D) {
- D = Decl::castFromDeclContext(D->getDeclContext());
- if (const TemplateDecl *TD = D->getDescribedTemplate())
- D = TD;
- return const_cast<Decl *>(D);
+ return const_cast<Decl *>(
+ Decl::castFromDeclContext(D->getDeclContext()));
}
void AddInnermostTemplateArguments(const Decl *D) {
@@ -239,12 +235,6 @@ struct TemplateInstantiationArgumentCollecter
}
void AddOuterTemplateArguments(const Decl *D, ArrayRef<TemplateArgument> Args, bool Final) {
- #if 0
- if (Innermost) {
- Args = *Innermost;
- Innermost.reset();
- }
- #endif
Result.addOuterTemplateArguments(const_cast<Decl*>(D), Args, Final);
}
@@ -342,6 +332,8 @@ struct TemplateInstantiationArgumentCollecter
#endif
Decl *VisitFunctionDecl(FunctionDecl *FD) {
+ assert(!FD->getDescribedFunctionTemplate() && "not for templated declarations");
+
if (!RelativeToPrimary) {
if (const MemberSpecializationInfo *MSI = FD->getMemberSpecializationInfo();
MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
@@ -392,11 +384,8 @@ struct TemplateInstantiationArgumentCollecter
isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD))
return Done();
- } else if (FD->getDescribedFunctionTemplate()) {
- assert(
- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "Outer template not instantiated?");
}
+
// If this is a friend or local declaration and it declares an entity at
// namespace scope, take arguments from its lexical parent
// instead of its semantic parent, unless of course the pattern we're
@@ -412,17 +401,7 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitCXXRecordDecl(CXXRecordDecl *RD) {
- if (ClassTemplateDecl *ClassTemplate = RD->getDescribedClassTemplate()) {
- assert(
- (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "Outer template not instantiated?");
- // llvm_unreachable("shouldn't get here");
- if (ClassTemplate->isMemberSpecialization())
- return Done();
- if (ForConstraintInstantiation)
- AddOuterTemplateArguments(
- RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false);
- }
+ assert(!RD->getDescribedClassTemplate() && "not for templated declarations");
if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo();
MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
@@ -609,7 +588,7 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(D);
}
- #if 0
+ #if 1
Decl *Visit(Decl *D) {
if (TemplateDecl *TD = D->getDescribedTemplate())
D = TD;
>From c7e047928a3092486a73b140d10de7d476b2cc1f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 23 Aug 2024 12:37:40 -0400
Subject: [PATCH 15/29] [FOLD] handle partial specializations that are member
specializations
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 43 +++++++++++++---------
1 file changed, 25 insertions(+), 18 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 9a30e42f132128..ee20c538411f45 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -490,11 +490,6 @@ struct TemplateInstantiationArgumentCollecter
!isa<ClassTemplatePartialSpecializationDecl>(CTSD))
return Done();
- // If this class template specialization was instantiated from a
- // specialized member that is a class template, we're done.
- assert(CTSD->getSpecializedTemplate() && "No class template?");
- llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>
- Specialized = CTSD->getSpecializedTemplateOrPartial();
#if 0
if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
Result.addOuterTemplateArguments(
@@ -511,12 +506,25 @@ struct TemplateInstantiationArgumentCollecter
return Done();
}
#else
+
if (Innermost)
AddInnermostTemplateArguments(CTSD);
else
AddOuterTemplateArguments(
CTSD, CTSD->getTemplateInstantiationArgs().asArray(),
/*Final=*/false);
+
+ if (auto *CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(CTSD)) {
+ if (CTPSD->isMemberSpecialization())
+ return Done();
+ }
+
+ // If this class template specialization was instantiated from a
+ // specialized member that is a class template, we're done.
+ assert(CTSD->getSpecializedTemplate() && "No class template?");
+ llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>
+ Specialized = CTSD->getSpecializedTemplateOrPartial();
+
if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
if (CTPSD->isMemberSpecialization())
return Done();
@@ -526,7 +534,6 @@ struct TemplateInstantiationArgumentCollecter
return Done();
}
#endif
-
return DontClearRelativeToPrimaryNextDecl(CTSD);
#endif
}
@@ -543,28 +550,28 @@ struct TemplateInstantiationArgumentCollecter
!isa<VarTemplatePartialSpecializationDecl>(VTSD))
return Done();
+ if (Innermost)
+ AddInnermostTemplateArguments(VTSD);
+ else
+ AddOuterTemplateArguments(
+ VTSD, VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
+
+ if (auto *VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl>(VTSD)) {
+ if (VTPSD->isMemberSpecialization())
+ return Done();
+ }
+
// If this variable template specialization was instantiated from a
// specialized member that is a variable template, we're done.
assert(VTSD->getSpecializedTemplate() && "No variable template?");
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
Specialized = VTSD->getSpecializedTemplateOrPartial();
if (auto *VTPSD = Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
- if (Innermost)
- AddInnermostTemplateArguments(VTPSD);
- else
- AddOuterTemplateArguments(
- VTPSD, VTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
if (VTPSD->isMemberSpecialization())
return Done();
} else {
auto *VTD = Specialized.get<VarTemplateDecl *>();
- if (Innermost)
- AddInnermostTemplateArguments(VTD);
- else
- AddOuterTemplateArguments(
- VTD, VTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
if (VTD->isMemberSpecialization())
return Done();
}
>From 27c0419f65dd6af9d0f4aff62330178f23c1dc59 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 23 Aug 2024 12:40:51 -0400
Subject: [PATCH 16/29] [FOLD] cleanups
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 92 +---------------------
1 file changed, 4 insertions(+), 88 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index ee20c538411f45..a8dfea1771ab4d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -323,40 +323,22 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(CD);
}
- #if 0
- Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) {
- if (!SkipForSpecialization)
- Result.addOuterRetainedLevels(CTPSD->getTemplateDepth());
- return Done();
- }
- #endif
-
Decl *VisitFunctionDecl(FunctionDecl *FD) {
assert(!FD->getDescribedFunctionTemplate() && "not for templated declarations");
if (!RelativeToPrimary) {
+ // Add template arguments from a function template specialization.
if (const MemberSpecializationInfo *MSI = FD->getMemberSpecializationInfo();
MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return Done();
+ // This is an implicit instantiation of an explicit specialization. We
+ // don't get any template arguments from this function but might get
+ // some from an enclosing template.
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return UseNextDecl(FD);
}
- #if 0
- // Add template arguments from a function template specialization.
- if (!RelativeToPrimary &&
- FD->getTemplateSpecializationKindForInstantiation() ==
- TSK_ExplicitSpecialization)
- return Done();
- if (!RelativeToPrimary &&
- FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
- // This is an implicit instantiation of an explicit specialization. We
- // don't get any template arguments from this function but might get
- // some from an enclosing template.
- return UseNextDecl(FD);
- } else
- #endif
if (const TemplateArgumentList *TemplateArgs =
FD->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
@@ -452,33 +434,6 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) {
- #if 0
- if (!CTSD->isClassScopeExplicitSpecialization()) {
- // We're done when we hit an explicit specialization.
- if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization &&
- !isa<ClassTemplatePartialSpecializationDecl>(CTSD))
- return Done();
-
- if (!SkipForSpecialization)
- Result.addOuterTemplateArguments(
- CTSD, CTSD->getTemplateInstantiationArgs().asArray(), /*Final=*/false);
-
- // If this class template specialization was instantiated from a
- // specialized member that is a class template, we're done.
- assert(CTSD->getSpecializedTemplate() && "No class template?");
- if (CTSD->getSpecializedTemplate()->isMemberSpecialization())
- return Done();
-
- // If this was instantiated from a partial template specialization, we need
- // to get the next level of declaration context from the partial
- // specialization, as the ClassTemplateSpecializationDecl's
- // DeclContext/LexicalDeclContext will be for the primary template.
- if (auto *CTPSD = CTSD->getSpecializedTemplateOrPartial()
- .dyn_cast<ClassTemplatePartialSpecializationDecl *>())
- return ChangeDecl(CTPSD->getLexicalDeclContext());
- }
- return UseNextDecl(CTSD);
- #else
// For a class-scope explicit specialization, there are no template arguments
// at this level, but there may be enclosing template arguments.
if (CTSD->isClassScopeExplicitSpecialization() &&
@@ -490,23 +445,6 @@ struct TemplateInstantiationArgumentCollecter
!isa<ClassTemplatePartialSpecializationDecl>(CTSD))
return Done();
- #if 0
- if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
- Result.addOuterTemplateArguments(
- CTPSD, CTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
- if (CTPSD->isMemberSpecialization())
- return Done();
- } else {
- auto *CTD = Specialized.get<ClassTemplateDecl *>();
- Result.addOuterTemplateArguments(
- CTD, CTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
- if (CTD->isMemberSpecialization())
- return Done();
- }
- #else
-
if (Innermost)
AddInnermostTemplateArguments(CTSD);
else
@@ -533,9 +471,7 @@ struct TemplateInstantiationArgumentCollecter
if (CTD->isMemberSpecialization())
return Done();
}
- #endif
return DontClearRelativeToPrimaryNextDecl(CTSD);
- #endif
}
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
@@ -595,13 +531,11 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(D);
}
- #if 1
Decl *Visit(Decl *D) {
if (TemplateDecl *TD = D->getDescribedTemplate())
D = TD;
return DeclVisitor::Visit(D);
}
- #endif
};
} // namespace
@@ -620,24 +554,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
if (!CurDecl)
CurDecl = Decl::castFromDeclContext(DC);
- #if 0
- if (Innermost) {
- Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost,
- Final);
- // Populate placeholder template arguments for TemplateTemplateParmDecls.
- // This is essential for the case e.g.
- //
- // template <class> concept Concept = false;
- // template <template <Concept C> class T> void foo(T<int>)
- //
- // where parameter C has a depth of 1 but the substituting argument `int`
- // has a depth of 0.
- if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl))
- HandleDefaultTempArgIntoTempTempParam(TTP, Result);
- CurDecl = Response::UseNextDecl(CurDecl).NextDecl;
- }
- #endif
-
TemplateInstantiationArgumentCollecter Collecter(
*this, Result, Innermost, RelativeToPrimary,
ForConstraintInstantiation);
>From 096eab19e70d0a20a536e79d6e973e5e0c8fda9a Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 27 Aug 2024 07:59:40 -0400
Subject: [PATCH 17/29] [FOLD] cleanup dead code
---
clang/lib/Sema/SemaTemplate.cpp | 23 ++--------
clang/lib/Sema/SemaTemplateDeduction.cpp | 57 ------------------------
2 files changed, 3 insertions(+), 77 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 398c0dac45cb53..b035f59ee395b8 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1982,21 +1982,6 @@ DeclResult Sema::CheckClassTemplate(
}
if (PrevClassTemplate) {
- #if 0
- // Ensure that the template parameter lists are compatible. Skip this check
- // for a friend in a dependent context: the template parameter list itself
- // could be dependent.
- if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) &&
- !TemplateParameterListsAreEqual(
- TemplateCompareNewDeclInfo(SemanticContext ? SemanticContext
- : CurContext,
- CurContext, KWLoc),
- TemplateParams, PrevClassTemplate,
- PrevClassTemplate->getTemplateParameters(), /*Complain=*/true,
- TPL_TemplateMatch))
- return true;
- #endif
-
// C++ [temp.class]p4:
// In a redeclaration, partial specialization, explicit
// specialization or explicit instantiation of a class template,
@@ -2114,14 +2099,15 @@ DeclResult Sema::CheckClassTemplate(
NewClass->setLexicalDeclContext(CurContext);
NewTemplate->setLexicalDeclContext(CurContext);
-
+ // Ensure that the template parameter lists are compatible. Skip this check
+ // for a friend in a dependent context: the template parameter list itself
+ // could be dependent.
if (ShouldAddRedecl && PrevClassTemplate && !TemplateParameterListsAreEqual(
NewTemplate, TemplateParams,
PrevClassTemplate, PrevClassTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
return true;
-
// Check the template parameter list of this declaration, possibly
// merging in the template parameter list from the previous class
// template declaration. Skip this check for a friend in a dependent
@@ -4102,9 +4088,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
VarTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;
- //if (PrevPartial && PrevPartial->getInstantiatedFromMember())
- // PrevPartial->setMemberSpecialization();
-
CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 4507a2204f78ce..d9dd2504cd92e9 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3171,23 +3171,6 @@ struct IsPartialSpecialization<VarTemplatePartialSpecializationDecl> {
static constexpr bool value = true;
};
-#if 0
-template <typename TemplateDeclT>
-static bool DeducedArgsNeedReplacement(TemplateDeclT *Template) {
- return false;
-}
-template <>
-bool DeducedArgsNeedReplacement<VarTemplatePartialSpecializationDecl>(
- VarTemplatePartialSpecializationDecl *Spec) {
- return !Spec->isClassScopeExplicitSpecialization();
-}
-template <>
-bool DeducedArgsNeedReplacement<ClassTemplatePartialSpecializationDecl>(
- ClassTemplatePartialSpecializationDecl *Spec) {
- return !Spec->isClassScopeExplicitSpecialization();
-}
-#endif
-
template <typename TemplateDeclT>
static TemplateDeductionResult
CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
@@ -3197,51 +3180,11 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
Template->getAssociatedConstraints(AssociatedConstraints);
- #if 0
- std::optional<ArrayRef<TemplateArgument>> Innermost;
- // If we don't need to replace the deduced template arguments,
- // we can add them immediately as the inner-most argument list.
- if (!DeducedArgsNeedReplacement(Template))
- Innermost = CanonicalDeducedArgs;
-
- MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
- Template, Template->getDeclContext(), /*Final=*/false, Innermost,
- /*RelativeToPrimary=*/true, /*Pattern=*/
- nullptr, /*ForConstraintInstantiation=*/true);
-
- // getTemplateInstantiationArgs picks up the non-deduced version of the
- // template args when this is a variable template partial specialization and
- // not class-scope explicit specialization, so replace with Deduced Args
- // instead of adding to inner-most.
- if (!Innermost)
- MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
- #endif
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
Template, Template->getDeclContext(), /*Final=*/false,
/*Innermost=*/CanonicalDeducedArgs, /*RelativeToPrimary=*/true,
/*ForConstraintInstantiation=*/true);
- #if 0
- if (DeducedArgsNeedReplacement(Template)) {
- MultiLevelTemplateArgumentList WithReplacement = S.getTemplateInstantiationArgs(
- Template, Template->getDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt,
- /*RelativeToPrimary=*/true, /*Pattern=*/
- nullptr, /*ForConstraintInstantiation=*/true);
-
- WithReplacement.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
-
- assert(MLTAL.getNumLevels() == WithReplacement.getNumLevels());
- assert(MLTAL.getNumSubstitutedLevels() == WithReplacement.getNumSubstitutedLevels());
- auto First0 = MLTAL.begin(), Last0 = MLTAL.end();
- auto First1 = WithReplacement.begin(), Last1 = WithReplacement.end();
-
- while (First0 != Last0) {
- assert(First0->Args.data() == First1->Args.data());
- ++First0, ++First1;
- }
- }
- #endif
-
if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
Info.getLocation(),
Info.AssociatedConstraintsSatisfaction) ||
>From 46543dcda057786ed7f410bc2c82b4beb44eed18 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 27 Aug 2024 08:01:09 -0400
Subject: [PATCH 18/29] [FOLD] revert whitespace only changes
---
.../namespace.udecl/p8-cxx0x.cpp | 4 +--
clang/test/PCH/cxx-templates.cpp | 6 ++---
clang/test/SemaCXX/friend.cpp | 4 +--
.../SemaTemplate/default-arguments-cxx0x.cpp | 2 +-
.../SemaTemplate/default-expr-arguments.cpp | 26 +++++++++----------
5 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
index 8361a35e96ec15..0ea4eeb1e9b08d 100644
--- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
+++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
@@ -61,14 +61,14 @@ namespace PR21933 {
}
};
template<typename T>
- struct Y : T {
+ struct Y : T {
static void StaticFun() {
using T::member; // expected-error 2{{class member}} expected-note {{use a reference instead}}
(void)member;
}
};
- void f() {
+ void f() {
X<A>::StaticFun(); // expected-note {{instantiation of}}
X<B>::StaticFun(); // expected-note {{instantiation of}}
X<C>::StaticFun();
diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp
index bbe8c79bec374c..11ad401de23a8c 100644
--- a/clang/test/PCH/cxx-templates.cpp
+++ b/clang/test/PCH/cxx-templates.cpp
@@ -34,15 +34,15 @@ struct A {
void test(const int (&a6)[17]) {
int x = templ_f<int, 5>(3);
-
+
S<char, float>::templ();
S<int, char>::partial();
S<int, float>::explicit_special();
-
+
Dep<A>::Ty ty;
Dep<A> a;
a.f();
-
+
S3<int> s3;
s3.m();
diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp
index 0283fa1f7b2122..53e6bbfcf42a8e 100644
--- a/clang/test/SemaCXX/friend.cpp
+++ b/clang/test/SemaCXX/friend.cpp
@@ -52,14 +52,14 @@ namespace test3 {
namespace test4 {
class T4A {
friend class T4B;
-
+
public:
T4A(class T4B *);
protected:
T4B *mB; // error here
};
-
+
class T4B {};
}
diff --git a/clang/test/SemaTemplate/default-arguments-cxx0x.cpp b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp
index bd9388eede316f..4972c57a719229 100644
--- a/clang/test/SemaTemplate/default-arguments-cxx0x.cpp
+++ b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp
@@ -12,7 +12,7 @@ void f0();
void g0() {
f0(); // okay!
-}
+}
template<typename T, int N = T::value>
int &f1(T);
diff --git a/clang/test/SemaTemplate/default-expr-arguments.cpp b/clang/test/SemaTemplate/default-expr-arguments.cpp
index 7570110caae81b..438f5b1aa95f74 100644
--- a/clang/test/SemaTemplate/default-expr-arguments.cpp
+++ b/clang/test/SemaTemplate/default-expr-arguments.cpp
@@ -23,10 +23,10 @@ template<typename T> void f3(T a, T b = T() + T()); // expected-error{{invalid o
void g() {
f1(10);
f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1<S>' required here}}
-
+
f2(10);
f2(S());
-
+
f3(10);
f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3<S>' required here}}
}
@@ -48,7 +48,7 @@ void g2() {
void g3(F<int> f, F<struct S> s) {
f.f();
s.f(); // expected-note{{in instantiation of default function argument expression for 'f<S>' required here}}
-
+
F<int> f2;
F<S> s2; // expected-note{{in instantiation of default function argument expression for 'F<S>' required here}}
}
@@ -115,7 +115,7 @@ template<typename T> struct A {
// expected-note 3{{passing argument to parameter here}}
};
-struct B : A<int*> {
+struct B : A<int*> {
B();
};
B::B() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
@@ -127,7 +127,7 @@ C::C() { } // expected-note {{in instantiation of default function argument expr
struct D {
D();
-
+
A<int*> a;
};
D::D() { } // expected-note {{in instantiation of default function argument expression for 'A<int *>' required he}}
@@ -162,12 +162,12 @@ namespace PR5810 {
struct allocator {
allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error2 {{array with a negative size}}
};
-
+
template<typename T>
struct vector {
vector(const allocator<T>& = allocator<T>()) {} // expected-note2 {{instantiation of}}
};
-
+
struct A { };
struct B { };
@@ -175,7 +175,7 @@ namespace PR5810 {
void FilterVTs() {
vector<A> Result;
}
-
+
void f() {
vector<A> Result;
}
@@ -229,8 +229,8 @@ namespace PR5810b {
namespace PR5810c {
template<typename T>
- struct X {
- X() {
+ struct X {
+ X() {
T t;
double *****p = t; // expected-error{{cannot initialize a variable of type 'double *****' with an lvalue of type 'int'}}
}
@@ -251,7 +251,7 @@ namespace PR8127 {
PointerClass( T * object_p ) : p_( object_p ) {
p_->acquire();
}
- private:
+ private:
T * p_;
};
@@ -285,8 +285,8 @@ namespace rdar8427926 {
}
namespace PR8401 {
- template<typename T>
- struct A {
+ template<typename T>
+ struct A {
A() { T* x = 1; } // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
};
>From 9a334390b57deee279fcf4708dd93513584469ad Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 27 Aug 2024 09:13:06 -0400
Subject: [PATCH 19/29] [FOLD] remove some redundant checks
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a8dfea1771ab4d..a79750280c9956 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -348,11 +348,8 @@ struct TemplateInstantiationArgumentCollecter
AddOuterTemplateArguments(
FD, TemplateArgs->asArray(), /*Final=*/false);
- if ( // RelativeToPrimary &&
- (FD->getTemplateSpecializationKind() ==
- TSK_ExplicitSpecialization ||
- (FD->getFriendObjectKind() &&
- !FD->getPrimaryTemplate()->getFriendObjectKind())))
+ if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization ||
+ (FD->getFriendObjectKind() && !FD->getPrimaryTemplate()->getFriendObjectKind()))
return UseNextDecl(FD);
// If this function was instantiated from a specialized member that is
@@ -365,7 +362,6 @@ struct TemplateInstantiationArgumentCollecter
if (!ForConstraintInstantiation &&
isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD))
return Done();
-
}
// If this is a friend or local declaration and it declares an entity at
@@ -389,10 +385,7 @@ struct TemplateInstantiationArgumentCollecter
MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return Done();
- bool IsFriend = RD->getFriendObjectKind() ||
- (RD->getDescribedClassTemplate() &&
- RD->getDescribedClassTemplate()->getFriendObjectKind());
- if (ForConstraintInstantiation && IsFriend &&
+ if (ForConstraintInstantiation && RD->getFriendObjectKind() &&
RD->getNonTransparentDeclContext()->isFileContext()) {
return ChangeDecl(RD->getLexicalDeclContext());
}
>From 3791fe16ceb0075099ff255c3a1483ddd88f2c2e Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 28 Aug 2024 10:51:24 -0400
Subject: [PATCH 20/29] [FOLD] fix common pointer being overwritten when
deserializing
---
clang/lib/Serialization/ASTReader.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index e5a1e20a265616..cd6cdacc20970a 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9978,7 +9978,7 @@ void ASTReader::finishPendingActions() {
auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl();
for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl())
- cast<RedeclarableTemplateDecl>(R)->Common = RTD->Common;
+ cast<RedeclarableTemplateDecl>(R)->Common.setPointer(RTD->Common.getPointer());
}
PendingDefinitions.clear();
>From 08e551ac85e680a9010009661d5599f4d7603918 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Thu, 29 Aug 2024 12:18:24 -0400
Subject: [PATCH 21/29] [FOLD] more cleanup
---
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 48 +++++------------
clang/lib/Sema/SemaTemplateInstantiate.cpp | 51 -------------------
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 27 +++++-----
clang/lib/Serialization/ASTWriterDecl.cpp | 10 ++--
4 files changed, 30 insertions(+), 106 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index e74f9abb3ea413..7415e1e15375c1 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -765,7 +765,7 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
}
// Template arguments used to transform the template arguments in
// DeducedResults.
- SmallVector<TemplateArgument> TemplateArgsForBuildingRC(
+ SmallVector<TemplateArgument> InnerArgsForBuildingRC(
F->getTemplateParameters()->size());
// Transform the transformed template args
MultiLevelTemplateArgumentList Args;
@@ -778,15 +778,15 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
NamedDecl *TP = F->getTemplateParameters()->getParam(Index);
MultiLevelTemplateArgumentList Args;
Args.setKind(TemplateSubstitutionKind::Rewrite);
- Args.addOuterTemplateArguments(TemplateArgsForBuildingRC);
+ Args.addOuterTemplateArguments(InnerArgsForBuildingRC);
// Rebuild the template parameter with updated depth and index.
NamedDecl *NewParam =
transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args,
/*NewIndex=*/FirstUndeducedParamIdx,
getDepthAndIndex(TP).first + AdjustDepth);
FirstUndeducedParamIdx += 1;
- assert(TemplateArgsForBuildingRC[Index].isNull());
- TemplateArgsForBuildingRC[Index] =
+ assert(InnerArgsForBuildingRC[Index].isNull());
+ InnerArgsForBuildingRC[Index] =
Context.getInjectedTemplateArg(NewParam);
continue;
}
@@ -794,23 +794,15 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{});
TemplateArgumentLoc Output;
if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) {
- assert(TemplateArgsForBuildingRC[Index].isNull() &&
+ assert(InnerArgsForBuildingRC[Index].isNull() &&
"InstantiatedArgs must be null before setting");
- TemplateArgsForBuildingRC[Index] = Output.getArgument();
+ InnerArgsForBuildingRC[Index] = Output.getArgument();
}
}
- // A list of template arguments for transforming the require-clause of F.
- // It must contain the entire set of template argument lists.
- MultiLevelTemplateArgumentList ArgsForBuildingRC =
- SemaRef.getTemplateInstantiationArgs(
- F, F->getLexicalDeclContext(),
- /*Final=*/false, /*Innermost=*/TemplateArgsForBuildingRC,
- /*RelativeToPrimary=*/true,
- /*ForConstraintInstantiation=*/true);;
- ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
- #if 0
- ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC);
+ // A list of template arguments for transforming the require-clause using
+ // the transformed template arguments as the template argument list of F.
+ //
// For 2), if the underlying deduction guide F is nested in a class template,
// we need the entire template argument list, as the constraint AST in the
// require-clause of F remains completely uninstantiated.
@@ -833,27 +825,15 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
// - The occurrence of U in the function parameter is [depth:0, index:0]
// - The template parameter of U is [depth:0, index:0]
//
- // We add the outer template arguments which is [int] to the multi-level arg
- // list to ensure that the occurrence U in `C<U>` will be replaced with int
- // during the substitution.
- //
// NOTE: The underlying deduction guide F is instantiated -- either from an
// explicitly-written deduction guide member, or from a constructor.
- // getInstantiatedFromMemberTemplate() can only handle the former case, so we
- // check the DeclContext kind.
- if (F->getLexicalDeclContext()->getDeclKind() ==
- clang::Decl::ClassTemplateSpecialization) {
- auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs(
+ MultiLevelTemplateArgumentList ArgsForBuildingRC =
+ SemaRef.getTemplateInstantiationArgs(
F, F->getLexicalDeclContext(),
- /*Final=*/false, /*Innermost=*/std::nullopt,
+ /*Final=*/false, /*Innermost=*/InnerArgsForBuildingRC,
/*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr,
- /*ForConstraintInstantiation=*/true);
- for (auto It : OuterLevelArgs)
- ArgsForBuildingRC.addOuterTemplateArguments(It.Args);
- }
- #endif
-
+ /*ForConstraintInstantiation=*/true);;
+ ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
if (E.isInvalid())
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a79750280c9956..24e8f8b5f488ee 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -52,36 +52,6 @@ using namespace sema;
//===----------------------------------------------------------------------===/
namespace {
-struct Response {
- const Decl *NextDecl = nullptr;
- bool IsDone = false;
- bool ClearRelativeToPrimary = true;
- static Response Done() {
- Response R;
- R.IsDone = true;
- return R;
- }
- static Response ChangeDecl(const Decl *ND) {
- Response R;
- R.NextDecl = ND;
- return R;
- }
- static Response ChangeDecl(const DeclContext *Ctx) {
- Response R;
- R.NextDecl = Decl::castFromDeclContext(Ctx);
- return R;
- }
-
- static Response UseNextDecl(const Decl *CurDecl) {
- return ChangeDecl(CurDecl->getDeclContext());
- }
-
- static Response DontClearRelativeToPrimaryNextDecl(const Decl *CurDecl) {
- Response R = Response::UseNextDecl(CurDecl);
- R.ClearRelativeToPrimary = false;
- return R;
- }
-};
// Retrieve the primary template for a lambda call operator. It's
// unfortunate that we only have the mappings of call operators rather
// than lambda classes.
@@ -169,25 +139,6 @@ bool isLambdaEnclosedByTypeAliasDecl(
.TraverseType(Underlying);
}
-namespace TemplateInstArgsHelpers {
-
-// If we have a template template parameter with translation unit context,
-// then we're performing substitution into a default template argument of
-// this template template parameter before we've constructed the template
-// that will own this template template parameter. In this case, we
-// use empty template parameter lists for all of the outer templates
-// to avoid performing any substitutions.
-Response
-HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP,
- MultiLevelTemplateArgumentList &Result) {
- for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
- Result.addOuterTemplateArguments(std::nullopt);
- return Response::Done();
-}
-
-} // namespace TemplateInstArgsHelpers
-
-
struct TemplateInstantiationArgumentCollecter
: DeclVisitor<TemplateInstantiationArgumentCollecter, Decl*> {
Sema &S;
@@ -540,8 +491,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
-
- using namespace TemplateInstArgsHelpers;
const Decl *CurDecl = ND;
if (!CurDecl)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 03cd9b5ffed303..1030fd571ecd13 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4684,25 +4684,30 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) {
assert(Param->hasUninstantiatedDefaultArg());
- NamedDecl *Pattern = nullptr;
+ NamedDecl *Pattern = FD;
std::optional<ArrayRef<TemplateArgument>> Innermost;
- #if 1
- if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) {
+ if (FD->isCXXClassMember() && !isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) {
+ if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) {
+ Pattern = FTD->getFirstDecl();
+ Innermost = FD->getTemplateSpecializationArgs()->asArray();
+ }
+ }
+ #if 0
+
Pattern = FTD->isCXXClassMember() ? FTD->getFirstDecl() : FTD;
- Innermost = FD->getTemplateSpecializationArgs()->asArray();
} else if (FD->isCXXClassMember()) {
Pattern = FD->getFirstDecl();
} else {
Pattern = FD;
}
- #else
+ #elif 0
Pattern = FD;
+ #elif 0
+ Pattern = FD->getTemplateInstantiationPattern(/*ForDefinition=*/true);
+ #elif 1
#endif
- if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD))
- Pattern = FD;
-
// Instantiate the expression.
//
// FIXME: Pass in a correct Pattern argument, otherwise
@@ -5201,14 +5206,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
RebuildTypeSourceInfoForDefaultSpecialMembers();
SetDeclDefaulted(Function, PatternDecl->getLocation());
} else {
- #if 0
- MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
- Function, Function->getLexicalDeclContext(), /*Final=*/false,
- /*Innermost=*/std::nullopt, false, PatternDecl);
- #else
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
Function, Function->getLexicalDeclContext());
- #endif
// Substitute into the qualifier; we can get a substitution failure here
// through evil use of alias templates.
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index eb45124f911475..020f82ef3ac47f 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1707,15 +1707,13 @@ void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitRedeclarable(D);
- // if (D->getInstantiatedFromMemberTemplate())
Record.push_back(D->isMemberSpecialization());
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
// getCommonPtr() can be used while this is still initializing.
- if (D->isFirstDecl()) {
+ if (D->isFirstDecl())
// This declaration owns the 'common' pointer, so serialize that data now.
Record.AddDeclRef(D->getInstantiatedFromMemberTemplate());
- }
VisitTemplateDecl(D);
Record.push_back(D->getIdentifierNamespace());
@@ -1791,9 +1789,8 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
Record.push_back(D->isMemberSpecialization());
// These are read/set from/to the first declaration.
- if (D->getPreviousDecl() == nullptr) {
+ if (D->isFirstDecl())
Record.AddDeclRef(D->getInstantiatedFromMember());
- }
Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
}
@@ -1860,9 +1857,8 @@ void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
Record.push_back(D->isMemberSpecialization());
// These are read/set from/to the first declaration.
- if (D->getPreviousDecl() == nullptr) {
+ if (D->isFirstDecl())
Record.AddDeclRef(D->getInstantiatedFromMember());
- }
Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION;
}
>From a85342898b26bd44b46816bfcb2b3e3f70f9d400 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Thu, 29 Aug 2024 12:29:21 -0400
Subject: [PATCH 22/29] [FOLD] more cleanups
---
clang/include/clang/AST/DeclTemplate.h | 1 +
clang/lib/Sema/SemaDecl.cpp | 2 --
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 14 --------------
3 files changed, 1 insertion(+), 16 deletions(-)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 3ad31243d5e559..6e6e075ac93d57 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -863,6 +863,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// Note that this member template is a specialization.
void setMemberSpecialization() {
+ assert(!isMemberSpecialization() && "already a member specialization");
Common.setInt(true);
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0eb58eb4339bc7..66dc4c318fcb83 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12005,8 +12005,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
// If this is an explicit specialization of a member that is a function
// template, mark it as a member specialization.
if (IsMemberSpecialization) {
- NewTemplateDecl->setMemberSpecialization();
- // assert(OldTemplateDecl->isMemberSpecialization());
// Explicit specializations of a member template do not inherit deleted
// status from the parent member template that they are specializing.
if (OldFD->isDeleted()) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 1030fd571ecd13..5a5edfc87dff61 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4693,20 +4693,6 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
Innermost = FD->getTemplateSpecializationArgs()->asArray();
}
}
- #if 0
-
- Pattern = FTD->isCXXClassMember() ? FTD->getFirstDecl() : FTD;
- } else if (FD->isCXXClassMember()) {
- Pattern = FD->getFirstDecl();
- } else {
- Pattern = FD;
- }
- #elif 0
- Pattern = FD;
- #elif 0
- Pattern = FD->getTemplateInstantiationPattern(/*ForDefinition=*/true);
- #elif 1
- #endif
// Instantiate the expression.
//
>From 21c0d6351b18048efff890f3d8fac997ca4b717f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Thu, 29 Aug 2024 12:55:52 -0400
Subject: [PATCH 23/29] [FOLD] format
---
clang/include/clang/AST/DeclTemplate.h | 15 +-
clang/include/clang/Sema/Sema.h | 6 +-
clang/lib/Sema/SemaConcept.cpp | 12 +-
clang/lib/Sema/SemaDecl.cpp | 8 +-
clang/lib/Sema/SemaDeclCXX.cpp | 3 +-
clang/lib/Sema/SemaTemplate.cpp | 54 +++---
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 17 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 170 +++++++++---------
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +-
clang/lib/Serialization/ASTReader.cpp | 3 +-
clang/lib/Serialization/ASTReaderDecl.cpp | 4 +-
11 files changed, 153 insertions(+), 142 deletions(-)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 6e6e075ac93d57..0e1f1f8b48cabe 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -809,7 +809,8 @@ class RedeclarableTemplateDecl : public TemplateDecl,
};
/// Pointer to the common data shared by all declarations of this
- /// template, and a flag indicating if the template is a member specialization.
+ /// template, and a flag indicating if the template is a member
+ /// specialization.
mutable llvm::PointerIntPair<CommonBase *, 1, bool> Common;
/// Retrieves the "common" pointer shared by all (re-)declarations of
@@ -857,9 +858,7 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// template<> template<typename T>
/// struct X<int>::Inner { /* ... */ };
/// \endcode
- bool isMemberSpecialization() const {
- return Common.getInt();
- }
+ bool isMemberSpecialization() const { return Common.getInt(); }
/// Note that this member template is a specialization.
void setMemberSpecialization() {
@@ -2190,9 +2189,7 @@ class ClassTemplatePartialSpecializationDecl
}
/// Note that this member template is a specialization.
- void setMemberSpecialization() {
- return InstantiatedFromMember.setInt(true);
- }
+ void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }
/// Retrieves the injected specialization type for this partial
/// specialization. This is not the same as the type-decl-type for
@@ -2947,9 +2944,7 @@ class VarTemplatePartialSpecializationDecl
}
/// Note that this member template is a specialization.
- void setMemberSpecialization() {
- return InstantiatedFromMember.setInt(true);
- }
+ void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }
SourceRange getSourceRange() const override LLVM_READONLY;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e8fea08a5783d5..ab00d8c8aa13a2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11392,7 +11392,8 @@ class Sema final : public SemaBase {
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
- SourceLocation FriendLoc, ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
+ SourceLocation FriendLoc,
+ ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr);
/// Translates template arguments as provided by the parser
@@ -11432,7 +11433,8 @@ class Sema final : public SemaBase {
DeclResult ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
- StorageClass SC, bool IsPartialSpecialization, bool IsMemberSpecialization);
+ StorageClass SC, bool IsPartialSpecialization,
+ bool IsMemberSpecialization);
/// Get the specialization of the given variable template corresponding to
/// the specified argument list, or a null-but-valid result if the arguments
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index bff98e21564cdd..f953ad19a4130e 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -586,7 +586,7 @@ static bool CheckConstraintSatisfaction(
ArrayRef<TemplateArgument> TemplateArgs =
TemplateArgsLists.getNumSubstitutedLevels() > 0
? TemplateArgsLists.getInnermost()
- : ArrayRef<TemplateArgument> {};
+ : ArrayRef<TemplateArgument>{};
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{},
const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
@@ -908,8 +908,8 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
// Figure out the to-translation-unit depth for this function declaration for
// the purpose of seeing if they differ by constraints. This isn't the same as
// getTemplateDepth, because it includes already instantiated parents.
-static unsigned
-CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND) {
+static unsigned CalculateTemplateDepthForConstraints(Sema &S,
+ const NamedDecl *ND) {
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
ND, ND->getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt,
@@ -1068,11 +1068,11 @@ bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
SmallVector<const Expr *, 3> ACs;
FTD->getAssociatedConstraints(ACs);
- #if 0
+#if 0
unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
- #else
+#else
unsigned OldTemplateDepth = FTD->getTemplateParameters()->getDepth();
- #endif
+#endif
for (const Expr *Constraint : ACs)
if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
Constraint))
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 66dc4c318fcb83..4b44cf15522011 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4505,10 +4505,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
adjustDeclContextForDeclaratorDecl(New, Old);
// Ensure the template parameters are compatible.
- if (NewTemplate &&
- !TemplateParameterListsAreEqual(NewTemplate, NewTemplate->getTemplateParameters(),
- OldTemplate, OldTemplate->getTemplateParameters(),
- /*Complain=*/true, TPL_TemplateMatch))
+ if (NewTemplate && !TemplateParameterListsAreEqual(
+ NewTemplate, NewTemplate->getTemplateParameters(),
+ OldTemplate, OldTemplate->getTemplateParameters(),
+ /*Complain=*/true, TPL_TemplateMatch))
return New->setInvalidDecl();
// C++ [class.mem]p1:
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8d0dfa4da33e4f..90f3bf1f8cf1f7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17411,7 +17411,8 @@ DeclResult Sema::ActOnTemplatedFriendTag(
return CheckClassTemplate(S, TagSpec, TagUseKind::Friend, TagLoc, SS,
Name, NameLoc, Attr, TemplateParams, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
- FriendLoc, TempParamLists.drop_back(), IsMemberSpecialization)
+ FriendLoc, TempParamLists.drop_back(),
+ IsMemberSpecialization)
.get();
} else {
// The "template<>" header is extraneous.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index b035f59ee395b8..a19c201be35929 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1793,7 +1793,8 @@ DeclResult Sema::CheckClassTemplate(
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
- SourceLocation FriendLoc, ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
+ SourceLocation FriendLoc,
+ ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
bool IsMemberSpecialization, SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
@@ -2058,8 +2059,7 @@ DeclResult Sema::CheckClassTemplate(
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(*this, NewClass, SS);
if (!OuterTemplateParamLists.empty())
- NewClass->setTemplateParameterListsInfo(
- Context, OuterTemplateParamLists);
+ NewClass->setTemplateParameterListsInfo(Context, OuterTemplateParamLists);
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
@@ -2102,26 +2102,28 @@ DeclResult Sema::CheckClassTemplate(
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
// could be dependent.
- if (ShouldAddRedecl && PrevClassTemplate && !TemplateParameterListsAreEqual(
- NewTemplate, TemplateParams,
- PrevClassTemplate, PrevClassTemplate->getTemplateParameters(),
- /*Complain=*/true, TPL_TemplateMatch))
+ if (ShouldAddRedecl && PrevClassTemplate &&
+ !TemplateParameterListsAreEqual(
+ NewTemplate, TemplateParams, PrevClassTemplate,
+ PrevClassTemplate->getTemplateParameters(),
+ /*Complain=*/true, TPL_TemplateMatch))
return true;
// Check the template parameter list of this declaration, possibly
// merging in the template parameter list from the previous class
// template declaration. Skip this check for a friend in a dependent
// context, because the template parameter list might be dependent.
- if (ShouldAddRedecl && CheckTemplateParameterList(
- TemplateParams,
- PrevClassTemplate ? PrevClassTemplate->getTemplateParameters()
- : nullptr,
- (SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
- SemanticContext->isDependentContext())
- ? TPC_ClassTemplateMember
- : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate
- : TPC_ClassTemplate,
- SkipBody))
+ if (ShouldAddRedecl &&
+ CheckTemplateParameterList(
+ TemplateParams,
+ PrevClassTemplate ? PrevClassTemplate->getTemplateParameters()
+ : nullptr,
+ (SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
+ SemanticContext->isDependentContext())
+ ? TPC_ClassTemplateMember
+ : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate
+ : TPC_ClassTemplate,
+ SkipBody))
Invalid = true;
if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
@@ -3961,7 +3963,8 @@ void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) {
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
- StorageClass SC, bool IsPartialSpecialization, bool IsMemberSpecialization) {
+ StorageClass SC, bool IsPartialSpecialization,
+ bool IsMemberSpecialization) {
// D must be variable template id.
assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
"Variable template specialization is declared with a template id.");
@@ -8285,15 +8288,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
<< /*class template*/ 0 << (TUK == TagUseKind::Definition)
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
- return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
- ClassTemplate->getIdentifier(),
- TemplateNameLoc,
- Attr,
- TemplateParams,
- AS_none, /*ModulePrivateLoc=*/SourceLocation(),
- /*FriendLoc*/SourceLocation(),
- TemplateParameterLists.drop_back(),
- isMemberSpecialization);
+ return CheckClassTemplate(
+ S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(),
+ TemplateNameLoc, Attr, TemplateParams, AS_none,
+ /*ModulePrivateLoc=*/SourceLocation(),
+ /*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(),
+ isMemberSpecialization);
}
// Create a new class template partial specialization declaration node.
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 7415e1e15375c1..10ca5d6664b83a 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -317,7 +317,8 @@ struct ConvertConstructorToDeductionGuideTransform {
}
if (NestedPattern)
- OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(/*D=*/nullptr, Template->getDeclContext());
+ OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(
+ /*D=*/nullptr, Template->getDeclContext());
}
Sema &SemaRef;
@@ -786,8 +787,7 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
getDepthAndIndex(TP).first + AdjustDepth);
FirstUndeducedParamIdx += 1;
assert(InnerArgsForBuildingRC[Index].isNull());
- InnerArgsForBuildingRC[Index] =
- Context.getInjectedTemplateArg(NewParam);
+ InnerArgsForBuildingRC[Index] = Context.getInjectedTemplateArg(NewParam);
continue;
}
TemplateArgumentLoc Input =
@@ -828,11 +828,12 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
// NOTE: The underlying deduction guide F is instantiated -- either from an
// explicitly-written deduction guide member, or from a constructor.
MultiLevelTemplateArgumentList ArgsForBuildingRC =
- SemaRef.getTemplateInstantiationArgs(
- F, F->getLexicalDeclContext(),
- /*Final=*/false, /*Innermost=*/InnerArgsForBuildingRC,
- /*RelativeToPrimary=*/true,
- /*ForConstraintInstantiation=*/true);;
+ SemaRef.getTemplateInstantiationArgs(F, F->getLexicalDeclContext(),
+ /*Final=*/false,
+ /*Innermost=*/InnerArgsForBuildingRC,
+ /*RelativeToPrimary=*/true,
+ /*ForConstraintInstantiation=*/true);
+ ;
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 24e8f8b5f488ee..f44bd839d32261 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -140,7 +140,7 @@ bool isLambdaEnclosedByTypeAliasDecl(
}
struct TemplateInstantiationArgumentCollecter
- : DeclVisitor<TemplateInstantiationArgumentCollecter, Decl*> {
+ : DeclVisitor<TemplateInstantiationArgumentCollecter, Decl *> {
Sema &S;
MultiLevelTemplateArgumentList &Result;
std::optional<ArrayRef<TemplateArgument>> Innermost;
@@ -148,18 +148,14 @@ struct TemplateInstantiationArgumentCollecter
bool ForConstraintInstantiation;
TemplateInstantiationArgumentCollecter(
- Sema &S,
- MultiLevelTemplateArgumentList &Result,
+ Sema &S, MultiLevelTemplateArgumentList &Result,
std::optional<ArrayRef<TemplateArgument>> Innermost,
- bool RelativeToPrimary,
- bool ForConstraintInstantiation) :
- S(S), Result(Result), Innermost(Innermost), RelativeToPrimary(RelativeToPrimary),
- ForConstraintInstantiation(ForConstraintInstantiation) {
- }
+ bool RelativeToPrimary, bool ForConstraintInstantiation)
+ : S(S), Result(Result), Innermost(Innermost),
+ RelativeToPrimary(RelativeToPrimary),
+ ForConstraintInstantiation(ForConstraintInstantiation) {}
- Decl *Done() {
- return nullptr;
- }
+ Decl *Done() { return nullptr; }
Decl *ChangeDecl(const Decl *D) {
RelativeToPrimary = false;
@@ -170,23 +166,22 @@ struct TemplateInstantiationArgumentCollecter
return ChangeDecl(Decl::castFromDeclContext(DC));
}
- Decl *UseNextDecl(const Decl *D) {
- return ChangeDecl(D->getDeclContext());
- }
+ Decl *UseNextDecl(const Decl *D) { return ChangeDecl(D->getDeclContext()); }
- Decl *DontClearRelativeToPrimaryNextDecl(const Decl* D) {
- return const_cast<Decl *>(
- Decl::castFromDeclContext(D->getDeclContext()));
+ Decl *DontClearRelativeToPrimaryNextDecl(const Decl *D) {
+ return const_cast<Decl *>(Decl::castFromDeclContext(D->getDeclContext()));
}
void AddInnermostTemplateArguments(const Decl *D) {
assert(Innermost);
- Result.addOuterTemplateArguments(const_cast<Decl*>(D), *Innermost, /*Final=*/false);
+ Result.addOuterTemplateArguments(const_cast<Decl *>(D), *Innermost,
+ /*Final=*/false);
Innermost.reset();
}
- void AddOuterTemplateArguments(const Decl *D, ArrayRef<TemplateArgument> Args, bool Final) {
- Result.addOuterTemplateArguments(const_cast<Decl*>(D), Args, Final);
+ void AddOuterTemplateArguments(const Decl *D, ArrayRef<TemplateArgument> Args,
+ bool Final) {
+ Result.addOuterTemplateArguments(const_cast<Decl *>(D), Args, Final);
}
Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) {
@@ -202,14 +197,15 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) {
- assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "outer template not instantiated?");
+ assert(
+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
if (Innermost)
AddInnermostTemplateArguments(FTD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(
- FTD, FTD->getInjectedTemplateArgs(), /*Final=*/false);
+ AddOuterTemplateArguments(FTD, FTD->getInjectedTemplateArgs(),
+ /*Final=*/false);
if (FTD->isMemberSpecialization())
return Done();
@@ -220,14 +216,15 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitVarTemplateDecl(VarTemplateDecl *VTD) {
- assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "outer template not instantiated?");
+ assert(
+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
if (Innermost)
AddInnermostTemplateArguments(VTD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(
- VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false);
+ AddOuterTemplateArguments(VTD, VTD->getInjectedTemplateArgs(),
+ /*Final=*/false);
if (VTD->isMemberSpecialization())
return Done();
@@ -236,14 +233,15 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitClassTemplateDecl(ClassTemplateDecl *CTD) {
- assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "outer template not instantiated?");
+ assert(
+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
if (Innermost)
AddInnermostTemplateArguments(CTD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(
- CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false);
+ AddOuterTemplateArguments(CTD, CTD->getInjectedTemplateArgs(),
+ /*Final=*/false);
if (CTD->isMemberSpecialization())
return Done();
@@ -254,20 +252,22 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *TATD) {
- assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "outer template not instantiated?");
+ assert(
+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
if (Innermost)
AddInnermostTemplateArguments(TATD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(
- TATD, TATD->getInjectedTemplateArgs(), /*Final=*/false);
+ AddOuterTemplateArguments(TATD, TATD->getInjectedTemplateArgs(),
+ /*Final=*/false);
return UseNextDecl(TATD);
}
Decl *VisitConceptDecl(ConceptDecl *CD) {
- assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
- "outer template not instantiated?");
+ assert(
+ (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
+ "outer template not instantiated?");
if (Innermost)
AddInnermostTemplateArguments(CD);
@@ -275,12 +275,15 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitFunctionDecl(FunctionDecl *FD) {
- assert(!FD->getDescribedFunctionTemplate() && "not for templated declarations");
+ assert(!FD->getDescribedFunctionTemplate() &&
+ "not for templated declarations");
if (!RelativeToPrimary) {
// Add template arguments from a function template specialization.
- if (const MemberSpecializationInfo *MSI = FD->getMemberSpecializationInfo();
- MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ if (const MemberSpecializationInfo *MSI =
+ FD->getMemberSpecializationInfo();
+ MSI &&
+ MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return Done();
// This is an implicit instantiation of an explicit specialization. We
@@ -291,16 +294,16 @@ struct TemplateInstantiationArgumentCollecter
}
if (const TemplateArgumentList *TemplateArgs =
- FD->getTemplateSpecializationArgs()) {
+ FD->getTemplateSpecializationArgs()) {
// Add the template arguments for this specialization.
if (Innermost)
AddInnermostTemplateArguments(FD);
else
- AddOuterTemplateArguments(
- FD, TemplateArgs->asArray(), /*Final=*/false);
+ AddOuterTemplateArguments(FD, TemplateArgs->asArray(), /*Final=*/false);
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization ||
- (FD->getFriendObjectKind() && !FD->getPrimaryTemplate()->getFriendObjectKind()))
+ (FD->getFriendObjectKind() &&
+ !FD->getPrimaryTemplate()->getFriendObjectKind()))
return UseNextDecl(FD);
// If this function was instantiated from a specialized member that is
@@ -330,10 +333,12 @@ struct TemplateInstantiationArgumentCollecter
}
Decl *VisitCXXRecordDecl(CXXRecordDecl *RD) {
- assert(!RD->getDescribedClassTemplate() && "not for templated declarations");
+ assert(!RD->getDescribedClassTemplate() &&
+ "not for templated declarations");
if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo();
- MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ MSI &&
+ MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
return Done();
if (ForConstraintInstantiation && RD->getFriendObjectKind() &&
@@ -352,7 +357,7 @@ struct TemplateInstantiationArgumentCollecter
if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S);
ForConstraintInstantiation && TypeAlias) {
if (isLambdaEnclosedByTypeAliasDecl(RD->getLambdaCallOperator(),
- TypeAlias.PrimaryTypeAliasDecl)) {
+ TypeAlias.PrimaryTypeAliasDecl)) {
AddOuterTemplateArguments(TypeAlias.Template,
TypeAlias.AssociatedTemplateArguments,
/*Final=*/false);
@@ -377,9 +382,10 @@ struct TemplateInstantiationArgumentCollecter
return UseNextDecl(RD);
}
- Decl *VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) {
- // For a class-scope explicit specialization, there are no template arguments
- // at this level, but there may be enclosing template arguments.
+ Decl *
+ VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) {
+ // For a class-scope explicit specialization, there are no template
+ // arguments at this level, but there may be enclosing template arguments.
if (CTSD->isClassScopeExplicitSpecialization() &&
!isa<ClassTemplatePartialSpecializationDecl>(CTSD))
return DontClearRelativeToPrimaryNextDecl(CTSD);
@@ -390,11 +396,11 @@ struct TemplateInstantiationArgumentCollecter
return Done();
if (Innermost)
- AddInnermostTemplateArguments(CTSD);
+ AddInnermostTemplateArguments(CTSD);
else
- AddOuterTemplateArguments(
- CTSD, CTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ AddOuterTemplateArguments(CTSD,
+ CTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (auto *CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(CTSD)) {
if (CTPSD->isMemberSpecialization())
@@ -404,10 +410,12 @@ struct TemplateInstantiationArgumentCollecter
// If this class template specialization was instantiated from a
// specialized member that is a class template, we're done.
assert(CTSD->getSpecializedTemplate() && "No class template?");
- llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
Specialized = CTSD->getSpecializedTemplateOrPartial();
- if (auto *CTPSD = Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
+ if (auto *CTPSD =
+ Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
if (CTPSD->isMemberSpecialization())
return Done();
} else {
@@ -418,9 +426,10 @@ struct TemplateInstantiationArgumentCollecter
return DontClearRelativeToPrimaryNextDecl(CTSD);
}
- Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
- // For a class-scope explicit specialization, there are no template arguments
- // at this level, but there may be enclosing template arguments.
+ Decl *
+ VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
+ // For a class-scope explicit specialization, there are no template
+ // arguments at this level, but there may be enclosing template arguments.
if (VTSD->isClassScopeExplicitSpecialization() &&
!isa<VarTemplatePartialSpecializationDecl>(VTSD))
return DontClearRelativeToPrimaryNextDecl(VTSD);
@@ -431,11 +440,11 @@ struct TemplateInstantiationArgumentCollecter
return Done();
if (Innermost)
- AddInnermostTemplateArguments(VTSD);
+ AddInnermostTemplateArguments(VTSD);
else
- AddOuterTemplateArguments(
- VTSD, VTSD->getTemplateInstantiationArgs().asArray(),
- /*Final=*/false);
+ AddOuterTemplateArguments(VTSD,
+ VTSD->getTemplateInstantiationArgs().asArray(),
+ /*Final=*/false);
if (auto *VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl>(VTSD)) {
if (VTPSD->isMemberSpecialization())
@@ -445,9 +454,11 @@ struct TemplateInstantiationArgumentCollecter
// If this variable template specialization was instantiated from a
// specialized member that is a variable template, we're done.
assert(VTSD->getSpecializedTemplate() && "No variable template?");
- llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ llvm::PointerUnion<VarTemplateDecl *,
+ VarTemplatePartialSpecializationDecl *>
Specialized = VTSD->getSpecializedTemplateOrPartial();
- if (auto *VTPSD = Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+ if (auto *VTPSD =
+ Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
if (VTPSD->isMemberSpecialization())
return Done();
} else {
@@ -458,10 +469,10 @@ struct TemplateInstantiationArgumentCollecter
return DontClearRelativeToPrimaryNextDecl(VTSD);
}
- Decl *VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl *ICSD) {
- AddOuterTemplateArguments(
- ICSD, ICSD->getTemplateArguments(),
- /*Final=*/false);
+ Decl *VisitImplicitConceptSpecializationDecl(
+ ImplicitConceptSpecializationDecl *ICSD) {
+ AddOuterTemplateArguments(ICSD, ICSD->getTemplateArguments(),
+ /*Final=*/false);
return UseNextDecl(ICSD);
}
@@ -486,8 +497,8 @@ struct TemplateInstantiationArgumentCollecter
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
const NamedDecl *ND, const DeclContext *DC, bool Final,
- std::optional<ArrayRef<TemplateArgument>> Innermost,
- bool RelativeToPrimary, bool ForConstraintInstantiation) {
+ std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
+ bool ForConstraintInstantiation) {
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
@@ -497,8 +508,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
CurDecl = Decl::castFromDeclContext(DC);
TemplateInstantiationArgumentCollecter Collecter(
- *this, Result, Innermost, RelativeToPrimary,
- ForConstraintInstantiation);
+ *this, Result, Innermost, RelativeToPrimary, ForConstraintInstantiation);
do {
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
} while (CurDecl);
@@ -1642,11 +1652,11 @@ namespace {
ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
LambdaScopeInfo *LSI) {
- #if 1
+#if 1
CXXMethodDecl *MD = LSI->CallOperator;
// if (MD->getParentFunctionOrMethod()) {
if (true) {
- #if 0
+#if 0
NamedDecl *Pattern = MD;
std::optional<ArrayRef<TemplateArgument>> Innermost;
if (FunctionTemplateDecl *FTD = MD->getDescribedFunctionTemplate()) {
@@ -1657,8 +1667,8 @@ namespace {
SemaRef.getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(),
/*Final=*/false, Innermost,
/*RelativeToPrimary=*/true);
- #endif
-;
+#endif
+ ;
for (ParmVarDecl *PVD : MD->parameters()) {
assert(PVD && "null in a parameter list");
if (!PVD->hasDefaultArg())
@@ -1672,13 +1682,13 @@ namespace {
// that downstream diagnostics are omitted.
ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(),
- { UninstExpr }, UninstExpr->getType());
+ {UninstExpr}, UninstExpr->getType());
if (ErrorResult.isUsable())
PVD->setDefaultArg(ErrorResult.get());
}
}
}
- #endif
+#endif
return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 5a5edfc87dff61..6d8cec35cbc1bb 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4687,7 +4687,8 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
NamedDecl *Pattern = FD;
std::optional<ArrayRef<TemplateArgument>> Innermost;
- if (FD->isCXXClassMember() && !isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) {
+ if (FD->isCXXClassMember() &&
+ !isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) {
if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) {
Pattern = FTD->getFirstDecl();
Innermost = FD->getTemplateSpecializationArgs()->asArray();
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index cd6cdacc20970a..a37d853db6bc1b 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9978,7 +9978,8 @@ void ASTReader::finishPendingActions() {
auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl();
for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl())
- cast<RedeclarableTemplateDecl>(R)->Common.setPointer(RTD->Common.getPointer());
+ cast<RedeclarableTemplateDecl>(R)->Common.setPointer(
+ RTD->Common.getPointer());
}
PendingDefinitions.clear();
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 5a893515de9cc6..4d9463535fef31 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2567,7 +2567,7 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
- readDeclAs<ClassTemplatePartialSpecializationDecl>());
+ readDeclAs<ClassTemplatePartialSpecializationDecl>());
}
}
@@ -2660,7 +2660,7 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
D->TemplateParams = Params;
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
- D->InstantiatedFromMember.setInt(Record.readInt());
+ D->InstantiatedFromMember.setInt(Record.readInt());
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
>From 60a2ab23b1380966ea74b04b1fa1d034fe3f4b8f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 30 Aug 2024 09:50:14 -0400
Subject: [PATCH 24/29] [FOLD] address some review feedback
---
clang/lib/Sema/SemaConcept.cpp | 4 --
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 4 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 50 ++++++-------------
3 files changed, 17 insertions(+), 41 deletions(-)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index f953ad19a4130e..8b83418c897f8d 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1068,11 +1068,7 @@ bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
SmallVector<const Expr *, 3> ACs;
FTD->getAssociatedConstraints(ACs);
-#if 0
- unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
-#else
unsigned OldTemplateDepth = FTD->getTemplateParameters()->getDepth();
-#endif
for (const Expr *Constraint : ACs)
if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
Constraint))
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 10ca5d6664b83a..ca93c840f03215 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -317,8 +317,7 @@ struct ConvertConstructorToDeductionGuideTransform {
}
if (NestedPattern)
- OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(
- /*D=*/nullptr, Template->getDeclContext());
+ OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template);
}
Sema &SemaRef;
@@ -833,7 +832,6 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
/*Innermost=*/InnerArgsForBuildingRC,
/*RelativeToPrimary=*/true,
/*ForConstraintInstantiation=*/true);
- ;
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index f44bd839d32261..17e4cf7db3c6d3 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1652,43 +1652,25 @@ namespace {
ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
LambdaScopeInfo *LSI) {
-#if 1
CXXMethodDecl *MD = LSI->CallOperator;
- // if (MD->getParentFunctionOrMethod()) {
- if (true) {
-#if 0
- NamedDecl *Pattern = MD;
- std::optional<ArrayRef<TemplateArgument>> Innermost;
- if (FunctionTemplateDecl *FTD = MD->getDescribedFunctionTemplate()) {
- Pattern = FTD;
- Innermost = FTD->getInjectedTemplateArgs();
- }
- MultiLevelTemplateArgumentList MLTAL =
- SemaRef.getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(),
- /*Final=*/false, Innermost,
- /*RelativeToPrimary=*/true);
-#endif
- ;
- for (ParmVarDecl *PVD : MD->parameters()) {
- assert(PVD && "null in a parameter list");
- if (!PVD->hasDefaultArg())
- continue;
- Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
- // FIXME: Obtain the source location for the '=' token.
- SourceLocation EqualLoc = UninstExpr->getBeginLoc();
- if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
- // If substitution fails, the default argument is set to a
- // RecoveryExpr that wraps the uninstantiated default argument so
- // that downstream diagnostics are omitted.
- ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
- UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(),
- {UninstExpr}, UninstExpr->getType());
- if (ErrorResult.isUsable())
- PVD->setDefaultArg(ErrorResult.get());
- }
+ for (ParmVarDecl *PVD : MD->parameters()) {
+ assert(PVD && "null in a parameter list");
+ if (!PVD->hasDefaultArg())
+ continue;
+ Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
+ // FIXME: Obtain the source location for the '=' token.
+ SourceLocation EqualLoc = UninstExpr->getBeginLoc();
+ if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
+ // If substitution fails, the default argument is set to a
+ // RecoveryExpr that wraps the uninstantiated default argument so
+ // that downstream diagnostics are omitted.
+ ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
+ UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), {UninstExpr},
+ UninstExpr->getType());
+ if (ErrorResult.isUsable())
+ PVD->setDefaultArg(ErrorResult.get());
}
}
-#endif
return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
}
>From a8e2c69b56ae56d45a3a5fb061051d9a1bb61ad2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 30 Aug 2024 10:12:27 -0400
Subject: [PATCH 25/29] [FOLD] use pointer for InstantiatedFromMember
---
clang/include/clang/AST/DeclTemplate.h | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 0e1f1f8b48cabe..90245a16ea3b59 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -781,15 +781,11 @@ class RedeclarableTemplateDecl : public TemplateDecl,
EntryType *Entry, void *InsertPos);
struct CommonBase {
- CommonBase() : InstantiatedFromMember(nullptr, false) {}
+ CommonBase() {}
/// The template from which this was most
/// directly instantiated (or null).
- ///
- /// The boolean value indicates whether this template
- /// was explicitly specialized.
- llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
- InstantiatedFromMember;
+ RedeclarableTemplateDecl *InstantiatedFromMember = nullptr;
/// If non-null, points to an array of specializations (including
/// partial specializations) known only by their external declaration IDs.
@@ -903,12 +899,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// void X<T>::f(T, U);
/// \endcode
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const {
- return getCommonPtr()->InstantiatedFromMember.getPointer();
+ return getCommonPtr()->InstantiatedFromMember;
}
void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
- assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
- getCommonPtr()->InstantiatedFromMember.setPointer(TD);
+ assert(!getCommonPtr()->InstantiatedFromMember);
+ getCommonPtr()->InstantiatedFromMember = TD;
}
/// Retrieve the "injected" template arguments that correspond to the
>From 124d6d48ff280000ac7bacdb73f0ec2e0d5dfe3f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 30 Aug 2024 11:46:18 -0400
Subject: [PATCH 26/29] [FOLD] add comment
---
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6d8cec35cbc1bb..bae1c8a1d47108 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4687,6 +4687,25 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
NamedDecl *Pattern = FD;
std::optional<ArrayRef<TemplateArgument>> Innermost;
+ // C++ [dcl.fct.default]p4
+ // For non-template functions, default arguments can be added in later
+ // declarations of a function that inhabit the same scope.
+ //
+ // C++ [dcl.fct.default]p6
+ // Except for member functions of templated classes, the default arguments
+ // in a member function definition that appears outside of the class
+ // definition are added to the set of default arguments provided by the
+ // member function declaration in the class definition; the program is
+ // ill-formed if a default constructor, copy or move constructor, or copy
+ // or move assignment operator is so declared. Default arguments for a
+ // member function of a templated class shall be specified on the initial
+ // declaration of the member function within the templated class.
+ //
+ // We need to collect the template arguments from the context of the function
+ // where the default argument was defined. For a specialization of a function
+ // template explicitly specialized for an implicit instantiation of a class
+ // template, that context is the (implicitly instantiated) declaration in the
+ // definition of the class template specialization.
if (FD->isCXXClassMember() &&
!isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) {
if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) {
>From fd20bd296e2fe53c234ada48e32b6187f88d76d2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 3 Sep 2024 09:00:15 -0400
Subject: [PATCH 27/29] [FOLD] diagnose redefinitions after checking template
parameter equivalence
---
clang/lib/Sema/SemaTemplate.cpp | 55 ++++++++++---------
...class-template-partial-specializations.cpp | 7 +--
2 files changed, 32 insertions(+), 30 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index a19c201be35929..3d29d862edca23 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1997,30 +1997,6 @@ DeclResult Sema::CheckClassTemplate(
Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
Kind = PrevRecordDecl->getTagKind();
}
-
- // Check for redefinition of this class template.
- if (TUK == TagUseKind::Definition) {
- if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
- // If we have a prior definition that is not visible, treat this as
- // simply making that previous definition visible.
- NamedDecl *Hidden = nullptr;
- if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
- SkipBody->ShouldSkip = true;
- SkipBody->Previous = Def;
- auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
- assert(Tmpl && "original definition of a class template is not a "
- "class template?");
- makeMergedDefinitionVisible(Hidden);
- makeMergedDefinitionVisible(Tmpl);
- } else {
- Diag(NameLoc, diag::err_redefinition) << Name;
- Diag(Def->getLocation(), diag::note_previous_definition);
- // FIXME: Would it make sense to try to "forget" the previous
- // definition, as part of error recovery?
- return true;
- }
- }
- }
} else if (PrevDecl) {
// C++ [temp]p5:
// A class template shall not have the same name as any other
@@ -2126,8 +2102,35 @@ DeclResult Sema::CheckClassTemplate(
SkipBody))
Invalid = true;
- if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
- NewClass->startDefinition();
+ if (TUK == TagUseKind::Definition) {
+ if (PrevClassTemplate) {
+ // Check for redefinition of this class template.
+ if (TagDecl *Def =
+ PrevClassTemplate->getTemplatedDecl()->getDefinition()) {
+ // If we have a prior definition that is not visible, treat this as
+ // simply making that previous definition visible.
+ NamedDecl *Hidden = nullptr;
+ if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
+ SkipBody->ShouldSkip = true;
+ SkipBody->Previous = Def;
+ auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
+ assert(Tmpl && "original definition of a class template is not a "
+ "class template?");
+ makeMergedDefinitionVisible(Hidden);
+ makeMergedDefinitionVisible(Tmpl);
+ } else {
+ Diag(NameLoc, diag::err_redefinition) << Name;
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ // FIXME: Would it make sense to try to "forget" the previous
+ // definition, as part of error recovery?
+ return true;
+ }
+ }
+ }
+
+ if (!SkipBody || !SkipBody->ShouldSkip)
+ NewClass->startDefinition();
+ }
ProcessDeclAttributeList(S, NewClass, Attr);
ProcessAPINotes(NewClass);
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp
index 3358869b95e370..7772eecc69be8b 100644
--- a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp
@@ -33,12 +33,11 @@ class D{}; // expected-note{{previous definition is here}}
template<typename T>
class D<T>{}; // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}} expected-error{{redefinition of 'D'}}
-template<typename T> requires C1<T>
-class E{}; // expected-note{{previous definition is here}}
+template<typename T> requires C1<T> // expected-note{{previous template declaration is here}}
+class E{};
-template<typename T>
+template<typename T> // expected-error{{requires clause differs in template redeclaration}}
class E<T>{}; // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
- // expected-error at -1{{redefinition of 'E'}}
template<typename T>
struct F{ enum{ value = 1 }; };
>From b7e0dd6792ce5479d7785e95bc57e19aa6e249d8 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 3 Sep 2024 09:31:16 -0400
Subject: [PATCH 28/29] [FOLD] more tests
---
.../temp/temp.constr/temp.constr.decl/p4.cpp | 66 +++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
index c39d13c47c8a15..70064f867e18e3 100644
--- a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -std=c++20 -verify %s
// expected-no-diagnostics
+template<typename T>
+concept D = true;
+
template<typename T>
struct A {
template<typename U, bool V>
@@ -9,6 +12,9 @@ struct A {
template<>
void f<short, true>();
+ template<D U>
+ void g();
+
template<typename U, bool V> requires V
struct B;
@@ -18,6 +24,12 @@ struct A {
template<>
struct B<short, true>;
+ template<D U>
+ struct C;
+
+ template<D U>
+ struct C<U*>;
+
template<typename U, bool V> requires V
static int x;
@@ -26,12 +38,22 @@ struct A {
template<>
int x<short, true>;
+
+ template<D U>
+ static int y;
+
+ template<D U>
+ static int y<U*>;
};
template<typename T>
template<typename U, bool V>
void A<T>::f() requires V { }
+template<typename T>
+template<D U>
+void A<T>::g() { }
+
template<typename T>
template<typename U, bool V> requires V
struct A<T>::B { };
@@ -44,6 +66,14 @@ template<typename T>
template<typename U, bool V> requires V
struct A<T>::B<U&, V> { };
+template<typename T>
+template<D U>
+struct A<T>::C { };
+
+template<typename T>
+template<D U>
+struct A<T>::C<U*> { };
+
template<typename T>
template<typename U, bool V> requires V
int A<T>::x = 0;
@@ -56,6 +86,14 @@ template<typename T>
template<typename U, bool V> requires V
int A<T>::x<U&, V> = 0;
+template<typename T>
+template<D U>
+int A<T>::y = 0;
+
+template<typename T>
+template<D U>
+int A<T>::y<U*> = 0;
+
template<>
template<typename U, bool V>
void A<short>::f() requires V;
@@ -68,6 +106,10 @@ template<>
template<>
void A<void>::f<int, true>();
+template<>
+template<D U>
+void A<short>::g();
+
template<>
template<typename U, bool V> requires V
struct A<int>::B;
@@ -88,6 +130,18 @@ template<>
template<typename U, bool V> requires V
struct A<int>::B<U&, V>;
+template<>
+template<D U>
+struct A<int>::C;
+
+template<>
+template<D U>
+struct A<int>::C<U*>;
+
+template<>
+template<D U>
+struct A<int>::C<U&>;
+
template<>
template<typename U, bool V> requires V
int A<long>::x;
@@ -107,3 +161,15 @@ int A<long>::x<U*, V>;
template<>
template<typename U, bool V> requires V
int A<long>::x<U&, V>;
+
+template<>
+template<D U>
+int A<long>::y;
+
+template<>
+template<D U>
+int A<long>::y<U*>;
+
+template<>
+template<D U>
+int A<long>::y<U&>;
>From e3338a97b69e8c2a31dcaf5aed69f46814af5b53 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 20 Sep 2024 10:23:31 -0400
Subject: [PATCH 29/29] [FOLD] add getCommonPtrInternal
---
clang/include/clang/AST/DeclTemplate.h | 2 ++
clang/lib/AST/DeclTemplate.cpp | 21 +++++++++++++--------
clang/lib/Serialization/ASTReader.cpp | 2 +-
clang/lib/Serialization/ASTReaderDecl.cpp | 6 +++---
4 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 90245a16ea3b59..7d0002afe31ee6 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -809,6 +809,8 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// specialization.
mutable llvm::PointerIntPair<CommonBase *, 1, bool> Common;
+ CommonBase *getCommonPtrInternal() const;
+
/// Retrieves the "common" pointer shared by all (re-)declarations of
/// the same template. Calling this routine may implicitly allocate memory
/// for the common pointer.
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 58ce956f4b916a..fb258195529eab 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -308,8 +308,13 @@ bool TemplateDecl::isTypeAlias() const {
void RedeclarableTemplateDecl::anchor() {}
+RedeclarableTemplateDecl::CommonBase *
+RedeclarableTemplateDecl::getCommonPtrInternal() const {
+ return Common.getPointer();
+}
+
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
- if (CommonBase *C = Common.getPointer())
+ if (CommonBase *C = getCommonPtrInternal())
return C;
// Walk the previous-declaration chain until we either find a declaration
@@ -317,7 +322,7 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
Prev = Prev->getPreviousDecl()) {
- if (CommonBase *C = Prev->Common.getPointer()) {
+ if (CommonBase *C = Prev->getCommonPtrInternal()) {
Common.setPointer(C);
break;
}
@@ -326,7 +331,7 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
}
// If we never found a common pointer, allocate one now.
- if (!Common.getPointer()) {
+ if (!getCommonPtrInternal()) {
// FIXME: If any of the declarations is from an AST file, we probably
// need an update record to add the common data.
@@ -335,9 +340,9 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
// Update any previous declarations we saw with the common pointer.
for (const RedeclarableTemplateDecl *Prev : PrevDecls)
- Prev->Common.setPointer(Common.getPointer());
+ Prev->Common.setPointer(getCommonPtrInternal());
- return Common.getPointer();
+ return getCommonPtrInternal();
}
void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
@@ -467,14 +472,14 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
// If we haven't created a common pointer yet, then it can just be created
// with the usual method.
- if (!Base::Common.getPointer())
+ if (!getCommonPtrInternal())
return;
- Common *ThisCommon = static_cast<Common *>(Base::Common.getPointer());
+ Common *ThisCommon = static_cast<Common *>(getCommonPtrInternal());
Common *PrevCommon = nullptr;
SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
for (; Prev; Prev = Prev->getPreviousDecl()) {
- if (CommonBase *C = Prev->Base::Common.getPointer()) {
+ if (CommonBase *C = Prev->getCommonPtrInternal()) {
PrevCommon = static_cast<Common *>(C);
break;
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index a37d853db6bc1b..5ee2446404b3e6 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9979,7 +9979,7 @@ void ASTReader::finishPendingActions() {
auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl();
for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl())
cast<RedeclarableTemplateDecl>(R)->Common.setPointer(
- RTD->Common.getPointer());
+ RTD->getCommonPtrInternal());
}
PendingDefinitions.clear();
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 4d9463535fef31..af8daaec938c18 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2416,11 +2416,11 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Make sure we've allocated the Common pointer first. We do this before
// VisitTemplateDecl so that getCommonPtr() can be used during initialization.
RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
- if (!CanonD->Common.getPointer()) {
+ if (!CanonD->getCommonPtrInternal()) {
CanonD->Common.setPointer(CanonD->newCommon(Reader.getContext()));
Reader.PendingDefinitions.insert(CanonD);
}
- D->Common.setPointer(CanonD->Common.getPointer());
+ D->Common.setPointer(CanonD->getCommonPtrInternal());
if (Record.readInt())
D->setMemberSpecialization();
@@ -2888,7 +2888,7 @@ void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
// If we merged the template with a prior declaration chain, merge the
// common pointer.
// FIXME: Actually merge here, don't just overwrite.
- D->Common.setPointer(D->getCanonicalDecl()->Common.getPointer());
+ D->Common.setPointer(D->getCanonicalDecl()->getCommonPtrInternal());
}
/// "Cast" to type T, asserting if we don't have an implicit conversion.
More information about the cfe-commits
mailing list