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 {
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,
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
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
595 Sema::ArgPackSubstIndexRAII _(S, AC.ArgPackSubstIndex);
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
750 InstantiatingTemplate Inst(
751 *this, FD->getPointOfInstantiation(),
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,
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);
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
1363 S, cast<concepts::NestedRequirement>(Req), First);
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
1540 : Constraint{CompoundConstraint{
1541 new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
1542 Kind}} {}
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(
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 {
1619 S, CSE->getExprLoc(),
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();
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())
1668 Kind, std::move(*RHS), FE->getPattern()}};
1669 else
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;
1682 Kind, std::move(*Sub), FE->getPattern()}};
1683 }
1684
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.");
1852 return cast<AtomicConstraint *>(Constraint);
1853}
1854
1857 assert(isFoldExpanded() &&
1858 "getFoldExpandedConstraint called on non-fold-expanded constraint.");
1859 return cast<FoldExpandedConstraint *>(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
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;
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
2035 const NormalizedConstraint *PNormalized =
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.
StringRef P
const Decl * D
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
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)
SourceLocation Loc
Definition: SemaObjC.cpp:754
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__device__ int
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
Definition: ASTContext.h:1223
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2898
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.
Definition: ExprConcepts.h:42
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: ExprConcepts.h:145
ArrayRef< TemplateArgument > getTemplateArguments() const
Definition: ExprConcepts.h:81
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition: ExprConcepts.h:100
SourceLocation getConceptNameLoc() const
Definition: ExprConcepts.h:97
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
Definition: ExprConcepts.h:135
ConceptDecl * getNamedConcept() const
Definition: ExprConcepts.h:87
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,...
Definition: DeclBase.cpp:1392
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1358
DeclContext * getNonTransparentContext()
Definition: DeclBase.cpp:1450
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
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:427
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.
Definition: LangOptions.h:919
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_MemberSpecialization
Definition: Decl.h:2011
@ TK_DependentNonTemplate
Definition: Decl.h:2020
@ 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.
Definition: DeclTemplate.h:952
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
Definition: DeclTemplate.h:998
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:13496
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:12359
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition: Sema.h:12392
SourceLocation getLocation() const
Definition: Sema.h:12133
const DeclContext * getDeclContext() const
Definition: Sema.h:12129
const NamedDecl * getDecl() const
Definition: Sema.h:12121
const DeclContext * getLexicalDeclContext() const
Definition: Sema.h:12125
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.
Definition: SemaConcept.cpp:90
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)
Definition: SemaDecl.cpp:1347
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...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
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)
void runWithSufficientStackSpace(SourceLocation Loc, llvm::function_ref< void()> Fn)
Run some code with "sufficient" stack space.
Definition: Sema.cpp:627
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.
Definition: SemaConcept.h:146
llvm::function_ref< bool(const AtomicConstraint &, const AtomicConstraint &)> SubsumptionCallable
Definition: SemaConcept.h:149
std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)
SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})
A convenient class for passing around template argument information.
Definition: TemplateBase.h:634
ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:661
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:528
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.).
Definition: DeclTemplate.h:396
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.
Definition: DeclTemplate.h:415
Represents a C++ template name within the type system.
Definition: TemplateName.h:222
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:74
Declaration of a template type parameter.
Wrapper for template type parameters.
Definition: TypeLoc.h:890
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
Definition: ExprConcepts.h:343
A requires-expression requirement which queries the validity and properties of an expression ('simple...
Definition: ExprConcepts.h:282
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
Definition: ExprConcepts.h:411
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
Definition: ExprConcepts.h:406
const ReturnTypeRequirement & getReturnTypeRequirement() const
Definition: ExprConcepts.h:401
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:395
SourceLocation getNoexceptLoc() const
Definition: ExprConcepts.h:393
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
Definition: ExprConcepts.h:432
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
Definition: ExprConcepts.h:487
A static requirement that can be used in a requires-expression to check properties of types and expre...
Definition: ExprConcepts.h:170
A requires-expression requirement which queries the existence of a type name or type template special...
Definition: ExprConcepts.h:227
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:262
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:253
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.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ CPlusPlus11
Definition: LangStandard.h:56
@ CPlusPlus26
Definition: LangStandard.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.
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
Definition: SemaInternal.h:62
@ Template
We are parsing a template declaration.
ExprResult ExprError()
Definition: Ownership.h:265
@ Concept
The name was classified as a concept name.
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)
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:135
const FunctionProtoType * T
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ Other
Other implicit parameter.
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>".
Definition: TemplateBase.h:678
SourceLocation getLAngleLoc() const
Definition: TemplateBase.h:698
ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:707
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
Definition: TemplateBase.h:696
SourceLocation getRAngleLoc() const
Definition: TemplateBase.h:699
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
Definition: SemaConcept.h:129
static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)
enum clang::FoldExpandedConstraint::FoldOperatorKind Kind
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
llvm::PointerIntPair< NormalizedConstraintPair *, 1, CompoundConstraintKind > CompoundConstraint
Definition: SemaConcept.h:74
CompoundConstraintKind getCompoundKind() const
NormalizedConstraint(AtomicConstraint *C)
Definition: SemaConcept.h:80
AtomicConstraint * getAtomicConstraint() const
FoldExpandedConstraint * getFoldExpandedConstraint() const
NormalizedConstraint & getLHS() const
A stack object to be created when performing template instantiation.
Definition: Sema.h:13144
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition: Sema.h:13304
static bool isEqual(const FoldingSetNodeID &LHS, const FoldingSetNodeID &RHS)
static unsigned getHashValue(const FoldingSetNodeID &Val)