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 "clang/Sema/SemaConcept.h"
14 #include "clang/Sema/Sema.h"
15 #include "clang/Sema/SemaInternal.h"
16 #include "clang/Sema/SemaDiagnostic.h"
17 #include "clang/Sema/TemplateDeduction.h"
18 #include "clang/Sema/Template.h"
19 #include "clang/Sema/Overload.h"
20 #include "clang/Sema/Initialization.h"
21 #include "clang/Sema/SemaInternal.h"
22 #include "clang/AST/ExprConcepts.h"
23 #include "clang/AST/RecursiveASTVisitor.h"
24 #include "clang/Basic/OperatorPrecedence.h"
25 #include "llvm/ADT/DenseMap.h"
26 #include "llvm/ADT/PointerUnion.h"
27 #include "llvm/ADT/StringExtras.h"
28
29 using namespace clang;
30 using namespace sema;
31
32 namespace {
33 class LogicalBinOp {
34 OverloadedOperatorKind Op = OO_None;
35 const Expr *LHS = nullptr;
36 const Expr *RHS = nullptr;
37
38 public:
LogicalBinOp(const Expr * E)39 LogicalBinOp(const Expr *E) {
40 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
41 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
42 LHS = BO->getLHS();
43 RHS = BO->getRHS();
44 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
45 // If OO is not || or && it might not have exactly 2 arguments.
46 if (OO->getNumArgs() == 2) {
47 Op = OO->getOperator();
48 LHS = OO->getArg(0);
49 RHS = OO->getArg(1);
50 }
51 }
52 }
53
isAnd() const54 bool isAnd() const { return Op == OO_AmpAmp; }
isOr() const55 bool isOr() const { return Op == OO_PipePipe; }
operator bool() const56 explicit operator bool() const { return isAnd() || isOr(); }
57
getLHS() const58 const Expr *getLHS() const { return LHS; }
getRHS() const59 const Expr *getRHS() const { return RHS; }
60 };
61 }
62
CheckConstraintExpression(const Expr * ConstraintExpression,Token NextToken,bool * PossibleNonPrimary,bool IsTrailingRequiresClause)63 bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
64 Token NextToken, bool *PossibleNonPrimary,
65 bool IsTrailingRequiresClause) {
66 // C++2a [temp.constr.atomic]p1
67 // ..E shall be a constant expression of type bool.
68
69 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
70
71 if (LogicalBinOp BO = ConstraintExpression) {
72 return CheckConstraintExpression(BO.getLHS(), NextToken,
73 PossibleNonPrimary) &&
74 CheckConstraintExpression(BO.getRHS(), NextToken,
75 PossibleNonPrimary);
76 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
77 return CheckConstraintExpression(C->getSubExpr(), NextToken,
78 PossibleNonPrimary);
79
80 QualType Type = ConstraintExpression->getType();
81
82 auto CheckForNonPrimary = [&] {
83 if (PossibleNonPrimary)
84 *PossibleNonPrimary =
85 // We have the following case:
86 // template<typename> requires func(0) struct S { };
87 // The user probably isn't aware of the parentheses required around
88 // the function call, and we're only going to parse 'func' as the
89 // primary-expression, and complain that it is of non-bool type.
90 (NextToken.is(tok::l_paren) &&
91 (IsTrailingRequiresClause ||
92 (Type->isDependentType() &&
93 isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
94 Type->isFunctionType() ||
95 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
96 // We have the following case:
97 // template<typename T> requires size_<T> == 0 struct S { };
98 // The user probably isn't aware of the parentheses required around
99 // the binary operator, and we're only going to parse 'func' as the
100 // first operand, and complain that it is of non-bool type.
101 getBinOpPrecedence(NextToken.getKind(),
102 /*GreaterThanIsOperator=*/true,
103 getLangOpts().CPlusPlus11) > prec::LogicalAnd;
104 };
105
106 // An atomic constraint!
107 if (ConstraintExpression->isTypeDependent()) {
108 CheckForNonPrimary();
109 return true;
110 }
111
112 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
113 Diag(ConstraintExpression->getExprLoc(),
114 diag::err_non_bool_atomic_constraint) << Type
115 << ConstraintExpression->getSourceRange();
116 CheckForNonPrimary();
117 return false;
118 }
119
120 if (PossibleNonPrimary)
121 *PossibleNonPrimary = false;
122 return true;
123 }
124
125 template <typename AtomicEvaluator>
126 static bool
calculateConstraintSatisfaction(Sema & S,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction,AtomicEvaluator && Evaluator)127 calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
128 ConstraintSatisfaction &Satisfaction,
129 AtomicEvaluator &&Evaluator) {
130 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
131
132 if (LogicalBinOp BO = ConstraintExpr) {
133 if (calculateConstraintSatisfaction(S, BO.getLHS(), Satisfaction,
134 Evaluator))
135 return true;
136
137 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
138
139 if (BO.isOr() && IsLHSSatisfied)
140 // [temp.constr.op] p3
141 // A disjunction is a constraint taking two operands. To determine if
142 // a disjunction is satisfied, the satisfaction of the first operand
143 // is checked. If that is satisfied, the disjunction is satisfied.
144 // Otherwise, the disjunction is satisfied if and only if the second
145 // operand is satisfied.
146 return false;
147
148 if (BO.isAnd() && !IsLHSSatisfied)
149 // [temp.constr.op] p2
150 // A conjunction is a constraint taking two operands. To determine if
151 // a conjunction is satisfied, the satisfaction of the first operand
152 // is checked. If that is not satisfied, the conjunction is not
153 // satisfied. Otherwise, the conjunction is satisfied if and only if
154 // the second operand is satisfied.
155 return false;
156
157 return calculateConstraintSatisfaction(
158 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
159 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
160 return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
161 std::forward<AtomicEvaluator>(Evaluator));
162 }
163
164 // An atomic constraint expression
165 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
166
167 if (SubstitutedAtomicExpr.isInvalid())
168 return true;
169
170 if (!SubstitutedAtomicExpr.isUsable())
171 // Evaluator has decided satisfaction without yielding an expression.
172 return false;
173
174 EnterExpressionEvaluationContext ConstantEvaluated(
175 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
176 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
177 Expr::EvalResult EvalResult;
178 EvalResult.Diag = &EvaluationDiags;
179 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
180 S.Context) ||
181 !EvaluationDiags.empty()) {
182 // C++2a [temp.constr.atomic]p1
183 // ...E shall be a constant expression of type bool.
184 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
185 diag::err_non_constant_constraint_expression)
186 << SubstitutedAtomicExpr.get()->getSourceRange();
187 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
188 S.Diag(PDiag.first, PDiag.second);
189 return true;
190 }
191
192 assert(EvalResult.Val.isInt() &&
193 "evaluating bool expression didn't produce int");
194 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
195 if (!Satisfaction.IsSatisfied)
196 Satisfaction.Details.emplace_back(ConstraintExpr,
197 SubstitutedAtomicExpr.get());
198
199 return false;
200 }
201
calculateConstraintSatisfaction(Sema & S,const NamedDecl * Template,ArrayRef<TemplateArgument> TemplateArgs,SourceLocation TemplateNameLoc,MultiLevelTemplateArgumentList & MLTAL,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)202 static bool calculateConstraintSatisfaction(
203 Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
204 SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
205 const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
206 return calculateConstraintSatisfaction(
207 S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
208 EnterExpressionEvaluationContext ConstantEvaluated(
209 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
210
211 // Atomic constraint - substitute arguments and check satisfaction.
212 ExprResult SubstitutedExpression;
213 {
214 TemplateDeductionInfo Info(TemplateNameLoc);
215 Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
216 Sema::InstantiatingTemplate::ConstraintSubstitution{},
217 const_cast<NamedDecl *>(Template), Info,
218 AtomicExpr->getSourceRange());
219 if (Inst.isInvalid())
220 return ExprError();
221 // We do not want error diagnostics escaping here.
222 Sema::SFINAETrap Trap(S);
223 SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
224 MLTAL);
225 // Substitution might have stripped off a contextual conversion to
226 // bool if this is the operand of an '&&' or '||'. For example, we
227 // might lose an lvalue-to-rvalue conversion here. If so, put it back
228 // before we try to evaluate.
229 if (!SubstitutedExpression.isInvalid())
230 SubstitutedExpression =
231 S.PerformContextuallyConvertToBool(SubstitutedExpression.get());
232 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
233 // C++2a [temp.constr.atomic]p1
234 // ...If substitution results in an invalid type or expression, the
235 // constraint is not satisfied.
236 if (!Trap.hasErrorOccurred())
237 // A non-SFINAE error has occurred as a result of this
238 // substitution.
239 return ExprError();
240
241 PartialDiagnosticAt SubstDiag{SourceLocation(),
242 PartialDiagnostic::NullDiagnostic()};
243 Info.takeSFINAEDiagnostic(SubstDiag);
244 // FIXME: Concepts: This is an unfortunate consequence of there
245 // being no serialization code for PartialDiagnostics and the fact
246 // that serializing them would likely take a lot more storage than
247 // just storing them as strings. We would still like, in the
248 // future, to serialize the proper PartialDiagnostic as serializing
249 // it as a string defeats the purpose of the diagnostic mechanism.
250 SmallString<128> DiagString;
251 DiagString = ": ";
252 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
253 unsigned MessageSize = DiagString.size();
254 char *Mem = new (S.Context) char[MessageSize];
255 memcpy(Mem, DiagString.c_str(), MessageSize);
256 Satisfaction.Details.emplace_back(
257 AtomicExpr,
258 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
259 SubstDiag.first, StringRef(Mem, MessageSize)});
260 Satisfaction.IsSatisfied = false;
261 return ExprEmpty();
262 }
263 }
264
265 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
266 return ExprError();
267
268 return SubstitutedExpression;
269 });
270 }
271
CheckConstraintSatisfaction(Sema & S,const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,ArrayRef<TemplateArgument> TemplateArgs,SourceRange TemplateIDRange,ConstraintSatisfaction & Satisfaction)272 static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
273 ArrayRef<const Expr *> ConstraintExprs,
274 ArrayRef<TemplateArgument> TemplateArgs,
275 SourceRange TemplateIDRange,
276 ConstraintSatisfaction &Satisfaction) {
277 if (ConstraintExprs.empty()) {
278 Satisfaction.IsSatisfied = true;
279 return false;
280 }
281
282 for (auto& Arg : TemplateArgs)
283 if (Arg.isInstantiationDependent()) {
284 // No need to check satisfaction for dependent constraint expressions.
285 Satisfaction.IsSatisfied = true;
286 return false;
287 }
288
289 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
290 Sema::InstantiatingTemplate::ConstraintsCheck{},
291 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
292 if (Inst.isInvalid())
293 return true;
294
295 MultiLevelTemplateArgumentList MLTAL;
296 MLTAL.addOuterTemplateArguments(TemplateArgs);
297
298 for (const Expr *ConstraintExpr : ConstraintExprs) {
299 if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
300 TemplateIDRange.getBegin(), MLTAL,
301 ConstraintExpr, Satisfaction))
302 return true;
303 if (!Satisfaction.IsSatisfied)
304 // [temp.constr.op] p2
305 // [...] To determine if a conjunction is satisfied, the satisfaction
306 // of the first operand is checked. If that is not satisfied, the
307 // conjunction is not satisfied. [...]
308 return false;
309 }
310 return false;
311 }
312
CheckConstraintSatisfaction(const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,ArrayRef<TemplateArgument> TemplateArgs,SourceRange TemplateIDRange,ConstraintSatisfaction & OutSatisfaction)313 bool Sema::CheckConstraintSatisfaction(
314 const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
315 ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
316 ConstraintSatisfaction &OutSatisfaction) {
317 if (ConstraintExprs.empty()) {
318 OutSatisfaction.IsSatisfied = true;
319 return false;
320 }
321
322 llvm::FoldingSetNodeID ID;
323 void *InsertPos;
324 ConstraintSatisfaction *Satisfaction = nullptr;
325 bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
326 if (ShouldCache) {
327 ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
328 Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
329 if (Satisfaction) {
330 OutSatisfaction = *Satisfaction;
331 return false;
332 }
333 Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs);
334 } else {
335 Satisfaction = &OutSatisfaction;
336 }
337 if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
338 TemplateArgs, TemplateIDRange,
339 *Satisfaction)) {
340 if (ShouldCache)
341 delete Satisfaction;
342 return true;
343 }
344
345 if (ShouldCache) {
346 // We cannot use InsertNode here because CheckConstraintSatisfaction might
347 // have invalidated it.
348 SatisfactionCache.InsertNode(Satisfaction);
349 OutSatisfaction = *Satisfaction;
350 }
351 return false;
352 }
353
CheckConstraintSatisfaction(const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)354 bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
355 ConstraintSatisfaction &Satisfaction) {
356 return calculateConstraintSatisfaction(
357 *this, ConstraintExpr, Satisfaction,
358 [](const Expr *AtomicExpr) -> ExprResult {
359 return ExprResult(const_cast<Expr *>(AtomicExpr));
360 });
361 }
362
CheckFunctionConstraints(const FunctionDecl * FD,ConstraintSatisfaction & Satisfaction,SourceLocation UsageLoc)363 bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
364 ConstraintSatisfaction &Satisfaction,
365 SourceLocation UsageLoc) {
366 const Expr *RC = FD->getTrailingRequiresClause();
367 if (RC->isInstantiationDependent()) {
368 Satisfaction.IsSatisfied = true;
369 return false;
370 }
371 Qualifiers ThisQuals;
372 CXXRecordDecl *Record = nullptr;
373 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
374 ThisQuals = Method->getMethodQualifiers();
375 Record = const_cast<CXXRecordDecl *>(Method->getParent());
376 }
377 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
378 // We substitute with empty arguments in order to rebuild the atomic
379 // constraint in a constant-evaluated context.
380 // FIXME: Should this be a dedicated TreeTransform?
381 return CheckConstraintSatisfaction(
382 FD, {RC}, /*TemplateArgs=*/{},
383 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
384 Satisfaction);
385 }
386
EnsureTemplateArgumentListConstraints(TemplateDecl * TD,ArrayRef<TemplateArgument> TemplateArgs,SourceRange TemplateIDRange)387 bool Sema::EnsureTemplateArgumentListConstraints(
388 TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
389 SourceRange TemplateIDRange) {
390 ConstraintSatisfaction Satisfaction;
391 llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
392 TD->getAssociatedConstraints(AssociatedConstraints);
393 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
394 TemplateIDRange, Satisfaction))
395 return true;
396
397 if (!Satisfaction.IsSatisfied) {
398 SmallString<128> TemplateArgString;
399 TemplateArgString = " ";
400 TemplateArgString += getTemplateArgumentBindingsText(
401 TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
402
403 Diag(TemplateIDRange.getBegin(),
404 diag::err_template_arg_list_constraints_not_satisfied)
405 << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
406 << TemplateArgString << TemplateIDRange;
407 DiagnoseUnsatisfiedConstraint(Satisfaction);
408 return true;
409 }
410 return false;
411 }
412
diagnoseUnsatisfiedRequirement(Sema & S,concepts::ExprRequirement * Req,bool First)413 static void diagnoseUnsatisfiedRequirement(Sema &S,
414 concepts::ExprRequirement *Req,
415 bool First) {
416 assert(!Req->isSatisfied()
417 && "Diagnose() can only be used on an unsatisfied requirement");
418 switch (Req->getSatisfactionStatus()) {
419 case concepts::ExprRequirement::SS_Dependent:
420 llvm_unreachable("Diagnosing a dependent requirement");
421 break;
422 case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
423 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
424 if (!SubstDiag->DiagMessage.empty())
425 S.Diag(SubstDiag->DiagLoc,
426 diag::note_expr_requirement_expr_substitution_error)
427 << (int)First << SubstDiag->SubstitutedEntity
428 << SubstDiag->DiagMessage;
429 else
430 S.Diag(SubstDiag->DiagLoc,
431 diag::note_expr_requirement_expr_unknown_substitution_error)
432 << (int)First << SubstDiag->SubstitutedEntity;
433 break;
434 }
435 case concepts::ExprRequirement::SS_NoexceptNotMet:
436 S.Diag(Req->getNoexceptLoc(),
437 diag::note_expr_requirement_noexcept_not_met)
438 << (int)First << Req->getExpr();
439 break;
440 case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
441 auto *SubstDiag =
442 Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
443 if (!SubstDiag->DiagMessage.empty())
444 S.Diag(SubstDiag->DiagLoc,
445 diag::note_expr_requirement_type_requirement_substitution_error)
446 << (int)First << SubstDiag->SubstitutedEntity
447 << SubstDiag->DiagMessage;
448 else
449 S.Diag(SubstDiag->DiagLoc,
450 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
451 << (int)First << SubstDiag->SubstitutedEntity;
452 break;
453 }
454 case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
455 ConceptSpecializationExpr *ConstraintExpr =
456 Req->getReturnTypeRequirementSubstitutedConstraintExpr();
457 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
458 // A simple case - expr type is the type being constrained and the concept
459 // was not provided arguments.
460 Expr *e = Req->getExpr();
461 S.Diag(e->getBeginLoc(),
462 diag::note_expr_requirement_constraints_not_satisfied_simple)
463 << (int)First << S.Context.getReferenceQualifiedType(e)
464 << ConstraintExpr->getNamedConcept();
465 } else {
466 S.Diag(ConstraintExpr->getBeginLoc(),
467 diag::note_expr_requirement_constraints_not_satisfied)
468 << (int)First << ConstraintExpr;
469 }
470 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
471 break;
472 }
473 case concepts::ExprRequirement::SS_Satisfied:
474 llvm_unreachable("We checked this above");
475 }
476 }
477
diagnoseUnsatisfiedRequirement(Sema & S,concepts::TypeRequirement * Req,bool First)478 static void diagnoseUnsatisfiedRequirement(Sema &S,
479 concepts::TypeRequirement *Req,
480 bool First) {
481 assert(!Req->isSatisfied()
482 && "Diagnose() can only be used on an unsatisfied requirement");
483 switch (Req->getSatisfactionStatus()) {
484 case concepts::TypeRequirement::SS_Dependent:
485 llvm_unreachable("Diagnosing a dependent requirement");
486 return;
487 case concepts::TypeRequirement::SS_SubstitutionFailure: {
488 auto *SubstDiag = Req->getSubstitutionDiagnostic();
489 if (!SubstDiag->DiagMessage.empty())
490 S.Diag(SubstDiag->DiagLoc,
491 diag::note_type_requirement_substitution_error) << (int)First
492 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
493 else
494 S.Diag(SubstDiag->DiagLoc,
495 diag::note_type_requirement_unknown_substitution_error)
496 << (int)First << SubstDiag->SubstitutedEntity;
497 return;
498 }
499 default:
500 llvm_unreachable("Unknown satisfaction status");
501 return;
502 }
503 }
504
diagnoseUnsatisfiedRequirement(Sema & S,concepts::NestedRequirement * Req,bool First)505 static void diagnoseUnsatisfiedRequirement(Sema &S,
506 concepts::NestedRequirement *Req,
507 bool First) {
508 if (Req->isSubstitutionFailure()) {
509 concepts::Requirement::SubstitutionDiagnostic *SubstDiag =
510 Req->getSubstitutionDiagnostic();
511 if (!SubstDiag->DiagMessage.empty())
512 S.Diag(SubstDiag->DiagLoc,
513 diag::note_nested_requirement_substitution_error)
514 << (int)First << SubstDiag->SubstitutedEntity
515 << SubstDiag->DiagMessage;
516 else
517 S.Diag(SubstDiag->DiagLoc,
518 diag::note_nested_requirement_unknown_substitution_error)
519 << (int)First << SubstDiag->SubstitutedEntity;
520 return;
521 }
522 S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First);
523 }
524
525
diagnoseWellFormedUnsatisfiedConstraintExpr(Sema & S,Expr * SubstExpr,bool First=true)526 static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
527 Expr *SubstExpr,
528 bool First = true) {
529 SubstExpr = SubstExpr->IgnoreParenImpCasts();
530 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
531 switch (BO->getOpcode()) {
532 // These two cases will in practice only be reached when using fold
533 // expressions with || and &&, since otherwise the || and && will have been
534 // broken down into atomic constraints during satisfaction checking.
535 case BO_LOr:
536 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
537 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
538 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
539 /*First=*/false);
540 return;
541 case BO_LAnd: {
542 bool LHSSatisfied =
543 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
544 if (LHSSatisfied) {
545 // LHS is true, so RHS must be false.
546 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
547 return;
548 }
549 // LHS is false
550 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
551
552 // RHS might also be false
553 bool RHSSatisfied =
554 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
555 if (!RHSSatisfied)
556 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
557 /*First=*/false);
558 return;
559 }
560 case BO_GE:
561 case BO_LE:
562 case BO_GT:
563 case BO_LT:
564 case BO_EQ:
565 case BO_NE:
566 if (BO->getLHS()->getType()->isIntegerType() &&
567 BO->getRHS()->getType()->isIntegerType()) {
568 Expr::EvalResult SimplifiedLHS;
569 Expr::EvalResult SimplifiedRHS;
570 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
571 Expr::SE_NoSideEffects,
572 /*InConstantContext=*/true);
573 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
574 Expr::SE_NoSideEffects,
575 /*InConstantContext=*/true);
576 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
577 S.Diag(SubstExpr->getBeginLoc(),
578 diag::note_atomic_constraint_evaluated_to_false_elaborated)
579 << (int)First << SubstExpr
580 << toString(SimplifiedLHS.Val.getInt(), 10)
581 << BinaryOperator::getOpcodeStr(BO->getOpcode())
582 << toString(SimplifiedRHS.Val.getInt(), 10);
583 return;
584 }
585 }
586 break;
587
588 default:
589 break;
590 }
591 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
592 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
593 S.Diag(
594 CSE->getSourceRange().getBegin(),
595 diag::
596 note_single_arg_concept_specialization_constraint_evaluated_to_false)
597 << (int)First
598 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
599 << CSE->getNamedConcept();
600 } else {
601 S.Diag(SubstExpr->getSourceRange().getBegin(),
602 diag::note_concept_specialization_constraint_evaluated_to_false)
603 << (int)First << CSE;
604 }
605 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
606 return;
607 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
608 for (concepts::Requirement *Req : RE->getRequirements())
609 if (!Req->isDependent() && !Req->isSatisfied()) {
610 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
611 diagnoseUnsatisfiedRequirement(S, E, First);
612 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
613 diagnoseUnsatisfiedRequirement(S, T, First);
614 else
615 diagnoseUnsatisfiedRequirement(
616 S, cast<concepts::NestedRequirement>(Req), First);
617 break;
618 }
619 return;
620 }
621
622 S.Diag(SubstExpr->getSourceRange().getBegin(),
623 diag::note_atomic_constraint_evaluated_to_false)
624 << (int)First << SubstExpr;
625 }
626
627 template<typename SubstitutionDiagnostic>
diagnoseUnsatisfiedConstraintExpr(Sema & S,const Expr * E,const llvm::PointerUnion<Expr *,SubstitutionDiagnostic * > & Record,bool First=true)628 static void diagnoseUnsatisfiedConstraintExpr(
629 Sema &S, const Expr *E,
630 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
631 bool First = true) {
632 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
633 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
634 << Diag->second;
635 return;
636 }
637
638 diagnoseWellFormedUnsatisfiedConstraintExpr(S,
639 Record.template get<Expr *>(), First);
640 }
641
642 void
DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction & Satisfaction,bool First)643 Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
644 bool First) {
645 assert(!Satisfaction.IsSatisfied &&
646 "Attempted to diagnose a satisfied constraint");
647 for (auto &Pair : Satisfaction.Details) {
648 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
649 First = false;
650 }
651 }
652
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction & Satisfaction,bool First)653 void Sema::DiagnoseUnsatisfiedConstraint(
654 const ASTConstraintSatisfaction &Satisfaction,
655 bool First) {
656 assert(!Satisfaction.IsSatisfied &&
657 "Attempted to diagnose a satisfied constraint");
658 for (auto &Pair : Satisfaction) {
659 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
660 First = false;
661 }
662 }
663
664 const NormalizedConstraint *
getNormalizedAssociatedConstraints(NamedDecl * ConstrainedDecl,ArrayRef<const Expr * > AssociatedConstraints)665 Sema::getNormalizedAssociatedConstraints(
666 NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
667 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
668 if (CacheEntry == NormalizationCache.end()) {
669 auto Normalized =
670 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
671 AssociatedConstraints);
672 CacheEntry =
673 NormalizationCache
674 .try_emplace(ConstrainedDecl,
675 Normalized
676 ? new (Context) NormalizedConstraint(
677 std::move(*Normalized))
678 : nullptr)
679 .first;
680 }
681 return CacheEntry->second;
682 }
683
substituteParameterMappings(Sema & S,NormalizedConstraint & N,ConceptDecl * Concept,ArrayRef<TemplateArgument> TemplateArgs,const ASTTemplateArgumentListInfo * ArgsAsWritten)684 static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
685 ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
686 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
687 if (!N.isAtomic()) {
688 if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
689 ArgsAsWritten))
690 return true;
691 return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
692 ArgsAsWritten);
693 }
694 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
695
696 AtomicConstraint &Atomic = *N.getAtomicConstraint();
697 TemplateArgumentListInfo SubstArgs;
698 MultiLevelTemplateArgumentList MLTAL;
699 MLTAL.addOuterTemplateArguments(TemplateArgs);
700 if (!Atomic.ParameterMapping) {
701 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
702 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
703 /*Depth=*/0, OccurringIndices);
704 Atomic.ParameterMapping.emplace(
705 MutableArrayRef<TemplateArgumentLoc>(
706 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
707 OccurringIndices.count()));
708 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
709 if (OccurringIndices[I])
710 new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
711 S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
712 // Here we assume we do not support things like
713 // template<typename A, typename B>
714 // concept C = ...;
715 //
716 // template<typename... Ts> requires C<Ts...>
717 // struct S { };
718 // The above currently yields a diagnostic.
719 // We still might have default arguments for concept parameters.
720 ArgsAsWritten->NumTemplateArgs > I ?
721 ArgsAsWritten->arguments()[I].getLocation() :
722 SourceLocation()));
723 }
724 Sema::InstantiatingTemplate Inst(
725 S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
726 Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
727 SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
728 ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
729 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
730 return true;
731 Atomic.ParameterMapping.emplace(
732 MutableArrayRef<TemplateArgumentLoc>(
733 new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
734 SubstArgs.size()));
735 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
736 N.getAtomicConstraint()->ParameterMapping->begin());
737 return false;
738 }
739
740 Optional<NormalizedConstraint>
fromConstraintExprs(Sema & S,NamedDecl * D,ArrayRef<const Expr * > E)741 NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
742 ArrayRef<const Expr *> E) {
743 assert(E.size() != 0);
744 auto Conjunction = fromConstraintExpr(S, D, E[0]);
745 if (!Conjunction)
746 return None;
747 for (unsigned I = 1; I < E.size(); ++I) {
748 auto Next = fromConstraintExpr(S, D, E[I]);
749 if (!Next)
750 return None;
751 *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
752 std::move(*Next), CCK_Conjunction);
753 }
754 return Conjunction;
755 }
756
757 llvm::Optional<NormalizedConstraint>
fromConstraintExpr(Sema & S,NamedDecl * D,const Expr * E)758 NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
759 assert(E != nullptr);
760
761 // C++ [temp.constr.normal]p1.1
762 // [...]
763 // - The normal form of an expression (E) is the normal form of E.
764 // [...]
765 E = E->IgnoreParenImpCasts();
766 if (LogicalBinOp BO = E) {
767 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
768 if (!LHS)
769 return None;
770 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
771 if (!RHS)
772 return None;
773
774 return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
775 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
776 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
777 const NormalizedConstraint *SubNF;
778 {
779 Sema::InstantiatingTemplate Inst(
780 S, CSE->getExprLoc(),
781 Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
782 CSE->getSourceRange());
783 // C++ [temp.constr.normal]p1.1
784 // [...]
785 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
786 // where C names a concept, is the normal form of the
787 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
788 // respective template parameters in the parameter mappings in each atomic
789 // constraint. If any such substitution results in an invalid type or
790 // expression, the program is ill-formed; no diagnostic is required.
791 // [...]
792 ConceptDecl *CD = CSE->getNamedConcept();
793 SubNF = S.getNormalizedAssociatedConstraints(CD,
794 {CD->getConstraintExpr()});
795 if (!SubNF)
796 return None;
797 }
798
799 Optional<NormalizedConstraint> New;
800 New.emplace(S.Context, *SubNF);
801
802 if (substituteParameterMappings(
803 S, *New, CSE->getNamedConcept(),
804 CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
805 return None;
806
807 return New;
808 }
809 return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
810 }
811
812 using NormalForm =
813 llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
814
makeCNF(const NormalizedConstraint & Normalized)815 static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
816 if (Normalized.isAtomic())
817 return {{Normalized.getAtomicConstraint()}};
818
819 NormalForm LCNF = makeCNF(Normalized.getLHS());
820 NormalForm RCNF = makeCNF(Normalized.getRHS());
821 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
822 LCNF.reserve(LCNF.size() + RCNF.size());
823 while (!RCNF.empty())
824 LCNF.push_back(RCNF.pop_back_val());
825 return LCNF;
826 }
827
828 // Disjunction
829 NormalForm Res;
830 Res.reserve(LCNF.size() * RCNF.size());
831 for (auto &LDisjunction : LCNF)
832 for (auto &RDisjunction : RCNF) {
833 NormalForm::value_type Combined;
834 Combined.reserve(LDisjunction.size() + RDisjunction.size());
835 std::copy(LDisjunction.begin(), LDisjunction.end(),
836 std::back_inserter(Combined));
837 std::copy(RDisjunction.begin(), RDisjunction.end(),
838 std::back_inserter(Combined));
839 Res.emplace_back(Combined);
840 }
841 return Res;
842 }
843
makeDNF(const NormalizedConstraint & Normalized)844 static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
845 if (Normalized.isAtomic())
846 return {{Normalized.getAtomicConstraint()}};
847
848 NormalForm LDNF = makeDNF(Normalized.getLHS());
849 NormalForm RDNF = makeDNF(Normalized.getRHS());
850 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
851 LDNF.reserve(LDNF.size() + RDNF.size());
852 while (!RDNF.empty())
853 LDNF.push_back(RDNF.pop_back_val());
854 return LDNF;
855 }
856
857 // Conjunction
858 NormalForm Res;
859 Res.reserve(LDNF.size() * RDNF.size());
860 for (auto &LConjunction : LDNF) {
861 for (auto &RConjunction : RDNF) {
862 NormalForm::value_type Combined;
863 Combined.reserve(LConjunction.size() + RConjunction.size());
864 std::copy(LConjunction.begin(), LConjunction.end(),
865 std::back_inserter(Combined));
866 std::copy(RConjunction.begin(), RConjunction.end(),
867 std::back_inserter(Combined));
868 Res.emplace_back(Combined);
869 }
870 }
871 return Res;
872 }
873
874 template<typename AtomicSubsumptionEvaluator>
subsumes(NormalForm PDNF,NormalForm QCNF,AtomicSubsumptionEvaluator E)875 static bool subsumes(NormalForm PDNF, NormalForm QCNF,
876 AtomicSubsumptionEvaluator E) {
877 // C++ [temp.constr.order] p2
878 // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
879 // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
880 // the conjuctive normal form of Q, where [...]
881 for (const auto &Pi : PDNF) {
882 for (const auto &Qj : QCNF) {
883 // C++ [temp.constr.order] p2
884 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
885 // and only if there exists an atomic constraint Pia in Pi for which
886 // there exists an atomic constraint, Qjb, in Qj such that Pia
887 // subsumes Qjb.
888 bool Found = false;
889 for (const AtomicConstraint *Pia : Pi) {
890 for (const AtomicConstraint *Qjb : Qj) {
891 if (E(*Pia, *Qjb)) {
892 Found = true;
893 break;
894 }
895 }
896 if (Found)
897 break;
898 }
899 if (!Found)
900 return false;
901 }
902 }
903 return true;
904 }
905
906 template<typename AtomicSubsumptionEvaluator>
subsumes(Sema & S,NamedDecl * DP,ArrayRef<const Expr * > P,NamedDecl * DQ,ArrayRef<const Expr * > Q,bool & Subsumes,AtomicSubsumptionEvaluator E)907 static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
908 NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
909 AtomicSubsumptionEvaluator E) {
910 // C++ [temp.constr.order] p2
911 // In order to determine if a constraint P subsumes a constraint Q, P is
912 // transformed into disjunctive normal form, and Q is transformed into
913 // conjunctive normal form. [...]
914 auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
915 if (!PNormalized)
916 return true;
917 const NormalForm PDNF = makeDNF(*PNormalized);
918
919 auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
920 if (!QNormalized)
921 return true;
922 const NormalForm QCNF = makeCNF(*QNormalized);
923
924 Subsumes = subsumes(PDNF, QCNF, E);
925 return false;
926 }
927
IsAtLeastAsConstrained(NamedDecl * D1,ArrayRef<const Expr * > AC1,NamedDecl * D2,ArrayRef<const Expr * > AC2,bool & Result)928 bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
929 NamedDecl *D2, ArrayRef<const Expr *> AC2,
930 bool &Result) {
931 if (AC1.empty()) {
932 Result = AC2.empty();
933 return false;
934 }
935 if (AC2.empty()) {
936 // TD1 has associated constraints and TD2 does not.
937 Result = true;
938 return false;
939 }
940
941 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
942 auto CacheEntry = SubsumptionCache.find(Key);
943 if (CacheEntry != SubsumptionCache.end()) {
944 Result = CacheEntry->second;
945 return false;
946 }
947
948 if (subsumes(*this, D1, AC1, D2, AC2, Result,
949 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
950 return A.subsumes(Context, B);
951 }))
952 return true;
953 SubsumptionCache.try_emplace(Key, Result);
954 return false;
955 }
956
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl * D1,ArrayRef<const Expr * > AC1,NamedDecl * D2,ArrayRef<const Expr * > AC2)957 bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
958 ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
959 if (isSFINAEContext())
960 // No need to work here because our notes would be discarded.
961 return false;
962
963 if (AC1.empty() || AC2.empty())
964 return false;
965
966 auto NormalExprEvaluator =
967 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
968 return A.subsumes(Context, B);
969 };
970
971 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
972 auto IdenticalExprEvaluator =
973 [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
974 if (!A.hasMatchingParameterMapping(Context, B))
975 return false;
976 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
977 if (EA == EB)
978 return true;
979
980 // Not the same source level expression - are the expressions
981 // identical?
982 llvm::FoldingSetNodeID IDA, IDB;
983 EA->Profile(IDA, Context, /*Canonical=*/true);
984 EB->Profile(IDB, Context, /*Canonical=*/true);
985 if (IDA != IDB)
986 return false;
987
988 AmbiguousAtomic1 = EA;
989 AmbiguousAtomic2 = EB;
990 return true;
991 };
992
993 {
994 // The subsumption checks might cause diagnostics
995 SFINAETrap Trap(*this);
996 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
997 if (!Normalized1)
998 return false;
999 const NormalForm DNF1 = makeDNF(*Normalized1);
1000 const NormalForm CNF1 = makeCNF(*Normalized1);
1001
1002 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1003 if (!Normalized2)
1004 return false;
1005 const NormalForm DNF2 = makeDNF(*Normalized2);
1006 const NormalForm CNF2 = makeCNF(*Normalized2);
1007
1008 bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1009 bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1010 bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1011 bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1012 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1013 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1014 // Same result - no ambiguity was caused by identical atomic expressions.
1015 return false;
1016 }
1017
1018 // A different result! Some ambiguous atomic constraint(s) caused a difference
1019 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1020
1021 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1022 << AmbiguousAtomic1->getSourceRange();
1023 Diag(AmbiguousAtomic2->getBeginLoc(),
1024 diag::note_ambiguous_atomic_constraints_similar_expression)
1025 << AmbiguousAtomic2->getSourceRange();
1026 return true;
1027 }
1028
ExprRequirement(Expr * E,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req,SatisfactionStatus Status,ConceptSpecializationExpr * SubstitutedConstraintExpr)1029 concepts::ExprRequirement::ExprRequirement(
1030 Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1031 ReturnTypeRequirement Req, SatisfactionStatus Status,
1032 ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1033 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1034 Status == SS_Dependent &&
1035 (E->containsUnexpandedParameterPack() ||
1036 Req.containsUnexpandedParameterPack()),
1037 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1038 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1039 Status(Status) {
1040 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1041 "Simple requirement must not have a return type requirement or a "
1042 "noexcept specification");
1043 assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1044 (SubstitutedConstraintExpr != nullptr));
1045 }
1046
ExprRequirement(SubstitutionDiagnostic * ExprSubstDiag,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req)1047 concepts::ExprRequirement::ExprRequirement(
1048 SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1049 SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1050 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1051 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1052 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1053 Status(SS_ExprSubstitutionFailure) {
1054 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1055 "Simple requirement must not have a return type requirement or a "
1056 "noexcept specification");
1057 }
1058
1059 concepts::ExprRequirement::ReturnTypeRequirement::
ReturnTypeRequirement(TemplateParameterList * TPL)1060 ReturnTypeRequirement(TemplateParameterList *TPL) :
1061 TypeConstraintInfo(TPL, 0) {
1062 assert(TPL->size() == 1);
1063 const TypeConstraint *TC =
1064 cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1065 assert(TC &&
1066 "TPL must have a template type parameter with a type constraint");
1067 auto *Constraint =
1068 cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1069 bool Dependent =
1070 Constraint->getTemplateArgsAsWritten() &&
1071 TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1072 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1073 TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1074 }
1075
TypeRequirement(TypeSourceInfo * T)1076 concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1077 Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1078 T->getType()->containsUnexpandedParameterPack(),
1079 // We reach this ctor with either dependent types (in which
1080 // IsSatisfied doesn't matter) or with non-dependent type in
1081 // which the existence of the type indicates satisfaction.
1082 /*IsSatisfied=*/true),
1083 Value(T),
1084 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1085 : SS_Satisfied) {}
1086