Thanks to visit codestin.com
Credit goes to clang.llvm.org

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"
16#include "clang/AST/ASTLambda.h"
17#include "clang/AST/DeclCXX.h"
23#include "clang/Sema/Overload.h"
25#include "clang/Sema/Sema.h"
27#include "clang/Sema/Template.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/PointerUnion.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/Support/SaveAndRestore.h"
33
34using namespace clang;
35using namespace sema;
36
37namespace {
38class LogicalBinOp {
39 SourceLocation Loc;
41 const Expr *LHS = nullptr;
42 const Expr *RHS = nullptr;
43
44public:
45 LogicalBinOp(const Expr *E) {
46 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
47 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
48 LHS = BO->getLHS();
49 RHS = BO->getRHS();
50 Loc = BO->getExprLoc();
51 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
52 // If OO is not || or && it might not have exactly 2 arguments.
53 if (OO->getNumArgs() == 2) {
54 Op = OO->getOperator();
55 LHS = OO->getArg(0);
56 RHS = OO->getArg(1);
57 Loc = OO->getOperatorLoc();
58 }
59 }
60 }
61
62 bool isAnd() const { return Op == OO_AmpAmp; }
63 bool isOr() const { return Op == OO_PipePipe; }
64 explicit operator bool() const { return isAnd() || isOr(); }
65
66 const Expr *getLHS() const { return LHS; }
67 const Expr *getRHS() const { return RHS; }
68 OverloadedOperatorKind getOp() const { return Op; }
69
70 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
71 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
72 }
73
74 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
75 ExprResult RHS) const {
76 assert((isAnd() || isOr()) && "Not the right kind of op?");
77 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
78
79 if (!LHS.isUsable() || !RHS.isUsable())
80 return ExprEmpty();
81
82 // We should just be able to 'normalize' these to the builtin Binary
83 // Operator, since that is how they are evaluated in constriant checks.
84 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
86 SemaRef.Context.BoolTy, VK_PRValue,
87 OK_Ordinary, Loc, FPOptionsOverride{});
88 }
89};
90} // namespace
91
92bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
93 Token NextToken, bool *PossibleNonPrimary,
94 bool IsTrailingRequiresClause) {
95 // C++2a [temp.constr.atomic]p1
96 // ..E shall be a constant expression of type bool.
97
98 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
99
100 if (LogicalBinOp BO = ConstraintExpression) {
101 return CheckConstraintExpression(BO.getLHS(), NextToken,
102 PossibleNonPrimary) &&
103 CheckConstraintExpression(BO.getRHS(), NextToken,
104 PossibleNonPrimary);
105 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
106 return CheckConstraintExpression(C->getSubExpr(), NextToken,
107 PossibleNonPrimary);
108
109 QualType Type = ConstraintExpression->getType();
110
111 auto CheckForNonPrimary = [&] {
112 if (!PossibleNonPrimary)
113 return;
114
115 *PossibleNonPrimary =
116 // We have the following case:
117 // template<typename> requires func(0) struct S { };
118 // The user probably isn't aware of the parentheses required around
119 // the function call, and we're only going to parse 'func' as the
120 // primary-expression, and complain that it is of non-bool type.
121 //
122 // However, if we're in a lambda, this might also be:
123 // []<typename> requires var () {};
124 // Which also looks like a function call due to the lambda parentheses,
125 // but unlike the first case, isn't an error, so this check is skipped.
126 (NextToken.is(tok::l_paren) &&
127 (IsTrailingRequiresClause ||
128 (Type->isDependentType() &&
129 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
130 !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
131 Type->isFunctionType() ||
132 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
133 // We have the following case:
134 // template<typename T> requires size_<T> == 0 struct S { };
135 // The user probably isn't aware of the parentheses required around
136 // the binary operator, and we're only going to parse 'func' as the
137 // first operand, and complain that it is of non-bool type.
138 getBinOpPrecedence(NextToken.getKind(),
139 /*GreaterThanIsOperator=*/true,
141 };
142
143 // An atomic constraint!
144 if (ConstraintExpression->isTypeDependent()) {
145 CheckForNonPrimary();
146 return true;
147 }
148
149 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
150 Diag(ConstraintExpression->getExprLoc(),
151 diag::err_non_bool_atomic_constraint)
152 << Type << ConstraintExpression->getSourceRange();
153 CheckForNonPrimary();
154 return false;
155 }
156
157 if (PossibleNonPrimary)
158 *PossibleNonPrimary = false;
159 return true;
160}
161
162namespace {
163struct SatisfactionStackRAII {
164 Sema &SemaRef;
165 bool Inserted = false;
166 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
167 const llvm::FoldingSetNodeID &FSNID)
168 : SemaRef(SemaRef) {
169 if (ND) {
170 SemaRef.PushSatisfactionStackEntry(ND, FSNID);
171 Inserted = true;
172 }
173 }
174 ~SatisfactionStackRAII() {
175 if (Inserted)
177 }
178};
179} // namespace
180
182 Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E,
183 const MultiLevelTemplateArgumentList *MLTAL = nullptr) {
184 E->Profile(ID, S.Context, /*Canonical=*/true);
185 if (MLTAL) {
186 for (const auto &List : *MLTAL)
187 for (const auto &TemplateArg : List.Args)
189 .Profile(ID, S.Context);
190 }
191 if (S.SatisfactionStackContains(Templ, ID)) {
192 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
193 << E << E->getSourceRange();
194 return true;
195 }
196 return false;
197}
198
199// Figure out the to-translation-unit depth for this function declaration for
200// the purpose of seeing if they differ by constraints. This isn't the same as
201// getTemplateDepth, because it includes already instantiated parents.
202static unsigned
204 bool SkipForSpecialization = false) {
206 ND, ND->getLexicalDeclContext(), /*Final=*/false,
207 /*Innermost=*/std::nullopt,
208 /*RelativeToPrimary=*/true,
209 /*Pattern=*/nullptr,
210 /*ForConstraintInstantiation=*/true, SkipForSpecialization);
211 return MLTAL.getNumLevels();
212}
213
214namespace {
215class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
216 unsigned TemplateDepth = 0;
217
218public:
219 using inherited = TreeTransform<AdjustConstraintDepth>;
220 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
221 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
222
223 using inherited::TransformTemplateTypeParmType;
224 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
225 TemplateTypeParmTypeLoc TL, bool) {
226 const TemplateTypeParmType *T = TL.getTypePtr();
227
228 TemplateTypeParmDecl *NewTTPDecl = nullptr;
229 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
230 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
231 TransformDecl(TL.getNameLoc(), OldTTPDecl));
232
233 QualType Result = getSema().Context.getTemplateTypeParmType(
234 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
235 NewTTPDecl);
236 TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
237 NewTL.setNameLoc(TL.getNameLoc());
238 return Result;
239 }
240
241 bool AlreadyTransformed(QualType T) {
242 if (T.isNull())
243 return true;
244
247 return false;
248 return true;
249 }
250};
251} // namespace
252
253namespace {
254
255// FIXME: Convert it to DynamicRecursiveASTVisitor
256class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
257 using inherited = RecursiveASTVisitor<HashParameterMapping>;
258 friend inherited;
259
260 Sema &SemaRef;
261 const MultiLevelTemplateArgumentList &TemplateArgs;
262 llvm::FoldingSetNodeID &ID;
263 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
264
265 UnsignedOrNone OuterPackSubstIndex;
266
267 bool shouldVisitTemplateInstantiations() const { return true; }
268
269public:
270 HashParameterMapping(Sema &SemaRef,
271 const MultiLevelTemplateArgumentList &TemplateArgs,
272 llvm::FoldingSetNodeID &ID,
273 UnsignedOrNone OuterPackSubstIndex)
274 : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),
275 OuterPackSubstIndex(OuterPackSubstIndex) {}
276
277 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
278 // A lambda expression can introduce template parameters that don't have
279 // corresponding template arguments yet.
280 if (T->getDepth() >= TemplateArgs.getNumLevels())
281 return true;
282
283 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
284
285 if (T->isParameterPack() && SemaRef.ArgPackSubstIndex) {
286 assert(Arg.getKind() == TemplateArgument::Pack &&
287 "Missing argument pack");
288
289 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
290 }
291
292 UsedTemplateArgs.push_back(
294 return true;
295 }
296
297 bool VisitDeclRefExpr(DeclRefExpr *E) {
298 NamedDecl *D = E->getDecl();
299 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
300 if (!NTTP)
301 return TraverseDecl(D);
302
303 TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
304 if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
305 assert(Arg.getKind() == TemplateArgument::Pack &&
306 "Missing argument pack");
307 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
308 }
309
310 UsedTemplateArgs.push_back(
312 return true;
313 }
314
315 bool VisitTypedefType(TypedefType *TT) {
316 return inherited::TraverseType(TT->desugar());
317 }
318
319 bool TraverseDecl(Decl *D) {
320 if (auto *VD = dyn_cast<ValueDecl>(D)) {
321 if (auto *Var = dyn_cast<VarDecl>(VD))
322 TraverseStmt(Var->getInit());
323 return TraverseType(VD->getType());
324 }
325
326 return inherited::TraverseDecl(D);
327 }
328
329 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
330 // We don't care about TypeLocs. So traverse Types instead.
331 return TraverseType(TL.getType(), TraverseQualifier);
332 }
333
334 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
335 // T's parent can be dependent while T doesn't have any template arguments.
336 // We should have already traversed its qualifier.
337 // FIXME: Add an assert to catch cases where we failed to profile the
338 // concept. assert(!T->isDependentType() && "We missed a case in profiling
339 // concepts!");
340 return true;
341 }
342
343 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
344 bool TraverseQualifier) {
345 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
346 }
347
348 bool TraverseTemplateArgument(const TemplateArgument &Arg) {
350 // Act as if we are fully expanding this pack, if it is a PackExpansion.
351 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
352 llvm::SaveAndRestore<UnsignedOrNone> _2(OuterPackSubstIndex,
353 std::nullopt);
354 return inherited::TraverseTemplateArgument(Arg);
355 }
356
357 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
358 return inherited::TraverseTemplateArgument(Arg);
359 }
360
361 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
362 return TraverseDecl(SOPE->getPack());
363 }
364
365 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
366 return inherited::TraverseStmt(E->getReplacement());
367 }
368
369 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
370 if (!Constraint.hasParameterMapping()) {
371 for (const auto &List : TemplateArgs)
372 for (const TemplateArgument &Arg : List.Args)
374 ID, SemaRef.Context);
375 return;
376 }
377
378 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
379 Constraint.getParameterMapping();
380 for (auto &ArgLoc : Mapping) {
381 TemplateArgument Canonical =
382 SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());
383 // We don't want sugars to impede the profile of cache.
384 UsedTemplateArgs.push_back(Canonical);
385 TraverseTemplateArgument(Canonical);
386 }
387
388 for (auto &Used : UsedTemplateArgs) {
389 llvm::FoldingSetNodeID R;
390 Used.Profile(R, SemaRef.Context);
391 ID.AddNodeID(R);
392 }
393 }
394};
395
396class ConstraintSatisfactionChecker {
397 Sema &S;
398 const NamedDecl *Template;
399 SourceLocation TemplateNameLoc;
400 UnsignedOrNone PackSubstitutionIndex;
401
402 ConstraintSatisfaction &Satisfaction;
403
404private:
406 EvaluateAtomicConstraint(const Expr *AtomicExpr,
407 const MultiLevelTemplateArgumentList &MLTAL);
408
409 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
410 const FoldExpandedConstraint &FE,
411 const MultiLevelTemplateArgumentList &MLTAL);
412
413 // XXX: It is SLOW! Use it very carefully.
414 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
415 const NormalizedConstraintWithParamMapping &Constraint,
416 MultiLevelTemplateArgumentList MLTAL,
417 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
418
419 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
420 const MultiLevelTemplateArgumentList &MLTAL);
421
422 ExprResult Evaluate(const AtomicConstraint &Constraint,
423 const MultiLevelTemplateArgumentList &MLTAL);
424
425 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
426 const MultiLevelTemplateArgumentList &MLTAL);
427
428 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
429 const MultiLevelTemplateArgumentList &MLTAL);
430
431 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
432 const MultiLevelTemplateArgumentList &MLTAL,
433 unsigned int Size);
434
435 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
436 const MultiLevelTemplateArgumentList &MLTAL);
437
438 ExprResult Evaluate(const CompoundConstraint &Constraint,
439 const MultiLevelTemplateArgumentList &MLTAL);
440
441public:
442 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
443 SourceLocation TemplateNameLoc,
444 UnsignedOrNone PackSubstitutionIndex,
445 ConstraintSatisfaction &Satisfaction)
446 : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),
447 PackSubstitutionIndex(PackSubstitutionIndex),
448 Satisfaction(Satisfaction) {}
449
450 ExprResult Evaluate(const NormalizedConstraint &Constraint,
451 const MultiLevelTemplateArgumentList &MLTAL);
452};
453
454StringRef allocateStringFromConceptDiagnostic(const Sema &S,
455 const PartialDiagnostic Diag) {
456 SmallString<128> DiagString;
457 DiagString = ": ";
458 Diag.EmitToString(S.getDiagnostics(), DiagString);
459 return S.getASTContext().backupStr(DiagString);
460}
461
462} // namespace
463
464ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
465 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
466 EnterExpressionEvaluationContext ConstantEvaluated(
469
470 llvm::FoldingSetNodeID ID;
471 if (Template &&
473 Satisfaction.IsSatisfied = false;
474 Satisfaction.ContainsErrors = true;
475 return ExprEmpty();
476 }
477 SatisfactionStackRAII StackRAII(S, Template, ID);
478
479 // Atomic constraint - substitute arguments and check satisfaction.
480 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
481 {
482 TemplateDeductionInfo Info(TemplateNameLoc);
486 // FIXME: improve const-correctness of InstantiatingTemplate
487 const_cast<NamedDecl *>(Template), Info, AtomicExpr->getSourceRange());
488 if (Inst.isInvalid())
489 return ExprError();
490
491 // We do not want error diagnostics escaping here.
492 Sema::SFINAETrap Trap(S);
493 SubstitutedExpression =
494 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
495
496 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
497 // C++2a [temp.constr.atomic]p1
498 // ...If substitution results in an invalid type or expression, the
499 // constraint is not satisfied.
500 if (!Trap.hasErrorOccurred())
501 // A non-SFINAE error has occurred as a result of this
502 // substitution.
503 return ExprError();
504
507 Info.takeSFINAEDiagnostic(SubstDiag);
508 // FIXME: This is an unfortunate consequence of there
509 // being no serialization code for PartialDiagnostics and the fact
510 // that serializing them would likely take a lot more storage than
511 // just storing them as strings. We would still like, in the
512 // future, to serialize the proper PartialDiagnostic as serializing
513 // it as a string defeats the purpose of the diagnostic mechanism.
514 Satisfaction.Details.emplace_back(
516 SubstDiag.first,
517 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
518 Satisfaction.IsSatisfied = false;
519 return ExprEmpty();
520 }
521 }
522
523 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
524 return ExprError();
525
526 // [temp.constr.atomic]p3: To determine if an atomic constraint is
527 // satisfied, the parameter mapping and template arguments are first
528 // substituted into its expression. If substitution results in an
529 // invalid type or expression, the constraint is not satisfied.
530 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
531 // and E shall be a constant expression of type bool.
532 //
533 // Perform the L to R Value conversion if necessary. We do so for all
534 // non-PRValue categories, else we fail to extend the lifetime of
535 // temporaries, and that fails the constant expression check.
536 if (!SubstitutedExpression.get()->isPRValue())
537 SubstitutedExpression = ImplicitCastExpr::Create(
538 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
539 SubstitutedExpression.get(),
540 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
541
542 return SubstitutedExpression;
543}
544
545std::optional<MultiLevelTemplateArgumentList>
546ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
547 const NormalizedConstraintWithParamMapping &Constraint,
549 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost) {
550
551 if (!Constraint.hasParameterMapping())
552 return std::move(MLTAL);
553
554 TemplateDeductionInfo Info(Constraint.getBeginLoc());
556 S, Constraint.getBeginLoc(),
558 // FIXME: improve const-correctness of InstantiatingTemplate
559 const_cast<NamedDecl *>(Template), Info, Constraint.getSourceRange());
560 if (Inst.isInvalid())
561 return std::nullopt;
562
563 Sema::SFINAETrap Trap(S);
564
565 TemplateArgumentListInfo SubstArgs;
567 S, Constraint.getPackSubstitutionIndex()
568 ? Constraint.getPackSubstitutionIndex()
569 : PackSubstitutionIndex);
570
572 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
573 SubstArgs, /*BuildPackExpansionTypes=*/true)) {
574 Satisfaction.IsSatisfied = false;
575 return std::nullopt;
576 }
577
579 auto *TD = const_cast<TemplateDecl *>(
582 TD->getLocation(), SubstArgs,
583 /*DefaultArguments=*/{},
584 /*PartialTemplateArgs=*/false, CTAI))
585 return std::nullopt;
587 Constraint.mappingOccurenceList();
588 SubstitutedOuterMost =
589 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
590 unsigned Offset = 0;
591 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
593 if (Used[I])
595 CTAI.SugaredConverted[MappedIndex++]);
596 if (I < SubstitutedOuterMost.size()) {
597 SubstitutedOuterMost[I] = Arg;
598 Offset = I + 1;
599 } else {
600 SubstitutedOuterMost.push_back(Arg);
601 Offset = SubstitutedOuterMost.size();
602 }
603 }
604 if (Offset < SubstitutedOuterMost.size())
605 SubstitutedOuterMost.erase(SubstitutedOuterMost.begin() + Offset);
606
608 const_cast<NamedDecl *>(Constraint.getConstraintDecl()),
609 SubstitutedOuterMost);
610 return std::move(MLTAL);
611}
612
613ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
614 const AtomicConstraint &Constraint,
615 const MultiLevelTemplateArgumentList &MLTAL) {
616
617 llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
618 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
619 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOuterMost);
620 if (!SubstitutedArgs) {
621 Satisfaction.IsSatisfied = false;
622 return ExprEmpty();
623 }
624
625 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
626 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
627 Constraint.getConstraintExpr(), *SubstitutedArgs);
628
629 if (SubstitutedAtomicExpr.isInvalid())
630 return ExprError();
631
632 if (SubstitutedAtomicExpr.isUnset())
633 // Evaluator has decided satisfaction without yielding an expression.
634 return ExprEmpty();
635
636 // We don't have the ability to evaluate this, since it contains a
637 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
638 // we'd potentially pick up a different overload, and cause confusing
639 // diagnostics. SO, add a failure detail that will cause us to make this
640 // overload set not viable.
641 if (SubstitutedAtomicExpr.get()->containsErrors()) {
642 Satisfaction.IsSatisfied = false;
643 Satisfaction.ContainsErrors = true;
644
645 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
646 Satisfaction.Details.emplace_back(
648 SubstitutedAtomicExpr.get()->getBeginLoc(),
649 allocateStringFromConceptDiagnostic(S, Msg)});
650 return SubstitutedAtomicExpr;
651 }
652
653 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
654 Satisfaction.IsSatisfied = true;
655 Satisfaction.ContainsErrors = false;
656 return SubstitutedAtomicExpr;
657 }
658
659 EnterExpressionEvaluationContext ConstantEvaluated(
662 Expr::EvalResult EvalResult;
663 EvalResult.Diag = &EvaluationDiags;
664 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
665 S.Context) ||
666 !EvaluationDiags.empty()) {
667 // C++2a [temp.constr.atomic]p1
668 // ...E shall be a constant expression of type bool.
669 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
670 diag::err_non_constant_constraint_expression)
671 << SubstitutedAtomicExpr.get()->getSourceRange();
672 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
673 S.Diag(PDiag.first, PDiag.second);
674 return ExprError();
675 }
676
677 assert(EvalResult.Val.isInt() &&
678 "evaluating bool expression didn't produce int");
679 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
680 if (!Satisfaction.IsSatisfied)
681 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
682
683 return SubstitutedAtomicExpr;
684}
685
686ExprResult ConstraintSatisfactionChecker::Evaluate(
687 const AtomicConstraint &Constraint,
688 const MultiLevelTemplateArgumentList &MLTAL) {
689
690 unsigned Size = Satisfaction.Details.size();
691 llvm::FoldingSetNodeID ID;
692 UnsignedOrNone OuterPackSubstIndex =
693 Constraint.getPackSubstitutionIndex()
694 ? Constraint.getPackSubstitutionIndex()
695 : PackSubstitutionIndex;
696
697 ID.AddPointer(Constraint.getConstraintExpr());
698 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
699 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
700 .VisitConstraint(Constraint);
701
702 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
704
705 auto &Cached = Iter->second.Satisfaction;
706 Satisfaction.ContainsErrors = Cached.ContainsErrors;
707 Satisfaction.IsSatisfied = Cached.IsSatisfied;
708 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
709 Cached.Details.begin(), Cached.Details.end());
710 return Iter->second.SubstExpr;
711 }
712
713 ExprResult E = EvaluateSlow(Constraint, MLTAL);
714
716 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
717 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
718 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
719 std::back_inserter(Cache.Satisfaction.Details));
720 Cache.SubstExpr = E;
721 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
722
723 return E;
724}
725
727ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
728 const FoldExpandedConstraint &FE,
729 const MultiLevelTemplateArgumentList &MLTAL) {
730
731 // We should ignore errors in the presence of packs of different size.
732 Sema::SFINAETrap Trap(S);
733
734 Expr *Pattern = const_cast<Expr *>(FE.getPattern());
735
737 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
738 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
739 bool Expand = true;
740 bool RetainExpansion = false;
741 UnsignedOrNone NumExpansions(std::nullopt);
743 Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
744 /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
745 NumExpansions) ||
746 !Expand || RetainExpansion)
747 return std::nullopt;
748
749 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) {
750 S.Diag(Pattern->getExprLoc(),
751 clang::diag::err_fold_expression_limit_exceeded)
752 << *NumExpansions << S.getLangOpts().BracketDepth
753 << Pattern->getSourceRange();
754 S.Diag(Pattern->getExprLoc(), diag::note_bracket_depth);
755 return std::nullopt;
756 }
757 return NumExpansions;
758}
759
760ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
761 const FoldExpandedConstraint &Constraint,
762 const MultiLevelTemplateArgumentList &MLTAL) {
763
764 bool Conjunction = Constraint.getFoldOperator() ==
766 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
767
768 llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
769 // FIXME: Is PackSubstitutionIndex correct?
770 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
771 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
772 SubstitutionInTemplateArguments(
773 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
774 MLTAL, SubstitutedOuterMost);
775 if (!SubstitutedArgs) {
776 Satisfaction.IsSatisfied = false;
777 return ExprError();
778 }
779
781 UnsignedOrNone NumExpansions =
782 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
783 if (!NumExpansions)
784 return ExprEmpty();
785
786 if (*NumExpansions == 0) {
787 Satisfaction.IsSatisfied = Conjunction;
788 return ExprEmpty();
789 }
790
791 for (unsigned I = 0; I < *NumExpansions; I++) {
792 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
793 Satisfaction.IsSatisfied = false;
794 Satisfaction.ContainsErrors = false;
796 ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,
797 UnsignedOrNone(I), Satisfaction)
798 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
799 if (Expr.isUsable()) {
800 if (Out.isUnset())
801 Out = Expr;
802 else
803 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
804 Conjunction ? BinaryOperatorKind::BO_LAnd
805 : BinaryOperatorKind::BO_LOr,
807 Constraint.getBeginLoc(),
809 } else {
810 assert(!Satisfaction.IsSatisfied);
811 }
812 if (!Conjunction && Satisfaction.IsSatisfied) {
813 Satisfaction.Details.erase(Satisfaction.Details.begin() +
814 EffectiveDetailEndIndex,
815 Satisfaction.Details.end());
816 break;
817 }
818 if (Satisfaction.IsSatisfied != Conjunction)
819 return Out;
820 }
821
822 return Out;
823}
824
825ExprResult ConstraintSatisfactionChecker::Evaluate(
826 const FoldExpandedConstraint &Constraint,
827 const MultiLevelTemplateArgumentList &MLTAL) {
828
829 llvm::FoldingSetNodeID ID;
830 ID.AddPointer(Constraint.getPattern());
831 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
832
833 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
835
836 auto &Cached = Iter->second.Satisfaction;
837 Satisfaction.ContainsErrors = Cached.ContainsErrors;
838 Satisfaction.IsSatisfied = Cached.IsSatisfied;
839 Satisfaction.Details.insert(Satisfaction.Details.end(),
840 Cached.Details.begin(), Cached.Details.end());
841 return Iter->second.SubstExpr;
842 }
843
844 unsigned Size = Satisfaction.Details.size();
845
846 ExprResult E = EvaluateSlow(Constraint, MLTAL);
848 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
849 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
850 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
851 std::back_inserter(Cache.Satisfaction.Details));
852 Cache.SubstExpr = E;
853 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
854 return E;
855}
856
857ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
858 const ConceptIdConstraint &Constraint,
859 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
860 const ConceptReference *ConceptId = Constraint.getConceptId();
861
862 llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
863 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
864 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOuterMost);
865
866 if (!SubstitutedArgs) {
867 Satisfaction.IsSatisfied = false;
868 // FIXME: diagnostics?
869 return ExprError();
870 }
871
872 Sema::SFINAETrap Trap(S);
874 S, Constraint.getPackSubstitutionIndex()
875 ? Constraint.getPackSubstitutionIndex()
876 : PackSubstitutionIndex);
877
878 const ASTTemplateArgumentListInfo *Ori =
879 ConceptId->getTemplateArgsAsWritten();
880 TemplateDeductionInfo Info(TemplateNameLoc);
883 const_cast<NamedDecl *>(Template), Info, Constraint.getSourceRange());
884
885 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
886 if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, OutArgs) ||
887 Trap.hasErrorOccurred()) {
888 Satisfaction.IsSatisfied = false;
889 if (!Trap.hasErrorOccurred())
890 return ExprError();
891
894 Info.takeSFINAEDiagnostic(SubstDiag);
895 // FIXME: This is an unfortunate consequence of there
896 // being no serialization code for PartialDiagnostics and the fact
897 // that serializing them would likely take a lot more storage than
898 // just storing them as strings. We would still like, in the
899 // future, to serialize the proper PartialDiagnostic as serializing
900 // it as a string defeats the purpose of the diagnostic mechanism.
901 Satisfaction.Details.insert(
902 Satisfaction.Details.begin() + Size,
904 SubstDiag.first,
905 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
906 return ExprError();
907 }
908
909 CXXScopeSpec SS;
910 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
911
912 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
913 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
914 ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs,
915 /*DoCheckConstraintSatisfaction=*/false);
916
917 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
918 return ExprError();
919
920 if (Size != Satisfaction.Details.size()) {
921 Satisfaction.Details.insert(
922 Satisfaction.Details.begin() + Size,
924 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
926 }
927 return SubstitutedConceptId;
928}
929
930ExprResult ConstraintSatisfactionChecker::Evaluate(
931 const ConceptIdConstraint &Constraint,
932 const MultiLevelTemplateArgumentList &MLTAL) {
933
934 const ConceptReference *ConceptId = Constraint.getConceptId();
935
936 UnsignedOrNone OuterPackSubstIndex =
937 Constraint.getPackSubstitutionIndex()
938 ? Constraint.getPackSubstitutionIndex()
939 : PackSubstitutionIndex;
940
943 ConceptId->getNamedConcept(),
944 MLTAL.getInnermost(),
945 Constraint.getSourceRange());
946
947 unsigned Size = Satisfaction.Details.size();
948
949 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
950
951 if (!E.isUsable()) {
952 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
953 return E;
954 }
955
956 // ConceptIdConstraint is only relevant for diagnostics,
957 // so if the normalized constraint is satisfied, we should not
958 // substitute into the constraint.
959 if (Satisfaction.IsSatisfied)
960 return E;
961
962 llvm::FoldingSetNodeID ID;
963 ID.AddPointer(Constraint.getConceptId());
964 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
965 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
966 .VisitConstraint(Constraint);
967
968 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
970
971 auto &Cached = Iter->second.Satisfaction;
972 Satisfaction.ContainsErrors = Cached.ContainsErrors;
973 Satisfaction.IsSatisfied = Cached.IsSatisfied;
974 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
975 Cached.Details.begin(), Cached.Details.end());
976 return Iter->second.SubstExpr;
977 }
978
979 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
980 if (CE.isInvalid())
981 return E;
983 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
984 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
985 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
986 std::back_inserter(Cache.Satisfaction.Details));
987 Cache.SubstExpr = CE;
988 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
989 return CE;
990}
991
992ExprResult ConstraintSatisfactionChecker::Evaluate(
993 const CompoundConstraint &Constraint,
994 const MultiLevelTemplateArgumentList &MLTAL) {
995
996 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
997
998 bool Conjunction =
1000
1001 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1002
1003 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1004 return LHS;
1005
1006 if (!Conjunction && LHS.isUsable() && Satisfaction.IsSatisfied &&
1007 !Satisfaction.ContainsErrors)
1008 return LHS;
1009
1010 Satisfaction.ContainsErrors = false;
1011 Satisfaction.IsSatisfied = false;
1012
1013 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1014
1015 if (RHS.isUsable() && Satisfaction.IsSatisfied &&
1016 !Satisfaction.ContainsErrors)
1017 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1018 EffectiveDetailEndIndex,
1019 Satisfaction.Details.end());
1020
1021 if (!LHS.isUsable())
1022 return RHS;
1023
1024 if (!RHS.isUsable())
1025 return LHS;
1026
1027 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1028 Conjunction ? BinaryOperatorKind::BO_LAnd
1029 : BinaryOperatorKind::BO_LOr,
1031 Constraint.getBeginLoc(), FPOptionsOverride{});
1032}
1033
1034ExprResult ConstraintSatisfactionChecker::Evaluate(
1035 const NormalizedConstraint &Constraint,
1036 const MultiLevelTemplateArgumentList &MLTAL) {
1037 switch (Constraint.getKind()) {
1039 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1040
1042 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1043 MLTAL);
1044
1046 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1047 MLTAL);
1048
1050 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1051 }
1052}
1053
1055 Sema &S, const NamedDecl *Template,
1056 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1057 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1058 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1059 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1060
1061 if (ConvertedExpr)
1062 *ConvertedExpr = nullptr;
1063
1064 if (AssociatedConstraints.empty()) {
1065 Satisfaction.IsSatisfied = true;
1066 return false;
1067 }
1068
1069 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1070 // No need to check satisfaction for dependent constraint expressions.
1071 Satisfaction.IsSatisfied = true;
1072 return false;
1073 }
1074
1076 if (TemplateArgsLists.getNumLevels() != 0)
1077 Args = TemplateArgsLists.getInnermost();
1078
1079 std::optional<Sema::InstantiatingTemplate> SynthesisContext;
1080 if (!TopLevelConceptId) {
1081 SynthesisContext.emplace(S, TemplateIDRange.getBegin(),
1083 const_cast<NamedDecl *>(Template), Args,
1084 TemplateIDRange);
1085 }
1086
1087 const NormalizedConstraint *C =
1088 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1089 if (!C) {
1090 Satisfaction.IsSatisfied = false;
1091 return true;
1092 }
1093
1094 if (TopLevelConceptId)
1095 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1096 const_cast<NormalizedConstraint *>(C),
1097 Template, /*CSE=*/nullptr,
1099
1100 ExprResult Res =
1101 ConstraintSatisfactionChecker(S, Template, TemplateIDRange.getBegin(),
1102 S.ArgPackSubstIndex, Satisfaction)
1103 .Evaluate(*C, TemplateArgsLists);
1104
1105 if (Res.isInvalid())
1106 return true;
1107
1108 if (Res.isUsable() && ConvertedExpr)
1109 *ConvertedExpr = Res.get();
1110
1111 return false;
1112}
1113
1116 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1117 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1118 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1119 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1120 if (AssociatedConstraints.empty()) {
1121 OutSatisfaction.IsSatisfied = true;
1122 return false;
1123 }
1124 const auto *Template = Entity.dyn_cast<const NamedDecl *>();
1125 if (!Template) {
1126 return ::CheckConstraintSatisfaction(
1127 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1128 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1129 }
1130 // Invalid templates could make their way here. Substituting them could result
1131 // in dependent expressions.
1132 if (Template->isInvalidDecl()) {
1133 OutSatisfaction.IsSatisfied = false;
1134 return true;
1135 }
1136
1137 // A list of the template argument list flattened in a predictible manner for
1138 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1139 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1140 // here.
1142 for (auto List : TemplateArgsLists)
1143 for (const TemplateArgument &Arg : List.Args)
1144 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1145
1146 const NamedDecl *Owner = Template;
1147 if (TopLevelConceptId)
1148 Owner = TopLevelConceptId->getNamedConcept();
1149
1150 llvm::FoldingSetNodeID ID;
1151 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1152 void *InsertPos;
1153 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1154 OutSatisfaction = *Cached;
1155 return false;
1156 }
1157
1158 auto Satisfaction =
1159 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1161 *this, Template, AssociatedConstraints, TemplateArgsLists,
1162 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1163 OutSatisfaction = std::move(*Satisfaction);
1164 return true;
1165 }
1166
1167 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1168 // The evaluation of this constraint resulted in us trying to re-evaluate it
1169 // recursively. This isn't really possible, except we try to form a
1170 // RecoveryExpr as a part of the evaluation. If this is the case, just
1171 // return the 'cached' version (which will have the same result), and save
1172 // ourselves the extra-insert. If it ever becomes possible to legitimately
1173 // recursively check a constraint, we should skip checking the 'inner' one
1174 // above, and replace the cached version with this one, as it would be more
1175 // specific.
1176 OutSatisfaction = *Cached;
1177 return false;
1178 }
1179
1180 // Else we can simply add this satisfaction to the list.
1181 OutSatisfaction = *Satisfaction;
1182 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
1183 // invalidated it.
1184 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1185 SatisfactionCache.InsertNode(Satisfaction.release());
1186 return false;
1187}
1188
1190 const ConceptSpecializationExpr *ConstraintExpr,
1191 ConstraintSatisfaction &Satisfaction) {
1192
1194 Constraints.emplace_back(
1195 ConstraintExpr->getNamedConcept()->getConstraintExpr());
1196
1197 MultiLevelTemplateArgumentList MLTAL(ConstraintExpr->getNamedConcept(),
1198 ConstraintExpr->getTemplateArguments(),
1199 true);
1200
1202 ConstraintExpr->getNamedConcept(), Constraints, MLTAL,
1203 ConstraintExpr->getSourceRange(), Satisfaction,
1204 ConstraintExpr->getConceptReference());
1205}
1206
1207bool Sema::SetupConstraintScope(
1208 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1209 const MultiLevelTemplateArgumentList &MLTAL,
1211 assert(!isLambdaCallOperator(FD) &&
1212 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1213 "instantiations");
1214 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1215 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1216 InstantiatingTemplate Inst(
1217 *this, FD->getPointOfInstantiation(),
1219 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1220 SourceRange());
1221 if (Inst.isInvalid())
1222 return true;
1223
1224 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1225 // 'instantiated' parameters and adds it to the context. For the case where
1226 // this function is a template being instantiated NOW, we also need to add
1227 // the list of current template arguments to the list so that they also can
1228 // be picked out of the map.
1229 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1230 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1231 /*Final=*/false);
1232 if (addInstantiatedParametersToScope(
1233 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1234 return true;
1235 }
1236
1237 // If this is a member function, make sure we get the parameters that
1238 // reference the original primary template.
1239 if (FunctionTemplateDecl *FromMemTempl =
1240 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1241 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1242 Scope, MLTAL))
1243 return true;
1244 }
1245
1246 return false;
1247 }
1248
1251 FunctionDecl *InstantiatedFrom =
1255
1257 *this, FD->getPointOfInstantiation(),
1258 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1259 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1260 SourceRange());
1261 if (Inst.isInvalid())
1262 return true;
1263
1264 // Case where this was not a template, but instantiated as a
1265 // child-function.
1266 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1267 return true;
1268 }
1269
1270 return false;
1271}
1272
1273// This function collects all of the template arguments for the purposes of
1274// constraint-instantiation and checking.
1275std::optional<MultiLevelTemplateArgumentList>
1276Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1277 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1279 MultiLevelTemplateArgumentList MLTAL;
1280
1281 // Collect the list of template arguments relative to the 'primary' template.
1282 // We need the entire list, since the constraint is completely uninstantiated
1283 // at this point.
1284 MLTAL =
1286 /*Final=*/false, /*Innermost=*/std::nullopt,
1287 /*RelativeToPrimary=*/true,
1288 /*Pattern=*/nullptr,
1289 /*ForConstraintInstantiation=*/true);
1290 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1291 if (isLambdaCallOperator(FD))
1292 return MLTAL;
1293 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1294 return std::nullopt;
1295
1296 return MLTAL;
1297}
1298
1300 ConstraintSatisfaction &Satisfaction,
1301 SourceLocation UsageLoc,
1302 bool ForOverloadResolution) {
1303 // Don't check constraints if the function is dependent. Also don't check if
1304 // this is a function template specialization, as the call to
1305 // CheckFunctionTemplateConstraints after this will check it
1306 // better.
1307 if (FD->isDependentContext() ||
1308 FD->getTemplatedKind() ==
1310 Satisfaction.IsSatisfied = true;
1311 return false;
1312 }
1313
1314 // A lambda conversion operator has the same constraints as the call operator
1315 // and constraints checking relies on whether we are in a lambda call operator
1316 // (and may refer to its parameters), so check the call operator instead.
1317 // Note that the declarations outside of the lambda should also be
1318 // considered. Turning on the 'ForOverloadResolution' flag results in the
1319 // LocalInstantiationScope not looking into its parents, but we can still
1320 // access Decls from the parents while building a lambda RAII scope later.
1321 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1322 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1323 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1324 Satisfaction, UsageLoc,
1325 /*ShouldAddDeclsFromParentScope=*/true);
1326
1327 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1328
1329 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1330 if (isLambdaCallOperator(CtxToSave))
1331 CtxToSave = CtxToSave->getParent()->getParent();
1332 else
1333 CtxToSave = CtxToSave->getNonTransparentContext();
1334 }
1335
1336 ContextRAII SavedContext{*this, CtxToSave};
1337 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1338 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1339 SetupConstraintCheckingTemplateArgumentsAndScope(
1340 const_cast<FunctionDecl *>(FD), {}, Scope);
1341
1342 if (!MLTAL)
1343 return true;
1344
1345 Qualifiers ThisQuals;
1346 CXXRecordDecl *Record = nullptr;
1347 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1348 ThisQuals = Method->getMethodQualifiers();
1349 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1350 }
1351 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1352
1354 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1355 ForOverloadResolution);
1356
1358 FD, FD->getTrailingRequiresClause(), *MLTAL,
1359 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1360 Satisfaction);
1361}
1362
1364 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
1365 const Expr *ConstrExpr) {
1367 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
1368 /*Innermost=*/std::nullopt,
1369 /*RelativeToPrimary=*/true,
1370 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
1371 /*SkipForSpecialization*/ false);
1372
1373 if (MLTAL.getNumSubstitutedLevels() == 0)
1374 return ConstrExpr;
1375
1376 Sema::SFINAETrap SFINAE(S);
1377
1379 S, DeclInfo.getLocation(),
1381 const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
1382 if (Inst.isInvalid())
1383 return nullptr;
1384
1385 // Set up a dummy 'instantiation' scope in the case of reference to function
1386 // parameters that the surrounding function hasn't been instantiated yet. Note
1387 // this may happen while we're comparing two templates' constraint
1388 // equivalence.
1389 std::optional<LocalInstantiationScope> ScopeForParameters;
1390 if (const NamedDecl *ND = DeclInfo.getDecl();
1391 ND && ND->isFunctionOrFunctionTemplate()) {
1392 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1393 const FunctionDecl *FD = ND->getAsFunction();
1395 Template && Template->getInstantiatedFromMemberTemplate())
1396 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1397 for (auto *PVD : FD->parameters()) {
1398 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1399 continue;
1400 if (!PVD->isParameterPack()) {
1401 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1402 continue;
1403 }
1404 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1405 // to avoid building SubstTemplateTypeParmPackTypes for
1406 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1407 // otherwise reference the AssociatedDecl of the template arguments, which
1408 // is, in this case, the template declaration.
1409 //
1410 // However, as we are in the process of comparing potential
1411 // re-declarations, the canonical declaration is the declaration itself at
1412 // this point. So if we didn't expand these packs, we would end up with an
1413 // incorrect profile difference because we will be profiling the
1414 // canonical types!
1415 //
1416 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1417 // that we can eliminate the Scope in the cases where the declarations are
1418 // not necessarily instantiated. It would also benefit the noexcept
1419 // specifier comparison.
1420 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1421 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1422 }
1423 }
1424
1425 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1426
1427 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1428 // essential for having an injected class as the canonical type for a template
1429 // specialization type at the rebuilding stage. This guarantees that, for
1430 // out-of-line definitions, injected class name types and their equivalent
1431 // template specializations can be profiled to the same value, which makes it
1432 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1433 // perceived identical.
1434 std::optional<Sema::ContextRAII> ContextScope;
1435 const DeclContext *DC = [&] {
1436 if (!DeclInfo.getDecl())
1437 return DeclInfo.getDeclContext();
1438 return DeclInfo.getDecl()->getFriendObjectKind()
1439 ? DeclInfo.getLexicalDeclContext()
1440 : DeclInfo.getDeclContext();
1441 }();
1442 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1443 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1444 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1445 /*NewThisContext=*/false);
1446 }
1447 EnterExpressionEvaluationContext UnevaluatedContext(
1451 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1452 if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
1453 return nullptr;
1454 return SubstConstr.get();
1455}
1456
1458 const Expr *OldConstr,
1460 const Expr *NewConstr) {
1461 if (OldConstr == NewConstr)
1462 return true;
1463 // C++ [temp.constr.decl]p4
1464 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1465 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1466 if (const Expr *SubstConstr =
1468 OldConstr))
1469 OldConstr = SubstConstr;
1470 else
1471 return false;
1472 if (const Expr *SubstConstr =
1474 NewConstr))
1475 NewConstr = SubstConstr;
1476 else
1477 return false;
1478 }
1479
1480 llvm::FoldingSetNodeID ID1, ID2;
1481 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1482 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1483 return ID1 == ID2;
1484}
1485
1487 assert(FD->getFriendObjectKind() && "Must be a friend!");
1488
1489 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1490 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1491 // non-function-template.
1492 assert(FD->getDescribedFunctionTemplate() &&
1493 "Non-function templates don't need to be checked");
1494
1497
1498 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1499 for (const AssociatedConstraint &AC : ACs)
1500 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1501 AC.ConstraintExpr))
1502 return true;
1503
1504 return false;
1505}
1506
1508 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1509 SourceRange TemplateIDRange) {
1510 ConstraintSatisfaction Satisfaction;
1511 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1512 TD->getAssociatedConstraints(AssociatedConstraints);
1513 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1514 TemplateIDRange, Satisfaction))
1515 return true;
1516
1517 if (!Satisfaction.IsSatisfied) {
1518 SmallString<128> TemplateArgString;
1519 TemplateArgString = " ";
1520 TemplateArgString += getTemplateArgumentBindingsText(
1521 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1522 TemplateArgsLists.getInnermost().size());
1523
1524 Diag(TemplateIDRange.getBegin(),
1525 diag::err_template_arg_list_constraints_not_satisfied)
1527 << TemplateArgString << TemplateIDRange;
1528 DiagnoseUnsatisfiedConstraint(Satisfaction);
1529 return true;
1530 }
1531 return false;
1532}
1533
1535 Sema &SemaRef, SourceLocation PointOfInstantiation,
1537 ConstraintSatisfaction &Satisfaction) {
1539 Template->getAssociatedConstraints(TemplateAC);
1540 if (TemplateAC.empty()) {
1541 Satisfaction.IsSatisfied = true;
1542 return false;
1543 }
1544
1546
1547 FunctionDecl *FD = Template->getTemplatedDecl();
1548 // Collect the list of template arguments relative to the 'primary'
1549 // template. We need the entire list, since the constraint is completely
1550 // uninstantiated at this point.
1551
1553 {
1554 // getTemplateInstantiationArgs uses this instantiation context to find out
1555 // template arguments for uninstantiated functions.
1556 // We don't want this RAII object to persist, because there would be
1557 // otherwise duplicate diagnostic notes.
1559 SemaRef, PointOfInstantiation,
1561 PointOfInstantiation);
1562 if (Inst.isInvalid())
1563 return true;
1564 MLTAL = SemaRef.getTemplateInstantiationArgs(
1565 /*D=*/FD, FD,
1566 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1567 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1568 }
1569
1570 Sema::ContextRAII SavedContext(SemaRef, FD);
1571 return SemaRef.CheckConstraintSatisfaction(
1572 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1573}
1574
1576 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1577 ArrayRef<TemplateArgument> TemplateArgs,
1578 ConstraintSatisfaction &Satisfaction) {
1579 // In most cases we're not going to have constraints, so check for that first.
1580 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1581
1582 if (!Template)
1583 return ::CheckFunctionConstraintsWithoutInstantiation(
1584 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1585 TemplateArgs, Satisfaction);
1586
1587 // Note - code synthesis context for the constraints check is created
1588 // inside CheckConstraintsSatisfaction.
1590 Template->getAssociatedConstraints(TemplateAC);
1591 if (TemplateAC.empty()) {
1592 Satisfaction.IsSatisfied = true;
1593 return false;
1594 }
1595
1596 // Enter the scope of this instantiation. We don't use
1597 // PushDeclContext because we don't have a scope.
1598 Sema::ContextRAII savedContext(*this, Decl);
1600
1601 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1602 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1603 Scope);
1604
1605 if (!MLTAL)
1606 return true;
1607
1608 Qualifiers ThisQuals;
1609 CXXRecordDecl *Record = nullptr;
1610 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1611 ThisQuals = Method->getMethodQualifiers();
1612 Record = Method->getParent();
1613 }
1614
1615 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1616 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1617 Scope);
1618
1619 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1620 PointOfInstantiation, Satisfaction);
1621}
1622
1625 bool First) {
1626 assert(!Req->isSatisfied() &&
1627 "Diagnose() can only be used on an unsatisfied requirement");
1628 switch (Req->getSatisfactionStatus()) {
1630 llvm_unreachable("Diagnosing a dependent requirement");
1631 break;
1633 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1634 if (!SubstDiag->DiagMessage.empty())
1635 S.Diag(SubstDiag->DiagLoc,
1636 diag::note_expr_requirement_expr_substitution_error)
1637 << (int)First << SubstDiag->SubstitutedEntity
1638 << SubstDiag->DiagMessage;
1639 else
1640 S.Diag(SubstDiag->DiagLoc,
1641 diag::note_expr_requirement_expr_unknown_substitution_error)
1642 << (int)First << SubstDiag->SubstitutedEntity;
1643 break;
1644 }
1646 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1647 << (int)First << Req->getExpr();
1648 break;
1650 auto *SubstDiag =
1652 if (!SubstDiag->DiagMessage.empty())
1653 S.Diag(SubstDiag->DiagLoc,
1654 diag::note_expr_requirement_type_requirement_substitution_error)
1655 << (int)First << SubstDiag->SubstitutedEntity
1656 << SubstDiag->DiagMessage;
1657 else
1658 S.Diag(
1659 SubstDiag->DiagLoc,
1660 diag::
1661 note_expr_requirement_type_requirement_unknown_substitution_error)
1662 << (int)First << SubstDiag->SubstitutedEntity;
1663 break;
1664 }
1666 ConceptSpecializationExpr *ConstraintExpr =
1668 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1669 break;
1670 }
1672 llvm_unreachable("We checked this above");
1673 }
1674}
1675
1678 bool First) {
1679 assert(!Req->isSatisfied() &&
1680 "Diagnose() can only be used on an unsatisfied requirement");
1681 switch (Req->getSatisfactionStatus()) {
1683 llvm_unreachable("Diagnosing a dependent requirement");
1684 return;
1686 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1687 if (!SubstDiag->DiagMessage.empty())
1688 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1689 << (int)First << SubstDiag->SubstitutedEntity
1690 << SubstDiag->DiagMessage;
1691 else
1692 S.Diag(SubstDiag->DiagLoc,
1693 diag::note_type_requirement_unknown_substitution_error)
1694 << (int)First << SubstDiag->SubstitutedEntity;
1695 return;
1696 }
1697 default:
1698 llvm_unreachable("Unknown satisfaction status");
1699 return;
1700 }
1701}
1702
1705 SourceLocation Loc, bool First) {
1706 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1707 S.Diag(
1708 Loc,
1709 diag::
1710 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1711 << (int)First
1712 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1713 << Concept->getNamedConcept();
1714 } else {
1715 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1716 << (int)First << Concept;
1717 }
1718}
1719
1722 bool First, concepts::NestedRequirement *Req = nullptr);
1723
1726 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1727 for (auto &Record : Records) {
1729 Loc = {};
1731 }
1732}
1733
1743
1745 const Expr *SubstExpr,
1746 bool First) {
1747 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1748 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1749 switch (BO->getOpcode()) {
1750 // These two cases will in practice only be reached when using fold
1751 // expressions with || and &&, since otherwise the || and && will have been
1752 // broken down into atomic constraints during satisfaction checking.
1753 case BO_LOr:
1754 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1757 /*First=*/false);
1758 return;
1759 case BO_LAnd: {
1760 bool LHSSatisfied =
1761 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1762 if (LHSSatisfied) {
1763 // LHS is true, so RHS must be false.
1765 return;
1766 }
1767 // LHS is false
1769
1770 // RHS might also be false
1771 bool RHSSatisfied =
1772 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1773 if (!RHSSatisfied)
1775 /*First=*/false);
1776 return;
1777 }
1778 case BO_GE:
1779 case BO_LE:
1780 case BO_GT:
1781 case BO_LT:
1782 case BO_EQ:
1783 case BO_NE:
1784 if (BO->getLHS()->getType()->isIntegerType() &&
1785 BO->getRHS()->getType()->isIntegerType()) {
1786 Expr::EvalResult SimplifiedLHS;
1787 Expr::EvalResult SimplifiedRHS;
1788 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1790 /*InConstantContext=*/true);
1791 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1793 /*InConstantContext=*/true);
1794 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1795 S.Diag(SubstExpr->getBeginLoc(),
1796 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1797 << (int)First << SubstExpr
1798 << toString(SimplifiedLHS.Val.getInt(), 10)
1799 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1800 << toString(SimplifiedRHS.Val.getInt(), 10);
1801 return;
1802 }
1803 }
1804 break;
1805
1806 default:
1807 break;
1808 }
1809 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1810 // FIXME: RequiresExpr should store dependent diagnostics.
1811 for (concepts::Requirement *Req : RE->getRequirements())
1812 if (!Req->isDependent() && !Req->isSatisfied()) {
1813 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1815 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1817 else
1820 break;
1821 }
1822 return;
1823 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1824 // Drill down concept ids treated as atomic constraints
1826 return;
1827 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1828 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1829 assert(TTE->getNumArgs() == 2);
1830 S.Diag(SubstExpr->getSourceRange().getBegin(),
1831 diag::note_is_deducible_constraint_evaluated_to_false)
1832 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1833 return;
1834 }
1835
1836 S.Diag(SubstExpr->getSourceRange().getBegin(),
1837 diag::note_atomic_constraint_evaluated_to_false)
1838 << (int)First << SubstExpr;
1839 S.DiagnoseTypeTraitDetails(SubstExpr);
1840}
1841
1845 if (auto *Diag =
1846 Record
1847 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1848 if (Req)
1849 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
1850 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
1851 else
1852 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1853 << Diag->second;
1854 return;
1855 }
1856 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
1857 if (Loc.isInvalid())
1858 Loc = Concept->getBeginLoc();
1860 return;
1861 }
1864}
1865
1867 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
1868 bool First) {
1869
1870 assert(!Satisfaction.IsSatisfied &&
1871 "Attempted to diagnose a satisfied constraint");
1872 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
1873}
1874
1876 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
1877
1878 const ASTConstraintSatisfaction &Satisfaction =
1879 ConstraintExpr->getSatisfaction();
1880
1881 assert(!Satisfaction.IsSatisfied &&
1882 "Attempted to diagnose a satisfied constraint");
1883
1884 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
1885 ConstraintExpr->getBeginLoc(), First);
1886}
1887
1888namespace {
1889
1890class SubstituteParameterMappings {
1891 Sema &SemaRef;
1892
1893 const MultiLevelTemplateArgumentList *MLTAL;
1894 const ASTTemplateArgumentListInfo *ArgsAsWritten;
1895
1896 bool InFoldExpr;
1897
1898 SubstituteParameterMappings(Sema &SemaRef,
1899 const MultiLevelTemplateArgumentList *MLTAL,
1900 const ASTTemplateArgumentListInfo *ArgsAsWritten,
1901 bool InFoldExpr)
1902 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
1903 InFoldExpr(InFoldExpr) {}
1904
1905 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
1906
1907 bool substitute(NormalizedConstraintWithParamMapping &N);
1908
1909 bool substitute(ConceptIdConstraint &CC);
1910
1911public:
1912 SubstituteParameterMappings(Sema &SemaRef, bool InFoldExpr = false)
1913 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
1914 InFoldExpr(InFoldExpr) {}
1915
1916 bool substitute(NormalizedConstraint &N);
1917};
1918
1919void SubstituteParameterMappings::buildParameterMapping(
1921 TemplateParameterList *TemplateParams =
1922 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
1923
1924 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1925 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
1926
1929 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
1930 /*OnlyDeduced=*/false,
1931 /*Depth=*/0, OccurringIndices);
1932
1934 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
1935 /*Depth=*/0, OccurringIndicesForSubsumption);
1936
1937 } else if (N.getKind() ==
1940 static_cast<FoldExpandedConstraint &>(N).getPattern(),
1941 /*OnlyDeduced=*/false,
1942 /*Depth=*/0, OccurringIndices);
1944 auto *Args = static_cast<ConceptIdConstraint &>(N)
1945 .getConceptId()
1946 ->getTemplateArgsAsWritten();
1947 if (Args)
1948 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
1949 /*Depth=*/0, OccurringIndices);
1950 }
1951 TemplateArgumentLoc *TempArgs =
1952 new (SemaRef.Context) TemplateArgumentLoc[OccurringIndices.count()];
1954 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
1955 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
1956 ? ArgsAsWritten->arguments()[I].getLocation()
1957 : SourceLocation();
1958 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
1959 // can't assert Loc.isValid() now.
1960 if (OccurringIndices[I]) {
1961 NamedDecl *Param = TemplateParams->begin()[I];
1962 new (&(TempArgs)[J]) TemplateArgumentLoc(
1963 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
1964 UsedParams.push_back(Param);
1965 J++;
1966 }
1967 }
1968 auto *UsedList = TemplateParameterList::Create(
1969 SemaRef.Context, TemplateParams->getTemplateLoc(),
1970 TemplateParams->getLAngleLoc(), UsedParams,
1971 /*RAngleLoc=*/SourceLocation(),
1972 /*RequiresClause=*/nullptr);
1973 unsigned Size = OccurringIndices.count();
1975 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
1976 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
1977}
1978
1979bool SubstituteParameterMappings::substitute(
1981 if (!N.hasParameterMapping())
1982 buildParameterMapping(N);
1983
1984 SourceLocation InstLocBegin, InstLocEnd;
1985 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
1986 if (Arguments.empty()) {
1987 InstLocBegin = ArgsAsWritten->getLAngleLoc();
1988 InstLocEnd = ArgsAsWritten->getRAngleLoc();
1989 } else {
1990 auto SR = Arguments[0].getSourceRange();
1991 InstLocBegin = SR.getBegin();
1992 InstLocEnd = SR.getEnd();
1993 }
1995 SemaRef, InstLocBegin,
1997 const_cast<NamedDecl *>(N.getConstraintDecl()),
1998 {InstLocBegin, InstLocEnd});
1999 if (Inst.isInvalid())
2000 return true;
2001
2002 // TransformTemplateArguments is unable to preserve the source location of a
2003 // pack. The SourceLocation is necessary for the instantiation location.
2004 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2005 // which is wrong.
2006 TemplateArgumentListInfo SubstArgs;
2008 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs,
2009 /*BuildPackExpansionTypes=*/!InFoldExpr))
2010 return true;
2012 auto *TD =
2015 TD->getLocation(), SubstArgs,
2016 /*DefaultArguments=*/{},
2017 /*PartialTemplateArgs=*/false, CTAI))
2018 return true;
2019
2020 TemplateArgumentLoc *TempArgs =
2021 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2022
2023 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2024 SourceLocation Loc;
2025 // If this is an empty pack, we have no corresponding SubstArgs.
2026 if (I < SubstArgs.size())
2027 Loc = SubstArgs.arguments()[I].getLocation();
2028
2029 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2030 CTAI.SugaredConverted[I], QualType(), Loc);
2031 }
2032
2033 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2034 CTAI.SugaredConverted.size());
2038 return false;
2039}
2040
2041bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2042 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2043
2044 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2045 return true;
2046
2047 auto *CSE = CC.getConceptSpecializationExpr();
2048 assert(CSE);
2049 assert(!CC.getBeginLoc().isInvalid());
2050
2051 SourceLocation InstLocBegin, InstLocEnd;
2052 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2053 Arguments.empty()) {
2054 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2055 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2056 } else {
2057 auto SR = Arguments[0].getSourceRange();
2058 InstLocBegin = SR.getBegin();
2059 InstLocEnd = SR.getEnd();
2060 }
2061 // This is useful for name lookup across modules; see Sema::getLookupModules.
2063 SemaRef, InstLocBegin,
2065 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2066 {InstLocBegin, InstLocEnd});
2067 if (Inst.isInvalid())
2068 return true;
2069
2071 // TransformTemplateArguments is unable to preserve the source location of a
2072 // pack. The SourceLocation is necessary for the instantiation location.
2073 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2074 // which is wrong.
2075 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2076 CSE->getTemplateArgsAsWritten();
2078 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out,
2079 /*BuildPackExpansionTypes=*/!InFoldExpr))
2080 return true;
2082 if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(),
2083 CSE->getConceptNameInfo().getLoc(), Out,
2084 /*DefaultArgs=*/{},
2085 /*PartialTemplateArgs=*/false, CTAI,
2086 /*UpdateArgsWithConversions=*/false))
2087 return true;
2088 auto TemplateArgs = *MLTAL;
2089 TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(),
2090 CTAI.SugaredConverted);
2091 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2092 InFoldExpr)
2093 .substitute(CC.getNormalizedConstraint());
2094}
2095
2096bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2097 switch (N.getKind()) {
2099 if (!MLTAL) {
2100 assert(!ArgsAsWritten);
2101 return false;
2102 }
2103 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2104 }
2106 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2107 if (!MLTAL) {
2108 llvm::SaveAndRestore _1(InFoldExpr, true);
2109 assert(!ArgsAsWritten);
2110 return substitute(FE.getNormalizedPattern());
2111 }
2112 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2113 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2114 return SubstituteParameterMappings(SemaRef, /*InFoldExpr=*/true)
2115 .substitute(FE.getNormalizedPattern());
2116 }
2118 auto &CC = static_cast<ConceptIdConstraint &>(N);
2119 if (MLTAL) {
2120 assert(ArgsAsWritten);
2121 return substitute(CC);
2122 }
2123 assert(!ArgsAsWritten);
2127 Concept, Concept->getLexicalDeclContext(),
2128 /*Final=*/true, CSE->getTemplateArguments(),
2129 /*RelativeToPrimary=*/true,
2130 /*Pattern=*/nullptr,
2131 /*ForConstraintInstantiation=*/true);
2132
2133 return SubstituteParameterMappings(
2134 SemaRef, &MLTAL, CSE->getTemplateArgsAsWritten(), InFoldExpr)
2135 .substitute(CC.getNormalizedConstraint());
2136 }
2138 auto &Compound = static_cast<CompoundConstraint &>(N);
2139 if (substitute(Compound.getLHS()))
2140 return true;
2141 return substitute(Compound.getRHS());
2142 }
2143 }
2144}
2145
2146} // namespace
2147
2148NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2149 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2150 assert(ACs.size() != 0);
2151 auto *Conjunction =
2152 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2153 if (!Conjunction)
2154 return nullptr;
2155 for (unsigned I = 1; I < ACs.size(); ++I) {
2156 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2157 ACs[I].ArgPackSubstIndex);
2158 if (!Next)
2159 return nullptr;
2161 Conjunction, Next);
2162 }
2163 return Conjunction;
2164}
2165
2166NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2167 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2168 assert(E != nullptr);
2169
2170 // C++ [temp.constr.normal]p1.1
2171 // [...]
2172 // - The normal form of an expression (E) is the normal form of E.
2173 // [...]
2174 E = E->IgnoreParenImpCasts();
2175
2176 llvm::FoldingSetNodeID ID;
2177 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2178 return nullptr;
2179 }
2180 SatisfactionStackRAII StackRAII(S, D, ID);
2181
2182 // C++2a [temp.param]p4:
2183 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2184 // Fold expression is considered atomic constraints per current wording.
2185 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2186
2187 if (LogicalBinOp BO = E) {
2188 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2189 if (!LHS)
2190 return nullptr;
2191 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2192 if (!RHS)
2193 return nullptr;
2194
2196 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2197 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2198 NormalizedConstraint *SubNF;
2199 {
2200 Sema::InstantiatingTemplate Inst(
2201 S, CSE->getExprLoc(),
2202 Sema::InstantiatingTemplate::ConstraintNormalization{},
2203 // FIXME: improve const-correctness of InstantiatingTemplate
2204 const_cast<NamedDecl *>(D), CSE->getSourceRange());
2205 if (Inst.isInvalid())
2206 return nullptr;
2207 // C++ [temp.constr.normal]p1.1
2208 // [...]
2209 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2210 // where C names a concept, is the normal form of the
2211 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2212 // respective template parameters in the parameter mappings in each atomic
2213 // constraint. If any such substitution results in an invalid type or
2214 // expression, the program is ill-formed; no diagnostic is required.
2215 // [...]
2216
2217 // Use canonical declarations to merge ConceptDecls across
2218 // different modules.
2219 ConceptDecl *CD = CSE->getNamedConcept()->getCanonicalDecl();
2220 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2221 S, CD, AssociatedConstraint(CD->getConstraintExpr(), SubstIndex));
2222
2223 if (!SubNF)
2224 return nullptr;
2225 }
2226
2228 CSE->getConceptReference(), SubNF, D,
2229 CSE, SubstIndex);
2230
2231 } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2232 FE && S.getLangOpts().CPlusPlus26 &&
2233 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2234 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2235
2236 // Normalize fold expressions in C++26.
2237
2239 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2242
2243 if (FE->getInit()) {
2244 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2245 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2246 if (!LHS || !RHS)
2247 return nullptr;
2248
2249 if (FE->isRightFold())
2251 FE->getPattern(), D, Kind, LHS);
2252 else
2254 FE->getPattern(), D, Kind, RHS);
2255
2257 S.getASTContext(), LHS,
2258 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2259 : CCK_Disjunction),
2260 RHS);
2261 }
2262 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2263 if (!Sub)
2264 return nullptr;
2266 D, Kind, Sub);
2267 }
2268 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2269}
2270
2272 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2273 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2274 if (!ConstrainedDeclOrNestedReq) {
2275 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2276 *this, nullptr, AssociatedConstraints);
2277 if (!Normalized ||
2278 SubstituteParameterMappings(*this).substitute(*Normalized))
2279 return nullptr;
2280
2281 return Normalized;
2282 }
2283
2284 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2285 const NamedDecl *ND =
2286 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2287 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2288 if (CacheEntry == NormalizationCache.end()) {
2289 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2290 *this, ND, AssociatedConstraints);
2291 CacheEntry =
2292 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2293 .first;
2294 if (!Normalized ||
2295 SubstituteParameterMappings(*this).substitute(*Normalized))
2296 return nullptr;
2297 }
2298 return CacheEntry->second;
2299}
2300
2303
2304 // [C++26] [temp.constr.fold]
2305 // Two fold expanded constraints are compatible for subsumption
2306 // if their respective constraints both contain an equivalent unexpanded pack.
2307
2310 APacks);
2312 BPacks);
2313
2314 for (const UnexpandedParameterPack &APack : APacks) {
2315 auto ADI = getDepthAndIndex(APack);
2316 if (!ADI)
2317 continue;
2318 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2319 return getDepthAndIndex(BPack) == ADI;
2320 });
2321 if (It != BPacks.end())
2322 return true;
2323 }
2324 return false;
2325}
2326
2329 const NamedDecl *D2,
2331 bool &Result) {
2332#ifndef NDEBUG
2333 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2334 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2336 return Kind == FunctionDecl::TK_NonTemplate ||
2338 };
2339 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2340 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2341 "use non-instantiated function declaration for constraints partial "
2342 "ordering");
2343 }
2344#endif
2345
2346 if (AC1.empty()) {
2347 Result = AC2.empty();
2348 return false;
2349 }
2350 if (AC2.empty()) {
2351 // TD1 has associated constraints and TD2 does not.
2352 Result = true;
2353 return false;
2354 }
2355
2356 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2357 auto CacheEntry = SubsumptionCache.find(Key);
2358 if (CacheEntry != SubsumptionCache.end()) {
2359 Result = CacheEntry->second;
2360 return false;
2361 }
2362
2363 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
2364 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
2365
2366 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2367 if (Depth2 > Depth1) {
2368 AC1[I].ConstraintExpr =
2369 AdjustConstraintDepth(*this, Depth2 - Depth1)
2370 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2371 .get();
2372 } else if (Depth1 > Depth2) {
2373 AC2[I].ConstraintExpr =
2374 AdjustConstraintDepth(*this, Depth1 - Depth2)
2375 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2376 .get();
2377 }
2378 }
2379
2380 SubsumptionChecker SC(*this);
2381 std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2);
2382 if (!Subsumes) {
2383 // Normalization failed
2384 return true;
2385 }
2386 Result = *Subsumes;
2387 SubsumptionCache.try_emplace(Key, *Subsumes);
2388 return false;
2389}
2390
2394 if (isSFINAEContext())
2395 // No need to work here because our notes would be discarded.
2396 return false;
2397
2398 if (AC1.empty() || AC2.empty())
2399 return false;
2400
2401 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2402 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2403 const AtomicConstraint &B) {
2405 return false;
2406 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2407 if (EA == EB)
2408 return true;
2409
2410 // Not the same source level expression - are the expressions
2411 // identical?
2412 llvm::FoldingSetNodeID IDA, IDB;
2413 EA->Profile(IDA, Context, /*Canonical=*/true);
2414 EB->Profile(IDB, Context, /*Canonical=*/true);
2415 if (IDA != IDB)
2416 return false;
2417
2418 AmbiguousAtomic1 = EA;
2419 AmbiguousAtomic2 = EB;
2420 return true;
2421 };
2422
2423 {
2424 // The subsumption checks might cause diagnostics
2425 SFINAETrap Trap(*this);
2426 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2427 if (!Normalized1)
2428 return false;
2429
2430 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2431 if (!Normalized2)
2432 return false;
2433
2434 SubsumptionChecker SC(*this);
2435
2436 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2437 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2438
2439 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2440 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2441 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2442
2443 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2444 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2445 // Same result - no ambiguity was caused by identical atomic expressions.
2446 return false;
2447 }
2448 // A different result! Some ambiguous atomic constraint(s) caused a difference
2449 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2450
2451 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2452 << AmbiguousAtomic1->getSourceRange();
2453 Diag(AmbiguousAtomic2->getBeginLoc(),
2454 diag::note_ambiguous_atomic_constraints_similar_expression)
2455 << AmbiguousAtomic2->getSourceRange();
2456 return true;
2457}
2458
2459//
2460//
2461// ------------------------ Subsumption -----------------------------------
2462//
2463//
2465 SubsumptionCallable Callable)
2466 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2467
2468uint16_t SubsumptionChecker::getNewLiteralId() {
2469 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2470 "too many constraints!");
2471 return NextID++;
2472}
2473
2474auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2475 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2476 // C++ [temp.constr.order] p2
2477 // - an atomic constraint A subsumes another atomic constraint B
2478 // if and only if the A and B are identical [...]
2479 //
2480 // C++ [temp.constr.atomic] p2
2481 // Two atomic constraints are identical if they are formed from the
2482 // same expression and the targets of the parameter mappings are
2483 // equivalent according to the rules for expressions [...]
2484
2485 // Because subsumption of atomic constraints is an identity
2486 // relationship that does not require further analysis
2487 // We cache the results such that if an atomic constraint literal
2488 // subsumes another, their literal will be the same
2489
2490 llvm::FoldingSetNodeID ID;
2491 ID.AddBoolean(Ori->hasParameterMapping());
2492 if (Ori->hasParameterMapping()) {
2493 const auto &Mapping = Ori->getParameterMapping();
2495 Ori->mappingOccurenceListForSubsumption();
2496 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2497 if (Indexes[Idx])
2498 SemaRef.getASTContext()
2499 .getCanonicalTemplateArgument(TAL.getArgument())
2500 .Profile(ID, SemaRef.getASTContext());
2501 }
2502 }
2503 auto It = Elems.find(ID);
2504 if (It == Elems.end()) {
2505 It = Elems
2506 .insert({ID,
2507 MappedAtomicConstraint{
2508 Ori, {getNewLiteralId(), Literal::Atomic}}})
2509 .first;
2510 ReverseMap[It->second.ID.Value] = Ori;
2511 }
2512 return It->getSecond().ID;
2513}
2514
2515auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2516 auto &Elems = FoldMap[Ori->getPattern()];
2517
2518 FoldExpendedConstraintKey K;
2519 K.Kind = Ori->getFoldOperator();
2520
2521 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2522 return K.Kind == Other.Kind;
2523 });
2524 if (It == Elems.end()) {
2525 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2526 It = Elems.insert(Elems.end(), std::move(K));
2527 ReverseMap[It->ID.Value] = Ori;
2528 }
2529 return It->ID;
2530}
2531
2532auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2533 return SubsumptionChecker::Normalize<CNFFormula>(C);
2534}
2535auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2536 return SubsumptionChecker::Normalize<DNFFormula>(C);
2537}
2538
2539///
2540/// \brief SubsumptionChecker::Normalize
2541///
2542/// Normalize a formula to Conjunctive Normal Form or
2543/// Disjunctive normal form.
2544///
2545/// Each Atomic (and Fold Expanded) constraint gets represented by
2546/// a single id to reduce space.
2547///
2548/// To minimize risks of exponential blow up, if two atomic
2549/// constraints subsumes each other (same constraint and mapping),
2550/// they are represented by the same literal.
2551///
2552template <typename FormulaType>
2553FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2554 FormulaType Res;
2555
2556 auto Add = [&, this](Clause C) {
2557 // Sort each clause and remove duplicates for faster comparisons.
2558 llvm::sort(C);
2559 C.erase(llvm::unique(C), C.end());
2560 AddUniqueClauseToFormula(Res, std::move(C));
2561 };
2562
2563 switch (NC.getKind()) {
2564
2566 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2567
2569 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2570
2572 return Normalize<FormulaType>(
2573 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2574
2576 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2577 FormulaType Left, Right;
2578 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2579 Left = Normalize<FormulaType>(Compound.getLHS());
2580 Right = Normalize<FormulaType>(Compound.getRHS());
2581 });
2582
2583 if (Compound.getCompoundKind() == FormulaType::Kind) {
2584 Res = std::move(Left);
2585 Res.reserve(Left.size() + Right.size());
2586 std::for_each(std::make_move_iterator(Right.begin()),
2587 std::make_move_iterator(Right.end()), Add);
2588 return Res;
2589 }
2590
2591 Res.reserve(Left.size() * Right.size());
2592 for (const auto &LTransform : Left) {
2593 for (const auto &RTransform : Right) {
2594 Clause Combined;
2595 Combined.reserve(LTransform.size() + RTransform.size());
2596 llvm::copy(LTransform, std::back_inserter(Combined));
2597 llvm::copy(RTransform, std::back_inserter(Combined));
2598 Add(std::move(Combined));
2599 }
2600 }
2601 return Res;
2602 }
2603 }
2604}
2605
2606void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2607 for (auto &Other : F) {
2608 if (llvm::equal(C, Other))
2609 return;
2610 }
2611 F.push_back(C);
2612}
2613
2615 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2617 const NormalizedConstraint *PNormalized =
2618 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2619 if (!PNormalized)
2620 return std::nullopt;
2621
2622 const NormalizedConstraint *QNormalized =
2623 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2624 if (!QNormalized)
2625 return std::nullopt;
2626
2627 return Subsumes(PNormalized, QNormalized);
2628}
2629
2631 const NormalizedConstraint *Q) {
2632
2633 DNFFormula DNFP = DNF(*P);
2634 CNFFormula CNFQ = CNF(*Q);
2635 return Subsumes(DNFP, CNFQ);
2636}
2637
2638bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2639 const CNFFormula &QCNF) {
2640 for (const auto &Pi : PDNF) {
2641 for (const auto &Qj : QCNF) {
2642 // C++ [temp.constr.order] p2
2643 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2644 // and only if there exists an atomic constraint Pia in Pi for which
2645 // there exists an atomic constraint, Qjb, in Qj such that Pia
2646 // subsumes Qjb.
2647 if (!DNFSubsumes(Pi, Qj))
2648 return false;
2649 }
2650 }
2651 return true;
2652}
2653
2654bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2655
2656 return llvm::any_of(P, [&](Literal LP) {
2657 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2658 });
2659}
2660
2662 const FoldExpandedConstraint *B) {
2663 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2664 A, B};
2665
2666 auto It = FoldSubsumptionCache.find(Key);
2667 if (It == FoldSubsumptionCache.end()) {
2668 // C++ [temp.constr.order]
2669 // a fold expanded constraint A subsumes another fold expanded
2670 // constraint B if they are compatible for subsumption, have the same
2671 // fold-operator, and the constraint of A subsumes that of B.
2672 bool DoesSubsume =
2673 A->getFoldOperator() == B->getFoldOperator() &&
2676 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2677 }
2678 return It->second;
2679}
2680
2681bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2682 if (A.Kind != B.Kind)
2683 return false;
2684 switch (A.Kind) {
2685 case Literal::Atomic:
2686 if (!Callable)
2687 return A.Value == B.Value;
2688 return Callable(
2689 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2690 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2691 case Literal::FoldExpanded:
2692 return Subsumes(
2693 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2694 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2695 }
2696 llvm_unreachable("unknown literal kind");
2697}
This file provides AST data structures related to concepts.
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E)
FormatToken * Next
The next token in the unwrapped line.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Records Records
Definition MachO.h:40
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 void diagnoseUnsatisfiedConstraintExpr(Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc, bool First, concepts::NestedRequirement *Req=nullptr)
static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)
static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, const Expr *SubstExpr, bool First)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList *MLTAL=nullptr)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId=nullptr)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)
static bool CheckFunctionConstraintsWithoutInstantiation(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
APSInt & getInt()
Definition APValue.h:489
bool isInt() const
Definition APValue.h:467
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
CanQualType BoolTy
llvm::StringRef backupStr(llvm::StringRef S) const
Definition ASTContext.h:854
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
const Expr * getConstraintExpr() const
static AtomicConstraint * Create(ASTContext &Ctx, const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6814
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:6945
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3972
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:4038
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:4979
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:2943
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:73
void Adopt(NestedNameSpecifierLoc Other)
Adopt an existing nested-name-specifier (with source-range information).
Definition DeclSpec.cpp:103
const NormalizedConstraint & getLHS() const
static CompoundConstraint * CreateConjunction(ASTContext &Ctx, NormalizedConstraint *LHS, NormalizedConstraint *RHS)
CompoundConstraintKind getCompoundKind() const
const NormalizedConstraint & getRHS() const
static CompoundConstraint * Create(ASTContext &Ctx, NormalizedConstraint *LHS, CompoundConstraintKind CCK, NormalizedConstraint *RHS)
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
ConceptDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
const NormalizedConstraint & getNormalizedConstraint() const
const ConceptSpecializationExpr * getConceptSpecializationExpr() const
static ConceptIdConstraint * Create(ASTContext &Ctx, const ConceptReference *ConceptId, NormalizedConstraint *SubConstraint, const NamedDecl *ConstraintDecl, const ConceptSpecializationExpr *CSE, UnsignedOrNone PackIndex)
const ConceptReference * getConceptId() const
A reference to a concept and its template args, as it appears in the code.
Definition ASTConcept.h:130
const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const
Definition ASTConcept.h:170
NamedDecl * getFoundDecl() const
Definition ASTConcept.h:197
const DeclarationNameInfo & getConceptNameInfo() const
Definition ASTConcept.h:174
SourceLocation getBeginLoc() const LLVM_READONLY
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition ASTConcept.h:203
TemplateDecl * getNamedConcept() const
Definition ASTConcept.h:201
SourceLocation getTemplateKWLoc() const
Definition ASTConcept.h:180
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getExprLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptReference * getConceptReference() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:47
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition ASTConcept.h:69
llvm::SmallVector< UnsatisfiedConstraintRecord, 4 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
Definition ASTConcept.h:67
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getNonTransparentContext()
ValueDecl * getDecl()
Definition Expr.h:1338
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
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition Decl.h:855
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 isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:177
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:3085
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.
static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)
FoldOperatorKind getFoldOperator() const
const Expr * getPattern() const
static FoldExpandedConstraint * Create(ASTContext &Ctx, const Expr *Pattern, const NamedDecl *ConstraintDecl, FoldOperatorKind OpKind, NormalizedConstraint *Constraint)
const NormalizedConstraint & getNormalizedPattern() const
Represents a function declaration or definition.
Definition Decl.h:2000
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4181
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4502
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition Decl.cpp:4301
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4317
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4245
TemplatedKind
The kind of templated function a FunctionDecl can be.
Definition Decl.h:2005
@ TK_FunctionTemplateSpecialization
Definition Decl.h:2016
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition Decl.cpp:4132
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4205
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4153
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
FunctionTemplateDecl * getInstantiatedFromMemberTemplate() const
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2068
const TypeClass * getTypePtr() const
Definition TypeLoc.h:531
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Definition Template.h:369
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:269
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
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
Definition Template.h:251
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
Definition Template.h:273
This represents a decl that may have a name.
Definition Decl.h:274
unsigned getPosition() const
Get the position of the template parameter within its parameter list.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getDepth() const
Get the nesting depth of the template parameter.
UnsignedOrNone getPackSubstitutionIndex() const
const NamedDecl * getConstraintDecl() const
bool hasMatchingParameterMapping(ASTContext &C, const NormalizedConstraint &Other) const
const OccurenceList & mappingOccurenceList() const
const OccurenceList & mappingOccurenceListForSubsumption() const
TemplateParameterList * getUsedTemplateParamList() const
llvm::MutableArrayRef< TemplateArgumentLoc > getParameterMapping() const
void updateParameterMapping(OccurenceList Indexes, OccurenceList IndexesForSubsumption, llvm::MutableArrayRef< TemplateArgumentLoc > Args, TemplateParameterList *ParamList)
A (possibly-)qualified type.
Definition TypeBase.h:937
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
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:13552
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8401
A RAII object to temporarily push a declaration context.
Definition Sema.h:3476
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition Sema.h:12392
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition Sema.h:12425
SourceLocation getLocation() const
Definition Sema.h:12166
const DeclContext * getDeclContext() const
Definition Sema.h:12162
const NamedDecl * getDecl() const
Definition Sema.h:12154
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12158
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, NamedDecl *TemplateParam=nullptr)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
llvm::DenseMap< llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult > UnsubstitutedConstraintSatisfactionCache
Cache the satisfaction of an atomic constraint.
Definition Sema.h:14888
ASTContext & Context
Definition Sema.h:1283
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
void MarkUsedTemplateParametersForSubsumptionParameterMapping(const Expr *E, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are named in a given expression.
DiagnosticsEngine & getDiagnostics() const
Definition Sema.h:922
void DiagnoseTypeTraitDetails(const Expr *E)
If E represents a built-in type trait, or a known standard type trait, try to print more information ...
ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
ASTContext & getASTContext() const
Definition Sema.h:925
ExprResult CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs, bool DoCheckConstraintSatisfaction=true)
llvm::PointerUnion< const NamedDecl *, const concepts::NestedRequirement * > ConstrainedDeclOrNestedRequirement
Definition Sema.h:14747
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool CheckConstraintSatisfaction(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, const ConceptReference *TopLevelConceptId=nullptr, Expr **ConvertedExpr=nullptr)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
const NormalizedConstraint * getNormalizedAssociatedConstraints(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints)
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:918
@ ReuseLambdaContextDecl
Definition Sema.h:6978
void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)
Collect the set of unexpanded parameter packs within the given template argument.
TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const
Definition Sema.h:11724
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1314
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...
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)
Check whether the given function decl's trailing requires clause is satisfied, if any.
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13546
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14707
void PopSatisfactionStackEntry()
Definition Sema.h:14713
ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
Definition Sema.h:6696
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6675
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition Sema.h:14715
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...
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)
bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes)
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...
bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions=true, bool *ConstraintsNotSatisfied=nullptr)
Check that the given template arguments can be provided to the given template, converting the argumen...
NamedDecl * getPack() const
Retrieve the parameter pack.
Definition ExprCXX.h:4511
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
SubsumptionChecker establishes subsumption between two set of constraints.
std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)
SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})
llvm::function_ref< bool( const AtomicConstraint &, const AtomicConstraint &)> SubsumptionCallable
A convenient class for passing around template argument information.
ArrayRef< TemplateArgumentLoc > arguments() const
Location wrapper for a TemplateArgument.
Represents a template argument.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
bool containsUnexpandedParameterPack() const
Whether this template argument contains an unexpanded parameter pack.
@ Pack
The template argument is actually a parameter pack.
ArgKind getKind() const
Return the kind of stored template argument.
bool isPackExpansion() const
Determine whether this template argument is a pack expansion.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< AssociatedConstraint > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Stores a list of template parameters for a TemplateDecl and its derived classes.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() const
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.
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition TypeLoc.h:133
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 isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2790
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8856
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2782
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2405
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2800
bool isFunctionType() const
Definition TypeBase.h:8527
QualType desugar() const
Definition Type.cpp:4041
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
A requires-expression requirement which queries the validity and properties of an expression ('simple...
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
const ReturnTypeRequirement & getReturnTypeRequirement() const
SatisfactionStatus getSatisfactionStatus() const
SourceLocation getNoexceptLoc() const
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
A static requirement that can be used in a requires-expression to check properties of types and expre...
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
Provides information about an attempted template argument deduction, whose success or failure was des...
#define bool
Definition gpuintrin.h:32
__inline void unsigned int _2
uint32_t Literal
Literals are represented as positive integers.
Definition CNFFormula.h:35
bool Sub(InterpState &S, CodePtr OpPC)
Definition Interp.h:425
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:398
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus11
@ CPlusPlus26
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
llvm::PointerUnion< const Expr *, const ConceptReference *, const ConstraintSubstitutionDiagnostic * > UnsatisfiedConstraintRecord
Definition ASTConcept.h:41
std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl *, const TemplateSpecializationType *, const SubstBuiltinTemplatePackType * >, SourceLocation > UnexpandedParameterPack
Definition Sema.h:236
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
ExprResult ExprEmpty()
Definition Ownership.h:272
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Result
The result type of a method or function.
Definition TypeBase.h:905
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
const FunctionProtoType * T
@ Template
We are parsing a template declaration.
Definition Parser.h:81
ExprResult ExprError()
Definition Ownership.h:265
@ Concept
The name was classified as a concept name.
Definition Sema.h:589
std::pair< SourceLocation, StringRef > ConstraintSubstitutionDiagnostic
Unsatisfied constraint expressions if the template arguments could be substituted into them,...
Definition ASTConcept.h:40
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
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1746
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:91
ArrayRef< UnsatisfiedConstraintRecord > records() const
Definition ASTConcept.h:104
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
SourceLocation RAngleLoc
The source location of the right angle bracket ('>').
SourceLocation LAngleLoc
The source location of the left angle bracket ('<').
ArrayRef< TemplateArgumentLoc > arguments() const
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
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
Definition SemaConcept.h:36
NormalizedConstraint(const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)
SourceRange getSourceRange() const
ConstraintKind getKind() const
SourceLocation getBeginLoc() const
llvm::SmallBitVector OccurenceList
Definition SemaConcept.h:51
SmallVector< TemplateArgument, 4 > SugaredConverted
The checked, converted argument will be added to the end of these vectors.
Definition Sema.h:11942
A stack object to be created when performing template instantiation.
Definition Sema.h:13197
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition Sema.h:13357
constexpr unsigned toInternalRepresentation() const