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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits