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