[clang] [Clang][Sema] Use the correct injected template arguments for partial specializations when collecting multi-level template argument lists (PR #112381)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 15 11:55:32 PDT 2024
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/112381
>From 146b209c90a5ced513ec886882ed57ce09ca2f56 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 15 Oct 2024 09:52:43 -0400
Subject: [PATCH 1/2] [Clang][Sema] Use the correct injected template arguments
for partial specializations when collecting multi-level template argument
lists
---
clang/include/clang/AST/DeclTemplate.h | 14 ++++++++++-
clang/lib/AST/DeclTemplate.cpp | 28 ++++++++++++++++++++++
clang/lib/Sema/SemaTemplateInstantiate.cpp | 4 ++--
3 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 141f58c4600af0..6c7f47cd5204c2 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -2085,7 +2085,9 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
class ClassTemplatePartialSpecializationDecl
: public ClassTemplateSpecializationDecl {
/// The list of template parameters
- TemplateParameterList* TemplateParams = nullptr;
+ TemplateParameterList *TemplateParams = nullptr;
+
+ TemplateArgument *InjectedArgs = nullptr;
/// The class template partial specialization from which this
/// class template partial specialization was instantiated.
@@ -2132,6 +2134,10 @@ class ClassTemplatePartialSpecializationDecl
return TemplateParams;
}
+ /// Retrieve the template arguments list of the template parameter list
+ /// of this template.
+ ArrayRef<TemplateArgument> getInjectedTemplateArgs();
+
/// \brief All associated constraints of this partial specialization,
/// including the requires clause and any constraints derived from
/// constrained-parameters.
@@ -2856,6 +2862,8 @@ class VarTemplatePartialSpecializationDecl
/// The list of template parameters
TemplateParameterList *TemplateParams = nullptr;
+ TemplateArgument *InjectedArgs = nullptr;
+
/// The variable template partial specialization from which this
/// variable template partial specialization was instantiated.
///
@@ -2902,6 +2910,10 @@ class VarTemplatePartialSpecializationDecl
return TemplateParams;
}
+ /// Retrieve the template arguments list of the template parameter list
+ /// of this template.
+ ArrayRef<TemplateArgument> getInjectedTemplateArgs();
+
/// \brief All associated constraints of this partial specialization,
/// including the requires clause and any constraints derived from
/// constrained-parameters.
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index d9b67b7bedf5a5..d2d8907b884ec8 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1185,6 +1185,20 @@ SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
return Range;
}
+ArrayRef<TemplateArgument>
+ClassTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
+ TemplateParameterList *Params = getTemplateParameters();
+ auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ if (!First->InjectedArgs) {
+ auto &Context = getASTContext();
+ SmallVector<TemplateArgument, 16> TemplateArgs;
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
+ First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
+ std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
+ }
+ return llvm::ArrayRef(First->InjectedArgs, Params->size());
+}
+
//===----------------------------------------------------------------------===//
// FriendTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -1535,6 +1549,20 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
return Range;
}
+ArrayRef<TemplateArgument>
+VarTemplatePartialSpecializationDecl::getInjectedTemplateArgs() {
+ TemplateParameterList *Params = getTemplateParameters();
+ auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ if (!First->InjectedArgs) {
+ auto &Context = getASTContext();
+ SmallVector<TemplateArgument, 16> TemplateArgs;
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
+ First->InjectedArgs = new (Context) TemplateArgument[TemplateArgs.size()];
+ std::copy(TemplateArgs.begin(), TemplateArgs.end(), First->InjectedArgs);
+ }
+ return llvm::ArrayRef(First->InjectedArgs, Params->size());
+}
+
static TemplateParameterList *
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// typename T
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8c7f694c09042e..8665c099903dc3 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -237,7 +237,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(VTPSD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(VTPSD, VTPSD->getTemplateArgs().asArray(),
+ AddOuterTemplateArguments(VTPSD, VTPSD->getInjectedTemplateArgs(),
/*Final=*/false);
if (VTPSD->isMemberSpecialization())
@@ -274,7 +274,7 @@ struct TemplateInstantiationArgumentCollecter
if (Innermost)
AddInnermostTemplateArguments(CTPSD);
else if (ForConstraintInstantiation)
- AddOuterTemplateArguments(CTPSD, CTPSD->getTemplateArgs().asArray(),
+ AddOuterTemplateArguments(CTPSD, CTPSD->getInjectedTemplateArgs(),
/*Final=*/false);
if (CTPSD->isMemberSpecialization())
>From 457c070b34197ffda633284c435bf16440378ef4 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 15 Oct 2024 14:55:19 -0400
Subject: [PATCH 2/2] [FOLD] add tests
---
.../temp/temp.constr/temp.constr.decl/p4.cpp | 284 ++++++++++--------
1 file changed, 164 insertions(+), 120 deletions(-)
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 70064f867e18e3..f144e14cd122f9 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,175 +1,219 @@
// RUN: %clang_cc1 -std=c++20 -verify %s
// expected-no-diagnostics
-template<typename T>
-concept D = true;
+namespace Primary {
+ template<typename T>
+ concept D = true;
-template<typename T>
-struct A {
- template<typename U, bool V>
- void f() requires V;
+ template<typename T>
+ struct A {
+ template<typename U, bool V>
+ void f() requires V;
- template<>
- void f<short, true>();
+ template<>
+ void f<short, true>();
+
+ template<D U>
+ void g();
+
+ 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<D U>
+ struct C;
+
+ template<D U>
+ struct C<U*>;
+ 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<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 g();
+ void A<T>::g() { }
+ template<typename T>
template<typename U, bool V> requires V
- struct B;
+ struct A<T>::B { };
+ template<typename T>
template<typename U, bool V> requires V
- struct B<U*, V>;
+ struct A<T>::B<U*, V> { };
- template<>
- struct B<short, true>;
+ template<typename T>
+ template<typename U, bool V> requires V
+ struct A<T>::B<U&, V> { };
+ template<typename T>
template<D U>
- struct C;
+ struct A<T>::C { };
+ template<typename T>
template<D U>
- struct C<U*>;
+ struct A<T>::C<U*> { };
+ template<typename T>
template<typename U, bool V> requires V
- static int x;
+ int A<T>::x = 0;
+ template<typename T>
template<typename U, bool V> requires V
- static int x<U*, V>;
+ int A<T>::x<U*, V> = 0;
- template<>
- int x<short, true>;
+ template<typename T>
+ template<typename U, bool V> requires V
+ int A<T>::x<U&, V> = 0;
+ template<typename T>
template<D U>
- static int y;
+ int A<T>::y = 0;
+ template<typename T>
template<D U>
- static int y<U*>;
-};
-
-template<typename T>
-template<typename U, bool V>
-void A<T>::f() requires V { }
+ int A<T>::y<U*> = 0;
-template<typename T>
-template<D U>
-void A<T>::g() { }
-
-template<typename T>
-template<typename U, bool V> requires V
-struct A<T>::B { };
+ template<>
+ template<typename U, bool V>
+ void A<short>::f() requires V;
-template<typename T>
-template<typename U, bool V> requires V
-struct A<T>::B<U*, V> { };
+ template<>
+ template<>
+ void A<short>::f<int, true>();
-template<typename T>
-template<typename U, bool V> requires V
-struct A<T>::B<U&, V> { };
+ template<>
+ template<>
+ void A<void>::f<int, true>();
-template<typename T>
-template<D U>
-struct A<T>::C { };
+ template<>
+ template<D U>
+ void A<short>::g();
-template<typename T>
-template<D U>
-struct A<T>::C<U*> { };
+ template<>
+ template<typename U, bool V> requires V
+ struct A<int>::B;
-template<typename T>
-template<typename U, bool V> requires V
-int A<T>::x = 0;
+ template<>
+ template<>
+ struct A<int>::B<int, true>;
-template<typename T>
-template<typename U, bool V> requires V
-int A<T>::x<U*, V> = 0;
+ template<>
+ template<>
+ struct A<void>::B<int, true>;
-template<typename T>
-template<typename U, bool V> requires V
-int A<T>::x<U&, V> = 0;
+ template<>
+ template<typename U, bool V> requires V
+ struct A<int>::B<U*, V>;
-template<typename T>
-template<D U>
-int A<T>::y = 0;
+ template<>
+ template<typename U, bool V> requires V
+ struct A<int>::B<U&, V>;
-template<typename T>
-template<D U>
-int A<T>::y<U*> = 0;
+ template<>
+ template<D U>
+ struct A<int>::C;
-template<>
-template<typename U, bool V>
-void A<short>::f() requires V;
+ template<>
+ template<D U>
+ struct A<int>::C<U*>;
-template<>
-template<>
-void A<short>::f<int, true>();
+ template<>
+ template<D U>
+ struct A<int>::C<U&>;
-template<>
-template<>
-void A<void>::f<int, true>();
+ template<>
+ template<typename U, bool V> requires V
+ int A<long>::x;
-template<>
-template<D U>
-void A<short>::g();
+ template<>
+ template<>
+ int A<long>::x<int, true>;
-template<>
-template<typename U, bool V> requires V
-struct A<int>::B;
+ template<>
+ template<>
+ int A<void>::x<int, true>;
-template<>
-template<>
-struct A<int>::B<int, true>;
+ template<>
+ template<typename U, bool V> requires V
+ int A<long>::x<U*, V>;
-template<>
-template<>
-struct A<void>::B<int, true>;
+ template<>
+ template<typename U, bool V> requires V
+ int A<long>::x<U&, V>;
-template<>
-template<typename U, bool V> requires V
-struct A<int>::B<U*, V>;
+ template<>
+ template<D U>
+ int A<long>::y;
-template<>
-template<typename U, bool V> requires V
-struct A<int>::B<U&, V>;
+ template<>
+ template<D U>
+ int A<long>::y<U*>;
-template<>
-template<D U>
-struct A<int>::C;
+ template<>
+ template<D U>
+ int A<long>::y<U&>;
+} // namespace Primary
-template<>
-template<D U>
-struct A<int>::C<U*>;
+namespace Partial {
+ template<typename T, bool B>
+ struct A;
-template<>
-template<D U>
-struct A<int>::C<U&>;
+ template<bool U>
+ struct A<int, U>
+ {
+ template<typename V> requires U
+ void f();
-template<>
-template<typename U, bool V> requires V
-int A<long>::x;
+ template<typename V> requires U
+ static const int x;
-template<>
-template<>
-int A<long>::x<int, true>;
+ template<typename V> requires U
+ struct B;
+ };
-template<>
-template<>
-int A<void>::x<int, true>;
+ template<bool U>
+ template<typename V> requires U
+ void A<int, U>::f() { }
-template<>
-template<typename U, bool V> requires V
-int A<long>::x<U*, V>;
+ template<bool U>
+ template<typename V> requires U
+ constexpr int A<int, U>::x = 0;
-template<>
-template<typename U, bool V> requires V
-int A<long>::x<U&, V>;
+ template<bool U>
+ template<typename V> requires U
+ struct A<int, U>::B { };
-template<>
-template<D U>
-int A<long>::y;
+ template<>
+ template<typename V> requires true
+ void A<int, true>::f() { }
-template<>
-template<D U>
-int A<long>::y<U*>;
+ template<>
+ template<typename V> requires true
+ constexpr int A<int, true>::x = 1;
-template<>
-template<D U>
-int A<long>::y<U&>;
+ template<>
+ template<typename V> requires true
+ struct A<int, true>::B { };
+} // namespace Partial
More information about the cfe-commits
mailing list