1 //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements semantic analysis for C++ constraints and concepts.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "TreeTransform.h"
14 #include "clang/Sema/SemaConcept.h"
15 #include "clang/Sema/Sema.h"
16 #include "clang/Sema/SemaInternal.h"
17 #include "clang/Sema/SemaDiagnostic.h"
18 #include "clang/Sema/TemplateDeduction.h"
19 #include "clang/Sema/Template.h"
20 #include "clang/Sema/Overload.h"
21 #include "clang/Sema/Initialization.h"
22 #include "clang/AST/ASTLambda.h"
23 #include "clang/AST/ExprConcepts.h"
24 #include "clang/AST/RecursiveASTVisitor.h"
25 #include "clang/Basic/OperatorPrecedence.h"
26 #include "llvm/ADT/DenseMap.h"
27 #include "llvm/ADT/PointerUnion.h"
28 #include "llvm/ADT/StringExtras.h"
29 #include <optional>
30
31 using namespace clang;
32 using namespace sema;
33
34 namespace {
35 class LogicalBinOp {
36 SourceLocation Loc;
37 OverloadedOperatorKind Op = OO_None;
38 const Expr *LHS = nullptr;
39 const Expr *RHS = nullptr;
40
41 public:
LogicalBinOp(const Expr * E)42 LogicalBinOp(const Expr *E) {
43 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
44 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
45 LHS = BO->getLHS();
46 RHS = BO->getRHS();
47 Loc = BO->getExprLoc();
48 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
49 // If OO is not || or && it might not have exactly 2 arguments.
50 if (OO->getNumArgs() == 2) {
51 Op = OO->getOperator();
52 LHS = OO->getArg(0);
53 RHS = OO->getArg(1);
54 Loc = OO->getOperatorLoc();
55 }
56 }
57 }
58
isAnd() const59 bool isAnd() const { return Op == OO_AmpAmp; }
isOr() const60 bool isOr() const { return Op == OO_PipePipe; }
operator bool() const61 explicit operator bool() const { return isAnd() || isOr(); }
62
getLHS() const63 const Expr *getLHS() const { return LHS; }
getRHS() const64 const Expr *getRHS() const { return RHS; }
65
recreateBinOp(Sema & SemaRef,ExprResult LHS) const66 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
67 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
68 }
69
recreateBinOp(Sema & SemaRef,ExprResult LHS,ExprResult RHS) const70 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
71 ExprResult RHS) const {
72 assert((isAnd() || isOr()) && "Not the right kind of op?");
73 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
74
75 if (!LHS.isUsable() || !RHS.isUsable())
76 return ExprEmpty();
77
78 // We should just be able to 'normalize' these to the builtin Binary
79 // Operator, since that is how they are evaluated in constriant checks.
80 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
81 BinaryOperator::getOverloadedOpcode(Op),
82 SemaRef.Context.BoolTy, VK_PRValue,
83 OK_Ordinary, Loc, FPOptionsOverride{});
84 }
85 };
86 }
87
CheckConstraintExpression(const Expr * ConstraintExpression,Token NextToken,bool * PossibleNonPrimary,bool IsTrailingRequiresClause)88 bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
89 Token NextToken, bool *PossibleNonPrimary,
90 bool IsTrailingRequiresClause) {
91 // C++2a [temp.constr.atomic]p1
92 // ..E shall be a constant expression of type bool.
93
94 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
95
96 if (LogicalBinOp BO = ConstraintExpression) {
97 return CheckConstraintExpression(BO.getLHS(), NextToken,
98 PossibleNonPrimary) &&
99 CheckConstraintExpression(BO.getRHS(), NextToken,
100 PossibleNonPrimary);
101 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
102 return CheckConstraintExpression(C->getSubExpr(), NextToken,
103 PossibleNonPrimary);
104
105 QualType Type = ConstraintExpression->getType();
106
107 auto CheckForNonPrimary = [&] {
108 if (PossibleNonPrimary)
109 *PossibleNonPrimary =
110 // We have the following case:
111 // template<typename> requires func(0) struct S { };
112 // The user probably isn't aware of the parentheses required around
113 // the function call, and we're only going to parse 'func' as the
114 // primary-expression, and complain that it is of non-bool type.
115 (NextToken.is(tok::l_paren) &&
116 (IsTrailingRequiresClause ||
117 (Type->isDependentType() &&
118 isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
119 Type->isFunctionType() ||
120 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
121 // We have the following case:
122 // template<typename T> requires size_<T> == 0 struct S { };
123 // The user probably isn't aware of the parentheses required around
124 // the binary operator, and we're only going to parse 'func' as the
125 // first operand, and complain that it is of non-bool type.
126 getBinOpPrecedence(NextToken.getKind(),
127 /*GreaterThanIsOperator=*/true,
128 getLangOpts().CPlusPlus11) > prec::LogicalAnd;
129 };
130
131 // An atomic constraint!
132 if (ConstraintExpression->isTypeDependent()) {
133 CheckForNonPrimary();
134 return true;
135 }
136
137 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
138 Diag(ConstraintExpression->getExprLoc(),
139 diag::err_non_bool_atomic_constraint) << Type
140 << ConstraintExpression->getSourceRange();
141 CheckForNonPrimary();
142 return false;
143 }
144
145 if (PossibleNonPrimary)
146 *PossibleNonPrimary = false;
147 return true;
148 }
149
150 namespace {
151 struct SatisfactionStackRAII {
152 Sema &SemaRef;
153 bool Inserted = false;
SatisfactionStackRAII__anone5e5f72e0311::SatisfactionStackRAII154 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
155 llvm::FoldingSetNodeID FSNID)
156 : SemaRef(SemaRef) {
157 if (ND) {
158 SemaRef.PushSatisfactionStackEntry(ND, FSNID);
159 Inserted = true;
160 }
161 }
~SatisfactionStackRAII__anone5e5f72e0311::SatisfactionStackRAII162 ~SatisfactionStackRAII() {
163 if (Inserted)
164 SemaRef.PopSatisfactionStackEntry();
165 }
166 };
167 } // namespace
168
169 template <typename AtomicEvaluator>
170 static ExprResult
calculateConstraintSatisfaction(Sema & S,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction,AtomicEvaluator && Evaluator)171 calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
172 ConstraintSatisfaction &Satisfaction,
173 AtomicEvaluator &&Evaluator) {
174 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
175
176 if (LogicalBinOp BO = ConstraintExpr) {
177 ExprResult LHSRes = calculateConstraintSatisfaction(
178 S, BO.getLHS(), Satisfaction, Evaluator);
179
180 if (LHSRes.isInvalid())
181 return ExprError();
182
183 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
184
185 if (BO.isOr() && IsLHSSatisfied)
186 // [temp.constr.op] p3
187 // A disjunction is a constraint taking two operands. To determine if
188 // a disjunction is satisfied, the satisfaction of the first operand
189 // is checked. If that is satisfied, the disjunction is satisfied.
190 // Otherwise, the disjunction is satisfied if and only if the second
191 // operand is satisfied.
192 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
193 return LHSRes;
194
195 if (BO.isAnd() && !IsLHSSatisfied)
196 // [temp.constr.op] p2
197 // A conjunction is a constraint taking two operands. To determine if
198 // a conjunction is satisfied, the satisfaction of the first operand
199 // is checked. If that is not satisfied, the conjunction is not
200 // satisfied. Otherwise, the conjunction is satisfied if and only if
201 // the second operand is satisfied.
202 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
203 return LHSRes;
204
205 ExprResult RHSRes = calculateConstraintSatisfaction(
206 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
207 if (RHSRes.isInvalid())
208 return ExprError();
209
210 return BO.recreateBinOp(S, LHSRes, RHSRes);
211 }
212
213 if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
214 // These aren't evaluated, so we don't care about cleanups, so we can just
215 // evaluate these as if the cleanups didn't exist.
216 return calculateConstraintSatisfaction(
217 S, C->getSubExpr(), Satisfaction,
218 std::forward<AtomicEvaluator>(Evaluator));
219 }
220
221 // An atomic constraint expression
222 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
223
224 if (SubstitutedAtomicExpr.isInvalid())
225 return ExprError();
226
227 if (!SubstitutedAtomicExpr.isUsable())
228 // Evaluator has decided satisfaction without yielding an expression.
229 return ExprEmpty();
230
231 // We don't have the ability to evaluate this, since it contains a
232 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
233 // we'd potentially pick up a different overload, and cause confusing
234 // diagnostics. SO, add a failure detail that will cause us to make this
235 // overload set not viable.
236 if (SubstitutedAtomicExpr.get()->containsErrors()) {
237 Satisfaction.IsSatisfied = false;
238 Satisfaction.ContainsErrors = true;
239
240 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
241 SmallString<128> DiagString;
242 DiagString = ": ";
243 Msg.EmitToString(S.getDiagnostics(), DiagString);
244 unsigned MessageSize = DiagString.size();
245 char *Mem = new (S.Context) char[MessageSize];
246 memcpy(Mem, DiagString.c_str(), MessageSize);
247 Satisfaction.Details.emplace_back(
248 ConstraintExpr,
249 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
250 SubstitutedAtomicExpr.get()->getBeginLoc(),
251 StringRef(Mem, MessageSize)});
252 return SubstitutedAtomicExpr;
253 }
254
255 EnterExpressionEvaluationContext ConstantEvaluated(
256 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
257 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
258 Expr::EvalResult EvalResult;
259 EvalResult.Diag = &EvaluationDiags;
260 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
261 S.Context) ||
262 !EvaluationDiags.empty()) {
263 // C++2a [temp.constr.atomic]p1
264 // ...E shall be a constant expression of type bool.
265 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
266 diag::err_non_constant_constraint_expression)
267 << SubstitutedAtomicExpr.get()->getSourceRange();
268 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
269 S.Diag(PDiag.first, PDiag.second);
270 return ExprError();
271 }
272
273 assert(EvalResult.Val.isInt() &&
274 "evaluating bool expression didn't produce int");
275 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
276 if (!Satisfaction.IsSatisfied)
277 Satisfaction.Details.emplace_back(ConstraintExpr,
278 SubstitutedAtomicExpr.get());
279
280 return SubstitutedAtomicExpr;
281 }
282
283 static bool
DiagRecursiveConstraintEval(Sema & S,llvm::FoldingSetNodeID & ID,const NamedDecl * Templ,const Expr * E,const MultiLevelTemplateArgumentList & MLTAL)284 DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
285 const NamedDecl *Templ, const Expr *E,
286 const MultiLevelTemplateArgumentList &MLTAL) {
287 E->Profile(ID, S.Context, /*Canonical=*/true);
288 for (const auto &List : MLTAL)
289 for (const auto &TemplateArg : List.Args)
290 TemplateArg.Profile(ID, S.Context);
291
292 // Note that we have to do this with our own collection, because there are
293 // times where a constraint-expression check can cause us to need to evaluate
294 // other constriants that are unrelated, such as when evaluating a recovery
295 // expression, or when trying to determine the constexpr-ness of special
296 // members. Otherwise we could just use the
297 // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
298 if (S.SatisfactionStackContains(Templ, ID)) {
299 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
300 << const_cast<Expr *>(E) << E->getSourceRange();
301 return true;
302 }
303
304 return false;
305 }
306
calculateConstraintSatisfaction(Sema & S,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)307 static ExprResult calculateConstraintSatisfaction(
308 Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
309 const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
310 ConstraintSatisfaction &Satisfaction) {
311 return calculateConstraintSatisfaction(
312 S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
313 EnterExpressionEvaluationContext ConstantEvaluated(
314 S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
315 Sema::ReuseLambdaContextDecl);
316
317 // Atomic constraint - substitute arguments and check satisfaction.
318 ExprResult SubstitutedExpression;
319 {
320 TemplateDeductionInfo Info(TemplateNameLoc);
321 Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
322 Sema::InstantiatingTemplate::ConstraintSubstitution{},
323 const_cast<NamedDecl *>(Template), Info,
324 AtomicExpr->getSourceRange());
325 if (Inst.isInvalid())
326 return ExprError();
327
328 llvm::FoldingSetNodeID ID;
329 if (Template &&
330 DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
331 Satisfaction.IsSatisfied = false;
332 Satisfaction.ContainsErrors = true;
333 return ExprEmpty();
334 }
335
336 SatisfactionStackRAII StackRAII(S, Template, ID);
337
338 // We do not want error diagnostics escaping here.
339 Sema::SFINAETrap Trap(S);
340 SubstitutedExpression =
341 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
342
343 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
344 // C++2a [temp.constr.atomic]p1
345 // ...If substitution results in an invalid type or expression, the
346 // constraint is not satisfied.
347 if (!Trap.hasErrorOccurred())
348 // A non-SFINAE error has occurred as a result of this
349 // substitution.
350 return ExprError();
351
352 PartialDiagnosticAt SubstDiag{SourceLocation(),
353 PartialDiagnostic::NullDiagnostic()};
354 Info.takeSFINAEDiagnostic(SubstDiag);
355 // FIXME: Concepts: This is an unfortunate consequence of there
356 // being no serialization code for PartialDiagnostics and the fact
357 // that serializing them would likely take a lot more storage than
358 // just storing them as strings. We would still like, in the
359 // future, to serialize the proper PartialDiagnostic as serializing
360 // it as a string defeats the purpose of the diagnostic mechanism.
361 SmallString<128> DiagString;
362 DiagString = ": ";
363 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
364 unsigned MessageSize = DiagString.size();
365 char *Mem = new (S.Context) char[MessageSize];
366 memcpy(Mem, DiagString.c_str(), MessageSize);
367 Satisfaction.Details.emplace_back(
368 AtomicExpr,
369 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
370 SubstDiag.first, StringRef(Mem, MessageSize)});
371 Satisfaction.IsSatisfied = false;
372 return ExprEmpty();
373 }
374 }
375
376 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
377 return ExprError();
378
379 // [temp.constr.atomic]p3: To determine if an atomic constraint is
380 // satisfied, the parameter mapping and template arguments are first
381 // substituted into its expression. If substitution results in an
382 // invalid type or expression, the constraint is not satisfied.
383 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
384 // and E shall be a constant expression of type bool.
385 //
386 // Perform the L to R Value conversion if necessary. We do so for all
387 // non-PRValue categories, else we fail to extend the lifetime of
388 // temporaries, and that fails the constant expression check.
389 if (!SubstitutedExpression.get()->isPRValue())
390 SubstitutedExpression = ImplicitCastExpr::Create(
391 S.Context, SubstitutedExpression.get()->getType(),
392 CK_LValueToRValue, SubstitutedExpression.get(),
393 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
394
395 return SubstitutedExpression;
396 });
397 }
398
CheckConstraintSatisfaction(Sema & S,const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,llvm::SmallVectorImpl<Expr * > & Converted,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & Satisfaction)399 static bool CheckConstraintSatisfaction(
400 Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
401 llvm::SmallVectorImpl<Expr *> &Converted,
402 const MultiLevelTemplateArgumentList &TemplateArgsLists,
403 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
404 if (ConstraintExprs.empty()) {
405 Satisfaction.IsSatisfied = true;
406 return false;
407 }
408
409 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
410 // No need to check satisfaction for dependent constraint expressions.
411 Satisfaction.IsSatisfied = true;
412 return false;
413 }
414
415 ArrayRef<TemplateArgument> TemplateArgs =
416 TemplateArgsLists.getNumSubstitutedLevels() > 0
417 ? TemplateArgsLists.getOutermost()
418 : ArrayRef<TemplateArgument> {};
419 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
420 Sema::InstantiatingTemplate::ConstraintsCheck{},
421 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
422 if (Inst.isInvalid())
423 return true;
424
425 for (const Expr *ConstraintExpr : ConstraintExprs) {
426 ExprResult Res = calculateConstraintSatisfaction(
427 S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
428 ConstraintExpr, Satisfaction);
429 if (Res.isInvalid())
430 return true;
431
432 Converted.push_back(Res.get());
433 if (!Satisfaction.IsSatisfied) {
434 // Backfill the 'converted' list with nulls so we can keep the Converted
435 // and unconverted lists in sync.
436 Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
437 // [temp.constr.op] p2
438 // [...] To determine if a conjunction is satisfied, the satisfaction
439 // of the first operand is checked. If that is not satisfied, the
440 // conjunction is not satisfied. [...]
441 return false;
442 }
443 }
444 return false;
445 }
446
CheckConstraintSatisfaction(const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,llvm::SmallVectorImpl<Expr * > & ConvertedConstraints,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & OutSatisfaction)447 bool Sema::CheckConstraintSatisfaction(
448 const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
449 llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
450 const MultiLevelTemplateArgumentList &TemplateArgsLists,
451 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
452 if (ConstraintExprs.empty()) {
453 OutSatisfaction.IsSatisfied = true;
454 return false;
455 }
456 if (!Template) {
457 return ::CheckConstraintSatisfaction(
458 *this, nullptr, ConstraintExprs, ConvertedConstraints,
459 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
460 }
461
462 // A list of the template argument list flattened in a predictible manner for
463 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
464 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
465 // here.
466 llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
467 for (auto List : TemplateArgsLists)
468 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
469 List.Args.end());
470
471 llvm::FoldingSetNodeID ID;
472 ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
473 void *InsertPos;
474 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
475 OutSatisfaction = *Cached;
476 return false;
477 }
478
479 auto Satisfaction =
480 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
481 if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
482 ConvertedConstraints, TemplateArgsLists,
483 TemplateIDRange, *Satisfaction)) {
484 OutSatisfaction = *Satisfaction;
485 return true;
486 }
487
488 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
489 // The evaluation of this constraint resulted in us trying to re-evaluate it
490 // recursively. This isn't really possible, except we try to form a
491 // RecoveryExpr as a part of the evaluation. If this is the case, just
492 // return the 'cached' version (which will have the same result), and save
493 // ourselves the extra-insert. If it ever becomes possible to legitimately
494 // recursively check a constraint, we should skip checking the 'inner' one
495 // above, and replace the cached version with this one, as it would be more
496 // specific.
497 OutSatisfaction = *Cached;
498 return false;
499 }
500
501 // Else we can simply add this satisfaction to the list.
502 OutSatisfaction = *Satisfaction;
503 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
504 // invalidated it.
505 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
506 SatisfactionCache.InsertNode(Satisfaction.release());
507 return false;
508 }
509
CheckConstraintSatisfaction(const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)510 bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
511 ConstraintSatisfaction &Satisfaction) {
512 return calculateConstraintSatisfaction(
513 *this, ConstraintExpr, Satisfaction,
514 [this](const Expr *AtomicExpr) -> ExprResult {
515 // We only do this to immitate lvalue-to-rvalue conversion.
516 return PerformContextuallyConvertToBool(
517 const_cast<Expr *>(AtomicExpr));
518 })
519 .isInvalid();
520 }
521
SetupConstraintScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,MultiLevelTemplateArgumentList MLTAL,LocalInstantiationScope & Scope)522 bool Sema::SetupConstraintScope(
523 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
524 MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
525 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
526 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
527 InstantiatingTemplate Inst(
528 *this, FD->getPointOfInstantiation(),
529 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
530 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
531 SourceRange());
532 if (Inst.isInvalid())
533 return true;
534
535 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
536 // 'instantiated' parameters and adds it to the context. For the case where
537 // this function is a template being instantiated NOW, we also need to add
538 // the list of current template arguments to the list so that they also can
539 // be picked out of the map.
540 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
541 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
542 /*Final=*/false);
543 if (addInstantiatedParametersToScope(
544 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
545 return true;
546 }
547
548 // If this is a member function, make sure we get the parameters that
549 // reference the original primary template.
550 if (const auto *FromMemTempl =
551 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
552 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
553 Scope, MLTAL))
554 return true;
555 }
556
557 return false;
558 }
559
560 if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
561 FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
562 FunctionDecl *InstantiatedFrom =
563 FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
564 ? FD->getInstantiatedFromMemberFunction()
565 : FD->getInstantiatedFromDecl();
566
567 InstantiatingTemplate Inst(
568 *this, FD->getPointOfInstantiation(),
569 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
570 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
571 SourceRange());
572 if (Inst.isInvalid())
573 return true;
574
575 // Case where this was not a template, but instantiated as a
576 // child-function.
577 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
578 return true;
579 }
580
581 return false;
582 }
583
584 // This function collects all of the template arguments for the purposes of
585 // constraint-instantiation and checking.
586 std::optional<MultiLevelTemplateArgumentList>
SetupConstraintCheckingTemplateArgumentsAndScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,LocalInstantiationScope & Scope)587 Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
588 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
589 LocalInstantiationScope &Scope) {
590 MultiLevelTemplateArgumentList MLTAL;
591
592 // Collect the list of template arguments relative to the 'primary' template.
593 // We need the entire list, since the constraint is completely uninstantiated
594 // at this point.
595 MLTAL =
596 getTemplateInstantiationArgs(FD, /*Final=*/false, /*Innermost=*/nullptr,
597 /*RelativeToPrimary=*/true,
598 /*Pattern=*/nullptr,
599 /*ForConstraintInstantiation=*/true);
600 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
601 return std::nullopt;
602
603 return MLTAL;
604 }
605
CheckFunctionConstraints(const FunctionDecl * FD,ConstraintSatisfaction & Satisfaction,SourceLocation UsageLoc,bool ForOverloadResolution)606 bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
607 ConstraintSatisfaction &Satisfaction,
608 SourceLocation UsageLoc,
609 bool ForOverloadResolution) {
610 // Don't check constraints if the function is dependent. Also don't check if
611 // this is a function template specialization, as the call to
612 // CheckinstantiatedFunctionTemplateConstraints after this will check it
613 // better.
614 if (FD->isDependentContext() ||
615 FD->getTemplatedKind() ==
616 FunctionDecl::TK_FunctionTemplateSpecialization) {
617 Satisfaction.IsSatisfied = true;
618 return false;
619 }
620
621 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
622
623 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
624 if (isLambdaCallOperator(CtxToSave))
625 CtxToSave = CtxToSave->getParent()->getParent();
626 else
627 CtxToSave = CtxToSave->getNonTransparentContext();
628 }
629
630 ContextRAII SavedContext{*this, CtxToSave};
631 LocalInstantiationScope Scope(*this, !ForOverloadResolution ||
632 isLambdaCallOperator(FD));
633 std::optional<MultiLevelTemplateArgumentList> MLTAL =
634 SetupConstraintCheckingTemplateArgumentsAndScope(
635 const_cast<FunctionDecl *>(FD), {}, Scope);
636
637 if (!MLTAL)
638 return true;
639
640 Qualifiers ThisQuals;
641 CXXRecordDecl *Record = nullptr;
642 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
643 ThisQuals = Method->getMethodQualifiers();
644 Record = const_cast<CXXRecordDecl *>(Method->getParent());
645 }
646 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
647 // We substitute with empty arguments in order to rebuild the atomic
648 // constraint in a constant-evaluated context.
649 // FIXME: Should this be a dedicated TreeTransform?
650 const Expr *RC = FD->getTrailingRequiresClause();
651 llvm::SmallVector<Expr *, 1> Converted;
652
653 if (CheckConstraintSatisfaction(
654 FD, {RC}, Converted, *MLTAL,
655 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
656 Satisfaction))
657 return true;
658
659 // FIXME: we need to do this for the function constraints for
660 // comparison of constraints to work, but do we also need to do it for
661 // CheckInstantiatedFunctionConstraints? That one is more difficult, but we
662 // seem to always just pick up the constraints from the primary template.
663 assert(Converted.size() <= 1 && "Got more expressions converted?");
664 if (!Converted.empty() && Converted[0] != nullptr)
665 const_cast<FunctionDecl *>(FD)->setTrailingRequiresClause(Converted[0]);
666 return false;
667 }
668
669
670 // Figure out the to-translation-unit depth for this function declaration for
671 // the purpose of seeing if they differ by constraints. This isn't the same as
672 // getTemplateDepth, because it includes already instantiated parents.
673 static unsigned
CalculateTemplateDepthForConstraints(Sema & S,const NamedDecl * ND,bool SkipForSpecialization=false)674 CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
675 bool SkipForSpecialization = false) {
676 MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
677 ND, /*Final=*/false, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true,
678 /*Pattern=*/nullptr,
679 /*ForConstraintInstantiation=*/true, SkipForSpecialization);
680 return MLTAL.getNumSubstitutedLevels();
681 }
682
683 namespace {
684 class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
685 unsigned TemplateDepth = 0;
686 public:
687 using inherited = TreeTransform<AdjustConstraintDepth>;
AdjustConstraintDepth(Sema & SemaRef,unsigned TemplateDepth)688 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
689 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
690
691 using inherited::TransformTemplateTypeParmType;
TransformTemplateTypeParmType(TypeLocBuilder & TLB,TemplateTypeParmTypeLoc TL,bool)692 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
693 TemplateTypeParmTypeLoc TL, bool) {
694 const TemplateTypeParmType *T = TL.getTypePtr();
695
696 TemplateTypeParmDecl *NewTTPDecl = nullptr;
697 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
698 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
699 TransformDecl(TL.getNameLoc(), OldTTPDecl));
700
701 QualType Result = getSema().Context.getTemplateTypeParmType(
702 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
703 NewTTPDecl);
704 TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
705 NewTL.setNameLoc(TL.getNameLoc());
706 return Result;
707 }
708 };
709 } // namespace
710
AreConstraintExpressionsEqual(const NamedDecl * Old,const Expr * OldConstr,const NamedDecl * New,const Expr * NewConstr)711 bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
712 const Expr *OldConstr,
713 const NamedDecl *New,
714 const Expr *NewConstr) {
715 if (Old && New && Old != New) {
716 unsigned Depth1 = CalculateTemplateDepthForConstraints(
717 *this, Old);
718 unsigned Depth2 = CalculateTemplateDepthForConstraints(
719 *this, New);
720
721 // Adjust the 'shallowest' verison of this to increase the depth to match
722 // the 'other'.
723 if (Depth2 > Depth1) {
724 OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1)
725 .TransformExpr(const_cast<Expr *>(OldConstr))
726 .get();
727 } else if (Depth1 > Depth2) {
728 NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2)
729 .TransformExpr(const_cast<Expr *>(NewConstr))
730 .get();
731 }
732 }
733
734 llvm::FoldingSetNodeID ID1, ID2;
735 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
736 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
737 return ID1 == ID2;
738 }
739
FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl * FD)740 bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
741 assert(FD->getFriendObjectKind() && "Must be a friend!");
742
743 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
744 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
745 // non-function-template.
746 assert(FD->getDescribedFunctionTemplate() &&
747 "Non-function templates don't need to be checked");
748
749 SmallVector<const Expr *, 3> ACs;
750 FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
751
752 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
753 for (const Expr *Constraint : ACs)
754 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
755 Constraint))
756 return true;
757
758 return false;
759 }
760
EnsureTemplateArgumentListConstraints(TemplateDecl * TD,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange)761 bool Sema::EnsureTemplateArgumentListConstraints(
762 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
763 SourceRange TemplateIDRange) {
764 ConstraintSatisfaction Satisfaction;
765 llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
766 TD->getAssociatedConstraints(AssociatedConstraints);
767 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
768 TemplateIDRange, Satisfaction))
769 return true;
770
771 if (!Satisfaction.IsSatisfied) {
772 SmallString<128> TemplateArgString;
773 TemplateArgString = " ";
774 TemplateArgString += getTemplateArgumentBindingsText(
775 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
776 TemplateArgsLists.getInnermost().size());
777
778 Diag(TemplateIDRange.getBegin(),
779 diag::err_template_arg_list_constraints_not_satisfied)
780 << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
781 << TemplateArgString << TemplateIDRange;
782 DiagnoseUnsatisfiedConstraint(Satisfaction);
783 return true;
784 }
785 return false;
786 }
787
CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation,FunctionDecl * Decl,ArrayRef<TemplateArgument> TemplateArgs,ConstraintSatisfaction & Satisfaction)788 bool Sema::CheckInstantiatedFunctionTemplateConstraints(
789 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
790 ArrayRef<TemplateArgument> TemplateArgs,
791 ConstraintSatisfaction &Satisfaction) {
792 // In most cases we're not going to have constraints, so check for that first.
793 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
794 // Note - code synthesis context for the constraints check is created
795 // inside CheckConstraintsSatisfaction.
796 SmallVector<const Expr *, 3> TemplateAC;
797 Template->getAssociatedConstraints(TemplateAC);
798 if (TemplateAC.empty()) {
799 Satisfaction.IsSatisfied = true;
800 return false;
801 }
802
803 // Enter the scope of this instantiation. We don't use
804 // PushDeclContext because we don't have a scope.
805 Sema::ContextRAII savedContext(*this, Decl);
806 LocalInstantiationScope Scope(*this);
807
808 std::optional<MultiLevelTemplateArgumentList> MLTAL =
809 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
810 Scope);
811
812 if (!MLTAL)
813 return true;
814
815 Qualifiers ThisQuals;
816 CXXRecordDecl *Record = nullptr;
817 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
818 ThisQuals = Method->getMethodQualifiers();
819 Record = Method->getParent();
820 }
821 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
822 FunctionScopeRAII FuncScope(*this);
823 if (isLambdaCallOperator(Decl))
824 PushLambdaScope();
825 else
826 FuncScope.disable();
827
828 llvm::SmallVector<Expr *, 1> Converted;
829 return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
830 PointOfInstantiation, Satisfaction);
831 }
832
diagnoseUnsatisfiedRequirement(Sema & S,concepts::ExprRequirement * Req,bool First)833 static void diagnoseUnsatisfiedRequirement(Sema &S,
834 concepts::ExprRequirement *Req,
835 bool First) {
836 assert(!Req->isSatisfied()
837 && "Diagnose() can only be used on an unsatisfied requirement");
838 switch (Req->getSatisfactionStatus()) {
839 case concepts::ExprRequirement::SS_Dependent:
840 llvm_unreachable("Diagnosing a dependent requirement");
841 break;
842 case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
843 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
844 if (!SubstDiag->DiagMessage.empty())
845 S.Diag(SubstDiag->DiagLoc,
846 diag::note_expr_requirement_expr_substitution_error)
847 << (int)First << SubstDiag->SubstitutedEntity
848 << SubstDiag->DiagMessage;
849 else
850 S.Diag(SubstDiag->DiagLoc,
851 diag::note_expr_requirement_expr_unknown_substitution_error)
852 << (int)First << SubstDiag->SubstitutedEntity;
853 break;
854 }
855 case concepts::ExprRequirement::SS_NoexceptNotMet:
856 S.Diag(Req->getNoexceptLoc(),
857 diag::note_expr_requirement_noexcept_not_met)
858 << (int)First << Req->getExpr();
859 break;
860 case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
861 auto *SubstDiag =
862 Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
863 if (!SubstDiag->DiagMessage.empty())
864 S.Diag(SubstDiag->DiagLoc,
865 diag::note_expr_requirement_type_requirement_substitution_error)
866 << (int)First << SubstDiag->SubstitutedEntity
867 << SubstDiag->DiagMessage;
868 else
869 S.Diag(SubstDiag->DiagLoc,
870 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
871 << (int)First << SubstDiag->SubstitutedEntity;
872 break;
873 }
874 case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
875 ConceptSpecializationExpr *ConstraintExpr =
876 Req->getReturnTypeRequirementSubstitutedConstraintExpr();
877 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
878 // A simple case - expr type is the type being constrained and the concept
879 // was not provided arguments.
880 Expr *e = Req->getExpr();
881 S.Diag(e->getBeginLoc(),
882 diag::note_expr_requirement_constraints_not_satisfied_simple)
883 << (int)First << S.Context.getReferenceQualifiedType(e)
884 << ConstraintExpr->getNamedConcept();
885 } else {
886 S.Diag(ConstraintExpr->getBeginLoc(),
887 diag::note_expr_requirement_constraints_not_satisfied)
888 << (int)First << ConstraintExpr;
889 }
890 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
891 break;
892 }
893 case concepts::ExprRequirement::SS_Satisfied:
894 llvm_unreachable("We checked this above");
895 }
896 }
897
diagnoseUnsatisfiedRequirement(Sema & S,concepts::TypeRequirement * Req,bool First)898 static void diagnoseUnsatisfiedRequirement(Sema &S,
899 concepts::TypeRequirement *Req,
900 bool First) {
901 assert(!Req->isSatisfied()
902 && "Diagnose() can only be used on an unsatisfied requirement");
903 switch (Req->getSatisfactionStatus()) {
904 case concepts::TypeRequirement::SS_Dependent:
905 llvm_unreachable("Diagnosing a dependent requirement");
906 return;
907 case concepts::TypeRequirement::SS_SubstitutionFailure: {
908 auto *SubstDiag = Req->getSubstitutionDiagnostic();
909 if (!SubstDiag->DiagMessage.empty())
910 S.Diag(SubstDiag->DiagLoc,
911 diag::note_type_requirement_substitution_error) << (int)First
912 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
913 else
914 S.Diag(SubstDiag->DiagLoc,
915 diag::note_type_requirement_unknown_substitution_error)
916 << (int)First << SubstDiag->SubstitutedEntity;
917 return;
918 }
919 default:
920 llvm_unreachable("Unknown satisfaction status");
921 return;
922 }
923 }
924 static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
925 Expr *SubstExpr,
926 bool First = true);
927
diagnoseUnsatisfiedRequirement(Sema & S,concepts::NestedRequirement * Req,bool First)928 static void diagnoseUnsatisfiedRequirement(Sema &S,
929 concepts::NestedRequirement *Req,
930 bool First) {
931 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
932 for (auto &Pair : Req->getConstraintSatisfaction()) {
933 if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
934 S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
935 << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second;
936 else
937 diagnoseWellFormedUnsatisfiedConstraintExpr(
938 S, Pair.second.dyn_cast<Expr *>(), First);
939 First = false;
940 }
941 }
942
diagnoseWellFormedUnsatisfiedConstraintExpr(Sema & S,Expr * SubstExpr,bool First)943 static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
944 Expr *SubstExpr,
945 bool First) {
946 SubstExpr = SubstExpr->IgnoreParenImpCasts();
947 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
948 switch (BO->getOpcode()) {
949 // These two cases will in practice only be reached when using fold
950 // expressions with || and &&, since otherwise the || and && will have been
951 // broken down into atomic constraints during satisfaction checking.
952 case BO_LOr:
953 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
954 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
955 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
956 /*First=*/false);
957 return;
958 case BO_LAnd: {
959 bool LHSSatisfied =
960 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
961 if (LHSSatisfied) {
962 // LHS is true, so RHS must be false.
963 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
964 return;
965 }
966 // LHS is false
967 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
968
969 // RHS might also be false
970 bool RHSSatisfied =
971 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
972 if (!RHSSatisfied)
973 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
974 /*First=*/false);
975 return;
976 }
977 case BO_GE:
978 case BO_LE:
979 case BO_GT:
980 case BO_LT:
981 case BO_EQ:
982 case BO_NE:
983 if (BO->getLHS()->getType()->isIntegerType() &&
984 BO->getRHS()->getType()->isIntegerType()) {
985 Expr::EvalResult SimplifiedLHS;
986 Expr::EvalResult SimplifiedRHS;
987 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
988 Expr::SE_NoSideEffects,
989 /*InConstantContext=*/true);
990 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
991 Expr::SE_NoSideEffects,
992 /*InConstantContext=*/true);
993 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
994 S.Diag(SubstExpr->getBeginLoc(),
995 diag::note_atomic_constraint_evaluated_to_false_elaborated)
996 << (int)First << SubstExpr
997 << toString(SimplifiedLHS.Val.getInt(), 10)
998 << BinaryOperator::getOpcodeStr(BO->getOpcode())
999 << toString(SimplifiedRHS.Val.getInt(), 10);
1000 return;
1001 }
1002 }
1003 break;
1004
1005 default:
1006 break;
1007 }
1008 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1009 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1010 S.Diag(
1011 CSE->getSourceRange().getBegin(),
1012 diag::
1013 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1014 << (int)First
1015 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1016 << CSE->getNamedConcept();
1017 } else {
1018 S.Diag(SubstExpr->getSourceRange().getBegin(),
1019 diag::note_concept_specialization_constraint_evaluated_to_false)
1020 << (int)First << CSE;
1021 }
1022 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1023 return;
1024 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1025 // FIXME: RequiresExpr should store dependent diagnostics.
1026 for (concepts::Requirement *Req : RE->getRequirements())
1027 if (!Req->isDependent() && !Req->isSatisfied()) {
1028 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1029 diagnoseUnsatisfiedRequirement(S, E, First);
1030 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1031 diagnoseUnsatisfiedRequirement(S, T, First);
1032 else
1033 diagnoseUnsatisfiedRequirement(
1034 S, cast<concepts::NestedRequirement>(Req), First);
1035 break;
1036 }
1037 return;
1038 }
1039
1040 S.Diag(SubstExpr->getSourceRange().getBegin(),
1041 diag::note_atomic_constraint_evaluated_to_false)
1042 << (int)First << SubstExpr;
1043 }
1044
1045 template<typename SubstitutionDiagnostic>
diagnoseUnsatisfiedConstraintExpr(Sema & S,const Expr * E,const llvm::PointerUnion<Expr *,SubstitutionDiagnostic * > & Record,bool First=true)1046 static void diagnoseUnsatisfiedConstraintExpr(
1047 Sema &S, const Expr *E,
1048 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1049 bool First = true) {
1050 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
1051 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1052 << Diag->second;
1053 return;
1054 }
1055
1056 diagnoseWellFormedUnsatisfiedConstraintExpr(S,
1057 Record.template get<Expr *>(), First);
1058 }
1059
1060 void
DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction & Satisfaction,bool First)1061 Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
1062 bool First) {
1063 assert(!Satisfaction.IsSatisfied &&
1064 "Attempted to diagnose a satisfied constraint");
1065 for (auto &Pair : Satisfaction.Details) {
1066 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1067 First = false;
1068 }
1069 }
1070
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction & Satisfaction,bool First)1071 void Sema::DiagnoseUnsatisfiedConstraint(
1072 const ASTConstraintSatisfaction &Satisfaction,
1073 bool First) {
1074 assert(!Satisfaction.IsSatisfied &&
1075 "Attempted to diagnose a satisfied constraint");
1076 for (auto &Pair : Satisfaction) {
1077 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1078 First = false;
1079 }
1080 }
1081
1082 const NormalizedConstraint *
getNormalizedAssociatedConstraints(NamedDecl * ConstrainedDecl,ArrayRef<const Expr * > AssociatedConstraints)1083 Sema::getNormalizedAssociatedConstraints(
1084 NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
1085 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1086 if (CacheEntry == NormalizationCache.end()) {
1087 auto Normalized =
1088 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1089 AssociatedConstraints);
1090 CacheEntry =
1091 NormalizationCache
1092 .try_emplace(ConstrainedDecl,
1093 Normalized
1094 ? new (Context) NormalizedConstraint(
1095 std::move(*Normalized))
1096 : nullptr)
1097 .first;
1098 }
1099 return CacheEntry->second;
1100 }
1101
1102 static bool
substituteParameterMappings(Sema & S,NormalizedConstraint & N,ConceptDecl * Concept,const MultiLevelTemplateArgumentList & MLTAL,const ASTTemplateArgumentListInfo * ArgsAsWritten)1103 substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1104 ConceptDecl *Concept,
1105 const MultiLevelTemplateArgumentList &MLTAL,
1106 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1107 if (!N.isAtomic()) {
1108 if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1109 ArgsAsWritten))
1110 return true;
1111 return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1112 ArgsAsWritten);
1113 }
1114 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1115
1116 AtomicConstraint &Atomic = *N.getAtomicConstraint();
1117 TemplateArgumentListInfo SubstArgs;
1118 if (!Atomic.ParameterMapping) {
1119 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1120 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1121 /*Depth=*/0, OccurringIndices);
1122 TemplateArgumentLoc *TempArgs =
1123 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1124 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1125 if (OccurringIndices[I])
1126 new (&(TempArgs)[J++])
1127 TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(
1128 TemplateParams->begin()[I],
1129 // Here we assume we do not support things like
1130 // template<typename A, typename B>
1131 // concept C = ...;
1132 //
1133 // template<typename... Ts> requires C<Ts...>
1134 // struct S { };
1135 // The above currently yields a diagnostic.
1136 // We still might have default arguments for concept parameters.
1137 ArgsAsWritten->NumTemplateArgs > I
1138 ? ArgsAsWritten->arguments()[I].getLocation()
1139 : SourceLocation()));
1140 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
1141 }
1142 Sema::InstantiatingTemplate Inst(
1143 S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
1144 Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
1145 ArgsAsWritten->arguments().front().getSourceRange());
1146 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1147 return true;
1148
1149 TemplateArgumentLoc *TempArgs =
1150 new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1151 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1152 TempArgs);
1153 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1154 return false;
1155 }
1156
substituteParameterMappings(Sema & S,NormalizedConstraint & N,const ConceptSpecializationExpr * CSE)1157 static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1158 const ConceptSpecializationExpr *CSE) {
1159 TemplateArgumentList TAL{TemplateArgumentList::OnStack,
1160 CSE->getTemplateArguments()};
1161 MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
1162 CSE->getNamedConcept(), /*Final=*/false, &TAL,
1163 /*RelativeToPrimary=*/true,
1164 /*Pattern=*/nullptr,
1165 /*ForConstraintInstantiation=*/true);
1166
1167 return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1168 CSE->getTemplateArgsAsWritten());
1169 }
1170
1171 std::optional<NormalizedConstraint>
fromConstraintExprs(Sema & S,NamedDecl * D,ArrayRef<const Expr * > E)1172 NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1173 ArrayRef<const Expr *> E) {
1174 assert(E.size() != 0);
1175 auto Conjunction = fromConstraintExpr(S, D, E[0]);
1176 if (!Conjunction)
1177 return std::nullopt;
1178 for (unsigned I = 1; I < E.size(); ++I) {
1179 auto Next = fromConstraintExpr(S, D, E[I]);
1180 if (!Next)
1181 return std::nullopt;
1182 *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1183 std::move(*Next), CCK_Conjunction);
1184 }
1185 return Conjunction;
1186 }
1187
1188 std::optional<NormalizedConstraint>
fromConstraintExpr(Sema & S,NamedDecl * D,const Expr * E)1189 NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1190 assert(E != nullptr);
1191
1192 // C++ [temp.constr.normal]p1.1
1193 // [...]
1194 // - The normal form of an expression (E) is the normal form of E.
1195 // [...]
1196 E = E->IgnoreParenImpCasts();
1197
1198 // C++2a [temp.param]p4:
1199 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1200 // Fold expression is considered atomic constraints per current wording.
1201 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1202
1203 if (LogicalBinOp BO = E) {
1204 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1205 if (!LHS)
1206 return std::nullopt;
1207 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1208 if (!RHS)
1209 return std::nullopt;
1210
1211 return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
1212 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1213 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1214 const NormalizedConstraint *SubNF;
1215 {
1216 Sema::InstantiatingTemplate Inst(
1217 S, CSE->getExprLoc(),
1218 Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
1219 CSE->getSourceRange());
1220 // C++ [temp.constr.normal]p1.1
1221 // [...]
1222 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1223 // where C names a concept, is the normal form of the
1224 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1225 // respective template parameters in the parameter mappings in each atomic
1226 // constraint. If any such substitution results in an invalid type or
1227 // expression, the program is ill-formed; no diagnostic is required.
1228 // [...]
1229 ConceptDecl *CD = CSE->getNamedConcept();
1230 SubNF = S.getNormalizedAssociatedConstraints(CD,
1231 {CD->getConstraintExpr()});
1232 if (!SubNF)
1233 return std::nullopt;
1234 }
1235
1236 std::optional<NormalizedConstraint> New;
1237 New.emplace(S.Context, *SubNF);
1238
1239 if (substituteParameterMappings(S, *New, CSE))
1240 return std::nullopt;
1241
1242 return New;
1243 }
1244 return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
1245 }
1246
1247 using NormalForm =
1248 llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
1249
makeCNF(const NormalizedConstraint & Normalized)1250 static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
1251 if (Normalized.isAtomic())
1252 return {{Normalized.getAtomicConstraint()}};
1253
1254 NormalForm LCNF = makeCNF(Normalized.getLHS());
1255 NormalForm RCNF = makeCNF(Normalized.getRHS());
1256 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
1257 LCNF.reserve(LCNF.size() + RCNF.size());
1258 while (!RCNF.empty())
1259 LCNF.push_back(RCNF.pop_back_val());
1260 return LCNF;
1261 }
1262
1263 // Disjunction
1264 NormalForm Res;
1265 Res.reserve(LCNF.size() * RCNF.size());
1266 for (auto &LDisjunction : LCNF)
1267 for (auto &RDisjunction : RCNF) {
1268 NormalForm::value_type Combined;
1269 Combined.reserve(LDisjunction.size() + RDisjunction.size());
1270 std::copy(LDisjunction.begin(), LDisjunction.end(),
1271 std::back_inserter(Combined));
1272 std::copy(RDisjunction.begin(), RDisjunction.end(),
1273 std::back_inserter(Combined));
1274 Res.emplace_back(Combined);
1275 }
1276 return Res;
1277 }
1278
makeDNF(const NormalizedConstraint & Normalized)1279 static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
1280 if (Normalized.isAtomic())
1281 return {{Normalized.getAtomicConstraint()}};
1282
1283 NormalForm LDNF = makeDNF(Normalized.getLHS());
1284 NormalForm RDNF = makeDNF(Normalized.getRHS());
1285 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
1286 LDNF.reserve(LDNF.size() + RDNF.size());
1287 while (!RDNF.empty())
1288 LDNF.push_back(RDNF.pop_back_val());
1289 return LDNF;
1290 }
1291
1292 // Conjunction
1293 NormalForm Res;
1294 Res.reserve(LDNF.size() * RDNF.size());
1295 for (auto &LConjunction : LDNF) {
1296 for (auto &RConjunction : RDNF) {
1297 NormalForm::value_type Combined;
1298 Combined.reserve(LConjunction.size() + RConjunction.size());
1299 std::copy(LConjunction.begin(), LConjunction.end(),
1300 std::back_inserter(Combined));
1301 std::copy(RConjunction.begin(), RConjunction.end(),
1302 std::back_inserter(Combined));
1303 Res.emplace_back(Combined);
1304 }
1305 }
1306 return Res;
1307 }
1308
1309 template<typename AtomicSubsumptionEvaluator>
subsumes(NormalForm PDNF,NormalForm QCNF,AtomicSubsumptionEvaluator E)1310 static bool subsumes(NormalForm PDNF, NormalForm QCNF,
1311 AtomicSubsumptionEvaluator E) {
1312 // C++ [temp.constr.order] p2
1313 // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
1314 // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
1315 // the conjuctive normal form of Q, where [...]
1316 for (const auto &Pi : PDNF) {
1317 for (const auto &Qj : QCNF) {
1318 // C++ [temp.constr.order] p2
1319 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
1320 // and only if there exists an atomic constraint Pia in Pi for which
1321 // there exists an atomic constraint, Qjb, in Qj such that Pia
1322 // subsumes Qjb.
1323 bool Found = false;
1324 for (const AtomicConstraint *Pia : Pi) {
1325 for (const AtomicConstraint *Qjb : Qj) {
1326 if (E(*Pia, *Qjb)) {
1327 Found = true;
1328 break;
1329 }
1330 }
1331 if (Found)
1332 break;
1333 }
1334 if (!Found)
1335 return false;
1336 }
1337 }
1338 return true;
1339 }
1340
1341 template<typename AtomicSubsumptionEvaluator>
subsumes(Sema & S,NamedDecl * DP,ArrayRef<const Expr * > P,NamedDecl * DQ,ArrayRef<const Expr * > Q,bool & Subsumes,AtomicSubsumptionEvaluator E)1342 static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
1343 NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
1344 AtomicSubsumptionEvaluator E) {
1345 // C++ [temp.constr.order] p2
1346 // In order to determine if a constraint P subsumes a constraint Q, P is
1347 // transformed into disjunctive normal form, and Q is transformed into
1348 // conjunctive normal form. [...]
1349 auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
1350 if (!PNormalized)
1351 return true;
1352 const NormalForm PDNF = makeDNF(*PNormalized);
1353
1354 auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
1355 if (!QNormalized)
1356 return true;
1357 const NormalForm QCNF = makeCNF(*QNormalized);
1358
1359 Subsumes = subsumes(PDNF, QCNF, E);
1360 return false;
1361 }
1362
IsAtLeastAsConstrained(NamedDecl * D1,MutableArrayRef<const Expr * > AC1,NamedDecl * D2,MutableArrayRef<const Expr * > AC2,bool & Result)1363 bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
1364 MutableArrayRef<const Expr *> AC1,
1365 NamedDecl *D2,
1366 MutableArrayRef<const Expr *> AC2,
1367 bool &Result) {
1368 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1369 auto IsExpectedEntity = [](const FunctionDecl *FD) {
1370 FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
1371 return Kind == FunctionDecl::TK_NonTemplate ||
1372 Kind == FunctionDecl::TK_FunctionTemplate;
1373 };
1374 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1375 (void)IsExpectedEntity;
1376 (void)FD1;
1377 (void)FD2;
1378 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1379 "use non-instantiated function declaration for constraints partial "
1380 "ordering");
1381 }
1382
1383 if (AC1.empty()) {
1384 Result = AC2.empty();
1385 return false;
1386 }
1387 if (AC2.empty()) {
1388 // TD1 has associated constraints and TD2 does not.
1389 Result = true;
1390 return false;
1391 }
1392
1393 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1394 auto CacheEntry = SubsumptionCache.find(Key);
1395 if (CacheEntry != SubsumptionCache.end()) {
1396 Result = CacheEntry->second;
1397 return false;
1398 }
1399
1400 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1401 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1402
1403 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1404 if (Depth2 > Depth1) {
1405 AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1406 .TransformExpr(const_cast<Expr *>(AC1[I]))
1407 .get();
1408 } else if (Depth1 > Depth2) {
1409 AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1410 .TransformExpr(const_cast<Expr *>(AC2[I]))
1411 .get();
1412 }
1413 }
1414
1415 if (subsumes(*this, D1, AC1, D2, AC2, Result,
1416 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1417 return A.subsumes(Context, B);
1418 }))
1419 return true;
1420 SubsumptionCache.try_emplace(Key, Result);
1421 return false;
1422 }
1423
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl * D1,ArrayRef<const Expr * > AC1,NamedDecl * D2,ArrayRef<const Expr * > AC2)1424 bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
1425 ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
1426 if (isSFINAEContext())
1427 // No need to work here because our notes would be discarded.
1428 return false;
1429
1430 if (AC1.empty() || AC2.empty())
1431 return false;
1432
1433 auto NormalExprEvaluator =
1434 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1435 return A.subsumes(Context, B);
1436 };
1437
1438 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1439 auto IdenticalExprEvaluator =
1440 [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1441 if (!A.hasMatchingParameterMapping(Context, B))
1442 return false;
1443 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1444 if (EA == EB)
1445 return true;
1446
1447 // Not the same source level expression - are the expressions
1448 // identical?
1449 llvm::FoldingSetNodeID IDA, IDB;
1450 EA->Profile(IDA, Context, /*Canonical=*/true);
1451 EB->Profile(IDB, Context, /*Canonical=*/true);
1452 if (IDA != IDB)
1453 return false;
1454
1455 AmbiguousAtomic1 = EA;
1456 AmbiguousAtomic2 = EB;
1457 return true;
1458 };
1459
1460 {
1461 // The subsumption checks might cause diagnostics
1462 SFINAETrap Trap(*this);
1463 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1464 if (!Normalized1)
1465 return false;
1466 const NormalForm DNF1 = makeDNF(*Normalized1);
1467 const NormalForm CNF1 = makeCNF(*Normalized1);
1468
1469 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1470 if (!Normalized2)
1471 return false;
1472 const NormalForm DNF2 = makeDNF(*Normalized2);
1473 const NormalForm CNF2 = makeCNF(*Normalized2);
1474
1475 bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1476 bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1477 bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1478 bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1479 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1480 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1481 // Same result - no ambiguity was caused by identical atomic expressions.
1482 return false;
1483 }
1484
1485 // A different result! Some ambiguous atomic constraint(s) caused a difference
1486 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1487
1488 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1489 << AmbiguousAtomic1->getSourceRange();
1490 Diag(AmbiguousAtomic2->getBeginLoc(),
1491 diag::note_ambiguous_atomic_constraints_similar_expression)
1492 << AmbiguousAtomic2->getSourceRange();
1493 return true;
1494 }
1495
ExprRequirement(Expr * E,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req,SatisfactionStatus Status,ConceptSpecializationExpr * SubstitutedConstraintExpr)1496 concepts::ExprRequirement::ExprRequirement(
1497 Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1498 ReturnTypeRequirement Req, SatisfactionStatus Status,
1499 ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1500 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1501 Status == SS_Dependent &&
1502 (E->containsUnexpandedParameterPack() ||
1503 Req.containsUnexpandedParameterPack()),
1504 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1505 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1506 Status(Status) {
1507 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1508 "Simple requirement must not have a return type requirement or a "
1509 "noexcept specification");
1510 assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1511 (SubstitutedConstraintExpr != nullptr));
1512 }
1513
ExprRequirement(SubstitutionDiagnostic * ExprSubstDiag,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req)1514 concepts::ExprRequirement::ExprRequirement(
1515 SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1516 SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1517 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1518 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1519 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1520 Status(SS_ExprSubstitutionFailure) {
1521 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1522 "Simple requirement must not have a return type requirement or a "
1523 "noexcept specification");
1524 }
1525
1526 concepts::ExprRequirement::ReturnTypeRequirement::
ReturnTypeRequirement(TemplateParameterList * TPL)1527 ReturnTypeRequirement(TemplateParameterList *TPL) :
1528 TypeConstraintInfo(TPL, false) {
1529 assert(TPL->size() == 1);
1530 const TypeConstraint *TC =
1531 cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1532 assert(TC &&
1533 "TPL must have a template type parameter with a type constraint");
1534 auto *Constraint =
1535 cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1536 bool Dependent =
1537 Constraint->getTemplateArgsAsWritten() &&
1538 TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1539 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1540 TypeConstraintInfo.setInt(Dependent ? true : false);
1541 }
1542
TypeRequirement(TypeSourceInfo * T)1543 concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1544 Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1545 T->getType()->containsUnexpandedParameterPack(),
1546 // We reach this ctor with either dependent types (in which
1547 // IsSatisfied doesn't matter) or with non-dependent type in
1548 // which the existence of the type indicates satisfaction.
1549 /*IsSatisfied=*/true),
1550 Value(T),
1551 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1552 : SS_Satisfied) {}
1553