diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bac6c7162a45b..f0dea0c9bc89b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -138,6 +138,9 @@ Bug Fixes to C++ Support - Fixed a bug where variables referenced by requires-clauses inside nested generic lambdas were not properly injected into the constraint scope. (`#73418 `_) +- Fixed a crash where substituting into a requires-expression that refers to function + parameters during the equivalence determination of two constraint expressions. + (`#74447 `_) - Fixed deducing auto& from const int in template parameters of partial specializations. (`#77189 `_) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 88fc846c89e42..19a460f411757 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -797,6 +797,15 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( if (Inst.isInvalid()) return nullptr; + // Set up a dummy 'instantiation' scope in the case of reference to function + // parameters that the surrounding function hasn't been instantiated yet. Note + // this may happen while we're comparing two templates' constraint + // equivalence. + LocalInstantiationScope ScopeForParameters(S); + if (auto *FD = llvm::dyn_cast(DeclInfo.getDecl())) + for (auto *PVD : FD->parameters()) + ScopeForParameters.InstantiatedLocal(PVD, PVD); + std::optional ThisScope; if (auto *RD = dyn_cast(DeclInfo.getDeclContext())) ThisScope.emplace(S, const_cast(RD), Qualifiers()); diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index c4e8e6f720c49..7323ad8d9ef2c 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -536,3 +536,25 @@ void X::bar(decltype(requires { requires something_interesting; })) {} template void X::bar(decltype(requires { requires is_not_same_v; })) {} } // namespace GH74314 + +namespace GH74447 { +template struct S { + template + void test(T target, U... value) + requires requires { + target; + sizeof...(value) == 1; + V == 2; + }; +}; + +template +template +void S::test(T target, U... value) + requires requires { + target; + sizeof...(value) == 1; + V == 2; + } +{} +} // namespace GH74447