[clang] ab70ac6 - [concepts] Push a CurContext before substituting into out-of-line constraints for comparison (#79985)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 30 20:18:00 PST 2024
Author: Younan Zhang
Date: 2024-01-31T12:17:41+08:00
New Revision: ab70ac605e784c630122b27c5971fde68e80bd1b
URL: https://github.com/llvm/llvm-project/commit/ab70ac605e784c630122b27c5971fde68e80bd1b
DIFF: https://github.com/llvm/llvm-project/commit/ab70ac605e784c630122b27c5971fde68e80bd1b.diff
LOG: [concepts] Push a CurContext before substituting into out-of-line constraints for comparison (#79985)
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/AST/DeclTemplate.cpp
clang/lib/Sema/SemaConcept.cpp
clang/test/SemaTemplate/concepts-out-of-line-def.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 323157c4db1f1..7b7a5b937a61e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -168,6 +168,9 @@ Bug Fixes to C++ Support
parameter where we did an incorrect specialization of the initialization of
the default parameter.
Fixes (`#68490 <https://github.com/llvm/llvm-project/issues/68490>`_)
+- Addressed an issue where constraints involving injected class types are perceived
+ distinct from its specialization types.
+ (`#56482 <https://github.com/llvm/llvm-project/issues/56482>`_)
- Fixed a bug where variables referenced by requires-clauses inside
nested generic lambdas were not properly injected into the constraint scope.
(`#73418 <https://github.com/llvm/llvm-project/issues/73418>`_)
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 7d7556e670f95..946a34ea8830e 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1583,6 +1583,10 @@ void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
TemplateParameterList *clang::getReplacedTemplateParameterList(Decl *D) {
switch (D->getKind()) {
+ case Decl::Kind::CXXRecord:
+ return cast<CXXRecordDecl>(D)
+ ->getDescribedTemplate()
+ ->getTemplateParameters();
case Decl::Kind::ClassTemplate:
return cast<ClassTemplateDecl>(D)->getTemplateParameters();
case Decl::Kind::ClassTemplateSpecialization: {
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 19a460f411757..5028879eda22f 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -807,8 +807,20 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
ScopeForParameters.InstantiatedLocal(PVD, PVD);
std::optional<Sema::CXXThisScopeRAII> ThisScope;
- if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext()))
+
+ // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
+ // essential for having an injected class as the canonical type for a template
+ // specialization type at the rebuilding stage. This guarantees that, for
+ // out-of-line definitions, injected class name types and their equivalent
+ // template specializations can be profiled to the same value, which makes it
+ // possible that e.g. constraints involving C<Class<T>> and C<Class> are
+ // perceived identical.
+ std::optional<Sema::ContextRAII> ContextScope;
+ if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext())) {
ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
+ ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
+ /*NewThisContext=*/false);
+ }
ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
const_cast<clang::Expr *>(ConstrExpr), MLTAL);
if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index 7323ad8d9ef2c..b6fea2e0b4b31 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -537,6 +537,29 @@ template <class T>
void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
} // namespace GH74314
+namespace GH56482 {
+template <typename SlotMap>
+concept slot_map_has_reserve = true;
+
+template <typename T> struct Slot_map {
+ constexpr void reserve() const noexcept
+ requires slot_map_has_reserve<Slot_map>;
+
+ constexpr void reserve(int) const noexcept
+ requires slot_map_has_reserve<Slot_map<T>>;
+};
+
+template <typename T>
+constexpr void Slot_map<T>::reserve() const noexcept
+ requires slot_map_has_reserve<Slot_map<T>>
+{}
+
+template <typename T>
+constexpr void Slot_map<T>::reserve(int) const noexcept
+ requires slot_map_has_reserve<Slot_map>
+{}
+} // namespace GH56482
+
namespace GH74447 {
template <typename T> struct S {
template <typename... U, int V>
More information about the cfe-commits
mailing list