Skip to content

Commit 8adf0a2

Browse files
author
git apple-llvm automerger
committed
Merge commit 'f5efa7496156' from llvm.org/main into next
2 parents 6c1e291 + f5efa74 commit 8adf0a2

File tree

5 files changed

+66
-12
lines changed

5 files changed

+66
-12
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10303,11 +10303,13 @@ class Sema final {
1030310303
~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); }
1030410304
};
1030510305

10306-
// Unlike the above, this evaluates constraints, which should only happen at
10307-
// 'constraint checking' time.
10306+
// Must be used instead of SubstExpr at 'constraint checking' time.
1030810307
ExprResult
1030910308
SubstConstraintExpr(Expr *E,
1031010309
const MultiLevelTemplateArgumentList &TemplateArgs);
10310+
// Unlike the above, this does not evaluates constraints.
10311+
ExprResult SubstConstraintExprWithoutSatisfaction(
10312+
Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs);
1031110313

1031210314
/// Substitute the given template arguments into a list of
1031310315
/// expressions, expanding pack expansions if required.

clang/include/clang/Sema/Template.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ enum class TemplateSubstitutionKind : char {
564564
const MultiLevelTemplateArgumentList &TemplateArgs;
565565
Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
566566
LocalInstantiationScope *StartingScope = nullptr;
567+
// Whether to evaluate the C++20 constraints or simply substitute into them.
567568
bool EvaluateConstraints = true;
568569

569570
/// A list of out-of-line class template partial

clang/lib/Sema/SemaConcept.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -771,10 +771,9 @@ namespace {
771771
};
772772
} // namespace
773773

774-
static const Expr *
775-
SubstituteConstraintExpression(Sema &S,
776-
const Sema::TemplateCompareNewDeclInfo &DeclInfo,
777-
const Expr *ConstrExpr) {
774+
static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
775+
Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
776+
const Expr *ConstrExpr) {
778777
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
779778
DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
780779
/*Innermost=*/nullptr,
@@ -797,8 +796,8 @@ SubstituteConstraintExpression(Sema &S,
797796
std::optional<Sema::CXXThisScopeRAII> ThisScope;
798797
if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext()))
799798
ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
800-
ExprResult SubstConstr =
801-
S.SubstConstraintExpr(const_cast<clang::Expr *>(ConstrExpr), MLTAL);
799+
ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
800+
const_cast<clang::Expr *>(ConstrExpr), MLTAL);
802801
if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
803802
return nullptr;
804803
return SubstConstr.get();
@@ -814,12 +813,14 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
814813
if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
815814
Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
816815
if (const Expr *SubstConstr =
817-
SubstituteConstraintExpression(*this, Old, OldConstr))
816+
SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
817+
OldConstr))
818818
OldConstr = SubstConstr;
819819
else
820820
return false;
821821
if (const Expr *SubstConstr =
822-
SubstituteConstraintExpression(*this, New, NewConstr))
822+
SubstituteConstraintExpressionWithoutSatisfaction(*this, New,
823+
NewConstr))
823824
NewConstr = SubstConstr;
824825
else
825826
return false;

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,7 @@ namespace {
11901190
const MultiLevelTemplateArgumentList &TemplateArgs;
11911191
SourceLocation Loc;
11921192
DeclarationName Entity;
1193+
// Whether to evaluate the C++20 constraints or simply substitute into them.
11931194
bool EvaluateConstraints = true;
11941195

11951196
public:
@@ -2499,6 +2500,17 @@ TemplateInstantiator::TransformNestedRequirement(
24992500
Req->getConstraintExpr()->getBeginLoc(), Req,
25002501
Sema::InstantiatingTemplate::ConstraintsCheck{},
25012502
Req->getConstraintExpr()->getSourceRange());
2503+
if (!getEvaluateConstraints()) {
2504+
ExprResult TransConstraint = TransformExpr(Req->getConstraintExpr());
2505+
if (TransConstraint.isInvalid() || !TransConstraint.get())
2506+
return nullptr;
2507+
if (TransConstraint.get()->isInstantiationDependent())
2508+
return new (SemaRef.Context)
2509+
concepts::NestedRequirement(TransConstraint.get());
2510+
ConstraintSatisfaction Satisfaction;
2511+
return new (SemaRef.Context) concepts::NestedRequirement(
2512+
SemaRef.Context, TransConstraint.get(), Satisfaction);
2513+
}
25022514

25032515
ExprResult TransConstraint;
25042516
ConstraintSatisfaction Satisfaction;
@@ -4093,13 +4105,19 @@ Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
40934105
ExprResult
40944106
Sema::SubstConstraintExpr(Expr *E,
40954107
const MultiLevelTemplateArgumentList &TemplateArgs) {
4108+
// FIXME: should call SubstExpr directly if this function is equivalent or
4109+
// should it be different?
4110+
return SubstExpr(E, TemplateArgs);
4111+
}
4112+
4113+
ExprResult Sema::SubstConstraintExprWithoutSatisfaction(
4114+
Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
40964115
if (!E)
40974116
return E;
40984117

4099-
// This is where we need to make sure we 'know' constraint checking needs to
4100-
// happen.
41014118
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
41024119
DeclarationName());
4120+
Instantiator.setEvaluateConstraints(false);
41034121
return Instantiator.TransformExpr(E);
41044122
}
41054123

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,3 +504,35 @@ struct bar {
504504
bar<int> x;
505505
} // namespace GH61763
506506

507+
508+
namespace GH74314 {
509+
template <class T, class U> constexpr bool is_same_v = __is_same(T, U);
510+
template <class T, class U> constexpr bool is_not_same_v = !__is_same(T, U);
511+
512+
template <class Result>
513+
concept something_interesting = requires {
514+
true;
515+
requires is_same_v<int, Result>;
516+
};
517+
518+
template <class T>
519+
struct X {
520+
void foo() requires requires { requires is_not_same_v<T, int>; };
521+
void bar(decltype(requires { requires is_not_same_v<T, int>; }));
522+
};
523+
524+
template <class T>
525+
void X<T>::foo() requires requires { requires something_interesting<T>; } {}
526+
// expected-error@-1{{definition of 'foo' does not match any declaration}}
527+
// expected-note@*{{}}
528+
529+
template <class T>
530+
void X<T>::foo() requires requires { requires is_not_same_v<T, int>; } {} // ok
531+
532+
template <class T>
533+
void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {}
534+
// expected-error@-1{{definition of 'bar' does not match any declaration}}
535+
536+
template <class T>
537+
void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
538+
} // namespace GH74314

0 commit comments

Comments
 (0)