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