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