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#include "llvm/Support/TimeProfiler.h"
34
35using namespace clang;
36using namespace sema;
37
38namespace {
39class LogicalBinOp {
40 SourceLocation Loc;
42 const Expr *LHS = nullptr;
43 const Expr *RHS = nullptr;
44
45public:
46 LogicalBinOp(const Expr *E) {
47 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
48 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
49 LHS = BO->getLHS();
50 RHS = BO->getRHS();
51 Loc = BO->getExprLoc();
52 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
53 // If OO is not || or && it might not have exactly 2 arguments.
54 if (OO->getNumArgs() == 2) {
55 Op = OO->getOperator();
56 LHS = OO->getArg(0);
57 RHS = OO->getArg(1);
58 Loc = OO->getOperatorLoc();
59 }
60 }
61 }
62
63 bool isAnd() const { return Op == OO_AmpAmp; }
64 bool isOr() const { return Op == OO_PipePipe; }
65 explicit operator bool() const { return isAnd() || isOr(); }
66
67 const Expr *getLHS() const { return LHS; }
68 const Expr *getRHS() const { return RHS; }
69 OverloadedOperatorKind getOp() const { return Op; }
70
71 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
72 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
73 }
74
75 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
76 ExprResult RHS) const {
77 assert((isAnd() || isOr()) && "Not the right kind of op?");
78 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
79
80 if (!LHS.isUsable() || !RHS.isUsable())
81 return ExprEmpty();
82
83 // We should just be able to 'normalize' these to the builtin Binary
84 // Operator, since that is how they are evaluated in constriant checks.
85 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
87 SemaRef.Context.BoolTy, VK_PRValue,
88 OK_Ordinary, Loc, FPOptionsOverride{});
89 }
90};
91} // namespace
92
93bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
94 Token NextToken, bool *PossibleNonPrimary,
95 bool IsTrailingRequiresClause) {
96 // C++2a [temp.constr.atomic]p1
97 // ..E shall be a constant expression of type bool.
98
99 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
100
101 if (LogicalBinOp BO = ConstraintExpression) {
102 return CheckConstraintExpression(BO.getLHS(), NextToken,
103 PossibleNonPrimary) &&
104 CheckConstraintExpression(BO.getRHS(), NextToken,
105 PossibleNonPrimary);
106 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
107 return CheckConstraintExpression(C->getSubExpr(), NextToken,
108 PossibleNonPrimary);
109
110 QualType Type = ConstraintExpression->getType();
111
112 auto CheckForNonPrimary = [&] {
113 if (!PossibleNonPrimary)
114 return;
115
116 *PossibleNonPrimary =
117 // We have the following case:
118 // template<typename> requires func(0) struct S { };
119 // The user probably isn't aware of the parentheses required around
120 // the function call, and we're only going to parse 'func' as the
121 // primary-expression, and complain that it is of non-bool type.
122 //
123 // However, if we're in a lambda, this might also be:
124 // []<typename> requires var () {};
125 // Which also looks like a function call due to the lambda parentheses,
126 // but unlike the first case, isn't an error, so this check is skipped.
127 (NextToken.is(tok::l_paren) &&
128 (IsTrailingRequiresClause ||
129 (Type->isDependentType() &&
130 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
131 !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
132 Type->isFunctionType() ||
133 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
134 // We have the following case:
135 // template<typename T> requires size_<T> == 0 struct S { };
136 // The user probably isn't aware of the parentheses required around
137 // the binary operator, and we're only going to parse 'func' as the
138 // first operand, and complain that it is of non-bool type.
139 getBinOpPrecedence(NextToken.getKind(),
140 /*GreaterThanIsOperator=*/true,
142 };
143
144 // An atomic constraint!
145 if (ConstraintExpression->isTypeDependent()) {
146 CheckForNonPrimary();
147 return true;
148 }
149
150 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
151 Diag(ConstraintExpression->getExprLoc(),
152 diag::err_non_bool_atomic_constraint)
153 << Type << ConstraintExpression->getSourceRange();
154 CheckForNonPrimary();
155 return false;
156 }
157
158 if (PossibleNonPrimary)
159 *PossibleNonPrimary = false;
160 return true;
161}
162
163namespace {
164struct SatisfactionStackRAII {
165 Sema &SemaRef;
166 bool Inserted = false;
167 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
168 const llvm::FoldingSetNodeID &FSNID)
169 : SemaRef(SemaRef) {
170 if (ND) {
171 SemaRef.PushSatisfactionStackEntry(ND, FSNID);
172 Inserted = true;
173 }
174 }
175 ~SatisfactionStackRAII() {
176 if (Inserted)
178 }
179};
180} // namespace
181
183 Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E,
184 const MultiLevelTemplateArgumentList *MLTAL = nullptr) {
185 E->Profile(ID, S.Context, /*Canonical=*/true);
186 if (MLTAL) {
187 for (const auto &List : *MLTAL)
188 for (const auto &TemplateArg : List.Args)
190 .Profile(ID, S.Context);
191 }
192 if (S.SatisfactionStackContains(Templ, ID)) {
193 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
194 << E << E->getSourceRange();
195 return true;
196 }
197 return false;
198}
199
200// Figure out the to-translation-unit depth for this function declaration for
201// the purpose of seeing if they differ by constraints. This isn't the same as
202// getTemplateDepth, because it includes already instantiated parents.
203static unsigned
205 bool SkipForSpecialization = false) {
207 ND, ND->getLexicalDeclContext(), /*Final=*/false,
208 /*Innermost=*/std::nullopt,
209 /*RelativeToPrimary=*/true,
210 /*Pattern=*/nullptr,
211 /*ForConstraintInstantiation=*/true, SkipForSpecialization);
212 return MLTAL.getNumLevels();
213}
214
215namespace {
216class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
217 unsigned TemplateDepth = 0;
218
219public:
220 using inherited = TreeTransform<AdjustConstraintDepth>;
221 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
222 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
223
224 using inherited::TransformTemplateTypeParmType;
225 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
226 TemplateTypeParmTypeLoc TL, bool) {
227 const TemplateTypeParmType *T = TL.getTypePtr();
228
229 TemplateTypeParmDecl *NewTTPDecl = nullptr;
230 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
231 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
232 TransformDecl(TL.getNameLoc(), OldTTPDecl));
233
234 QualType Result = getSema().Context.getTemplateTypeParmType(
235 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
236 NewTTPDecl);
237 TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
238 NewTL.setNameLoc(TL.getNameLoc());
239 return Result;
240 }
241
242 bool AlreadyTransformed(QualType T) {
243 if (T.isNull())
244 return true;
245
248 return false;
249 return true;
250 }
251};
252} // namespace
253
254namespace {
255
256// FIXME: Convert it to DynamicRecursiveASTVisitor
257class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
258 using inherited = RecursiveASTVisitor<HashParameterMapping>;
259 friend inherited;
260
261 Sema &SemaRef;
262 const MultiLevelTemplateArgumentList &TemplateArgs;
263 llvm::FoldingSetNodeID &ID;
264 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
265
266 UnsignedOrNone OuterPackSubstIndex;
267
268 bool shouldVisitTemplateInstantiations() const { return true; }
269
270public:
271 HashParameterMapping(Sema &SemaRef,
272 const MultiLevelTemplateArgumentList &TemplateArgs,
273 llvm::FoldingSetNodeID &ID,
274 UnsignedOrNone OuterPackSubstIndex)
275 : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),
276 OuterPackSubstIndex(OuterPackSubstIndex) {}
277
278 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
279 // A lambda expression can introduce template parameters that don't have
280 // corresponding template arguments yet.
281 if (T->getDepth() >= TemplateArgs.getNumLevels())
282 return true;
283
284 // There might not be a corresponding template argument before substituting
285 // into the parameter mapping, e.g. a sizeof... expression.
286 if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
287 return true;
288
289 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
290
291 if (T->isParameterPack() && SemaRef.ArgPackSubstIndex) {
292 assert(Arg.getKind() == TemplateArgument::Pack &&
293 "Missing argument pack");
294
295 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
296 }
297
298 UsedTemplateArgs.push_back(
300 return true;
301 }
302
303 bool VisitDeclRefExpr(DeclRefExpr *E) {
304 NamedDecl *D = E->getDecl();
305 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
306 if (!NTTP)
307 return TraverseDecl(D);
308
309 if (NTTP->getDepth() >= TemplateArgs.getNumLevels())
310 return true;
311
312 if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), NTTP->getIndex()))
313 return true;
314
315 TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
316 if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
317 assert(Arg.getKind() == TemplateArgument::Pack &&
318 "Missing argument pack");
319 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
320 }
321
322 UsedTemplateArgs.push_back(
324 return true;
325 }
326
327 bool VisitTypedefType(TypedefType *TT) {
328 return inherited::TraverseType(TT->desugar());
329 }
330
331 bool TraverseDecl(Decl *D) {
332 if (auto *VD = dyn_cast<ValueDecl>(D)) {
333 if (auto *Var = dyn_cast<VarDecl>(VD))
334 TraverseStmt(Var->getInit());
335 return TraverseType(VD->getType());
336 }
337
338 return inherited::TraverseDecl(D);
339 }
340
341 bool TraverseCallExpr(CallExpr *CE) {
342 inherited::TraverseStmt(CE->getCallee());
343
344 for (Expr *Arg : CE->arguments())
345 inherited::TraverseStmt(Arg);
346
347 return true;
348 }
349
350 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
351 // We don't care about TypeLocs. So traverse Types instead.
352 return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);
353 }
354
355 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
356 // T's parent can be dependent while T doesn't have any template arguments.
357 // We should have already traversed its qualifier.
358 // FIXME: Add an assert to catch cases where we failed to profile the
359 // concept.
360 return true;
361 }
362
363 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
364 bool TraverseQualifier) {
365 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
366 }
367
368 bool TraverseTemplateArgument(const TemplateArgument &Arg) {
370 // Act as if we are fully expanding this pack, if it is a PackExpansion.
371 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
372 llvm::SaveAndRestore<UnsignedOrNone> _2(OuterPackSubstIndex,
373 std::nullopt);
374 return inherited::TraverseTemplateArgument(Arg);
375 }
376
377 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
378 return inherited::TraverseTemplateArgument(Arg);
379 }
380
381 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
382 return TraverseDecl(SOPE->getPack());
383 }
384
385 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
386 return inherited::TraverseStmt(E->getReplacement());
387 }
388
389 bool TraverseTemplateName(TemplateName Template) {
390 if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
391 Template.getAsTemplateDecl());
392 TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
393 if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
394 TTP->getPosition()))
395 return true;
396
397 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
398 if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
399 assert(Arg.getKind() == TemplateArgument::Pack &&
400 "Missing argument pack");
401 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
402 }
403 assert(!Arg.getAsTemplate().isNull() &&
404 "Null template template argument");
405 UsedTemplateArgs.push_back(
407 }
408 return inherited::TraverseTemplateName(Template);
409 }
410
411 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
412 if (!Constraint.hasParameterMapping()) {
413 for (const auto &List : TemplateArgs)
414 for (const TemplateArgument &Arg : List.Args)
416 ID, SemaRef.Context);
417 return;
418 }
419
420 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
421 Constraint.getParameterMapping();
422 for (auto &ArgLoc : Mapping) {
423 TemplateArgument Canonical =
424 SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());
425 // We don't want sugars to impede the profile of cache.
426 UsedTemplateArgs.push_back(Canonical);
427 TraverseTemplateArgument(Canonical);
428 }
429
430 for (auto &Used : UsedTemplateArgs) {
431 llvm::FoldingSetNodeID R;
432 Used.Profile(R, SemaRef.Context);
433 ID.AddNodeID(R);
434 }
435 }
436};
437
438class ConstraintSatisfactionChecker {
439 Sema &S;
440 const NamedDecl *Template;
441 SourceLocation TemplateNameLoc;
442 UnsignedOrNone PackSubstitutionIndex;
443 ConstraintSatisfaction &Satisfaction;
444 bool BuildExpression;
445
446private:
448 EvaluateAtomicConstraint(const Expr *AtomicExpr,
449 const MultiLevelTemplateArgumentList &MLTAL);
450
451 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
452 const FoldExpandedConstraint &FE,
453 const MultiLevelTemplateArgumentList &MLTAL);
454
455 // XXX: It is SLOW! Use it very carefully.
456 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
457 const NormalizedConstraintWithParamMapping &Constraint,
458 const MultiLevelTemplateArgumentList &MLTAL,
459 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
460
461 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
462 const MultiLevelTemplateArgumentList &MLTAL);
463
464 ExprResult Evaluate(const AtomicConstraint &Constraint,
465 const MultiLevelTemplateArgumentList &MLTAL);
466
467 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
468 const MultiLevelTemplateArgumentList &MLTAL);
469
470 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
471 const MultiLevelTemplateArgumentList &MLTAL);
472
473 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
474 const MultiLevelTemplateArgumentList &MLTAL,
475 unsigned int Size);
476
477 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
478 const MultiLevelTemplateArgumentList &MLTAL);
479
480 ExprResult Evaluate(const CompoundConstraint &Constraint,
481 const MultiLevelTemplateArgumentList &MLTAL);
482
483public:
484 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
485 SourceLocation TemplateNameLoc,
486 UnsignedOrNone PackSubstitutionIndex,
487 ConstraintSatisfaction &Satisfaction,
488 bool BuildExpression)
489 : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),
490 PackSubstitutionIndex(PackSubstitutionIndex),
491 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
492
493 ExprResult Evaluate(const NormalizedConstraint &Constraint,
494 const MultiLevelTemplateArgumentList &MLTAL);
495};
496
497StringRef allocateStringFromConceptDiagnostic(const Sema &S,
498 const PartialDiagnostic Diag) {
499 SmallString<128> DiagString;
500 DiagString = ": ";
501 Diag.EmitToString(S.getDiagnostics(), DiagString);
502 return S.getASTContext().backupStr(DiagString);
503}
504
505} // namespace
506
507ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
508 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
509 EnterExpressionEvaluationContext ConstantEvaluated(
512
513 llvm::FoldingSetNodeID ID;
514 if (Template &&
516 Satisfaction.IsSatisfied = false;
517 Satisfaction.ContainsErrors = true;
518 return ExprEmpty();
519 }
520 SatisfactionStackRAII StackRAII(S, Template, ID);
521
522 // Atomic constraint - substitute arguments and check satisfaction.
523 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
524 {
525 TemplateDeductionInfo Info(TemplateNameLoc);
529 // FIXME: improve const-correctness of InstantiatingTemplate
530 const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());
531 if (Inst.isInvalid())
532 return ExprError();
533
534 // We do not want error diagnostics escaping here.
535 Sema::SFINAETrap Trap(S, Info);
536 SubstitutedExpression =
537 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
538
539 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
540 // C++2a [temp.constr.atomic]p1
541 // ...If substitution results in an invalid type or expression, the
542 // constraint is not satisfied.
543 if (!Trap.hasErrorOccurred())
544 // A non-SFINAE error has occurred as a result of this
545 // substitution.
546 return ExprError();
547
550 Info.takeSFINAEDiagnostic(SubstDiag);
551 // FIXME: This is an unfortunate consequence of there
552 // being no serialization code for PartialDiagnostics and the fact
553 // that serializing them would likely take a lot more storage than
554 // just storing them as strings. We would still like, in the
555 // future, to serialize the proper PartialDiagnostic as serializing
556 // it as a string defeats the purpose of the diagnostic mechanism.
557 Satisfaction.Details.emplace_back(
559 SubstDiag.first,
560 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
561 Satisfaction.IsSatisfied = false;
562 return ExprEmpty();
563 }
564 }
565
566 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
567 return ExprError();
568
569 // [temp.constr.atomic]p3: To determine if an atomic constraint is
570 // satisfied, the parameter mapping and template arguments are first
571 // substituted into its expression. If substitution results in an
572 // invalid type or expression, the constraint is not satisfied.
573 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
574 // and E shall be a constant expression of type bool.
575 //
576 // Perform the L to R Value conversion if necessary. We do so for all
577 // non-PRValue categories, else we fail to extend the lifetime of
578 // temporaries, and that fails the constant expression check.
579 if (!SubstitutedExpression.get()->isPRValue())
580 SubstitutedExpression = ImplicitCastExpr::Create(
581 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
582 SubstitutedExpression.get(),
583 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
584
585 return SubstitutedExpression;
586}
587
588std::optional<MultiLevelTemplateArgumentList>
589ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
590 const NormalizedConstraintWithParamMapping &Constraint,
592 llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {
593
594 if (!Constraint.hasParameterMapping())
595 return std::move(MLTAL);
596
597 // The mapping is empty, meaning no template arguments are needed for
598 // evaluation.
599 if (Constraint.getParameterMapping().empty())
601
602 TemplateDeductionInfo Info(Constraint.getBeginLoc());
603 Sema::SFINAETrap Trap(S, Info);
605 S, Constraint.getBeginLoc(),
607 // FIXME: improve const-correctness of InstantiatingTemplate
608 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
609 if (Inst.isInvalid())
610 return std::nullopt;
611
612 TemplateArgumentListInfo SubstArgs;
614 S, Constraint.getPackSubstitutionIndex()
615 ? Constraint.getPackSubstitutionIndex()
616 : PackSubstitutionIndex);
617
619 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
620 SubstArgs, /*BuildPackExpansionTypes=*/true)) {
621 Satisfaction.IsSatisfied = false;
622 return std::nullopt;
623 }
624
626 auto *TD = const_cast<TemplateDecl *>(
629 TD->getLocation(), SubstArgs,
630 /*DefaultArguments=*/{},
631 /*PartialTemplateArgs=*/false, CTAI))
632 return std::nullopt;
634 Constraint.mappingOccurenceList();
635 // The empty MLTAL situation should only occur when evaluating non-dependent
636 // constraints.
637 if (MLTAL.getNumSubstitutedLevels())
638 SubstitutedOutermost =
639 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
640 unsigned Offset = 0;
641 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
643 if (Used[I])
645 CTAI.SugaredConverted[MappedIndex++]);
646 if (I < SubstitutedOutermost.size()) {
647 SubstitutedOutermost[I] = Arg;
648 Offset = I + 1;
649 } else {
650 SubstitutedOutermost.push_back(Arg);
651 Offset = SubstitutedOutermost.size();
652 }
653 }
654 if (Offset < SubstitutedOutermost.size())
655 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
656
657 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
658 SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,
659 /*Final=*/false);
660 return std::move(SubstitutedTemplateArgs);
661}
662
663ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
664 const AtomicConstraint &Constraint,
665 const MultiLevelTemplateArgumentList &MLTAL) {
666
667 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
668 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
669 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
670 if (!SubstitutedArgs) {
671 Satisfaction.IsSatisfied = false;
672 return ExprEmpty();
673 }
674
675 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
676 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
677 Constraint.getConstraintExpr(), *SubstitutedArgs);
678
679 if (SubstitutedAtomicExpr.isInvalid())
680 return ExprError();
681
682 if (SubstitutedAtomicExpr.isUnset())
683 // Evaluator has decided satisfaction without yielding an expression.
684 return ExprEmpty();
685
686 // We don't have the ability to evaluate this, since it contains a
687 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
688 // we'd potentially pick up a different overload, and cause confusing
689 // diagnostics. SO, add a failure detail that will cause us to make this
690 // overload set not viable.
691 if (SubstitutedAtomicExpr.get()->containsErrors()) {
692 Satisfaction.IsSatisfied = false;
693 Satisfaction.ContainsErrors = true;
694
695 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
696 Satisfaction.Details.emplace_back(
698 SubstitutedAtomicExpr.get()->getBeginLoc(),
699 allocateStringFromConceptDiagnostic(S, Msg)});
700 return SubstitutedAtomicExpr;
701 }
702
703 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
704 Satisfaction.IsSatisfied = true;
705 Satisfaction.ContainsErrors = false;
706 return SubstitutedAtomicExpr;
707 }
708
709 EnterExpressionEvaluationContext ConstantEvaluated(
712 Expr::EvalResult EvalResult;
713 EvalResult.Diag = &EvaluationDiags;
714 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
715 S.Context) ||
716 !EvaluationDiags.empty()) {
717 // C++2a [temp.constr.atomic]p1
718 // ...E shall be a constant expression of type bool.
719 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
720 diag::err_non_constant_constraint_expression)
721 << SubstitutedAtomicExpr.get()->getSourceRange();
722 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
723 S.Diag(PDiag.first, PDiag.second);
724 return ExprError();
725 }
726
727 assert(EvalResult.Val.isInt() &&
728 "evaluating bool expression didn't produce int");
729 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
730 if (!Satisfaction.IsSatisfied)
731 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
732
733 return SubstitutedAtomicExpr;
734}
735
736ExprResult ConstraintSatisfactionChecker::Evaluate(
737 const AtomicConstraint &Constraint,
738 const MultiLevelTemplateArgumentList &MLTAL) {
739
740 unsigned Size = Satisfaction.Details.size();
741 llvm::FoldingSetNodeID ID;
742 UnsignedOrNone OuterPackSubstIndex =
743 Constraint.getPackSubstitutionIndex()
744 ? Constraint.getPackSubstitutionIndex()
745 : PackSubstitutionIndex;
746
747 ID.AddPointer(Constraint.getConstraintExpr());
748 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
749 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
750 .VisitConstraint(Constraint);
751
752 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
754 auto &Cached = Iter->second.Satisfaction;
755 Satisfaction.ContainsErrors = Cached.ContainsErrors;
756 Satisfaction.IsSatisfied = Cached.IsSatisfied;
757 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
758 Cached.Details.begin(), Cached.Details.end());
759 return Iter->second.SubstExpr;
760 }
761
762 ExprResult E = EvaluateSlow(Constraint, MLTAL);
763
765 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
766 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
767 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
768 Satisfaction.Details.begin() + Size,
769 Satisfaction.Details.end());
770 Cache.SubstExpr = E;
771 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
772
773 return E;
774}
775
777ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
778 const FoldExpandedConstraint &FE,
779 const MultiLevelTemplateArgumentList &MLTAL) {
780
781 Expr *Pattern = const_cast<Expr *>(FE.getPattern());
782
784 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
785 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
786 bool Expand = true;
787 bool RetainExpansion = false;
788 UnsignedOrNone NumExpansions(std::nullopt);
790 Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
791 /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
792 NumExpansions, /*Diagnose=*/false) ||
793 !Expand || RetainExpansion)
794 return std::nullopt;
795
796 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)
797 return std::nullopt;
798 return NumExpansions;
799}
800
801ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
802 const FoldExpandedConstraint &Constraint,
803 const MultiLevelTemplateArgumentList &MLTAL) {
804
805 bool Conjunction = Constraint.getFoldOperator() ==
807 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
808
809 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
810 // FIXME: Is PackSubstitutionIndex correct?
811 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
812 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
813 SubstitutionInTemplateArguments(
814 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
815 MLTAL, SubstitutedOutermost);
816 if (!SubstitutedArgs) {
817 Satisfaction.IsSatisfied = false;
818 return ExprError();
819 }
820
822 UnsignedOrNone NumExpansions =
823 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
824 if (!NumExpansions)
825 return ExprEmpty();
826
827 if (*NumExpansions == 0) {
828 Satisfaction.IsSatisfied = Conjunction;
829 return ExprEmpty();
830 }
831
832 for (unsigned I = 0; I < *NumExpansions; I++) {
833 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
834 Satisfaction.IsSatisfied = false;
835 Satisfaction.ContainsErrors = false;
837 ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,
838 UnsignedOrNone(I), Satisfaction,
839 /*BuildExpression=*/false)
840 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
841 if (BuildExpression && Expr.isUsable()) {
842 if (Out.isUnset())
843 Out = Expr;
844 else
845 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
846 Conjunction ? BinaryOperatorKind::BO_LAnd
847 : BinaryOperatorKind::BO_LOr,
849 Constraint.getBeginLoc(),
851 } else {
852 assert(!BuildExpression || !Satisfaction.IsSatisfied);
853 }
854 if (!Conjunction && Satisfaction.IsSatisfied) {
855 Satisfaction.Details.erase(Satisfaction.Details.begin() +
856 EffectiveDetailEndIndex,
857 Satisfaction.Details.end());
858 break;
859 }
860 if (Satisfaction.IsSatisfied != Conjunction)
861 return Out;
862 }
863
864 return Out;
865}
866
867ExprResult ConstraintSatisfactionChecker::Evaluate(
868 const FoldExpandedConstraint &Constraint,
869 const MultiLevelTemplateArgumentList &MLTAL) {
870
871 llvm::FoldingSetNodeID ID;
872 ID.AddPointer(Constraint.getPattern());
873 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
874
875 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
877
878 auto &Cached = Iter->second.Satisfaction;
879 Satisfaction.ContainsErrors = Cached.ContainsErrors;
880 Satisfaction.IsSatisfied = Cached.IsSatisfied;
881 Satisfaction.Details.insert(Satisfaction.Details.end(),
882 Cached.Details.begin(), Cached.Details.end());
883 return Iter->second.SubstExpr;
884 }
885
886 unsigned Size = Satisfaction.Details.size();
887
888 ExprResult E = EvaluateSlow(Constraint, MLTAL);
890 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
891 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
892 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
893 Satisfaction.Details.begin() + Size,
894 Satisfaction.Details.end());
895 Cache.SubstExpr = E;
896 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
897 return E;
898}
899
900ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
901 const ConceptIdConstraint &Constraint,
902 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
903 const ConceptReference *ConceptId = Constraint.getConceptId();
904
905 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
906 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
907 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
908
909 if (!SubstitutedArgs) {
910 Satisfaction.IsSatisfied = false;
911 // FIXME: diagnostics?
912 return ExprError();
913 }
914
916 S, Constraint.getPackSubstitutionIndex()
917 ? Constraint.getPackSubstitutionIndex()
918 : PackSubstitutionIndex);
919
920 const ASTTemplateArgumentListInfo *Ori =
921 ConceptId->getTemplateArgsAsWritten();
922 TemplateDeductionInfo Info(TemplateNameLoc);
923 Sema::SFINAETrap Trap(S, Info);
926 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
927
928 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
929 if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, OutArgs) ||
930 Trap.hasErrorOccurred()) {
931 Satisfaction.IsSatisfied = false;
932 if (!Trap.hasErrorOccurred())
933 return ExprError();
934
937 Info.takeSFINAEDiagnostic(SubstDiag);
938 // FIXME: This is an unfortunate consequence of there
939 // being no serialization code for PartialDiagnostics and the fact
940 // that serializing them would likely take a lot more storage than
941 // just storing them as strings. We would still like, in the
942 // future, to serialize the proper PartialDiagnostic as serializing
943 // it as a string defeats the purpose of the diagnostic mechanism.
944 Satisfaction.Details.insert(
945 Satisfaction.Details.begin() + Size,
947 SubstDiag.first,
948 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
949 return ExprError();
950 }
951
952 CXXScopeSpec SS;
953 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
954
955 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
956 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
957 ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs,
958 /*DoCheckConstraintSatisfaction=*/false);
959
960 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
961 return ExprError();
962
963 if (Size != Satisfaction.Details.size()) {
964 Satisfaction.Details.insert(
965 Satisfaction.Details.begin() + Size,
967 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
969 }
970 return SubstitutedConceptId;
971}
972
973ExprResult ConstraintSatisfactionChecker::Evaluate(
974 const ConceptIdConstraint &Constraint,
975 const MultiLevelTemplateArgumentList &MLTAL) {
976
977 const ConceptReference *ConceptId = Constraint.getConceptId();
978
979 UnsignedOrNone OuterPackSubstIndex =
980 Constraint.getPackSubstitutionIndex()
981 ? Constraint.getPackSubstitutionIndex()
982 : PackSubstitutionIndex;
983
984 Sema::InstantiatingTemplate InstTemplate(
985 S, ConceptId->getBeginLoc(),
987 ConceptId->getNamedConcept(),
988 // We may have empty template arguments when checking non-dependent
989 // nested constraint expressions.
990 // In such cases, non-SFINAE errors would have already been diagnosed
991 // during parameter mapping substitution, so the instantiating template
992 // arguments are less useful here.
993 MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
995 Constraint.getSourceRange());
996 if (InstTemplate.isInvalid())
997 return ExprError();
998
999 unsigned Size = Satisfaction.Details.size();
1000
1001 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
1002
1003 if (E.isInvalid()) {
1004 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1005 return E;
1006 }
1007
1008 // ConceptIdConstraint is only relevant for diagnostics,
1009 // so if the normalized constraint is satisfied, we should not
1010 // substitute into the constraint.
1011 if (Satisfaction.IsSatisfied)
1012 return E;
1013
1014 llvm::FoldingSetNodeID ID;
1015 ID.AddPointer(Constraint.getConceptId());
1016 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
1017 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1018 .VisitConstraint(Constraint);
1019
1020 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
1022
1023 auto &Cached = Iter->second.Satisfaction;
1024 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1025 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1026 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1027 Cached.Details.begin(), Cached.Details.end());
1028 return Iter->second.SubstExpr;
1029 }
1030
1031 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1032 if (CE.isInvalid())
1033 return E;
1035 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1036 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1037 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1038 Satisfaction.Details.begin() + Size,
1039 Satisfaction.Details.end());
1040 Cache.SubstExpr = CE;
1041 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1042 return CE;
1043}
1044
1045ExprResult ConstraintSatisfactionChecker::Evaluate(
1046 const CompoundConstraint &Constraint,
1047 const MultiLevelTemplateArgumentList &MLTAL) {
1048
1049 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1050
1051 bool Conjunction =
1053
1054 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1055
1056 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1057 return LHS;
1058
1059 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
1060 !Satisfaction.ContainsErrors)
1061 return LHS;
1062
1063 Satisfaction.ContainsErrors = false;
1064 Satisfaction.IsSatisfied = false;
1065
1066 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1067
1068 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
1069 !Satisfaction.ContainsErrors)
1070 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1071 EffectiveDetailEndIndex,
1072 Satisfaction.Details.end());
1073
1074 if (!BuildExpression)
1075 return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
1076
1077 if (!LHS.isUsable())
1078 return RHS;
1079
1080 if (!RHS.isUsable())
1081 return LHS;
1082
1083 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1084 Conjunction ? BinaryOperatorKind::BO_LAnd
1085 : BinaryOperatorKind::BO_LOr,
1087 Constraint.getBeginLoc(), FPOptionsOverride{});
1088}
1089
1090ExprResult ConstraintSatisfactionChecker::Evaluate(
1091 const NormalizedConstraint &Constraint,
1092 const MultiLevelTemplateArgumentList &MLTAL) {
1093 switch (Constraint.getKind()) {
1095 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1096
1098 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1099 MLTAL);
1100
1102 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1103 MLTAL);
1104
1106 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1107 }
1108 llvm_unreachable("Unknown ConstraintKind enum");
1109}
1110
1112 Sema &S, const NamedDecl *Template,
1113 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1114 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1115 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1116 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1117
1118 if (ConvertedExpr)
1119 *ConvertedExpr = nullptr;
1120
1121 if (AssociatedConstraints.empty()) {
1122 Satisfaction.IsSatisfied = true;
1123 return false;
1124 }
1125
1126 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1127 // No need to check satisfaction for dependent constraint expressions.
1128 Satisfaction.IsSatisfied = true;
1129 return false;
1130 }
1131
1133 if (TemplateArgsLists.getNumLevels() != 0)
1134 Args = TemplateArgsLists.getInnermost();
1135
1136 struct SynthesisContextPair {
1139 SynthesisContextPair(Sema &S, NamedDecl *Template,
1140 ArrayRef<TemplateArgument> TemplateArgs,
1141 SourceRange InstantiationRange)
1142 : Inst(S, InstantiationRange.getBegin(),
1144 TemplateArgs, InstantiationRange),
1145 NSC(S) {}
1146 };
1147 std::optional<SynthesisContextPair> SynthesisContext;
1148 if (!TopLevelConceptId)
1149 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
1150 TemplateIDRange);
1151
1152 const NormalizedConstraint *C =
1153 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1154 if (!C) {
1155 Satisfaction.IsSatisfied = false;
1156 return true;
1157 }
1158
1159 if (TopLevelConceptId)
1160 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1161 const_cast<NormalizedConstraint *>(C),
1162 Template, /*CSE=*/nullptr,
1164
1165 ExprResult Res = ConstraintSatisfactionChecker(
1166 S, Template, TemplateIDRange.getBegin(),
1167 S.ArgPackSubstIndex, Satisfaction,
1168 /*BuildExpression=*/ConvertedExpr != nullptr)
1169 .Evaluate(*C, TemplateArgsLists);
1170
1171 if (Res.isInvalid())
1172 return true;
1173
1174 if (Res.isUsable() && ConvertedExpr)
1175 *ConvertedExpr = Res.get();
1176
1177 return false;
1178}
1179
1182 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1183 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1184 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1185 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1186 llvm::TimeTraceScope TimeScope(
1187 "CheckConstraintSatisfaction", [TemplateIDRange, this] {
1188 return TemplateIDRange.printToString(getSourceManager());
1189 });
1190 if (AssociatedConstraints.empty()) {
1191 OutSatisfaction.IsSatisfied = true;
1192 return false;
1193 }
1194 const auto *Template = Entity.dyn_cast<const NamedDecl *>();
1195 if (!Template) {
1196 return ::CheckConstraintSatisfaction(
1197 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1198 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1199 }
1200 // Invalid templates could make their way here. Substituting them could result
1201 // in dependent expressions.
1202 if (Template->isInvalidDecl()) {
1203 OutSatisfaction.IsSatisfied = false;
1204 return true;
1205 }
1206
1207 // A list of the template argument list flattened in a predictible manner for
1208 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1209 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1210 // here.
1212 for (auto List : TemplateArgsLists)
1213 for (const TemplateArgument &Arg : List.Args)
1214 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1215
1216 const NamedDecl *Owner = Template;
1217 if (TopLevelConceptId)
1218 Owner = TopLevelConceptId->getNamedConcept();
1219
1220 llvm::FoldingSetNodeID ID;
1221 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1222 void *InsertPos;
1223 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1224 OutSatisfaction = *Cached;
1225 return false;
1226 }
1227
1228 auto Satisfaction =
1229 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1231 *this, Template, AssociatedConstraints, TemplateArgsLists,
1232 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1233 OutSatisfaction = std::move(*Satisfaction);
1234 return true;
1235 }
1236
1237 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1238 // The evaluation of this constraint resulted in us trying to re-evaluate it
1239 // recursively. This isn't really possible, except we try to form a
1240 // RecoveryExpr as a part of the evaluation. If this is the case, just
1241 // return the 'cached' version (which will have the same result), and save
1242 // ourselves the extra-insert. If it ever becomes possible to legitimately
1243 // recursively check a constraint, we should skip checking the 'inner' one
1244 // above, and replace the cached version with this one, as it would be more
1245 // specific.
1246 OutSatisfaction = *Cached;
1247 return false;
1248 }
1249
1250 // Else we can simply add this satisfaction to the list.
1251 OutSatisfaction = *Satisfaction;
1252 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
1253 // invalidated it.
1254 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1255 SatisfactionCache.InsertNode(Satisfaction.release());
1256 return false;
1257}
1258
1259static ExprResult
1261 const ConceptSpecializationExpr *CSE,
1262 UnsignedOrNone SubstIndex) {
1263
1264 // [C++2c] [temp.constr.normal]
1265 // Otherwise, to form CE, any non-dependent concept template argument Ai
1266 // is substituted into the constraint-expression of C.
1267 // If any such substitution results in an invalid concept-id,
1268 // the program is ill-formed; no diagnostic is required.
1269
1271 Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
1272
1273 const ASTTemplateArgumentListInfo *ArgsAsWritten =
1275 if (llvm::none_of(
1276 ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {
1277 return !ArgLoc.getArgument().isDependent() &&
1278 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1279 })) {
1280 return Concept->getConstraintExpr();
1281 }
1282
1284 Concept, Concept->getLexicalDeclContext(),
1285 /*Final=*/false, CSE->getTemplateArguments(),
1286 /*RelativeToPrimary=*/true,
1287 /*Pattern=*/nullptr,
1288 /*ForConstraintInstantiation=*/true);
1289 return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),
1290 MLTAL);
1291}
1292
1294 const ConceptSpecializationExpr *ConstraintExpr,
1295 ConstraintSatisfaction &Satisfaction) {
1296
1298 *this, nullptr, ConstraintExpr, ArgPackSubstIndex);
1299 if (!Res.isUsable())
1300 return true;
1301
1303 Constraints.emplace_back(Res.get());
1304
1305 MultiLevelTemplateArgumentList MLTAL(ConstraintExpr->getNamedConcept(),
1306 ConstraintExpr->getTemplateArguments(),
1307 true);
1308
1310 ConstraintExpr->getNamedConcept(), Constraints, MLTAL,
1311 ConstraintExpr->getSourceRange(), Satisfaction,
1312 ConstraintExpr->getConceptReference());
1313}
1314
1315bool Sema::SetupConstraintScope(
1316 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1317 const MultiLevelTemplateArgumentList &MLTAL,
1319 assert(!isLambdaCallOperator(FD) &&
1320 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1321 "instantiations");
1322 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1323 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1324 InstantiatingTemplate Inst(
1325 *this, FD->getPointOfInstantiation(),
1327 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1328 SourceRange());
1329 if (Inst.isInvalid())
1330 return true;
1331
1332 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1333 // 'instantiated' parameters and adds it to the context. For the case where
1334 // this function is a template being instantiated NOW, we also need to add
1335 // the list of current template arguments to the list so that they also can
1336 // be picked out of the map.
1337 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1338 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1339 /*Final=*/false);
1340 if (addInstantiatedParametersToScope(
1341 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1342 return true;
1343 }
1344
1345 // If this is a member function, make sure we get the parameters that
1346 // reference the original primary template.
1347 if (FunctionTemplateDecl *FromMemTempl =
1348 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1349 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1350 Scope, MLTAL))
1351 return true;
1352 }
1353
1354 return false;
1355 }
1356
1359 FunctionDecl *InstantiatedFrom =
1363
1365 *this, FD->getPointOfInstantiation(),
1366 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1367 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1368 SourceRange());
1369 if (Inst.isInvalid())
1370 return true;
1371
1372 // Case where this was not a template, but instantiated as a
1373 // child-function.
1374 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1375 return true;
1376 }
1377
1378 return false;
1379}
1380
1381// This function collects all of the template arguments for the purposes of
1382// constraint-instantiation and checking.
1383std::optional<MultiLevelTemplateArgumentList>
1384Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1385 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1387 MultiLevelTemplateArgumentList MLTAL;
1388
1389 // Collect the list of template arguments relative to the 'primary' template.
1390 // We need the entire list, since the constraint is completely uninstantiated
1391 // at this point.
1392 MLTAL =
1394 /*Final=*/false, /*Innermost=*/std::nullopt,
1395 /*RelativeToPrimary=*/true,
1396 /*Pattern=*/nullptr,
1397 /*ForConstraintInstantiation=*/true);
1398 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1399 if (isLambdaCallOperator(FD))
1400 return MLTAL;
1401 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1402 return std::nullopt;
1403
1404 return MLTAL;
1405}
1406
1408 ConstraintSatisfaction &Satisfaction,
1409 SourceLocation UsageLoc,
1410 bool ForOverloadResolution) {
1411 // Don't check constraints if the function is dependent. Also don't check if
1412 // this is a function template specialization, as the call to
1413 // CheckFunctionTemplateConstraints after this will check it
1414 // better.
1415 if (FD->isDependentContext() ||
1416 FD->getTemplatedKind() ==
1418 Satisfaction.IsSatisfied = true;
1419 return false;
1420 }
1421
1422 // A lambda conversion operator has the same constraints as the call operator
1423 // and constraints checking relies on whether we are in a lambda call operator
1424 // (and may refer to its parameters), so check the call operator instead.
1425 // Note that the declarations outside of the lambda should also be
1426 // considered. Turning on the 'ForOverloadResolution' flag results in the
1427 // LocalInstantiationScope not looking into its parents, but we can still
1428 // access Decls from the parents while building a lambda RAII scope later.
1429 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1430 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1431 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1432 Satisfaction, UsageLoc,
1433 /*ShouldAddDeclsFromParentScope=*/true);
1434
1435 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1436
1437 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1438 if (isLambdaCallOperator(CtxToSave))
1439 CtxToSave = CtxToSave->getParent()->getParent();
1440 else
1441 CtxToSave = CtxToSave->getNonTransparentContext();
1442 }
1443
1444 ContextRAII SavedContext{*this, CtxToSave};
1445 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1446 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1447 SetupConstraintCheckingTemplateArgumentsAndScope(
1448 const_cast<FunctionDecl *>(FD), {}, Scope);
1449
1450 if (!MLTAL)
1451 return true;
1452
1453 Qualifiers ThisQuals;
1454 CXXRecordDecl *Record = nullptr;
1455 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1456 ThisQuals = Method->getMethodQualifiers();
1457 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1458 }
1459 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1460
1462 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1463 ForOverloadResolution);
1464
1466 FD, FD->getTrailingRequiresClause(), *MLTAL,
1467 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1468 Satisfaction);
1469}
1470
1472 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
1473 const Expr *ConstrExpr) {
1475 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
1476 /*Innermost=*/std::nullopt,
1477 /*RelativeToPrimary=*/true,
1478 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
1479 /*SkipForSpecialization*/ false);
1480
1481 if (MLTAL.getNumSubstitutedLevels() == 0)
1482 return ConstrExpr;
1483
1486 S, DeclInfo.getLocation(),
1488 const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
1489 if (Inst.isInvalid())
1490 return nullptr;
1491
1492 // Set up a dummy 'instantiation' scope in the case of reference to function
1493 // parameters that the surrounding function hasn't been instantiated yet. Note
1494 // this may happen while we're comparing two templates' constraint
1495 // equivalence.
1496 std::optional<LocalInstantiationScope> ScopeForParameters;
1497 if (const NamedDecl *ND = DeclInfo.getDecl();
1498 ND && ND->isFunctionOrFunctionTemplate()) {
1499 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1500 const FunctionDecl *FD = ND->getAsFunction();
1502 Template && Template->getInstantiatedFromMemberTemplate())
1503 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1504 for (auto *PVD : FD->parameters()) {
1505 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1506 continue;
1507 if (!PVD->isParameterPack()) {
1508 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1509 continue;
1510 }
1511 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1512 // to avoid building SubstTemplateTypeParmPackTypes for
1513 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1514 // otherwise reference the AssociatedDecl of the template arguments, which
1515 // is, in this case, the template declaration.
1516 //
1517 // However, as we are in the process of comparing potential
1518 // re-declarations, the canonical declaration is the declaration itself at
1519 // this point. So if we didn't expand these packs, we would end up with an
1520 // incorrect profile difference because we will be profiling the
1521 // canonical types!
1522 //
1523 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1524 // that we can eliminate the Scope in the cases where the declarations are
1525 // not necessarily instantiated. It would also benefit the noexcept
1526 // specifier comparison.
1527 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1528 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1529 }
1530 }
1531
1532 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1533
1534 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1535 // essential for having an injected class as the canonical type for a template
1536 // specialization type at the rebuilding stage. This guarantees that, for
1537 // out-of-line definitions, injected class name types and their equivalent
1538 // template specializations can be profiled to the same value, which makes it
1539 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1540 // perceived identical.
1541 std::optional<Sema::ContextRAII> ContextScope;
1542 const DeclContext *DC = [&] {
1543 if (!DeclInfo.getDecl())
1544 return DeclInfo.getDeclContext();
1545 return DeclInfo.getDecl()->getFriendObjectKind()
1546 ? DeclInfo.getLexicalDeclContext()
1547 : DeclInfo.getDeclContext();
1548 }();
1549 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1550 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1551 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1552 /*NewThisContext=*/false);
1553 }
1554 EnterExpressionEvaluationContext UnevaluatedContext(
1558 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1559 if (!SubstConstr.isUsable())
1560 return nullptr;
1561 return SubstConstr.get();
1562}
1563
1565 const Expr *OldConstr,
1567 const Expr *NewConstr) {
1568 if (OldConstr == NewConstr)
1569 return true;
1570 // C++ [temp.constr.decl]p4
1571 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1572 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1573 if (const Expr *SubstConstr =
1575 OldConstr))
1576 OldConstr = SubstConstr;
1577 else
1578 return false;
1579 if (const Expr *SubstConstr =
1581 NewConstr))
1582 NewConstr = SubstConstr;
1583 else
1584 return false;
1585 }
1586
1587 llvm::FoldingSetNodeID ID1, ID2;
1588 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1589 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1590 return ID1 == ID2;
1591}
1592
1594 assert(FD->getFriendObjectKind() && "Must be a friend!");
1595
1596 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1597 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1598 // non-function-template.
1599 assert(FD->getDescribedFunctionTemplate() &&
1600 "Non-function templates don't need to be checked");
1601
1604
1605 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1606 for (const AssociatedConstraint &AC : ACs)
1607 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1608 AC.ConstraintExpr))
1609 return true;
1610
1611 return false;
1612}
1613
1615 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1616 SourceRange TemplateIDRange) {
1617 ConstraintSatisfaction Satisfaction;
1618 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1619 TD->getAssociatedConstraints(AssociatedConstraints);
1620 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1621 TemplateIDRange, Satisfaction))
1622 return true;
1623
1624 if (!Satisfaction.IsSatisfied) {
1625 SmallString<128> TemplateArgString;
1626 TemplateArgString = " ";
1627 TemplateArgString += getTemplateArgumentBindingsText(
1628 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1629 TemplateArgsLists.getInnermost().size());
1630
1631 Diag(TemplateIDRange.getBegin(),
1632 diag::err_template_arg_list_constraints_not_satisfied)
1634 << TemplateArgString << TemplateIDRange;
1635 DiagnoseUnsatisfiedConstraint(Satisfaction);
1636 return true;
1637 }
1638 return false;
1639}
1640
1642 Sema &SemaRef, SourceLocation PointOfInstantiation,
1644 ConstraintSatisfaction &Satisfaction) {
1646 Template->getAssociatedConstraints(TemplateAC);
1647 if (TemplateAC.empty()) {
1648 Satisfaction.IsSatisfied = true;
1649 return false;
1650 }
1651
1653
1654 FunctionDecl *FD = Template->getTemplatedDecl();
1655 // Collect the list of template arguments relative to the 'primary'
1656 // template. We need the entire list, since the constraint is completely
1657 // uninstantiated at this point.
1658
1660 {
1661 // getTemplateInstantiationArgs uses this instantiation context to find out
1662 // template arguments for uninstantiated functions.
1663 // We don't want this RAII object to persist, because there would be
1664 // otherwise duplicate diagnostic notes.
1666 SemaRef, PointOfInstantiation,
1668 PointOfInstantiation);
1669 if (Inst.isInvalid())
1670 return true;
1671 MLTAL = SemaRef.getTemplateInstantiationArgs(
1672 /*D=*/FD, FD,
1673 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1674 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1675 }
1676
1677 Sema::ContextRAII SavedContext(SemaRef, FD);
1678 return SemaRef.CheckConstraintSatisfaction(
1679 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1680}
1681
1683 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1684 ArrayRef<TemplateArgument> TemplateArgs,
1685 ConstraintSatisfaction &Satisfaction) {
1686 // In most cases we're not going to have constraints, so check for that first.
1687 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1688
1689 if (!Template)
1690 return ::CheckFunctionConstraintsWithoutInstantiation(
1691 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1692 TemplateArgs, Satisfaction);
1693
1694 // Note - code synthesis context for the constraints check is created
1695 // inside CheckConstraintsSatisfaction.
1697 Template->getAssociatedConstraints(TemplateAC);
1698 if (TemplateAC.empty()) {
1699 Satisfaction.IsSatisfied = true;
1700 return false;
1701 }
1702
1703 // Enter the scope of this instantiation. We don't use
1704 // PushDeclContext because we don't have a scope.
1705 Sema::ContextRAII savedContext(*this, Decl);
1707
1708 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1709 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1710 Scope);
1711
1712 if (!MLTAL)
1713 return true;
1714
1715 Qualifiers ThisQuals;
1716 CXXRecordDecl *Record = nullptr;
1717 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1718 ThisQuals = Method->getMethodQualifiers();
1719 Record = Method->getParent();
1720 }
1721
1722 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1723 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1724 Scope);
1725
1726 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1727 PointOfInstantiation, Satisfaction);
1728}
1729
1732 bool First) {
1733 assert(!Req->isSatisfied() &&
1734 "Diagnose() can only be used on an unsatisfied requirement");
1735 switch (Req->getSatisfactionStatus()) {
1737 llvm_unreachable("Diagnosing a dependent requirement");
1738 break;
1740 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1741 if (!SubstDiag->DiagMessage.empty())
1742 S.Diag(SubstDiag->DiagLoc,
1743 diag::note_expr_requirement_expr_substitution_error)
1744 << (int)First << SubstDiag->SubstitutedEntity
1745 << SubstDiag->DiagMessage;
1746 else
1747 S.Diag(SubstDiag->DiagLoc,
1748 diag::note_expr_requirement_expr_unknown_substitution_error)
1749 << (int)First << SubstDiag->SubstitutedEntity;
1750 break;
1751 }
1753 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1754 << (int)First << Req->getExpr();
1755 break;
1757 auto *SubstDiag =
1759 if (!SubstDiag->DiagMessage.empty())
1760 S.Diag(SubstDiag->DiagLoc,
1761 diag::note_expr_requirement_type_requirement_substitution_error)
1762 << (int)First << SubstDiag->SubstitutedEntity
1763 << SubstDiag->DiagMessage;
1764 else
1765 S.Diag(
1766 SubstDiag->DiagLoc,
1767 diag::
1768 note_expr_requirement_type_requirement_unknown_substitution_error)
1769 << (int)First << SubstDiag->SubstitutedEntity;
1770 break;
1771 }
1773 ConceptSpecializationExpr *ConstraintExpr =
1775 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1776 break;
1777 }
1779 llvm_unreachable("We checked this above");
1780 }
1781}
1782
1785 bool First) {
1786 assert(!Req->isSatisfied() &&
1787 "Diagnose() can only be used on an unsatisfied requirement");
1788 switch (Req->getSatisfactionStatus()) {
1790 llvm_unreachable("Diagnosing a dependent requirement");
1791 return;
1793 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1794 if (!SubstDiag->DiagMessage.empty())
1795 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1796 << (int)First << SubstDiag->SubstitutedEntity
1797 << SubstDiag->DiagMessage;
1798 else
1799 S.Diag(SubstDiag->DiagLoc,
1800 diag::note_type_requirement_unknown_substitution_error)
1801 << (int)First << SubstDiag->SubstitutedEntity;
1802 return;
1803 }
1804 default:
1805 llvm_unreachable("Unknown satisfaction status");
1806 return;
1807 }
1808}
1809
1812 SourceLocation Loc, bool First) {
1813 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1814 S.Diag(
1815 Loc,
1816 diag::
1817 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1818 << (int)First
1819 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1820 << Concept->getNamedConcept();
1821 } else {
1822 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1823 << (int)First << Concept;
1824 }
1825}
1826
1829 bool First, concepts::NestedRequirement *Req = nullptr);
1830
1833 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1834 for (auto &Record : Records) {
1836 Loc = {};
1838 }
1839}
1840
1850
1852 const Expr *SubstExpr,
1853 bool First) {
1854 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1855 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1856 switch (BO->getOpcode()) {
1857 // These two cases will in practice only be reached when using fold
1858 // expressions with || and &&, since otherwise the || and && will have been
1859 // broken down into atomic constraints during satisfaction checking.
1860 case BO_LOr:
1861 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1864 /*First=*/false);
1865 return;
1866 case BO_LAnd: {
1867 bool LHSSatisfied =
1868 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1869 if (LHSSatisfied) {
1870 // LHS is true, so RHS must be false.
1872 return;
1873 }
1874 // LHS is false
1876
1877 // RHS might also be false
1878 bool RHSSatisfied =
1879 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1880 if (!RHSSatisfied)
1882 /*First=*/false);
1883 return;
1884 }
1885 case BO_GE:
1886 case BO_LE:
1887 case BO_GT:
1888 case BO_LT:
1889 case BO_EQ:
1890 case BO_NE:
1891 if (BO->getLHS()->getType()->isIntegerType() &&
1892 BO->getRHS()->getType()->isIntegerType()) {
1893 Expr::EvalResult SimplifiedLHS;
1894 Expr::EvalResult SimplifiedRHS;
1895 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1897 /*InConstantContext=*/true);
1898 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1900 /*InConstantContext=*/true);
1901 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1902 S.Diag(SubstExpr->getBeginLoc(),
1903 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1904 << (int)First << SubstExpr
1905 << toString(SimplifiedLHS.Val.getInt(), 10)
1906 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1907 << toString(SimplifiedRHS.Val.getInt(), 10);
1908 return;
1909 }
1910 }
1911 break;
1912
1913 default:
1914 break;
1915 }
1916 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1917 // FIXME: RequiresExpr should store dependent diagnostics.
1918 for (concepts::Requirement *Req : RE->getRequirements())
1919 if (!Req->isDependent() && !Req->isSatisfied()) {
1920 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1922 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1924 else
1927 break;
1928 }
1929 return;
1930 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1931 // Drill down concept ids treated as atomic constraints
1933 return;
1934 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1935 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1936 assert(TTE->getNumArgs() == 2);
1937 S.Diag(SubstExpr->getSourceRange().getBegin(),
1938 diag::note_is_deducible_constraint_evaluated_to_false)
1939 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1940 return;
1941 }
1942
1943 S.Diag(SubstExpr->getSourceRange().getBegin(),
1944 diag::note_atomic_constraint_evaluated_to_false)
1945 << (int)First << SubstExpr;
1946 S.DiagnoseTypeTraitDetails(SubstExpr);
1947}
1948
1952 if (auto *Diag =
1953 Record
1954 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1955 if (Req)
1956 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
1957 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
1958 else
1959 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1960 << Diag->second;
1961 return;
1962 }
1963 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
1964 if (Loc.isInvalid())
1965 Loc = Concept->getBeginLoc();
1967 return;
1968 }
1971}
1972
1974 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
1975 bool First) {
1976
1977 assert(!Satisfaction.IsSatisfied &&
1978 "Attempted to diagnose a satisfied constraint");
1979 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
1980}
1981
1983 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
1984
1985 const ASTConstraintSatisfaction &Satisfaction =
1986 ConstraintExpr->getSatisfaction();
1987
1988 assert(!Satisfaction.IsSatisfied &&
1989 "Attempted to diagnose a satisfied constraint");
1990
1991 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
1992 ConstraintExpr->getBeginLoc(), First);
1993}
1994
1995namespace {
1996
1997class SubstituteParameterMappings {
1998 Sema &SemaRef;
1999
2000 const MultiLevelTemplateArgumentList *MLTAL;
2001 const ASTTemplateArgumentListInfo *ArgsAsWritten;
2002
2003 bool InFoldExpr;
2004
2005 SubstituteParameterMappings(Sema &SemaRef,
2006 const MultiLevelTemplateArgumentList *MLTAL,
2007 const ASTTemplateArgumentListInfo *ArgsAsWritten,
2008 bool InFoldExpr)
2009 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2010 InFoldExpr(InFoldExpr) {}
2011
2012 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
2013
2014 bool substitute(NormalizedConstraintWithParamMapping &N);
2015
2016 bool substitute(ConceptIdConstraint &CC);
2017
2018public:
2019 SubstituteParameterMappings(Sema &SemaRef, bool InFoldExpr = false)
2020 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
2021 InFoldExpr(InFoldExpr) {}
2022
2023 bool substitute(NormalizedConstraint &N);
2024};
2025
2026void SubstituteParameterMappings::buildParameterMapping(
2028 TemplateParameterList *TemplateParams =
2029 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
2030
2031 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2032 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2033
2036 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2037 /*OnlyDeduced=*/false,
2038 /*Depth=*/0, OccurringIndices);
2039
2041 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2042 /*Depth=*/0, OccurringIndicesForSubsumption);
2043
2044 } else if (N.getKind() ==
2047 static_cast<FoldExpandedConstraint &>(N).getPattern(),
2048 /*OnlyDeduced=*/false,
2049 /*Depth=*/0, OccurringIndices);
2051 auto *Args = static_cast<ConceptIdConstraint &>(N)
2052 .getConceptId()
2053 ->getTemplateArgsAsWritten();
2054 if (Args)
2055 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2056 /*Depth=*/0, OccurringIndices);
2057 }
2058 unsigned Size = OccurringIndices.count();
2059 // When the constraint is independent of any template parameters,
2060 // we build an empty mapping so that we can distinguish these cases
2061 // from cases where no mapping exists at all, e.g. when there are only atomic
2062 // constraints.
2063 TemplateArgumentLoc *TempArgs =
2064 new (SemaRef.Context) TemplateArgumentLoc[Size];
2066 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2067 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2068 ? ArgsAsWritten->arguments()[I].getLocation()
2069 : SourceLocation();
2070 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
2071 // can't assert Loc.isValid() now.
2072 if (OccurringIndices[I]) {
2073 NamedDecl *Param = TemplateParams->begin()[I];
2074 new (&(TempArgs)[J]) TemplateArgumentLoc(
2075 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2076 UsedParams.push_back(Param);
2077 J++;
2078 }
2079 }
2080 auto *UsedList = TemplateParameterList::Create(
2081 SemaRef.Context, TemplateParams->getTemplateLoc(),
2082 TemplateParams->getLAngleLoc(), UsedParams,
2083 /*RAngleLoc=*/SourceLocation(),
2084 /*RequiresClause=*/nullptr);
2086 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2087 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
2088}
2089
2090bool SubstituteParameterMappings::substitute(
2092 if (!N.hasParameterMapping())
2093 buildParameterMapping(N);
2094
2095 // If the parameter mapping is empty, there is nothing to substitute.
2096 if (N.getParameterMapping().empty())
2097 return false;
2098
2099 SourceLocation InstLocBegin, InstLocEnd;
2100 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2101 if (Arguments.empty()) {
2102 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2103 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2104 } else {
2105 auto SR = Arguments[0].getSourceRange();
2106 InstLocBegin = SR.getBegin();
2107 InstLocEnd = SR.getEnd();
2108 }
2109 Sema::NonSFINAEContext _(SemaRef);
2111 SemaRef, InstLocBegin,
2113 const_cast<NamedDecl *>(N.getConstraintDecl()),
2114 {InstLocBegin, InstLocEnd});
2115 if (Inst.isInvalid())
2116 return true;
2117
2118 // TransformTemplateArguments is unable to preserve the source location of a
2119 // pack. The SourceLocation is necessary for the instantiation location.
2120 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2121 // which is wrong.
2122 TemplateArgumentListInfo SubstArgs;
2124 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs,
2125 /*BuildPackExpansionTypes=*/!InFoldExpr))
2126 return true;
2128 auto *TD =
2131 TD->getLocation(), SubstArgs,
2132 /*DefaultArguments=*/{},
2133 /*PartialTemplateArgs=*/false, CTAI))
2134 return true;
2135
2136 TemplateArgumentLoc *TempArgs =
2137 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2138
2139 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2140 SourceLocation Loc;
2141 // If this is an empty pack, we have no corresponding SubstArgs.
2142 if (I < SubstArgs.size())
2143 Loc = SubstArgs.arguments()[I].getLocation();
2144
2145 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2146 CTAI.SugaredConverted[I], QualType(), Loc);
2147 }
2148
2149 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2150 CTAI.SugaredConverted.size());
2154 return false;
2155}
2156
2157bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2158 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2159
2160 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2161 return true;
2162
2163 auto *CSE = CC.getConceptSpecializationExpr();
2164 assert(CSE);
2165 assert(!CC.getBeginLoc().isInvalid());
2166
2167 SourceLocation InstLocBegin, InstLocEnd;
2168 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2169 Arguments.empty()) {
2170 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2171 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2172 } else {
2173 auto SR = Arguments[0].getSourceRange();
2174 InstLocBegin = SR.getBegin();
2175 InstLocEnd = SR.getEnd();
2176 }
2177 Sema::NonSFINAEContext _(SemaRef);
2178 // This is useful for name lookup across modules; see Sema::getLookupModules.
2180 SemaRef, InstLocBegin,
2182 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2183 {InstLocBegin, InstLocEnd});
2184 if (Inst.isInvalid())
2185 return true;
2186
2188 // TransformTemplateArguments is unable to preserve the source location of a
2189 // pack. The SourceLocation is necessary for the instantiation location.
2190 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2191 // which is wrong.
2192 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2193 CSE->getTemplateArgsAsWritten();
2195 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out,
2196 /*BuildPackExpansionTypes=*/!InFoldExpr))
2197 return true;
2199 if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(),
2200 CSE->getConceptNameInfo().getLoc(), Out,
2201 /*DefaultArgs=*/{},
2202 /*PartialTemplateArgs=*/false, CTAI,
2203 /*UpdateArgsWithConversions=*/false))
2204 return true;
2205 auto TemplateArgs = *MLTAL;
2206 TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(),
2207 CTAI.SugaredConverted);
2208 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2209 InFoldExpr)
2210 .substitute(CC.getNormalizedConstraint());
2211}
2212
2213bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2214 switch (N.getKind()) {
2216 if (!MLTAL) {
2217 assert(!ArgsAsWritten);
2218 return false;
2219 }
2220 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2221 }
2223 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2224 if (!MLTAL) {
2225 llvm::SaveAndRestore _1(InFoldExpr, true);
2226 assert(!ArgsAsWritten);
2227 return substitute(FE.getNormalizedPattern());
2228 }
2229 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2230 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2231 return SubstituteParameterMappings(SemaRef, /*InFoldExpr=*/true)
2232 .substitute(FE.getNormalizedPattern());
2233 }
2235 auto &CC = static_cast<ConceptIdConstraint &>(N);
2236 if (MLTAL) {
2237 assert(ArgsAsWritten);
2238 return substitute(CC);
2239 }
2240 assert(!ArgsAsWritten);
2244 Concept, Concept->getLexicalDeclContext(),
2245 /*Final=*/true, CSE->getTemplateArguments(),
2246 /*RelativeToPrimary=*/true,
2247 /*Pattern=*/nullptr,
2248 /*ForConstraintInstantiation=*/true);
2249
2250 return SubstituteParameterMappings(
2251 SemaRef, &MLTAL, CSE->getTemplateArgsAsWritten(), InFoldExpr)
2252 .substitute(CC.getNormalizedConstraint());
2253 }
2255 auto &Compound = static_cast<CompoundConstraint &>(N);
2256 if (substitute(Compound.getLHS()))
2257 return true;
2258 return substitute(Compound.getRHS());
2259 }
2260 }
2261 llvm_unreachable("Unknown ConstraintKind enum");
2262}
2263
2264} // namespace
2265
2266NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2267 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2268 assert(ACs.size() != 0);
2269 auto *Conjunction =
2270 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2271 if (!Conjunction)
2272 return nullptr;
2273 for (unsigned I = 1; I < ACs.size(); ++I) {
2274 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2275 ACs[I].ArgPackSubstIndex);
2276 if (!Next)
2277 return nullptr;
2279 Conjunction, Next);
2280 }
2281 return Conjunction;
2282}
2283
2284NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2285 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2286 assert(E != nullptr);
2287
2288 // C++ [temp.constr.normal]p1.1
2289 // [...]
2290 // - The normal form of an expression (E) is the normal form of E.
2291 // [...]
2292 E = E->IgnoreParenImpCasts();
2293
2294 llvm::FoldingSetNodeID ID;
2295 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2296 return nullptr;
2297 }
2298 SatisfactionStackRAII StackRAII(S, D, ID);
2299
2300 // C++2a [temp.param]p4:
2301 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2302 // Fold expression is considered atomic constraints per current wording.
2303 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2304
2305 if (LogicalBinOp BO = E) {
2306 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2307 if (!LHS)
2308 return nullptr;
2309 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2310 if (!RHS)
2311 return nullptr;
2312
2314 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2315 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2316 NormalizedConstraint *SubNF;
2317 {
2318 Sema::NonSFINAEContext _(S);
2319 Sema::InstantiatingTemplate Inst(
2320 S, CSE->getExprLoc(),
2321 Sema::InstantiatingTemplate::ConstraintNormalization{},
2322 // FIXME: improve const-correctness of InstantiatingTemplate
2323 const_cast<NamedDecl *>(D), CSE->getSourceRange());
2324 if (Inst.isInvalid())
2325 return nullptr;
2326 // C++ [temp.constr.normal]p1.1
2327 // [...]
2328 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2329 // where C names a concept, is the normal form of the
2330 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2331 // respective template parameters in the parameter mappings in each atomic
2332 // constraint. If any such substitution results in an invalid type or
2333 // expression, the program is ill-formed; no diagnostic is required.
2334 // [...]
2335
2336 // Use canonical declarations to merge ConceptDecls across
2337 // different modules.
2338 ConceptDecl *CD = CSE->getNamedConcept()->getCanonicalDecl();
2339
2340 ExprResult Res =
2341 SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);
2342 if (!Res.isUsable())
2343 return nullptr;
2344
2345 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2346 S, CD, AssociatedConstraint(Res.get(), SubstIndex));
2347
2348 if (!SubNF)
2349 return nullptr;
2350 }
2351
2353 CSE->getConceptReference(), SubNF, D,
2354 CSE, SubstIndex);
2355
2356 } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2357 FE && S.getLangOpts().CPlusPlus26 &&
2358 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2359 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2360
2361 // Normalize fold expressions in C++26.
2362
2364 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2367
2368 if (FE->getInit()) {
2369 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2370 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2371 if (!LHS || !RHS)
2372 return nullptr;
2373
2374 if (FE->isRightFold())
2376 FE->getPattern(), D, Kind, LHS);
2377 else
2379 FE->getPattern(), D, Kind, RHS);
2380
2382 S.getASTContext(), LHS,
2383 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2384 : CCK_Disjunction),
2385 RHS);
2386 }
2387 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2388 if (!Sub)
2389 return nullptr;
2391 D, Kind, Sub);
2392 }
2393 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2394}
2395
2397 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2398 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2399 if (!ConstrainedDeclOrNestedReq) {
2400 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2401 *this, nullptr, AssociatedConstraints);
2402 if (!Normalized ||
2403 SubstituteParameterMappings(*this).substitute(*Normalized))
2404 return nullptr;
2405
2406 return Normalized;
2407 }
2408
2409 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2410 const NamedDecl *ND =
2411 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2412 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2413 if (CacheEntry == NormalizationCache.end()) {
2414 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2415 *this, ND, AssociatedConstraints);
2416 if (!Normalized) {
2417 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);
2418 return nullptr;
2419 }
2420 // substitute() can invalidate iterators of NormalizationCache.
2421 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2422 CacheEntry =
2423 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2424 .first;
2425 if (Failed)
2426 return nullptr;
2427 }
2428 return CacheEntry->second;
2429}
2430
2433
2434 // [C++26] [temp.constr.fold]
2435 // Two fold expanded constraints are compatible for subsumption
2436 // if their respective constraints both contain an equivalent unexpanded pack.
2437
2440 APacks);
2442 BPacks);
2443
2444 for (const UnexpandedParameterPack &APack : APacks) {
2445 auto ADI = getDepthAndIndex(APack);
2446 if (!ADI)
2447 continue;
2448 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2449 return getDepthAndIndex(BPack) == ADI;
2450 });
2451 if (It != BPacks.end())
2452 return true;
2453 }
2454 return false;
2455}
2456
2459 const NamedDecl *D2,
2461 bool &Result) {
2462#ifndef NDEBUG
2463 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2464 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2466 return Kind == FunctionDecl::TK_NonTemplate ||
2468 };
2469 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2470 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2471 "use non-instantiated function declaration for constraints partial "
2472 "ordering");
2473 }
2474#endif
2475
2476 if (AC1.empty()) {
2477 Result = AC2.empty();
2478 return false;
2479 }
2480 if (AC2.empty()) {
2481 // TD1 has associated constraints and TD2 does not.
2482 Result = true;
2483 return false;
2484 }
2485
2486 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2487 auto CacheEntry = SubsumptionCache.find(Key);
2488 if (CacheEntry != SubsumptionCache.end()) {
2489 Result = CacheEntry->second;
2490 return false;
2491 }
2492
2493 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
2494 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
2495
2496 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2497 if (Depth2 > Depth1) {
2498 AC1[I].ConstraintExpr =
2499 AdjustConstraintDepth(*this, Depth2 - Depth1)
2500 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2501 .get();
2502 } else if (Depth1 > Depth2) {
2503 AC2[I].ConstraintExpr =
2504 AdjustConstraintDepth(*this, Depth1 - Depth2)
2505 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2506 .get();
2507 }
2508 }
2509
2510 SubsumptionChecker SC(*this);
2511 std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2);
2512 if (!Subsumes) {
2513 // Normalization failed
2514 return true;
2515 }
2516 Result = *Subsumes;
2517 SubsumptionCache.try_emplace(Key, *Subsumes);
2518 return false;
2519}
2520
2524 if (isSFINAEContext())
2525 // No need to work here because our notes would be discarded.
2526 return false;
2527
2528 if (AC1.empty() || AC2.empty())
2529 return false;
2530
2531 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2532 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2533 const AtomicConstraint &B) {
2535 return false;
2536 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2537 if (EA == EB)
2538 return true;
2539
2540 // Not the same source level expression - are the expressions
2541 // identical?
2542 llvm::FoldingSetNodeID IDA, IDB;
2543 EA->Profile(IDA, Context, /*Canonical=*/true);
2544 EB->Profile(IDB, Context, /*Canonical=*/true);
2545 if (IDA != IDB)
2546 return false;
2547
2548 AmbiguousAtomic1 = EA;
2549 AmbiguousAtomic2 = EB;
2550 return true;
2551 };
2552
2553 {
2554 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2555 if (!Normalized1)
2556 return false;
2557
2558 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2559 if (!Normalized2)
2560 return false;
2561
2562 SubsumptionChecker SC(*this);
2563
2564 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2565 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2566
2567 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2568 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2569 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2570
2571 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2572 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2573 // Same result - no ambiguity was caused by identical atomic expressions.
2574 return false;
2575 }
2576 // A different result! Some ambiguous atomic constraint(s) caused a difference
2577 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2578
2579 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2580 << AmbiguousAtomic1->getSourceRange();
2581 Diag(AmbiguousAtomic2->getBeginLoc(),
2582 diag::note_ambiguous_atomic_constraints_similar_expression)
2583 << AmbiguousAtomic2->getSourceRange();
2584 return true;
2585}
2586
2587//
2588//
2589// ------------------------ Subsumption -----------------------------------
2590//
2591//
2593 SubsumptionCallable Callable)
2594 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2595
2596uint16_t SubsumptionChecker::getNewLiteralId() {
2597 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2598 "too many constraints!");
2599 return NextID++;
2600}
2601
2602auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2603 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2604 // C++ [temp.constr.order] p2
2605 // - an atomic constraint A subsumes another atomic constraint B
2606 // if and only if the A and B are identical [...]
2607 //
2608 // C++ [temp.constr.atomic] p2
2609 // Two atomic constraints are identical if they are formed from the
2610 // same expression and the targets of the parameter mappings are
2611 // equivalent according to the rules for expressions [...]
2612
2613 // Because subsumption of atomic constraints is an identity
2614 // relationship that does not require further analysis
2615 // We cache the results such that if an atomic constraint literal
2616 // subsumes another, their literal will be the same
2617
2618 llvm::FoldingSetNodeID ID;
2619 ID.AddBoolean(Ori->hasParameterMapping());
2620 if (Ori->hasParameterMapping()) {
2621 const auto &Mapping = Ori->getParameterMapping();
2623 Ori->mappingOccurenceListForSubsumption();
2624 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2625 if (Indexes[Idx])
2626 SemaRef.getASTContext()
2627 .getCanonicalTemplateArgument(TAL.getArgument())
2628 .Profile(ID, SemaRef.getASTContext());
2629 }
2630 }
2631 auto It = Elems.find(ID);
2632 if (It == Elems.end()) {
2633 It = Elems
2634 .insert({ID,
2635 MappedAtomicConstraint{
2636 Ori, {getNewLiteralId(), Literal::Atomic}}})
2637 .first;
2638 ReverseMap[It->second.ID.Value] = Ori;
2639 }
2640 return It->getSecond().ID;
2641}
2642
2643auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2644 auto &Elems = FoldMap[Ori->getPattern()];
2645
2646 FoldExpendedConstraintKey K;
2647 K.Kind = Ori->getFoldOperator();
2648
2649 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2650 return K.Kind == Other.Kind;
2651 });
2652 if (It == Elems.end()) {
2653 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2654 It = Elems.insert(Elems.end(), std::move(K));
2655 ReverseMap[It->ID.Value] = Ori;
2656 }
2657 return It->ID;
2658}
2659
2660auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2661 return SubsumptionChecker::Normalize<CNFFormula>(C);
2662}
2663auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2664 return SubsumptionChecker::Normalize<DNFFormula>(C);
2665}
2666
2667///
2668/// \brief SubsumptionChecker::Normalize
2669///
2670/// Normalize a formula to Conjunctive Normal Form or
2671/// Disjunctive normal form.
2672///
2673/// Each Atomic (and Fold Expanded) constraint gets represented by
2674/// a single id to reduce space.
2675///
2676/// To minimize risks of exponential blow up, if two atomic
2677/// constraints subsumes each other (same constraint and mapping),
2678/// they are represented by the same literal.
2679///
2680template <typename FormulaType>
2681FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2682 FormulaType Res;
2683
2684 auto Add = [&, this](Clause C) {
2685 // Sort each clause and remove duplicates for faster comparisons.
2686 llvm::sort(C);
2687 C.erase(llvm::unique(C), C.end());
2688 AddUniqueClauseToFormula(Res, std::move(C));
2689 };
2690
2691 switch (NC.getKind()) {
2693 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2694
2696 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2697
2699 return Normalize<FormulaType>(
2700 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2701
2703 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2704 FormulaType Left, Right;
2705 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2706 Left = Normalize<FormulaType>(Compound.getLHS());
2707 Right = Normalize<FormulaType>(Compound.getRHS());
2708 });
2709
2710 if (Compound.getCompoundKind() == FormulaType::Kind) {
2711 unsigned SizeLeft = Left.size();
2712 Res = std::move(Left);
2713 Res.reserve(SizeLeft + Right.size());
2714 std::for_each(std::make_move_iterator(Right.begin()),
2715 std::make_move_iterator(Right.end()), Add);
2716 return Res;
2717 }
2718
2719 Res.reserve(Left.size() * Right.size());
2720 for (const auto &LTransform : Left) {
2721 for (const auto &RTransform : Right) {
2722 Clause Combined;
2723 Combined.reserve(LTransform.size() + RTransform.size());
2724 llvm::copy(LTransform, std::back_inserter(Combined));
2725 llvm::copy(RTransform, std::back_inserter(Combined));
2726 Add(std::move(Combined));
2727 }
2728 }
2729 return Res;
2730 }
2731 }
2732 llvm_unreachable("Unknown ConstraintKind enum");
2733}
2734
2735void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2736 for (auto &Other : F) {
2737 if (llvm::equal(C, Other))
2738 return;
2739 }
2740 F.push_back(C);
2741}
2742
2744 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2746 const NormalizedConstraint *PNormalized =
2747 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2748 if (!PNormalized)
2749 return std::nullopt;
2750
2751 const NormalizedConstraint *QNormalized =
2752 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2753 if (!QNormalized)
2754 return std::nullopt;
2755
2756 return Subsumes(PNormalized, QNormalized);
2757}
2758
2760 const NormalizedConstraint *Q) {
2761
2762 DNFFormula DNFP = DNF(*P);
2763 CNFFormula CNFQ = CNF(*Q);
2764 return Subsumes(DNFP, CNFQ);
2765}
2766
2767bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2768 const CNFFormula &QCNF) {
2769 for (const auto &Pi : PDNF) {
2770 for (const auto &Qj : QCNF) {
2771 // C++ [temp.constr.order] p2
2772 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2773 // and only if there exists an atomic constraint Pia in Pi for which
2774 // there exists an atomic constraint, Qjb, in Qj such that Pia
2775 // subsumes Qjb.
2776 if (!DNFSubsumes(Pi, Qj))
2777 return false;
2778 }
2779 }
2780 return true;
2781}
2782
2783bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2784
2785 return llvm::any_of(P, [&](Literal LP) {
2786 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2787 });
2788}
2789
2791 const FoldExpandedConstraint *B) {
2792 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2793 A, B};
2794
2795 auto It = FoldSubsumptionCache.find(Key);
2796 if (It == FoldSubsumptionCache.end()) {
2797 // C++ [temp.constr.order]
2798 // a fold expanded constraint A subsumes another fold expanded
2799 // constraint B if they are compatible for subsumption, have the same
2800 // fold-operator, and the constraint of A subsumes that of B.
2801 bool DoesSubsume =
2802 A->getFoldOperator() == B->getFoldOperator() &&
2805 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2806 }
2807 return It->second;
2808}
2809
2810bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2811 if (A.Kind != B.Kind)
2812 return false;
2813 switch (A.Kind) {
2814 case Literal::Atomic:
2815 if (!Callable)
2816 return A.Value == B.Value;
2817 return Callable(
2818 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2819 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2820 case Literal::FoldExpanded:
2821 return Subsumes(
2822 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2823 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2824 }
2825 llvm_unreachable("unknown literal kind");
2826}
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 ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)
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:873
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:2179
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:4981
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2141
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2939
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
Expr * getCallee()
Definition Expr.h:3024
arg_range arguments()
Definition Expr.h:3129
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.
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:273
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:3089
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:276
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:4189
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4510
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:4309
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4325
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4253
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:4140
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4213
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4161
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:2072
const TypeClass * getTypePtr() const
Definition TypeLoc.h:526
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
bool hasTemplateArgument(unsigned Depth, unsigned Index) const
Determine whether there is a non-NULL template argument at the given depth and index.
Definition Template.h:175
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
Definition Template.h:269
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
Definition Template.h:210
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 getIndex() const
Get the index of the template parameter within its parameter list.
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
QualType getCanonicalType() const
Definition TypeBase.h:8330
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
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition SemaBase.cpp:33
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
RAII object used to change the argument pack substitution index within a Sema object.
Definition Sema.h:13608
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8432
A RAII object to temporarily push a declaration context.
Definition Sema.h:3467
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition Sema.h:12436
SourceLocation getLocation() const
Definition Sema.h:12196
const DeclContext * getDeclContext() const
Definition Sema.h:12192
const NamedDecl * getDecl() const
Definition Sema.h:12184
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12188
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.
ExprResult SubstConceptTemplateArguments(const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, const MultiLevelTemplateArgumentList &MLTAL)
Substitute concept template arguments in the constraint expression of a concept-id.
llvm::DenseMap< llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult > UnsubstitutedConstraintSatisfactionCache
Cache the satisfaction of an atomic constraint.
Definition Sema.h:14951
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 ...
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions, bool Diagnose=true)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
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:14810
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:7005
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:11754
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1314
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)
SourceManager & getSourceManager() const
Definition Sema.h:923
bool isSFINAEContext() const
Definition Sema.h:13644
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13602
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14770
void PopSatisfactionStackEntry()
Definition Sema.h:14776
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:6718
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6697
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition Sema.h:14778
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:4509
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
std::string printToString(const SourceManager &SM) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
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:350
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.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
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.
bool isNull() const
Determine whether this template name is NULL.
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:547
void setNameLoc(SourceLocation Loc)
Definition TypeLoc.h:551
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:8840
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:8511
QualType desugar() const
Definition Type.cpp:4040
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:330
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:310
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
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ 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:11972
A stack object to be created when performing template instantiation.
Definition Sema.h:13264
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition Sema.h:13417
constexpr unsigned toInternalRepresentation() const