Skip to content

Commit ab70ac6

Browse files
authored
[concepts] Push a CurContext before substituting into out-of-line constraints for comparison (#79985)
1 parent 7155c1e commit ab70ac6

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ Bug Fixes to C++ Support
168168
parameter where we did an incorrect specialization of the initialization of
169169
the default parameter.
170170
Fixes (`#68490 <https://github.com/llvm/llvm-project/issues/68490>`_)
171+
- Addressed an issue where constraints involving injected class types are perceived
172+
distinct from its specialization types.
173+
(`#56482 <https://github.com/llvm/llvm-project/issues/56482>`_)
171174
- Fixed a bug where variables referenced by requires-clauses inside
172175
nested generic lambdas were not properly injected into the constraint scope.
173176
(`#73418 <https://github.com/llvm/llvm-project/issues/73418>`_)

clang/lib/AST/DeclTemplate.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,10 @@ void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
15831583

15841584
TemplateParameterList *clang::getReplacedTemplateParameterList(Decl *D) {
15851585
switch (D->getKind()) {
1586+
case Decl::Kind::CXXRecord:
1587+
return cast<CXXRecordDecl>(D)
1588+
->getDescribedTemplate()
1589+
->getTemplateParameters();
15861590
case Decl::Kind::ClassTemplate:
15871591
return cast<ClassTemplateDecl>(D)->getTemplateParameters();
15881592
case Decl::Kind::ClassTemplateSpecialization: {

clang/lib/Sema/SemaConcept.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,8 +807,20 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
807807
ScopeForParameters.InstantiatedLocal(PVD, PVD);
808808

809809
std::optional<Sema::CXXThisScopeRAII> ThisScope;
810-
if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext()))
810+
811+
// See TreeTransform::RebuildTemplateSpecializationType. A context scope is
812+
// essential for having an injected class as the canonical type for a template
813+
// specialization type at the rebuilding stage. This guarantees that, for
814+
// out-of-line definitions, injected class name types and their equivalent
815+
// template specializations can be profiled to the same value, which makes it
816+
// possible that e.g. constraints involving C<Class<T>> and C<Class> are
817+
// perceived identical.
818+
std::optional<Sema::ContextRAII> ContextScope;
819+
if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext())) {
811820
ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
821+
ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
822+
/*NewThisContext=*/false);
823+
}
812824
ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
813825
const_cast<clang::Expr *>(ConstrExpr), MLTAL);
814826
if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())

clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,29 @@ template <class T>
537537
void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
538538
} // namespace GH74314
539539

540+
namespace GH56482 {
541+
template <typename SlotMap>
542+
concept slot_map_has_reserve = true;
543+
544+
template <typename T> struct Slot_map {
545+
constexpr void reserve() const noexcept
546+
requires slot_map_has_reserve<Slot_map>;
547+
548+
constexpr void reserve(int) const noexcept
549+
requires slot_map_has_reserve<Slot_map<T>>;
550+
};
551+
552+
template <typename T>
553+
constexpr void Slot_map<T>::reserve() const noexcept
554+
requires slot_map_has_reserve<Slot_map<T>>
555+
{}
556+
557+
template <typename T>
558+
constexpr void Slot_map<T>::reserve(int) const noexcept
559+
requires slot_map_has_reserve<Slot_map>
560+
{}
561+
} // namespace GH56482
562+
540563
namespace GH74447 {
541564
template <typename T> struct S {
542565
template <typename... U, int V>

0 commit comments

Comments
 (0)