Skip to content

Commit 04d20b1

Browse files
authored
[concepts] Set up an instantiation scope for constraint expression comparison (#79698)
This is a follow-up for the comparison of constraints on out-of-line function template definitions. We require the instantiation of a ParmVarDecl while transforming the expression if that Decl gets referenced by a DeclRefExpr. However, we're not actually performing the class or function template instantiation at the time of such comparison. Therefore, let's map these parameters to themselves so that they get preserved after the substitution. Fixes #74447.
1 parent 0e17684 commit 04d20b1

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ Bug Fixes to C++ Support
138138
- Fixed a bug where variables referenced by requires-clauses inside
139139
nested generic lambdas were not properly injected into the constraint scope.
140140
(`#73418 <https://github.com/llvm/llvm-project/issues/73418>`_)
141+
- Fixed a crash where substituting into a requires-expression that refers to function
142+
parameters during the equivalence determination of two constraint expressions.
143+
(`#74447 <https://github.com/llvm/llvm-project/issues/74447>`_)
141144
- Fixed deducing auto& from const int in template parameters of partial
142145
specializations.
143146
(`#77189 <https://github.com/llvm/llvm-project/issues/77189>`_)

clang/lib/Sema/SemaConcept.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,15 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
797797
if (Inst.isInvalid())
798798
return nullptr;
799799

800+
// Set up a dummy 'instantiation' scope in the case of reference to function
801+
// parameters that the surrounding function hasn't been instantiated yet. Note
802+
// this may happen while we're comparing two templates' constraint
803+
// equivalence.
804+
LocalInstantiationScope ScopeForParameters(S);
805+
if (auto *FD = llvm::dyn_cast<FunctionDecl>(DeclInfo.getDecl()))
806+
for (auto *PVD : FD->parameters())
807+
ScopeForParameters.InstantiatedLocal(PVD, PVD);
808+
800809
std::optional<Sema::CXXThisScopeRAII> ThisScope;
801810
if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext()))
802811
ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,3 +536,25 @@ void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {}
536536
template <class T>
537537
void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
538538
} // namespace GH74314
539+
540+
namespace GH74447 {
541+
template <typename T> struct S {
542+
template <typename... U, int V>
543+
void test(T target, U... value)
544+
requires requires {
545+
target;
546+
sizeof...(value) == 1;
547+
V == 2;
548+
};
549+
};
550+
551+
template <typename T>
552+
template <typename... U, int V>
553+
void S<T>::test(T target, U... value)
554+
requires requires {
555+
target;
556+
sizeof...(value) == 1;
557+
V == 2;
558+
}
559+
{}
560+
} // namespace GH74447

0 commit comments

Comments
 (0)