clang 22.0.0git
SemaConcept.cpp
Go to the documentation of this file.
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
14#include "TreeTransform.h"
15#include "clang/AST/ASTLambda.h"
16#include "clang/AST/DeclCXX.h"
21#include "clang/Sema/Overload.h"
23#include "clang/Sema/Sema.h"
25#include "clang/Sema/Template.h"
27#include "llvm/ADT/DenseMap.h"
28#include "llvm/ADT/PointerUnion.h"
29#include "llvm/ADT/StringExtras.h"
30#include <optional>
31
32using namespace clang;
33using namespace sema;
34
35namespace {
36class LogicalBinOp {
37 SourceLocation Loc;
39 const Expr *LHS = nullptr;
40 const Expr *RHS = nullptr;
41
42public:
43 LogicalBinOp(const Expr *E) {
44 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
45 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
46 LHS = BO->getLHS();
47 RHS = BO->getRHS();
48 Loc = BO->getExprLoc();
49 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
50 // If OO is not || or && it might not have exactly 2 arguments.
51 if (OO->getNumArgs() == 2) {
52 Op = OO->getOperator();
53 LHS = OO->getArg(0);
54 RHS = OO->getArg(1);
55 Loc = OO->getOperatorLoc();
56 }
57 }
58 }
59
60 bool isAnd() const { return Op == OO_AmpAmp; }
61 bool isOr() const { return Op == OO_PipePipe; }
62 explicit operator bool() const { return isAnd() || isOr(); }
63
64 const Expr *getLHS() const { return LHS; }
65 const Expr *getRHS() const { return RHS; }
66 OverloadedOperatorKind getOp() const { return Op; }
67
68 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
69 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
70 }
71
72 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
73 ExprResult RHS) const {
74 assert((isAnd() || isOr()) && "Not the right kind of op?");
75 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
76
77 if (!LHS.isUsable() || !RHS.isUsable())
78 return ExprEmpty();
79
80 // We should just be able to 'normalize' these to the builtin Binary
81 // Operator, since that is how they are evaluated in constriant checks.
82 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
84 SemaRef.Context.BoolTy, VK_PRValue,
85 OK_Ordinary, Loc, FPOptionsOverride{});
86 }
87};
88}
89
90bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
91 Token NextToken, bool *PossibleNonPrimary,
92 bool IsTrailingRequiresClause) {
93 // C++2a [temp.constr.atomic]p1
94 // ..E shall be a constant expression of type bool.
95
96 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
97
98 if (LogicalBinOp BO = ConstraintExpression) {
99 return CheckConstraintExpression(BO.getLHS(), NextToken,
100 PossibleNonPrimary) &&
101 CheckConstraintExpression(BO.getRHS(), NextToken,
102 PossibleNonPrimary);
103 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
104 return CheckConstraintExpression(C->getSubExpr(), NextToken,
105 PossibleNonPrimary);
106
107 QualType Type = ConstraintExpression->getType();
108
109 auto CheckForNonPrimary = [&] {
110 if (!PossibleNonPrimary)
111 return;
112
113 *PossibleNonPrimary =
114 // We have the following case:
115 // template<typename> requires func(0) struct S { };
116 // The user probably isn't aware of the parentheses required around
117 // the function call, and we're only going to parse 'func' as the
118 // primary-expression, and complain that it is of non-bool type.
119 //
120 // However, if we're in a lambda, this might also be:
121 // []<typename> requires var () {};
122 // Which also looks like a function call due to the lambda parentheses,
123 // but unlike the first case, isn't an error, so this check is skipped.
124 (NextToken.is(tok::l_paren) &&
125 (IsTrailingRequiresClause ||
126 (Type->isDependentType() &&
127 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
128 !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
129 Type->isFunctionType() ||
130 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
131 // We have the following case:
132 // template<typename T> requires size_<T> == 0 struct S { };
133 // The user probably isn't aware of the parentheses required around
134 // the binary operator, and we're only going to parse 'func' as the
135 // first operand, and complain that it is of non-bool type.
136 getBinOpPrecedence(NextToken.getKind(),
137 /*GreaterThanIsOperator=*/true,
139 };
140
141 // An atomic constraint!
142 if (ConstraintExpression->isTypeDependent()) {
143 CheckForNonPrimary();
144 return true;
145 }
146
147 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
148 Diag(ConstraintExpression->getExprLoc(),
149 diag::err_non_bool_atomic_constraint) << Type
150 << ConstraintExpression->getSourceRange();
151 CheckForNonPrimary();
152 return false;
153 }
154
155 if (PossibleNonPrimary)
156 *PossibleNonPrimary = false;
157 return true;
158}
159
160namespace {
161struct SatisfactionStackRAII {
162 Sema &SemaRef;
163 bool Inserted = false;
164 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
165 const llvm::FoldingSetNodeID &FSNID)
166 : SemaRef(SemaRef) {
167 if (ND) {
168 SemaRef.PushSatisfactionStackEntry(ND, FSNID);
169 Inserted = true;
170 }
171 }
172 ~SatisfactionStackRAII() {
173 if (Inserted)
175 }
176};
177} // namespace
178
179static bool
180DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
181 const NamedDecl *Templ, const Expr *E,
182 const MultiLevelTemplateArgumentList &MLTAL) {
183 E->Profile(ID, S.Context, /*Canonical=*/true);
184 for (const auto &List : MLTAL)
185 for (const auto &TemplateArg : List.Args)
186 TemplateArg.Profile(ID, S.Context);
187
188 // Note that we have to do this with our own collection, because there are
189 // times where a constraint-expression check can cause us to need to evaluate
190 // other constriants that are unrelated, such as when evaluating a recovery
191 // expression, or when trying to determine the constexpr-ness of special
192 // members. Otherwise we could just use the
193 // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
194 if (S.SatisfactionStackContains(Templ, ID)) {
195 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
196 << const_cast<Expr *>(E) << E->getSourceRange();
197 return true;
198 }
199
200 return false;
201}
202
204 Sema &S, const Expr *AtomicExpr, const NamedDecl *Template,
205 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
206 ConstraintSatisfaction &Satisfaction) {
207 EnterExpressionEvaluationContext ConstantEvaluated(
210
211 // Atomic constraint - substitute arguments and check satisfaction.
212 ExprResult SubstitutedExpression;
213 {
214 TemplateDeductionInfo Info(TemplateNameLoc);
218 // FIXME: improve const-correctness of InstantiatingTemplate
219 const_cast<NamedDecl *>(Template), Info, AtomicExpr->getSourceRange());
220 if (Inst.isInvalid())
221 return ExprError();
222
223 llvm::FoldingSetNodeID ID;
224 if (Template &&
226 Satisfaction.IsSatisfied = false;
227 Satisfaction.ContainsErrors = true;
228 return ExprEmpty();
229 }
230
231 SatisfactionStackRAII StackRAII(S, Template, ID);
232
233 // We do not want error diagnostics escaping here.
234 Sema::SFINAETrap Trap(S);
235 SubstitutedExpression =
236 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
237
238 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
239 // C++2a [temp.constr.atomic]p1
240 // ...If substitution results in an invalid type or expression, the
241 // constraint is not satisfied.
242 if (!Trap.hasErrorOccurred())
243 // A non-SFINAE error has occurred as a result of this
244 // substitution.
245 return ExprError();
246
249 Info.takeSFINAEDiagnostic(SubstDiag);
250 // FIXME: Concepts: This is an unfortunate consequence of there
251 // being no serialization code for PartialDiagnostics and the fact
252 // that serializing them would likely take a lot more storage than
253 // just storing them as strings. We would still like, in the
254 // future, to serialize the proper PartialDiagnostic as serializing
255 // it as a string defeats the purpose of the diagnostic mechanism.
256 SmallString<128> DiagString;
257 DiagString = ": ";
258 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
259 unsigned MessageSize = DiagString.size();
260 char *Mem = new (S.Context) char[MessageSize];
261 memcpy(Mem, DiagString.c_str(), MessageSize);
262 Satisfaction.Details.emplace_back(
264 SubstDiag.first, StringRef(Mem, MessageSize)});
265 Satisfaction.IsSatisfied = false;
266 return ExprEmpty();
267 }
268 }
269
270 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
271 return ExprError();
272
273 // [temp.constr.atomic]p3: To determine if an atomic constraint is
274 // satisfied, the parameter mapping and template arguments are first
275 // substituted into its expression. If substitution results in an
276 // invalid type or expression, the constraint is not satisfied.
277 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
278 // and E shall be a constant expression of type bool.
279 //
280 // Perform the L to R Value conversion if necessary. We do so for all
281 // non-PRValue categories, else we fail to extend the lifetime of
282 // temporaries, and that fails the constant expression check.
283 if (!SubstitutedExpression.get()->isPRValue())
284 SubstitutedExpression = ImplicitCastExpr::Create(
285 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
286 SubstitutedExpression.get(),
287 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
288
289 return SubstitutedExpression;
290}
291
293 Sema &S, const CXXFoldExpr *FE, const NamedDecl *Template,
294 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
295 ConstraintSatisfaction &Satisfaction) {
296
297 // We should ignore errors in the presence of packs of different size.
298 Sema::SFINAETrap Trap(S);
299
300 Expr *Pattern = FE->getPattern();
301
303 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
304 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
305 bool Expand = true;
306 bool RetainExpansion = false;
307 UnsignedOrNone NumExpansions = FE->getNumExpansions();
309 FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
310 /*FailOnPackProducingTemplates=*/true, Expand, RetainExpansion,
311 NumExpansions) ||
312 !Expand || RetainExpansion)
313 return std::nullopt;
314
315 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) {
316 S.Diag(FE->getEllipsisLoc(),
317 clang::diag::err_fold_expression_limit_exceeded)
318 << *NumExpansions << S.getLangOpts().BracketDepth
319 << FE->getSourceRange();
320 S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth);
321 return std::nullopt;
322 }
323 return NumExpansions;
324}
325
327 Sema &S, const Expr *ConstraintExpr, const NamedDecl *Template,
328 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
329 ConstraintSatisfaction &Satisfaction);
330
332 Sema &S, const Expr *LHS, OverloadedOperatorKind Op, const Expr *RHS,
333 const NamedDecl *Template, SourceLocation TemplateNameLoc,
335 ConstraintSatisfaction &Satisfaction) {
336 size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
337
339 S, LHS, Template, TemplateNameLoc, MLTAL, Satisfaction);
340
341 if (LHSRes.isInvalid())
342 return ExprError();
343
344 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
345
346 if (Op == clang::OO_PipePipe && IsLHSSatisfied)
347 // [temp.constr.op] p3
348 // A disjunction is a constraint taking two operands. To determine if
349 // a disjunction is satisfied, the satisfaction of the first operand
350 // is checked. If that is satisfied, the disjunction is satisfied.
351 // Otherwise, the disjunction is satisfied if and only if the second
352 // operand is satisfied.
353 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
354 return LHSRes;
355
356 if (Op == clang::OO_AmpAmp && !IsLHSSatisfied)
357 // [temp.constr.op] p2
358 // A conjunction is a constraint taking two operands. To determine if
359 // a conjunction is satisfied, the satisfaction of the first operand
360 // is checked. If that is not satisfied, the conjunction is not
361 // satisfied. Otherwise, the conjunction is satisfied if and only if
362 // the second operand is satisfied.
363 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
364 return LHSRes;
365
367 S, RHS, Template, TemplateNameLoc, MLTAL, Satisfaction);
368 if (RHSRes.isInvalid())
369 return ExprError();
370
371 bool IsRHSSatisfied = Satisfaction.IsSatisfied;
372 // Current implementation adds diagnostic information about the falsity
373 // of each false atomic constraint expression when it evaluates them.
374 // When the evaluation results to `false || true`, the information
375 // generated during the evaluation of left-hand side is meaningless
376 // because the whole expression evaluates to true.
377 // The following code removes the irrelevant diagnostic information.
378 // FIXME: We should probably delay the addition of diagnostic information
379 // until we know the entire expression is false.
380 if (Op == clang::OO_PipePipe && IsRHSSatisfied) {
381 auto EffectiveDetailEnd = Satisfaction.Details.begin();
382 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
383 Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end());
384 }
385
386 if (!LHSRes.isUsable() || !RHSRes.isUsable())
387 return ExprEmpty();
388
389 return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(),
393}
394
396 Sema &S, const CXXFoldExpr *FE, const NamedDecl *Template,
397 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
398 ConstraintSatisfaction &Satisfaction) {
399 bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd;
400 size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
401
402 ExprResult Out;
403 if (FE->isLeftFold() && FE->getInit()) {
405 TemplateNameLoc, MLTAL, Satisfaction);
406 if (Out.isInvalid())
407 return ExprError();
408
409 // If the first clause of a conjunction is not satisfied,
410 // or if the first clause of a disjection is satisfied,
411 // we have established satisfaction of the whole constraint
412 // and we should not continue further.
413 if (Conjunction != Satisfaction.IsSatisfied)
414 return Out;
415 }
417 S, FE, Template, TemplateNameLoc, MLTAL, Satisfaction);
418 if (!NumExpansions)
419 return ExprError();
420 for (unsigned I = 0; I < *NumExpansions; I++) {
421 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
423 S, FE->getPattern(), Template, TemplateNameLoc, MLTAL, Satisfaction);
424 if (Res.isInvalid())
425 return ExprError();
426 bool IsRHSSatisfied = Satisfaction.IsSatisfied;
427 if (!Conjunction && IsRHSSatisfied) {
428 auto EffectiveDetailEnd = Satisfaction.Details.begin();
429 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
430 Satisfaction.Details.erase(EffectiveDetailEnd,
431 Satisfaction.Details.end());
432 }
433 if (Out.isUnset())
434 Out = Res;
435 else if (!Res.isUnset()) {
437 S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
439 }
440 if (Conjunction != IsRHSSatisfied)
441 return Out;
442 }
443
444 if (FE->isRightFold() && FE->getInit()) {
446 S, FE->getInit(), Template, TemplateNameLoc, MLTAL, Satisfaction);
447 if (Out.isInvalid())
448 return ExprError();
449
450 if (Out.isUnset())
451 Out = Res;
452 else if (!Res.isUnset()) {
454 S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
456 }
457 }
458
459 if (Out.isUnset()) {
460 Satisfaction.IsSatisfied = Conjunction;
461 Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator());
462 }
463 return Out;
464}
465
467 Sema &S, const Expr *ConstraintExpr, const NamedDecl *Template,
468 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
469 ConstraintSatisfaction &Satisfaction) {
470 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
471
472 if (LogicalBinOp BO = ConstraintExpr)
474 S, BO.getLHS(), BO.getOp(), BO.getRHS(), Template, TemplateNameLoc,
475 MLTAL, Satisfaction);
476
477 if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
478 // These aren't evaluated, so we don't care about cleanups, so we can just
479 // evaluate these as if the cleanups didn't exist.
481 S, C->getSubExpr(), Template, TemplateNameLoc, MLTAL, Satisfaction);
482 }
483
484 if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr);
485 FE && S.getLangOpts().CPlusPlus26 &&
486 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
487 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
488 return calculateConstraintSatisfaction(S, FE, Template, TemplateNameLoc,
489 MLTAL, Satisfaction);
490 }
491
492 // FIXME: We should not treat ConceptSpecializationExpr as atomic constraints.
493
494 // An atomic constraint expression
495 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
496 S, ConstraintExpr, Template, TemplateNameLoc, MLTAL, Satisfaction);
497
498 if (SubstitutedAtomicExpr.isInvalid())
499 return ExprError();
500
501 if (!SubstitutedAtomicExpr.isUsable())
502 // Evaluator has decided satisfaction without yielding an expression.
503 return ExprEmpty();
504
505 // We don't have the ability to evaluate this, since it contains a
506 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
507 // we'd potentially pick up a different overload, and cause confusing
508 // diagnostics. SO, add a failure detail that will cause us to make this
509 // overload set not viable.
510 if (SubstitutedAtomicExpr.get()->containsErrors()) {
511 Satisfaction.IsSatisfied = false;
512 Satisfaction.ContainsErrors = true;
513
514 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
515 SmallString<128> DiagString;
516 DiagString = ": ";
517 Msg.EmitToString(S.getDiagnostics(), DiagString);
518 unsigned MessageSize = DiagString.size();
519 char *Mem = new (S.Context) char[MessageSize];
520 memcpy(Mem, DiagString.c_str(), MessageSize);
521 Satisfaction.Details.emplace_back(
523 SubstitutedAtomicExpr.get()->getBeginLoc(),
524 StringRef(Mem, MessageSize)});
525 return SubstitutedAtomicExpr;
526 }
527
528 EnterExpressionEvaluationContext ConstantEvaluated(
531 Expr::EvalResult EvalResult;
532 EvalResult.Diag = &EvaluationDiags;
533 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
534 S.Context) ||
535 !EvaluationDiags.empty()) {
536 // C++2a [temp.constr.atomic]p1
537 // ...E shall be a constant expression of type bool.
538 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
539 diag::err_non_constant_constraint_expression)
540 << SubstitutedAtomicExpr.get()->getSourceRange();
541 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
542 S.Diag(PDiag.first, PDiag.second);
543 return ExprError();
544 }
545
546 assert(EvalResult.Val.isInt() &&
547 "evaluating bool expression didn't produce int");
548 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
549 if (!Satisfaction.IsSatisfied)
550 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
551
552 return SubstitutedAtomicExpr;
553}
554
556 Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
557 const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
558 ConstraintSatisfaction &Satisfaction) {
559
560 return calculateConstraintSatisfaction(S, ConstraintExpr, Template,
561 TemplateNameLoc, MLTAL, Satisfaction);
562}
563
565 Sema &S, const NamedDecl *Template,
566 ArrayRef<AssociatedConstraint> AssociatedConstraints,
568 const MultiLevelTemplateArgumentList &TemplateArgsLists,
569 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
570 if (AssociatedConstraints.empty()) {
571 Satisfaction.IsSatisfied = true;
572 return false;
573 }
574
575 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
576 // No need to check satisfaction for dependent constraint expressions.
577 Satisfaction.IsSatisfied = true;
578 return false;
579 }
580
581 ArrayRef<TemplateArgument> TemplateArgs =
582 TemplateArgsLists.getNumSubstitutedLevels() > 0
583 ? TemplateArgsLists.getOutermost()
585 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
587 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
588 if (Inst.isInvalid())
589 return true;
590
591 for (const AssociatedConstraint &AC : AssociatedConstraints) {
592 if (AC.isNull())
593 return true;
594
597 S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
598 AC.ConstraintExpr, Satisfaction);
599 if (Res.isInvalid())
600 return true;
601
602 Converted.push_back(Res.get());
603 if (!Satisfaction.IsSatisfied) {
604 // Backfill the 'converted' list with nulls so we can keep the Converted
605 // and unconverted lists in sync.
606 Converted.append(AssociatedConstraints.size() - Converted.size(),
607 nullptr);
608 // [temp.constr.op] p2
609 // [...] To determine if a conjunction is satisfied, the satisfaction
610 // of the first operand is checked. If that is not satisfied, the
611 // conjunction is not satisfied. [...]
612 return false;
613 }
614 }
615 return false;
616}
617
619 const NamedDecl *Template,
620 ArrayRef<AssociatedConstraint> AssociatedConstraints,
621 llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
622 const MultiLevelTemplateArgumentList &TemplateArgsLists,
623 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
624 if (AssociatedConstraints.empty()) {
625 OutSatisfaction.IsSatisfied = true;
626 return false;
627 }
628 if (!Template) {
629 return ::CheckConstraintSatisfaction(
630 *this, nullptr, AssociatedConstraints, ConvertedConstraints,
631 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
632 }
633 // Invalid templates could make their way here. Substituting them could result
634 // in dependent expressions.
635 if (Template->isInvalidDecl()) {
636 OutSatisfaction.IsSatisfied = false;
637 return true;
638 }
639
640 // A list of the template argument list flattened in a predictible manner for
641 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
642 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
643 // here.
645 for (auto List : TemplateArgsLists)
646 llvm::append_range(FlattenedArgs, List.Args);
647
648 llvm::FoldingSetNodeID ID;
650 void *InsertPos;
651 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
652 OutSatisfaction = *Cached;
653 return false;
654 }
655
656 auto Satisfaction =
657 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
658 if (::CheckConstraintSatisfaction(*this, Template, AssociatedConstraints,
659 ConvertedConstraints, TemplateArgsLists,
660 TemplateIDRange, *Satisfaction)) {
661 OutSatisfaction = *Satisfaction;
662 return true;
663 }
664
665 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
666 // The evaluation of this constraint resulted in us trying to re-evaluate it
667 // recursively. This isn't really possible, except we try to form a
668 // RecoveryExpr as a part of the evaluation. If this is the case, just
669 // return the 'cached' version (which will have the same result), and save
670 // ourselves the extra-insert. If it ever becomes possible to legitimately
671 // recursively check a constraint, we should skip checking the 'inner' one
672 // above, and replace the cached version with this one, as it would be more
673 // specific.
674 OutSatisfaction = *Cached;
675 return false;
676 }
677
678 // Else we can simply add this satisfaction to the list.
679 OutSatisfaction = *Satisfaction;
680 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
681 // invalidated it.
682 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
683 SatisfactionCache.InsertNode(Satisfaction.release());
684 return false;
685}
686
688 const ConceptSpecializationExpr *ConstraintExpr,
689 ConstraintSatisfaction &Satisfaction) {
690
691 MultiLevelTemplateArgumentList MLTAL(ConstraintExpr->getNamedConcept(),
692 ConstraintExpr->getTemplateArguments(),
693 true);
694
696 *this, ConstraintExpr, ConstraintExpr->getNamedConcept(),
697 ConstraintExpr->getConceptNameLoc(), MLTAL, Satisfaction)
698 .isInvalid();
699}
700
701bool Sema::SetupConstraintScope(
702 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
705 assert(!isLambdaCallOperator(FD) &&
706 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
707 "instantiations");
708 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
709 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
710 InstantiatingTemplate Inst(
711 *this, FD->getPointOfInstantiation(),
713 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
714 SourceRange());
715 if (Inst.isInvalid())
716 return true;
717
718 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
719 // 'instantiated' parameters and adds it to the context. For the case where
720 // this function is a template being instantiated NOW, we also need to add
721 // the list of current template arguments to the list so that they also can
722 // be picked out of the map.
723 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
724 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
725 /*Final=*/false);
726 if (addInstantiatedParametersToScope(
727 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
728 return true;
729 }
730
731 // If this is a member function, make sure we get the parameters that
732 // reference the original primary template.
733 if (FunctionTemplateDecl *FromMemTempl =
734 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
735 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
736 Scope, MLTAL))
737 return true;
738 }
739
740 return false;
741 }
742
745 FunctionDecl *InstantiatedFrom =
749
751 *this, FD->getPointOfInstantiation(),
752 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
753 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
754 SourceRange());
755 if (Inst.isInvalid())
756 return true;
757
758 // Case where this was not a template, but instantiated as a
759 // child-function.
760 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
761 return true;
762 }
763
764 return false;
765}
766
767// This function collects all of the template arguments for the purposes of
768// constraint-instantiation and checking.
769std::optional<MultiLevelTemplateArgumentList>
770Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
771 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
773 MultiLevelTemplateArgumentList MLTAL;
774
775 // Collect the list of template arguments relative to the 'primary' template.
776 // We need the entire list, since the constraint is completely uninstantiated
777 // at this point.
778 MLTAL =
780 /*Final=*/false, /*Innermost=*/std::nullopt,
781 /*RelativeToPrimary=*/true,
782 /*Pattern=*/nullptr,
783 /*ForConstraintInstantiation=*/true);
784 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
785 if (isLambdaCallOperator(FD))
786 return MLTAL;
787 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
788 return std::nullopt;
789
790 return MLTAL;
791}
792
794 ConstraintSatisfaction &Satisfaction,
795 SourceLocation UsageLoc,
796 bool ForOverloadResolution) {
797 // Don't check constraints if the function is dependent. Also don't check if
798 // this is a function template specialization, as the call to
799 // CheckFunctionTemplateConstraints after this will check it
800 // better.
801 if (FD->isDependentContext() ||
802 FD->getTemplatedKind() ==
804 Satisfaction.IsSatisfied = true;
805 return false;
806 }
807
808 // A lambda conversion operator has the same constraints as the call operator
809 // and constraints checking relies on whether we are in a lambda call operator
810 // (and may refer to its parameters), so check the call operator instead.
811 // Note that the declarations outside of the lambda should also be
812 // considered. Turning on the 'ForOverloadResolution' flag results in the
813 // LocalInstantiationScope not looking into its parents, but we can still
814 // access Decls from the parents while building a lambda RAII scope later.
815 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
816 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
817 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
818 Satisfaction, UsageLoc,
819 /*ShouldAddDeclsFromParentScope=*/true);
820
821 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
822
823 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
824 if (isLambdaCallOperator(CtxToSave))
825 CtxToSave = CtxToSave->getParent()->getParent();
826 else
827 CtxToSave = CtxToSave->getNonTransparentContext();
828 }
829
830 ContextRAII SavedContext{*this, CtxToSave};
831 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
832 std::optional<MultiLevelTemplateArgumentList> MLTAL =
833 SetupConstraintCheckingTemplateArgumentsAndScope(
834 const_cast<FunctionDecl *>(FD), {}, Scope);
835
836 if (!MLTAL)
837 return true;
838
839 Qualifiers ThisQuals;
840 CXXRecordDecl *Record = nullptr;
841 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
842 ThisQuals = Method->getMethodQualifiers();
843 Record = const_cast<CXXRecordDecl *>(Method->getParent());
844 }
845 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
846
848 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
849 ForOverloadResolution);
850
852 FD, FD->getTrailingRequiresClause(), *MLTAL,
853 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
854 Satisfaction);
855}
856
857
858// Figure out the to-translation-unit depth for this function declaration for
859// the purpose of seeing if they differ by constraints. This isn't the same as
860// getTemplateDepth, because it includes already instantiated parents.
861static unsigned
863 bool SkipForSpecialization = false) {
865 ND, ND->getLexicalDeclContext(), /*Final=*/false,
866 /*Innermost=*/std::nullopt,
867 /*RelativeToPrimary=*/true,
868 /*Pattern=*/nullptr,
869 /*ForConstraintInstantiation=*/true, SkipForSpecialization);
870 return MLTAL.getNumLevels();
871}
872
873namespace {
874 class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
875 unsigned TemplateDepth = 0;
876 public:
877 using inherited = TreeTransform<AdjustConstraintDepth>;
878 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
879 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
880
881 using inherited::TransformTemplateTypeParmType;
882 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
883 TemplateTypeParmTypeLoc TL, bool) {
884 const TemplateTypeParmType *T = TL.getTypePtr();
885
886 TemplateTypeParmDecl *NewTTPDecl = nullptr;
887 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
888 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
889 TransformDecl(TL.getNameLoc(), OldTTPDecl));
890
891 QualType Result = getSema().Context.getTemplateTypeParmType(
892 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
893 NewTTPDecl);
894 TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
895 NewTL.setNameLoc(TL.getNameLoc());
896 return Result;
897 }
898 };
899} // namespace
900
902 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
903 const Expr *ConstrExpr) {
905 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
906 /*Innermost=*/std::nullopt,
907 /*RelativeToPrimary=*/true,
908 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
909 /*SkipForSpecialization*/ false);
910
911 if (MLTAL.getNumSubstitutedLevels() == 0)
912 return ConstrExpr;
913
914 Sema::SFINAETrap SFINAE(S);
915
917 S, DeclInfo.getLocation(),
919 const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
920 if (Inst.isInvalid())
921 return nullptr;
922
923 // Set up a dummy 'instantiation' scope in the case of reference to function
924 // parameters that the surrounding function hasn't been instantiated yet. Note
925 // this may happen while we're comparing two templates' constraint
926 // equivalence.
927 std::optional<LocalInstantiationScope> ScopeForParameters;
928 if (const NamedDecl *ND = DeclInfo.getDecl();
929 ND && ND->isFunctionOrFunctionTemplate()) {
930 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
931 const FunctionDecl *FD = ND->getAsFunction();
933 Template && Template->getInstantiatedFromMemberTemplate())
934 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
935 for (auto *PVD : FD->parameters()) {
936 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
937 continue;
938 if (!PVD->isParameterPack()) {
939 ScopeForParameters->InstantiatedLocal(PVD, PVD);
940 continue;
941 }
942 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
943 // to avoid building SubstTemplateTypeParmPackTypes for
944 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
945 // otherwise reference the AssociatedDecl of the template arguments, which
946 // is, in this case, the template declaration.
947 //
948 // However, as we are in the process of comparing potential
949 // re-declarations, the canonical declaration is the declaration itself at
950 // this point. So if we didn't expand these packs, we would end up with an
951 // incorrect profile difference because we will be profiling the
952 // canonical types!
953 //
954 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
955 // that we can eliminate the Scope in the cases where the declarations are
956 // not necessarily instantiated. It would also benefit the noexcept
957 // specifier comparison.
958 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
959 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
960 }
961 }
962
963 std::optional<Sema::CXXThisScopeRAII> ThisScope;
964
965 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
966 // essential for having an injected class as the canonical type for a template
967 // specialization type at the rebuilding stage. This guarantees that, for
968 // out-of-line definitions, injected class name types and their equivalent
969 // template specializations can be profiled to the same value, which makes it
970 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
971 // perceived identical.
972 std::optional<Sema::ContextRAII> ContextScope;
973 const DeclContext *DC = [&] {
974 if (!DeclInfo.getDecl())
975 return DeclInfo.getDeclContext();
976 return DeclInfo.getDecl()->getFriendObjectKind()
977 ? DeclInfo.getLexicalDeclContext()
978 : DeclInfo.getDeclContext();
979 }();
980 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
981 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
982 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
983 /*NewThisContext=*/false);
984 }
985 EnterExpressionEvaluationContext UnevaluatedContext(
989 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
990 if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
991 return nullptr;
992 return SubstConstr.get();
993}
994
996 const Expr *OldConstr,
998 const Expr *NewConstr) {
999 if (OldConstr == NewConstr)
1000 return true;
1001 // C++ [temp.constr.decl]p4
1002 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1003 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1004 if (const Expr *SubstConstr =
1006 OldConstr))
1007 OldConstr = SubstConstr;
1008 else
1009 return false;
1010 if (const Expr *SubstConstr =
1012 NewConstr))
1013 NewConstr = SubstConstr;
1014 else
1015 return false;
1016 }
1017
1018 llvm::FoldingSetNodeID ID1, ID2;
1019 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1020 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1021 return ID1 == ID2;
1022}
1023
1025 assert(FD->getFriendObjectKind() && "Must be a friend!");
1026
1027 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1028 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1029 // non-function-template.
1030 assert(FD->getDescribedFunctionTemplate() &&
1031 "Non-function templates don't need to be checked");
1032
1035
1036 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1037 for (const AssociatedConstraint &AC : ACs)
1038 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1039 AC.ConstraintExpr))
1040 return true;
1041
1042 return false;
1043}
1044
1046 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1047 SourceRange TemplateIDRange) {
1048 ConstraintSatisfaction Satisfaction;
1049 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1050 TD->getAssociatedConstraints(AssociatedConstraints);
1051 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1052 TemplateIDRange, Satisfaction))
1053 return true;
1054
1055 if (!Satisfaction.IsSatisfied) {
1056 SmallString<128> TemplateArgString;
1057 TemplateArgString = " ";
1058 TemplateArgString += getTemplateArgumentBindingsText(
1059 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1060 TemplateArgsLists.getInnermost().size());
1061
1062 Diag(TemplateIDRange.getBegin(),
1063 diag::err_template_arg_list_constraints_not_satisfied)
1065 << TemplateArgString << TemplateIDRange;
1066 DiagnoseUnsatisfiedConstraint(Satisfaction);
1067 return true;
1068 }
1069 return false;
1070}
1071
1073 Sema &SemaRef, SourceLocation PointOfInstantiation,
1075 ConstraintSatisfaction &Satisfaction) {
1077 Template->getAssociatedConstraints(TemplateAC);
1078 if (TemplateAC.empty()) {
1079 Satisfaction.IsSatisfied = true;
1080 return false;
1081 }
1082
1084
1085 FunctionDecl *FD = Template->getTemplatedDecl();
1086 // Collect the list of template arguments relative to the 'primary'
1087 // template. We need the entire list, since the constraint is completely
1088 // uninstantiated at this point.
1089
1091 {
1092 // getTemplateInstantiationArgs uses this instantiation context to find out
1093 // template arguments for uninstantiated functions.
1094 // We don't want this RAII object to persist, because there would be
1095 // otherwise duplicate diagnostic notes.
1097 SemaRef, PointOfInstantiation,
1099 PointOfInstantiation);
1100 if (Inst.isInvalid())
1101 return true;
1102 MLTAL = SemaRef.getTemplateInstantiationArgs(
1103 /*D=*/FD, FD,
1104 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1105 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1106 }
1107
1108 Sema::ContextRAII SavedContext(SemaRef, FD);
1109 return SemaRef.CheckConstraintSatisfaction(
1110 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1111}
1112
1114 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1115 ArrayRef<TemplateArgument> TemplateArgs,
1116 ConstraintSatisfaction &Satisfaction) {
1117 // In most cases we're not going to have constraints, so check for that first.
1118 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1119
1120 if (!Template)
1121 return ::CheckFunctionConstraintsWithoutInstantiation(
1122 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1123 TemplateArgs, Satisfaction);
1124
1125 // Note - code synthesis context for the constraints check is created
1126 // inside CheckConstraintsSatisfaction.
1128 Template->getAssociatedConstraints(TemplateAC);
1129 if (TemplateAC.empty()) {
1130 Satisfaction.IsSatisfied = true;
1131 return false;
1132 }
1133
1134 // Enter the scope of this instantiation. We don't use
1135 // PushDeclContext because we don't have a scope.
1136 Sema::ContextRAII savedContext(*this, Decl);
1138
1139 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1140 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1141 Scope);
1142
1143 if (!MLTAL)
1144 return true;
1145
1146 Qualifiers ThisQuals;
1147 CXXRecordDecl *Record = nullptr;
1148 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1149 ThisQuals = Method->getMethodQualifiers();
1150 Record = Method->getParent();
1151 }
1152
1153 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1154 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1155 Scope);
1156
1157 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1158 PointOfInstantiation, Satisfaction);
1159}
1160
1163 bool First) {
1164 assert(!Req->isSatisfied()
1165 && "Diagnose() can only be used on an unsatisfied requirement");
1166 switch (Req->getSatisfactionStatus()) {
1168 llvm_unreachable("Diagnosing a dependent requirement");
1169 break;
1171 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1172 if (!SubstDiag->DiagMessage.empty())
1173 S.Diag(SubstDiag->DiagLoc,
1174 diag::note_expr_requirement_expr_substitution_error)
1175 << (int)First << SubstDiag->SubstitutedEntity
1176 << SubstDiag->DiagMessage;
1177 else
1178 S.Diag(SubstDiag->DiagLoc,
1179 diag::note_expr_requirement_expr_unknown_substitution_error)
1180 << (int)First << SubstDiag->SubstitutedEntity;
1181 break;
1182 }
1184 S.Diag(Req->getNoexceptLoc(),
1185 diag::note_expr_requirement_noexcept_not_met)
1186 << (int)First << Req->getExpr();
1187 break;
1189 auto *SubstDiag =
1191 if (!SubstDiag->DiagMessage.empty())
1192 S.Diag(SubstDiag->DiagLoc,
1193 diag::note_expr_requirement_type_requirement_substitution_error)
1194 << (int)First << SubstDiag->SubstitutedEntity
1195 << SubstDiag->DiagMessage;
1196 else
1197 S.Diag(SubstDiag->DiagLoc,
1198 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
1199 << (int)First << SubstDiag->SubstitutedEntity;
1200 break;
1201 }
1203 ConceptSpecializationExpr *ConstraintExpr =
1205 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1206 // A simple case - expr type is the type being constrained and the concept
1207 // was not provided arguments.
1208 Expr *e = Req->getExpr();
1209 S.Diag(e->getBeginLoc(),
1210 diag::note_expr_requirement_constraints_not_satisfied_simple)
1212 << ConstraintExpr->getNamedConcept();
1213 } else {
1214 S.Diag(ConstraintExpr->getBeginLoc(),
1215 diag::note_expr_requirement_constraints_not_satisfied)
1216 << (int)First << ConstraintExpr;
1217 }
1219 break;
1220 }
1222 llvm_unreachable("We checked this above");
1223 }
1224}
1225
1228 bool First) {
1229 assert(!Req->isSatisfied()
1230 && "Diagnose() can only be used on an unsatisfied requirement");
1231 switch (Req->getSatisfactionStatus()) {
1233 llvm_unreachable("Diagnosing a dependent requirement");
1234 return;
1236 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1237 if (!SubstDiag->DiagMessage.empty())
1238 S.Diag(SubstDiag->DiagLoc,
1239 diag::note_type_requirement_substitution_error) << (int)First
1240 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
1241 else
1242 S.Diag(SubstDiag->DiagLoc,
1243 diag::note_type_requirement_unknown_substitution_error)
1244 << (int)First << SubstDiag->SubstitutedEntity;
1245 return;
1246 }
1247 default:
1248 llvm_unreachable("Unknown satisfaction status");
1249 return;
1250 }
1251}
1253 Expr *SubstExpr,
1254 bool First = true);
1255
1258 bool First) {
1259 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1260 for (auto &Record : Req->getConstraintSatisfaction()) {
1261 if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>())
1262 S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1264 << SubstDiag->second;
1265 else
1267 First);
1268 First = false;
1269 }
1270}
1271
1273 Expr *SubstExpr,
1274 bool First) {
1275 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1276 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1277 switch (BO->getOpcode()) {
1278 // These two cases will in practice only be reached when using fold
1279 // expressions with || and &&, since otherwise the || and && will have been
1280 // broken down into atomic constraints during satisfaction checking.
1281 case BO_LOr:
1282 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1285 /*First=*/false);
1286 return;
1287 case BO_LAnd: {
1288 bool LHSSatisfied =
1289 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1290 if (LHSSatisfied) {
1291 // LHS is true, so RHS must be false.
1293 return;
1294 }
1295 // LHS is false
1297
1298 // RHS might also be false
1299 bool RHSSatisfied =
1300 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1301 if (!RHSSatisfied)
1303 /*First=*/false);
1304 return;
1305 }
1306 case BO_GE:
1307 case BO_LE:
1308 case BO_GT:
1309 case BO_LT:
1310 case BO_EQ:
1311 case BO_NE:
1312 if (BO->getLHS()->getType()->isIntegerType() &&
1313 BO->getRHS()->getType()->isIntegerType()) {
1314 Expr::EvalResult SimplifiedLHS;
1315 Expr::EvalResult SimplifiedRHS;
1316 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1318 /*InConstantContext=*/true);
1319 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1321 /*InConstantContext=*/true);
1322 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1323 S.Diag(SubstExpr->getBeginLoc(),
1324 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1325 << (int)First << SubstExpr
1326 << toString(SimplifiedLHS.Val.getInt(), 10)
1327 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1328 << toString(SimplifiedRHS.Val.getInt(), 10);
1329 return;
1330 }
1331 }
1332 break;
1333
1334 default:
1335 break;
1336 }
1337 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1338 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1339 S.Diag(
1340 CSE->getSourceRange().getBegin(),
1341 diag::
1342 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1343 << (int)First
1344 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1345 << CSE->getNamedConcept();
1346 } else {
1347 S.Diag(SubstExpr->getSourceRange().getBegin(),
1348 diag::note_concept_specialization_constraint_evaluated_to_false)
1349 << (int)First << CSE;
1350 }
1351 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1352 return;
1353 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1354 // FIXME: RequiresExpr should store dependent diagnostics.
1355 for (concepts::Requirement *Req : RE->getRequirements())
1356 if (!Req->isDependent() && !Req->isSatisfied()) {
1357 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1359 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1361 else
1364 break;
1365 }
1366 return;
1367 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1368 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1369 assert(TTE->getNumArgs() == 2);
1370 S.Diag(SubstExpr->getSourceRange().getBegin(),
1371 diag::note_is_deducible_constraint_evaluated_to_false)
1372 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1373 return;
1374 }
1375
1376 S.Diag(SubstExpr->getSourceRange().getBegin(),
1377 diag::note_atomic_constraint_evaluated_to_false)
1378 << (int)First << SubstExpr;
1379 S.DiagnoseTypeTraitDetails(SubstExpr);
1380}
1381
1382template <typename SubstitutionDiagnostic>
1384 Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1385 bool First = true) {
1386 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) {
1387 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1388 << Diag->second;
1389 return;
1390 }
1391
1393}
1394
1395void
1397 bool First) {
1398 assert(!Satisfaction.IsSatisfied &&
1399 "Attempted to diagnose a satisfied constraint");
1400 for (auto &Record : Satisfaction.Details) {
1402 First = false;
1403 }
1404}
1405
1407 const ASTConstraintSatisfaction &Satisfaction,
1408 bool First) {
1409 assert(!Satisfaction.IsSatisfied &&
1410 "Attempted to diagnose a satisfied constraint");
1411 for (auto &Record : Satisfaction) {
1413 First = false;
1414 }
1415}
1416
1418 const NamedDecl *ConstrainedDecl,
1419 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1420 // In case the ConstrainedDecl comes from modules, it is necessary to use
1421 // the canonical decl to avoid different atomic constraints with the 'same'
1422 // declarations.
1423 ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl());
1424
1425 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1426 if (CacheEntry == NormalizationCache.end()) {
1427 auto Normalized = NormalizedConstraint::fromAssociatedConstraints(
1428 *this, ConstrainedDecl, AssociatedConstraints);
1429 CacheEntry =
1430 NormalizationCache
1431 .try_emplace(ConstrainedDecl,
1432 Normalized
1434 std::move(*Normalized))
1435 : nullptr)
1436 .first;
1437 }
1438 return CacheEntry->second;
1439}
1440
1442 Sema &S, const NamedDecl *ConstrainedDecl,
1443 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1444 return S.getNormalizedAssociatedConstraints(ConstrainedDecl,
1445 AssociatedConstraints);
1446}
1447
1448static bool
1451 const MultiLevelTemplateArgumentList &MLTAL,
1452 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1453
1454 if (N.isCompound()) {
1455 if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1456 ArgsAsWritten))
1457 return true;
1458 return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1459 ArgsAsWritten);
1460 }
1461
1462 if (N.isFoldExpanded()) {
1463 Sema::ArgPackSubstIndexRAII _(S, std::nullopt);
1466 ArgsAsWritten);
1467 }
1468
1469 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1470
1472 TemplateArgumentListInfo SubstArgs;
1473 if (!Atomic.ParameterMapping) {
1474 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1475 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1476 /*Depth=*/0, OccurringIndices);
1477 TemplateArgumentLoc *TempArgs =
1478 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1479 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1480 if (OccurringIndices[I])
1481 new (&(TempArgs)[J++])
1483 TemplateParams->begin()[I],
1484 // Here we assume we do not support things like
1485 // template<typename A, typename B>
1486 // concept C = ...;
1487 //
1488 // template<typename... Ts> requires C<Ts...>
1489 // struct S { };
1490 // The above currently yields a diagnostic.
1491 // We still might have default arguments for concept parameters.
1492 ArgsAsWritten->NumTemplateArgs > I
1493 ? ArgsAsWritten->arguments()[I].getLocation()
1494 : SourceLocation()));
1495 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
1496 }
1497 SourceLocation InstLocBegin =
1498 ArgsAsWritten->arguments().empty()
1499 ? ArgsAsWritten->getLAngleLoc()
1500 : ArgsAsWritten->arguments().front().getSourceRange().getBegin();
1501 SourceLocation InstLocEnd =
1502 ArgsAsWritten->arguments().empty()
1503 ? ArgsAsWritten->getRAngleLoc()
1504 : ArgsAsWritten->arguments().front().getSourceRange().getEnd();
1506 S, InstLocBegin,
1508 const_cast<NamedDecl *>(Atomic.ConstraintDecl),
1509 {InstLocBegin, InstLocEnd});
1510 if (Inst.isInvalid())
1511 return true;
1512 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1513 return true;
1514
1515 TemplateArgumentLoc *TempArgs =
1516 new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1517 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1518 TempArgs);
1519 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1520 return false;
1521}
1522
1524 const ConceptSpecializationExpr *CSE) {
1527 /*Final=*/false, CSE->getTemplateArguments(),
1528 /*RelativeToPrimary=*/true,
1529 /*Pattern=*/nullptr,
1530 /*ForConstraintInstantiation=*/true);
1531
1532 return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1534}
1535
1543
1545 const NormalizedConstraint &Other) {
1546 if (Other.isAtomic()) {
1547 Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
1548 } else if (Other.isFoldExpanded()) {
1550 Other.getFoldExpandedConstraint()->Kind,
1551 NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint),
1552 Other.getFoldExpandedConstraint()->Pattern);
1553 } else {
1555 new (C)
1557 NormalizedConstraint(C, Other.getRHS())},
1558 Other.getCompoundKind());
1559 }
1560}
1561
1563 assert(isCompound() && "getLHS called on a non-compound constraint.");
1564 return cast<CompoundConstraint>(Constraint).getPointer()->LHS;
1565}
1566
1568 assert(isCompound() && "getRHS called on a non-compound constraint.");
1569 return cast<CompoundConstraint>(Constraint).getPointer()->RHS;
1570}
1571
1572std::optional<NormalizedConstraint>
1573NormalizedConstraint::fromAssociatedConstraints(
1574 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
1575 assert(ACs.size() != 0);
1576 auto Conjunction = fromConstraintExpr(S, D, ACs[0].ConstraintExpr);
1577 if (!Conjunction)
1578 return std::nullopt;
1579 for (unsigned I = 1; I < ACs.size(); ++I) {
1580 auto Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr);
1581 if (!Next)
1582 return std::nullopt;
1583 *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1584 std::move(*Next), CCK_Conjunction);
1585 }
1586 return Conjunction;
1587}
1588
1589std::optional<NormalizedConstraint>
1590NormalizedConstraint::fromConstraintExpr(Sema &S, const NamedDecl *D,
1591 const Expr *E) {
1592 assert(E != nullptr);
1593
1594 // C++ [temp.constr.normal]p1.1
1595 // [...]
1596 // - The normal form of an expression (E) is the normal form of E.
1597 // [...]
1598 E = E->IgnoreParenImpCasts();
1599
1600 // C++2a [temp.param]p4:
1601 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1602 // Fold expression is considered atomic constraints per current wording.
1603 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1604
1605 if (LogicalBinOp BO = E) {
1606 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1607 if (!LHS)
1608 return std::nullopt;
1609 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1610 if (!RHS)
1611 return std::nullopt;
1612
1613 return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
1614 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1615 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1616 const NormalizedConstraint *SubNF;
1617 {
1618 Sema::InstantiatingTemplate Inst(
1619 S, CSE->getExprLoc(),
1620 Sema::InstantiatingTemplate::ConstraintNormalization{},
1621 // FIXME: improve const-correctness of InstantiatingTemplate
1622 const_cast<NamedDecl *>(D), CSE->getSourceRange());
1623 if (Inst.isInvalid())
1624 return std::nullopt;
1625 // C++ [temp.constr.normal]p1.1
1626 // [...]
1627 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1628 // where C names a concept, is the normal form of the
1629 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1630 // respective template parameters in the parameter mappings in each atomic
1631 // constraint. If any such substitution results in an invalid type or
1632 // expression, the program is ill-formed; no diagnostic is required.
1633 // [...]
1634 ConceptDecl *CD = CSE->getNamedConcept();
1636 CD, AssociatedConstraint(CD->getConstraintExpr()));
1637 if (!SubNF)
1638 return std::nullopt;
1639 }
1640
1641 std::optional<NormalizedConstraint> New;
1642 New.emplace(S.Context, *SubNF);
1643
1644 if (substituteParameterMappings(S, *New, CSE))
1645 return std::nullopt;
1646
1647 return New;
1648 } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
1649 FE && S.getLangOpts().CPlusPlus26 &&
1650 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
1651 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
1652
1653 // Normalize fold expressions in C++26.
1654
1656 FE->getOperator() == BinaryOperatorKind::BO_LAnd
1659
1660 if (FE->getInit()) {
1661 auto LHS = fromConstraintExpr(S, D, FE->getLHS());
1662 auto RHS = fromConstraintExpr(S, D, FE->getRHS());
1663 if (!LHS || !RHS)
1664 return std::nullopt;
1665
1666 if (FE->isRightFold())
1667 RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1668 Kind, std::move(*RHS), FE->getPattern()}};
1669 else
1670 LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1671 Kind, std::move(*LHS), FE->getPattern()}};
1672
1673 return NormalizedConstraint(
1674 S.Context, std::move(*LHS), std::move(*RHS),
1675 FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
1676 : CCK_Disjunction);
1677 }
1678 auto Sub = fromConstraintExpr(S, D, FE->getPattern());
1679 if (!Sub)
1680 return std::nullopt;
1681 return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1682 Kind, std::move(*Sub), FE->getPattern()}};
1683 }
1684
1685 return NormalizedConstraint{new (S.Context) AtomicConstraint(E, D)};
1686}
1687
1690
1691 // [C++26] [temp.constr.fold]
1692 // Two fold expanded constraints are compatible for subsumption
1693 // if their respective constraints both contain an equivalent unexpanded pack.
1694
1696 Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks);
1697 Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks);
1698
1699 for (const UnexpandedParameterPack &APack : APacks) {
1700 auto ADI = getDepthAndIndex(APack);
1701 if (!ADI)
1702 continue;
1703 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
1704 return getDepthAndIndex(BPack) == ADI;
1705 });
1706 if (It != BPacks.end())
1707 return true;
1708 }
1709 return false;
1710}
1711
1714 const NamedDecl *D2,
1716 bool &Result) {
1717#ifndef NDEBUG
1718 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1719 auto IsExpectedEntity = [](const FunctionDecl *FD) {
1721 return Kind == FunctionDecl::TK_NonTemplate ||
1723 };
1724 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1725 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1726 "use non-instantiated function declaration for constraints partial "
1727 "ordering");
1728 }
1729#endif
1730
1731 if (AC1.empty()) {
1732 Result = AC2.empty();
1733 return false;
1734 }
1735 if (AC2.empty()) {
1736 // TD1 has associated constraints and TD2 does not.
1737 Result = true;
1738 return false;
1739 }
1740
1741 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
1742 auto CacheEntry = SubsumptionCache.find(Key);
1743 if (CacheEntry != SubsumptionCache.end()) {
1744 Result = CacheEntry->second;
1745 return false;
1746 }
1747
1748 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1749 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1750
1751 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1752 if (Depth2 > Depth1) {
1753 AC1[I].ConstraintExpr =
1754 AdjustConstraintDepth(*this, Depth2 - Depth1)
1755 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
1756 .get();
1757 } else if (Depth1 > Depth2) {
1758 AC2[I].ConstraintExpr =
1759 AdjustConstraintDepth(*this, Depth1 - Depth2)
1760 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
1761 .get();
1762 }
1763 }
1764
1765 SubsumptionChecker SC(*this);
1766 std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2);
1767 if (!Subsumes) {
1768 // Normalization failed
1769 return true;
1770 }
1771 Result = *Subsumes;
1772 SubsumptionCache.try_emplace(Key, *Subsumes);
1773 return false;
1774}
1775
1779 if (isSFINAEContext())
1780 // No need to work here because our notes would be discarded.
1781 return false;
1782
1783 if (AC1.empty() || AC2.empty())
1784 return false;
1785
1786 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1787 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
1788 const AtomicConstraint &B) {
1790 return false;
1791 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1792 if (EA == EB)
1793 return true;
1794
1795 // Not the same source level expression - are the expressions
1796 // identical?
1797 llvm::FoldingSetNodeID IDA, IDB;
1798 EA->Profile(IDA, Context, /*Canonical=*/true);
1799 EB->Profile(IDB, Context, /*Canonical=*/true);
1800 if (IDA != IDB)
1801 return false;
1802
1803 AmbiguousAtomic1 = EA;
1804 AmbiguousAtomic2 = EB;
1805 return true;
1806 };
1807
1808 {
1809 // The subsumption checks might cause diagnostics
1810 SFINAETrap Trap(*this);
1811 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1812 if (!Normalized1)
1813 return false;
1814
1815 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1816 if (!Normalized2)
1817 return false;
1818
1819 SubsumptionChecker SC(*this);
1820
1821 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
1822 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
1823
1824 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
1825 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
1826 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
1827
1828 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1829 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1830 // Same result - no ambiguity was caused by identical atomic expressions.
1831 return false;
1832 }
1833 // A different result! Some ambiguous atomic constraint(s) caused a difference
1834 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1835
1836 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1837 << AmbiguousAtomic1->getSourceRange();
1838 Diag(AmbiguousAtomic2->getBeginLoc(),
1839 diag::note_ambiguous_atomic_constraints_similar_expression)
1840 << AmbiguousAtomic2->getSourceRange();
1841 return true;
1842}
1843
1846 assert(isCompound() && "getCompoundKind on a non-compound constraint..");
1847 return cast<CompoundConstraint>(Constraint).getInt();
1848}
1849
1851 assert(isAtomic() && "getAtomicConstraint called on non-atomic constraint.");
1853}
1854
1857 assert(isFoldExpanded() &&
1858 "getFoldExpandedConstraint called on non-fold-expanded constraint.");
1860}
1861
1862//
1863//
1864// ------------------------ Subsumption -----------------------------------
1865//
1866//
1867
1868template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
1869
1870 static FoldingSetNodeID getEmptyKey() {
1871 FoldingSetNodeID ID;
1872 ID.AddInteger(std::numeric_limits<unsigned>::max());
1873 return ID;
1874 }
1875
1876 static FoldingSetNodeID getTombstoneKey() {
1877 FoldingSetNodeID ID;
1878 for (unsigned I = 0; I < sizeof(ID) / sizeof(unsigned); ++I) {
1879 ID.AddInteger(std::numeric_limits<unsigned>::max());
1880 }
1881 return ID;
1882 }
1883
1884 static unsigned getHashValue(const FoldingSetNodeID &Val) {
1885 return Val.ComputeHash();
1886 }
1887
1888 static bool isEqual(const FoldingSetNodeID &LHS,
1889 const FoldingSetNodeID &RHS) {
1890 return LHS == RHS;
1891 }
1892};
1893
1895 SubsumptionCallable Callable)
1896 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
1897
1898uint16_t SubsumptionChecker::getNewLiteralId() {
1899 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
1900 "too many constraints!");
1901 return NextID++;
1902}
1903
1904auto SubsumptionChecker::find(AtomicConstraint *Ori) -> Literal {
1905 auto &Elems = AtomicMap[Ori->ConstraintExpr];
1906 // C++ [temp.constr.order] p2
1907 // - an atomic constraint A subsumes another atomic constraint B
1908 // if and only if the A and B are identical [...]
1909 //
1910 // C++ [temp.constr.atomic] p2
1911 // Two atomic constraints are identical if they are formed from the
1912 // same expression and the targets of the parameter mappings are
1913 // equivalent according to the rules for expressions [...]
1914
1915 // Because subsumption of atomic constraints is an identity
1916 // relationship that does not require further analysis
1917 // We cache the results such that if an atomic constraint literal
1918 // subsumes another, their literal will be the same
1919
1920 llvm::FoldingSetNodeID ID;
1921 const auto &Mapping = Ori->ParameterMapping;
1922 ID.AddBoolean(Mapping.has_value());
1923 if (Mapping) {
1924 for (const TemplateArgumentLoc &TAL : *Mapping) {
1925 SemaRef.getASTContext()
1926 .getCanonicalTemplateArgument(TAL.getArgument())
1927 .Profile(ID, SemaRef.getASTContext());
1928 }
1929 }
1930 auto It = Elems.find(ID);
1931 if (It == Elems.end()) {
1932 It = Elems
1933 .insert({ID,
1934 MappedAtomicConstraint{
1935 Ori, {getNewLiteralId(), Literal::Atomic}}})
1936 .first;
1937 ReverseMap[It->second.ID.Value] = Ori;
1938 }
1939 return It->getSecond().ID;
1940}
1941
1942auto SubsumptionChecker::find(FoldExpandedConstraint *Ori) -> Literal {
1943 auto &Elems = FoldMap[Ori->Pattern];
1944
1945 FoldExpendedConstraintKey K;
1946 K.Kind = Ori->Kind;
1947
1948 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
1949 return K.Kind == Other.Kind;
1950 });
1951 if (It == Elems.end()) {
1952 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
1953 It = Elems.insert(Elems.end(), std::move(K));
1954 ReverseMap[It->ID.Value] = Ori;
1955 }
1956 return It->ID;
1957}
1958
1959auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
1960 return SubsumptionChecker::Normalize<CNFFormula>(C);
1961}
1962auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
1963 return SubsumptionChecker::Normalize<DNFFormula>(C);
1964}
1965
1966///
1967/// \brief SubsumptionChecker::Normalize
1968///
1969/// Normalize a formula to Conjunctive Normal Form or
1970/// Disjunctive normal form.
1971///
1972/// Each Atomic (and Fold Expanded) constraint gets represented by
1973/// a single id to reduce space.
1974///
1975/// To minimize risks of exponential blow up, if two atomic
1976/// constraints subsumes each other (same constraint and mapping),
1977/// they are represented by the same literal.
1978///
1979template <typename FormulaType>
1980FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
1981 FormulaType Res;
1982
1983 auto Add = [&, this](Clause C) {
1984 // Sort each clause and remove duplicates for faster comparisons.
1985 llvm::sort(C);
1986 C.erase(llvm::unique(C), C.end());
1987 AddUniqueClauseToFormula(Res, std::move(C));
1988 };
1989
1990 if (NC.isAtomic())
1991 return {{find(NC.getAtomicConstraint())}};
1992
1993 if (NC.isFoldExpanded())
1994 return {{find(NC.getFoldExpandedConstraint())}};
1995
1996 FormulaType Left, Right;
1997 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
1998 Left = Normalize<FormulaType>(NC.getLHS());
1999 Right = Normalize<FormulaType>(NC.getRHS());
2000 });
2001
2002 if (NC.getCompoundKind() == FormulaType::Kind) {
2003 auto SizeLeft = Left.size();
2004 Res = std::move(Left);
2005 Res.reserve(SizeLeft + Right.size());
2006 std::for_each(std::make_move_iterator(Right.begin()),
2007 std::make_move_iterator(Right.end()), Add);
2008 return Res;
2009 }
2010
2011 Res.reserve(Left.size() * Right.size());
2012 for (const auto &LTransform : Left) {
2013 for (const auto &RTransform : Right) {
2014 Clause Combined;
2015 Combined.reserve(LTransform.size() + RTransform.size());
2016 llvm::append_range(Combined, LTransform);
2017 llvm::append_range(Combined, RTransform);
2018 Add(std::move(Combined));
2019 }
2020 }
2021 return Res;
2022}
2023
2024void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2025 for (auto &Other : F) {
2026 if (llvm::equal(C, Other))
2027 return;
2028 }
2029 F.push_back(C);
2030}
2031
2033 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2035 const NormalizedConstraint *PNormalized =
2036 getNormalizedAssociatedConstraints(SemaRef, DP, P);
2037 if (!PNormalized)
2038 return std::nullopt;
2039
2040 const NormalizedConstraint *QNormalized =
2041 getNormalizedAssociatedConstraints(SemaRef, DQ, Q);
2042 if (!QNormalized)
2043 return std::nullopt;
2044
2045 return Subsumes(PNormalized, QNormalized);
2046}
2047
2049 const NormalizedConstraint *Q) {
2050
2051 DNFFormula DNFP = DNF(*P);
2052 CNFFormula CNFQ = CNF(*Q);
2053 return Subsumes(DNFP, CNFQ);
2054}
2055
2056bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2057 const CNFFormula &QCNF) {
2058 for (const auto &Pi : PDNF) {
2059 for (const auto &Qj : QCNF) {
2060 // C++ [temp.constr.order] p2
2061 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2062 // and only if there exists an atomic constraint Pia in Pi for which
2063 // there exists an atomic constraint, Qjb, in Qj such that Pia
2064 // subsumes Qjb.
2065 if (!DNFSubsumes(Pi, Qj))
2066 return false;
2067 }
2068 }
2069 return true;
2070}
2071
2072bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2073
2074 return llvm::any_of(P, [&](Literal LP) {
2075 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2076 });
2077}
2078
2080 const FoldExpandedConstraint *B) {
2081 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2082 A, B};
2083
2084 auto It = FoldSubsumptionCache.find(Key);
2085 if (It == FoldSubsumptionCache.end()) {
2086 // C++ [temp.constr.order]
2087 // a fold expanded constraint A subsumes another fold expanded
2088 // constraint B if they are compatible for subsumption, have the same
2089 // fold-operator, and the constraint of A subsumes that of B.
2090 bool DoesSubsume =
2091 A->Kind == B->Kind &&
2093 Subsumes(&A->Constraint, &B->Constraint);
2094 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2095 }
2096 return It->second;
2097}
2098
2099bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2100 if (A.Kind != B.Kind)
2101 return false;
2102 switch (A.Kind) {
2103 case Literal::Atomic:
2104 if (!Callable)
2105 return A.Value == B.Value;
2106 return Callable(
2107 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2108 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2109 case Literal::FoldExpanded:
2110 return Subsumes(
2111 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2112 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2113 }
2114 llvm_unreachable("unknown literal kind");
2115}
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
FormatToken * Next
The next token in the unwrapped line.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Record Record
Definition MachO.h:31
Defines and computes precedence levels for binary/ternary operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static UnsignedOrNone EvaluateFoldExpandedConstraintSize(Sema &S, const CXXFoldExpr *FE, const NamedDecl *Template, SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, ConstraintSatisfaction &Satisfaction)
static ExprResult calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, const NamedDecl *Template, SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, ConstraintSatisfaction &Satisfaction)
static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList &MLTAL)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, llvm::SmallVectorImpl< Expr * > &Converted, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
static ExprResult EvaluateAtomicConstraint(Sema &S, const Expr *AtomicExpr, const NamedDecl *Template, SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, ConstraintSatisfaction &Satisfaction)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static bool CheckFunctionConstraintsWithoutInstantiation(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, const MultiLevelTemplateArgumentList &MLTAL, const ASTTemplateArgumentListInfo *ArgsAsWritten)
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
APSInt & getInt()
Definition APValue.h:489
bool isInt() const
Definition APValue.h:467
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:188
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
QualType getReferenceQualifiedType(const Expr *e) const
getReferenceQualifiedType - Given an expr, will return the type for that expression,...
CanQualType BoolTy
bool isUnset() const
Definition Ownership.h:168
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
bool isUsable() const
Definition Ownership.h:169
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6816
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:6932
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3974
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2175
StringRef getOpcodeStr() const
Definition Expr.h:4040
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Definition Expr.cpp:4938
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2137
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2937
Represents a folding of a pack over an operator.
Definition ExprCXX.h:5026
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprCXX.h:5075
Expr * getInit() const
Get the operand that doesn't contain a pack, for a binary fold.
Definition ExprCXX.h:5066
SourceLocation getEllipsisLoc() const
Definition ExprCXX.h:5070
bool isLeftFold() const
Does this produce a left-associated sequence of operators?
Definition ExprCXX.h:5060
UnsignedOrNone getNumExpansions() const
Definition ExprCXX.h:5073
bool isRightFold() const
Does this produce a right-associated sequence of operators?
Definition ExprCXX.h:5055
Expr * getPattern() const
Get the pattern, that is, the operand that contains an unexpanded pack.
Definition ExprCXX.h:5063
BinaryOperatorKind getOperator() const
Definition ExprCXX.h:5071
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
SourceLocation getConceptNameLoc() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:37
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
Definition ASTConcept.h:51
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition ASTConcept.h:62
llvm::SmallVector< Detail, 4 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
Definition ASTConcept.h:60
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getNonTransparentContext()
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
Definition DeclBase.h:1226
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition DeclBase.h:1119
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:251
SourceLocation getLocation() const
Definition DeclBase.h:439
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:918
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:978
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition Decl.h:854
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition Expr.h:112
@ SE_NoSideEffects
Strictly evaluate the expression.
Definition Expr.h:671
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3073
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:246
bool isPRValue() const
Definition Expr.h:285
bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required to be a constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Definition Decl.h:1999
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4134
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4455
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2771
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition Decl.cpp:4254
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4270
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4198
TemplatedKind
The kind of templated function a FunctionDecl can be.
Definition Decl.h:2004
@ TK_FunctionTemplateSpecialization
Definition Decl.h:2015
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition Decl.cpp:4085
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4158
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4106
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
FunctionTemplateDecl * getInstantiatedFromMemberTemplate() const
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2068
const TypeClass * getTypePtr() const
Definition TypeLoc.h:531
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Definition Template.h:365
Data structure that captures multiple levels of template argument lists for use in template instantia...
Definition Template.h:76
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
Definition Template.h:265
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
Definition Template.h:123
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
Definition Template.h:129
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
Definition Template.h:269
This represents a decl that may have a name.
Definition Decl.h:273
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
A (possibly-)qualified type.
Definition TypeBase.h:937
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition SemaBase.cpp:61
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition SemaBase.cpp:33
RAII object used to change the argument pack substitution index within a Sema object.
Definition Sema.h:13497
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8393
A RAII object to temporarily push a declaration context.
Definition Sema.h:3468
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition Sema.h:12360
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition Sema.h:12393
SourceLocation getLocation() const
Definition Sema.h:12134
const DeclContext * getDeclContext() const
Definition Sema.h:12130
const NamedDecl * getDecl() const
Definition Sema.h:12122
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12126
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:850
ASTContext & Context
Definition Sema.h:1276
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
DiagnosticsEngine & getDiagnostics() const
Definition Sema.h:915
void DiagnoseTypeTraitDetails(const Expr *E)
If E represents a built-in type trait, or a known standard type trait, try to print more information ...
ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
ASTContext & getASTContext() const
Definition Sema.h:918
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
const LangOptions & getLangOpts() const
Definition Sema.h:911
bool CheckConstraintSatisfaction(const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
Definition Sema.h:14709
@ ReuseLambdaContextDecl
Definition Sema.h:6970
void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)
Collect the set of unexpanded parameter packs within the given template argument.
const NormalizedConstraint * getNormalizedAssociatedConstraints(const NamedDecl *ConstrainedDecl, ArrayRef< AssociatedConstraint > AssociatedConstraints)
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1307
std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const
Determines whether we are currently in a context where template argument substitution failures are no...
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, const DeclContext *DC=nullptr, bool Final=false, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false, bool ForDefaultArgumentSubstitution=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)
Check whether the given function decl's trailing requires clause is satisfied, if any.
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13491
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14646
void PopSatisfactionStackEntry()
Definition Sema.h:14652
ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
Definition Sema.h:6688
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6667
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition Sema.h:14654
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, BinaryOperatorKind Operator)
bool IsAtLeastAsConstrained(const NamedDecl *D1, MutableArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, MutableArrayRef< AssociatedConstraint > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(const NamedDecl *D1, ArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, ArrayRef< AssociatedConstraint > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
SubsumptionChecker establishes subsumption between two set of constraints.
std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)
SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})
llvm::function_ref< bool( const AtomicConstraint &, const AtomicConstraint &)> SubsumptionCallable
A convenient class for passing around template argument information.
ArrayRef< TemplateArgumentLoc > arguments() const
Location wrapper for a TemplateArgument.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< AssociatedConstraint > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Stores a list of template parameters for a TemplateDecl and its derived classes.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition Token.h:102
tok::TokenKind getKind() const
Definition Token.h:97
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
SourceLocation getNameLoc() const
Definition TypeLoc.h:552
void setNameLoc(SourceLocation Loc)
Definition TypeLoc.h:556
The base class of the type hierarchy.
Definition TypeBase.h:1833
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8905
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2800
bool isFunctionType() const
Definition TypeBase.h:8576
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
A requires-expression requirement which queries the validity and properties of an expression ('simple...
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
const ReturnTypeRequirement & getReturnTypeRequirement() const
SatisfactionStatus getSatisfactionStatus() const
SourceLocation getNoexceptLoc() const
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
A static requirement that can be used in a requires-expression to check properties of types and expre...
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
Provides information about an attempted template argument deduction, whose success or failure was des...
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
#define bool
Definition gpuintrin.h:32
uint32_t Literal
Literals are represented as positive integers.
Definition CNFFormula.h:35
bool Sub(InterpState &S, CodePtr OpPC)
Definition Interp.h:425
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:398
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus11
@ CPlusPlus26
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl *, const TemplateSpecializationType *, const SubstBuiltinTemplatePackType * >, SourceLocation > UnexpandedParameterPack
Definition Sema.h:235
ExprResult ExprEmpty()
Definition Ownership.h:272
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Result
The result type of a method or function.
Definition TypeBase.h:905
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
@ Template
We are parsing a template declaration.
Definition Parser.h:81
ExprResult ExprError()
Definition Ownership.h:265
@ Concept
The name was classified as a concept name.
Definition Sema.h:589
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
Definition ASTLambda.h:69
const NormalizedConstraint * getNormalizedAssociatedConstraints(Sema &S, const NamedDecl *ConstrainedDecl, ArrayRef< AssociatedConstraint > AssociatedConstraints)
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1745
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:91
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
SourceLocation getLAngleLoc() const
ArrayRef< TemplateArgumentLoc > arguments() const
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
SourceLocation getRAngleLoc() const
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
Definition SemaConcept.h:40
const Expr * ConstraintExpr
Definition SemaConcept.h:33
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition Expr.h:633
NormalizedConstraint Constraint
static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)
enum clang::FoldExpandedConstraint::FoldOperatorKind Kind
FoldExpandedConstraint(FoldOperatorKind K, NormalizedConstraint C, const Expr *Pattern)
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
Definition SemaConcept.h:68
llvm::PointerUnion< AtomicConstraint *, FoldExpandedConstraint *, CompoundConstraint > Constraint
Definition SemaConcept.h:78
NormalizedConstraint & getRHS() const
CompoundConstraintKind getCompoundKind() const
NormalizedConstraint(AtomicConstraint *C)
Definition SemaConcept.h:80
llvm::PointerIntPair< NormalizedConstraintPair *, 1, CompoundConstraintKind > CompoundConstraint
Definition SemaConcept.h:73
AtomicConstraint * getAtomicConstraint() const
FoldExpandedConstraint * getFoldExpandedConstraint() const
NormalizedConstraint & getLHS() const
A stack object to be created when performing template instantiation.
Definition Sema.h:13145
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition Sema.h:13305
static bool isEqual(const FoldingSetNodeID &LHS, const FoldingSetNodeID &RHS)
static unsigned getHashValue(const FoldingSetNodeID &Val)