clang 24.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"
24#include "clang/Sema/Overload.h"
26#include "clang/Sema/Sema.h"
28#include "clang/Sema/Template.h"
30#include "llvm/ADT/DenseMap.h"
31#include "llvm/ADT/PointerUnion.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/Support/SaveAndRestore.h"
34#include "llvm/Support/ScopedPrinter.h"
35#include "llvm/Support/TimeProfiler.h"
36
37using namespace clang;
38using namespace sema;
39
40namespace {
41class LogicalBinOp {
42 SourceLocation Loc;
44 const Expr *LHS = nullptr;
45 const Expr *RHS = nullptr;
46
47public:
48 LogicalBinOp(const Expr *E) {
49 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
50 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
51 LHS = BO->getLHS();
52 RHS = BO->getRHS();
53 Loc = BO->getExprLoc();
54 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
55 // If OO is not || or && it might not have exactly 2 arguments.
56 if (OO->getNumArgs() == 2) {
57 Op = OO->getOperator();
58 LHS = OO->getArg(0);
59 RHS = OO->getArg(1);
60 Loc = OO->getOperatorLoc();
61 }
62 }
63 }
64
65 bool isAnd() const { return Op == OO_AmpAmp; }
66 bool isOr() const { return Op == OO_PipePipe; }
67 explicit operator bool() const { return isAnd() || isOr(); }
68
69 const Expr *getLHS() const { return LHS; }
70 const Expr *getRHS() const { return RHS; }
71 OverloadedOperatorKind getOp() const { return Op; }
72
73 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
74 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
75 }
76
77 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
78 ExprResult RHS) const {
79 assert((isAnd() || isOr()) && "Not the right kind of op?");
80 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
81
82 if (!LHS.isUsable() || !RHS.isUsable())
83 return ExprEmpty();
84
85 // We should just be able to 'normalize' these to the builtin Binary
86 // Operator, since that is how they are evaluated in constriant checks.
87 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
89 SemaRef.Context.BoolTy, VK_PRValue,
90 OK_Ordinary, Loc, FPOptionsOverride{});
91 }
92};
93} // namespace
94
95bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
96 Token NextToken, bool *PossibleNonPrimary,
97 bool IsTrailingRequiresClause) {
98 // C++2a [temp.constr.atomic]p1
99 // ..E shall be a constant expression of type bool.
100
101 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
102
103 if (LogicalBinOp BO = ConstraintExpression) {
104 return CheckConstraintExpression(BO.getLHS(), NextToken,
105 PossibleNonPrimary) &&
106 CheckConstraintExpression(BO.getRHS(), NextToken,
107 PossibleNonPrimary);
108 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
109 return CheckConstraintExpression(C->getSubExpr(), NextToken,
110 PossibleNonPrimary);
111
112 QualType Type = ConstraintExpression->getType();
113
114 auto CheckForNonPrimary = [&] {
115 if (!PossibleNonPrimary)
116 return;
117
118 *PossibleNonPrimary =
119 // We have the following case:
120 // template<typename> requires func(0) struct S { };
121 // The user probably isn't aware of the parentheses required around
122 // the function call, and we're only going to parse 'func' as the
123 // primary-expression, and complain that it is of non-bool type.
124 //
125 // However, if we're in a lambda, this might also be:
126 // []<typename> requires var () {};
127 // Which also looks like a function call due to the lambda parentheses,
128 // but unlike the first case, isn't an error, so this check is skipped.
129 (NextToken.is(tok::l_paren) &&
130 (IsTrailingRequiresClause ||
131 (Type->isDependentType() &&
132 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
133 !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
134 Type->isFunctionType() ||
135 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
136 // We have the following case:
137 // template<typename T> requires size_<T> == 0 struct S { };
138 // The user probably isn't aware of the parentheses required around
139 // the binary operator, and we're only going to parse 'func' as the
140 // first operand, and complain that it is of non-bool type.
141 getBinOpPrecedence(NextToken.getKind(),
142 /*GreaterThanIsOperator=*/true,
144 };
145
146 // An atomic constraint!
147 if (ConstraintExpression->isTypeDependent()) {
148 CheckForNonPrimary();
149 return true;
150 }
151
152 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
153 Diag(ConstraintExpression->getExprLoc(),
154 diag::err_non_bool_atomic_constraint)
155 << Type << ConstraintExpression->getSourceRange();
156 CheckForNonPrimary();
157 return false;
158 }
159
160 if (PossibleNonPrimary)
161 *PossibleNonPrimary = false;
162 return true;
163}
164
165namespace {
166struct SatisfactionStackRAII {
167 Sema &SemaRef;
168 bool Inserted = false;
169 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
170 const llvm::FoldingSetNodeID &FSNID)
171 : SemaRef(SemaRef) {
172 if (ND) {
173 SemaRef.PushSatisfactionStackEntry(ND, FSNID);
174 Inserted = true;
175 }
176 }
177 ~SatisfactionStackRAII() {
178 if (Inserted)
180 }
181};
182} // namespace
183
185 Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E,
186 const MultiLevelTemplateArgumentList *MLTAL = nullptr) {
187 E->Profile(ID, S.Context, /*Canonical=*/true);
188 if (MLTAL) {
189 for (const auto &List : *MLTAL)
190 for (const auto &TemplateArg : List.Args)
192 .Profile(ID, S.Context);
193 }
194 if (S.SatisfactionStackContains(Templ, ID)) {
195 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
196 << E << E->getSourceRange();
197 return true;
198 }
199 return false;
200}
201
202// Figure out the to-translation-unit depth for this function declaration for
203// the purpose of seeing if they differ by constraints. This isn't the same as
204// getTemplateDepth, because it includes already instantiated parents.
205static unsigned
207 bool SkipForSpecialization = false) {
209 ND, ND->getLexicalDeclContext(), /*Final=*/false,
210 /*Innermost=*/std::nullopt,
211 /*RelativeToPrimary=*/true,
212 /*Pattern=*/nullptr,
213 /*ForConstraintInstantiation=*/true, SkipForSpecialization);
214 return MLTAL.getNumLevels();
215}
216
217namespace {
218class AdjustConstraints : public TreeTransform<AdjustConstraints> {
219 unsigned TemplateDepth = 0;
220
221 bool RemoveNonPackExpansionPacks = false;
222
223public:
224 using inherited = TreeTransform<AdjustConstraints>;
225 AdjustConstraints(Sema &SemaRef, unsigned TemplateDepth,
226 bool RemoveNonPackExpansionPacks = false)
227 : inherited(SemaRef), TemplateDepth(TemplateDepth),
228 RemoveNonPackExpansionPacks(RemoveNonPackExpansionPacks) {}
229
230 ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
231 UnsignedOrNone NumExpansions) {
232 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc, NumExpansions);
233 }
234
235 TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
236 SourceLocation EllipsisLoc,
237 UnsignedOrNone NumExpansions) {
238 if (!RemoveNonPackExpansionPacks)
239 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc,
240 NumExpansions);
241 return Pattern;
242 }
243
244 bool PreparePackForExpansion(TemplateArgumentLoc In, bool Uneval,
245 TemplateArgumentLoc &Out, UnexpandedInfo &Info) {
246 if (!RemoveNonPackExpansionPacks)
247 return inherited::PreparePackForExpansion(In, Uneval, Out, Info);
248 assert(In.getArgument().isPackExpansion());
249 Out = In;
250 Info.Expand = false;
251 return false;
252 }
253
254 using inherited::TransformTemplateTypeParmType;
255 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
256 TemplateTypeParmTypeLoc TL, bool) {
257 const TemplateTypeParmType *T = TL.getTypePtr();
258
259 TemplateTypeParmDecl *NewTTPDecl = nullptr;
260 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
261 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
262 TransformDecl(TL.getNameLoc(), OldTTPDecl));
263
264 QualType Result = getSema().Context.getTemplateTypeParmType(
265 T->getDepth() + TemplateDepth, T->getIndex(),
266 RemoveNonPackExpansionPacks ? false : T->isParameterPack(), NewTTPDecl);
267 TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
268 NewTL.setNameLoc(TL.getNameLoc());
269 return Result;
270 }
271
272 bool AlreadyTransformed(QualType T) {
273 if (T.isNull())
274 return true;
275
278 return false;
279 return true;
280 }
281
282 ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
283 NonTypeTemplateParmDecl *NTTP =
284 dyn_cast<NonTypeTemplateParmDecl>(E->getDecl());
285 if (!NTTP)
286 return inherited::TransformDeclRefExpr(E);
287
288 assert(E->getTemplateArgs() == nullptr &&
289 "Template arguments for NTTP decl?");
290 auto *TSI = inherited::TransformType(NTTP->getTypeSourceInfo());
291 if (!TSI)
292 return ExprError();
293
295 SemaRef.getASTContext(), NTTP->getDeclContext(),
296 NTTP->getInnerLocStart(), NTTP->getLocation(),
297 NTTP->getDepth() + TemplateDepth, NTTP->getPosition(),
298 NTTP->getIdentifier(), TSI->getType(),
299 RemoveNonPackExpansionPacks ? false : NTTP->isParameterPack(), TSI);
300
301 return DeclRefExpr::Create(
302 SemaRef.getASTContext(), E->getQualifierLoc(),
304 E->getNameInfo(), TSI->getType(), E->getValueKind(),
305 RemoveNonPackExpansionPacks ? NTTP : D,
306 /*TemplateArgs=*/nullptr, E->isNonOdrUse());
307 }
308};
309} // namespace
310
311namespace {
312
313// FIXME: Convert it to DynamicRecursiveASTVisitor
314class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
315 using inherited = RecursiveASTVisitor<HashParameterMapping>;
316 friend inherited;
317
318 Sema &SemaRef;
319 const MultiLevelTemplateArgumentList &TemplateArgs;
320 llvm::FoldingSetNodeID &ID;
321 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
322
323 UnsignedOrNone OuterPackSubstIndex;
324
325 bool shouldVisitTemplateInstantiations() const { return true; }
326
327public:
328 HashParameterMapping(Sema &SemaRef,
329 const MultiLevelTemplateArgumentList &TemplateArgs,
330 llvm::FoldingSetNodeID &ID,
331 UnsignedOrNone OuterPackSubstIndex)
332 : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),
333 OuterPackSubstIndex(OuterPackSubstIndex) {}
334
335 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
336 // A lambda expression can introduce template parameters that don't have
337 // corresponding template arguments yet.
338 if (T->getDepth() >= TemplateArgs.getNumLevels())
339 return true;
340
341 // There might not be a corresponding template argument before substituting
342 // into the parameter mapping, e.g. a sizeof... expression.
343 if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
344 return true;
345
346 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
347
348 // In concept parameter mapping for fold expressions, packs that aren't
349 // expanded in place are treated as having non-pack dependency, so that
350 // a PackExpansionType won't prevent expanding the packs outside the
351 // TreeTransform. However we still need to check the pack at this point.
352 if ((T->isParameterPack() ||
353 (T->getDecl() && T->getDecl()->isTemplateParameterPack())) &&
354 SemaRef.ArgPackSubstIndex) {
355 assert(Arg.getKind() == TemplateArgument::Pack &&
356 "Missing argument pack");
357
358 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
359 }
360
361 UsedTemplateArgs.push_back(
363 return true;
364 }
365
366 bool VisitDeclRefExpr(DeclRefExpr *E) {
367 NamedDecl *D = E->getDecl();
368 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
369 if (!NTTP)
370 return TraverseDecl(D);
371
372 if (NTTP->getDepth() >= TemplateArgs.getNumLevels())
373 return true;
374
375 if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), NTTP->getIndex()))
376 return true;
377
378 TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
379 // In concept parameter mapping for fold expressions, packs that aren't
380 // expanded in place are treated as having non-pack dependency, so that
381 // a PackExpansionType won't prevent expanding the packs outside the
382 // TreeTransform. However we still need to check the pack at this point.
383 if ((NTTP->isParameterPack() ||
384 (E->getFoundDecl() && E->getFoundDecl() != E->getDecl() &&
385 E->getFoundDecl()->isParameterPack())) &&
386 SemaRef.ArgPackSubstIndex) {
387 assert(Arg.getKind() == TemplateArgument::Pack &&
388 "Missing argument pack");
389 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
390 }
391
392 UsedTemplateArgs.push_back(
394 return true;
395 }
396
397 bool VisitTypedefType(TypedefType *TT) {
398 return inherited::TraverseType(TT->desugar());
399 }
400
401 bool TraverseDecl(Decl *D) {
402 if (auto *VD = dyn_cast<ValueDecl>(D)) {
403 if (auto *Var = dyn_cast<VarDecl>(VD))
404 TraverseStmt(Var->getInit());
405 return TraverseType(VD->getType());
406 }
407
408 return inherited::TraverseDecl(D);
409 }
410
411 bool TraverseCallExpr(CallExpr *CE) {
412 inherited::TraverseStmt(CE->getCallee());
413
414 for (Expr *Arg : CE->arguments())
415 inherited::TraverseStmt(Arg);
416
417 return true;
418 }
419
420 bool TraverseCXXThisExpr(CXXThisExpr *E) {
421 return inherited::TraverseType(E->getType());
422 }
423
424 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
425 // We don't care about TypeLocs. So traverse Types instead.
426 return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);
427 }
428
429 bool TraverseDependentNameType(const DependentNameType *T,
430 bool /*TraverseQualifier*/) {
431 return TraverseNestedNameSpecifier(T->getQualifier());
432 }
433
434 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
435 // T's parent can be dependent while T doesn't have any template arguments.
436 // We should have already traversed its qualifier.
437 // FIXME: Add an assert to catch cases where we failed to profile the
438 // concept.
439 return true;
440 }
441
442 bool TraverseUnresolvedUsingType(UnresolvedUsingType *T,
443 bool TraverseQualifier) {
444 // Sometimes the written type doesn't contain a qualifier which contains
445 // necessary template arguments, whereas the declaration does.
446 if (NestedNameSpecifier NNS = T->getDecl()->getQualifier();
447 TraverseQualifier && NNS)
448 return inherited::TraverseNestedNameSpecifier(NNS);
449 return inherited::TraverseUnresolvedUsingType(T, TraverseQualifier);
450 }
451
452 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
453 bool TraverseQualifier) {
454 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
455 }
456
457 bool TraverseTemplateArgument(const TemplateArgument &Arg) {
459 // Act as if we are fully expanding this pack, if it is a PackExpansion.
460 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
461 llvm::SaveAndRestore<UnsignedOrNone> _2(OuterPackSubstIndex,
462 std::nullopt);
463 return inherited::TraverseTemplateArgument(Arg);
464 }
465
466 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
467 return inherited::TraverseTemplateArgument(Arg);
468 }
469
470 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
471 return TraverseDecl(SOPE->getPack());
472 }
473
474 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
475 return inherited::TraverseStmt(E->getReplacement());
476 }
477
478 bool TraverseTemplateName(TemplateName Template) {
479 if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
480 Template.getAsTemplateDecl());
481 TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
482 if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
483 TTP->getPosition()))
484 return true;
485
486 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
487 if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
488 assert(Arg.getKind() == TemplateArgument::Pack &&
489 "Missing argument pack");
490 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
491 }
492 assert(!Arg.getAsTemplate().isNull() &&
493 "Null template template argument");
494 UsedTemplateArgs.push_back(
496 }
497 return inherited::TraverseTemplateName(Template);
498 }
499
500 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
501 if (!Constraint.hasParameterMapping()) {
502 for (const auto &List : TemplateArgs)
503 for (const TemplateArgument &Arg : List.Args)
505 ID, SemaRef.Context);
506 return;
507 }
508
509 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
510 Constraint.getParameterMapping();
511 for (auto &ArgLoc : Mapping) {
512 TemplateArgument Canonical =
513 SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());
514 // We don't want sugars to impede the profile of cache.
515 UsedTemplateArgs.push_back(Canonical);
516 TraverseTemplateArgument(Canonical);
517 }
518
519 for (auto &Used : UsedTemplateArgs) {
520 llvm::FoldingSetNodeID R;
521 Used.Profile(R, SemaRef.Context);
522 ID.AddNodeID(R);
523 }
524 }
525};
526
527class ConstraintSatisfactionChecker {
528 Sema &S;
529 const NamedDecl *Template;
530 const ConceptReference *TopLevelConceptId;
531 SourceLocation TemplateNameLoc;
532 UnsignedOrNone PackSubstitutionIndex;
533 ConstraintSatisfaction &Satisfaction;
534 bool BuildExpression;
535
536 // The closest concept declaration when evaluating atomic constraints.
537 ConceptDecl *ParentConcept = nullptr;
538
539 // This is for TemplateInstantiator to not instantiate the same template
540 // parameter mapping many times, in order to improve substitution performance.
541 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
542 CachedTemplateArgs;
543
544private:
545 template <class Constraint>
546 UnsignedOrNone getOuterPackIndex(const Constraint &C) const {
547 return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex()
548 : PackSubstitutionIndex;
549 }
550
552 EvaluateAtomicConstraint(const Expr *AtomicExpr,
553 const MultiLevelTemplateArgumentList &MLTAL);
554
555 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
556 const FoldExpandedConstraint &FE,
557 const MultiLevelTemplateArgumentList &MLTAL);
558
559 // XXX: It is SLOW! Use it very carefully.
560 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
561 const NormalizedConstraintWithParamMapping &Constraint,
562 const MultiLevelTemplateArgumentList &MLTAL,
563 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
564
565 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
566 const MultiLevelTemplateArgumentList &MLTAL);
567
568 ExprResult Evaluate(const AtomicConstraint &Constraint,
569 const MultiLevelTemplateArgumentList &MLTAL);
570
571 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
572 const MultiLevelTemplateArgumentList &MLTAL);
573
574 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
575 const MultiLevelTemplateArgumentList &MLTAL);
576
577 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
578 const MultiLevelTemplateArgumentList &MLTAL,
579 unsigned int Size);
580
581 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
582 const MultiLevelTemplateArgumentList &MLTAL);
583
584 ExprResult Evaluate(const CompoundConstraint &Constraint,
585 const MultiLevelTemplateArgumentList &MLTAL);
586
587public:
588 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
589 const ConceptReference *TopLevelConceptId,
590 SourceLocation TemplateNameLoc,
591 UnsignedOrNone PackSubstitutionIndex,
592 ConstraintSatisfaction &Satisfaction,
593 bool BuildExpression)
594 : S(SemaRef), Template(Template), TopLevelConceptId(TopLevelConceptId),
595 TemplateNameLoc(TemplateNameLoc),
596 PackSubstitutionIndex(PackSubstitutionIndex),
597 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
598
599 ExprResult Evaluate(const NormalizedConstraint &Constraint,
600 const MultiLevelTemplateArgumentList &MLTAL);
601};
602
603StringRef allocateStringFromConceptDiagnostic(const Sema &S,
604 const PartialDiagnostic Diag) {
605 SmallString<128> DiagString;
606 DiagString = ": ";
607 Diag.EmitToString(S.getDiagnostics(), DiagString);
608 return S.getASTContext().backupStr(DiagString);
609}
610
611} // namespace
612
613ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
614 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
615 llvm::FoldingSetNodeID ID;
616 if (Template &&
618 Satisfaction.IsSatisfied = false;
619 Satisfaction.ContainsErrors = true;
620 return ExprEmpty();
621 }
622 SatisfactionStackRAII StackRAII(S, Template, ID);
623
624 // Atomic constraint - substitute arguments and check satisfaction.
625 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
626 {
627 TemplateDeductionInfo Info(TemplateNameLoc);
631 // FIXME: improve const-correctness of InstantiatingTemplate
632 const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());
633 if (Inst.isInvalid())
634 return ExprError();
635
636 // We do not want error diagnostics escaping here.
637 Sema::SFINAETrap Trap(S, Info);
638 SubstitutedExpression =
639 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
640
641 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
642 // C++2a [temp.constr.atomic]p1
643 // ...If substitution results in an invalid type or expression, the
644 // constraint is not satisfied.
645 if (!Trap.hasErrorOccurred())
646 // A non-SFINAE error has occurred as a result of this
647 // substitution.
648 return ExprError();
649
652 Info.takeSFINAEDiagnostic(SubstDiag);
653 // FIXME: This is an unfortunate consequence of there
654 // being no serialization code for PartialDiagnostics and the fact
655 // that serializing them would likely take a lot more storage than
656 // just storing them as strings. We would still like, in the
657 // future, to serialize the proper PartialDiagnostic as serializing
658 // it as a string defeats the purpose of the diagnostic mechanism.
659 Satisfaction.Details.emplace_back(
661 SubstDiag.first,
662 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
663 Satisfaction.IsSatisfied = false;
664 return ExprEmpty();
665 }
666 }
667
668 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
669 return ExprError();
670
671 // [temp.constr.atomic]p3: To determine if an atomic constraint is
672 // satisfied, the parameter mapping and template arguments are first
673 // substituted into its expression. If substitution results in an
674 // invalid type or expression, the constraint is not satisfied.
675 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
676 // and E shall be a constant expression of type bool.
677 //
678 // Perform the L to R Value conversion if necessary. We do so for all
679 // non-PRValue categories, else we fail to extend the lifetime of
680 // temporaries, and that fails the constant expression check.
681 if (!SubstitutedExpression.get()->isPRValue())
682 SubstitutedExpression = ImplicitCastExpr::Create(
683 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
684 SubstitutedExpression.get(),
685 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
686
687 return SubstitutedExpression;
688}
689
690std::optional<MultiLevelTemplateArgumentList>
691ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
692 const NormalizedConstraintWithParamMapping &Constraint,
694 llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {
695
696 if (!Constraint.hasParameterMapping()) {
697 if (MLTAL.getNumSubstitutedLevels())
698 SubstitutedOutermost.assign(MLTAL.getOutermost());
699 return MLTAL;
700 }
701
702 // The mapping is empty, meaning no template arguments are needed for
703 // evaluation.
704 if (Constraint.getParameterMapping().empty())
706
707 TemplateDeductionInfo Info(Constraint.getBeginLoc());
708 Sema::SFINAETrap Trap(S, Info);
710 S, Constraint.getBeginLoc(),
712 // FIXME: improve const-correctness of InstantiatingTemplate
713 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
714 if (Inst.isInvalid())
715 return std::nullopt;
716
717 TemplateArgumentListInfo SubstArgs;
718 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
719
720 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
721 &CachedTemplateArgs);
722
723 // We don't want the template argument substitution into parameter
724 // mappings to preserve the outer depths.
726 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
727 SubstArgs)) {
728 Satisfaction.IsSatisfied = false;
729 return std::nullopt;
730 }
731
733 auto *TD = const_cast<TemplateDecl *>(
736 TD->getLocation(), SubstArgs,
737 /*DefaultArguments=*/{},
738 /*PartialTemplateArgs=*/false, CTAI))
739 return std::nullopt;
741 Constraint.mappingOccurenceList();
742 // The empty MLTAL situation should only occur when evaluating non-dependent
743 // constraints.
744 if (MLTAL.getNumSubstitutedLevels())
745 SubstitutedOutermost =
746 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
747 unsigned Offset = 0;
748 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
750 if (Used[I])
752 CTAI.SugaredConverted[MappedIndex++]);
753 if (I < SubstitutedOutermost.size()) {
754 SubstitutedOutermost[I] = Arg;
755 Offset = I + 1;
756 } else {
757 SubstitutedOutermost.push_back(Arg);
758 Offset = SubstitutedOutermost.size();
759 }
760 }
761 if (Offset < SubstitutedOutermost.size())
762 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
763
764 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
765 SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,
766 /*Final=*/false);
767 return std::move(SubstitutedTemplateArgs);
768}
769
770ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
771 const AtomicConstraint &Constraint,
772 const MultiLevelTemplateArgumentList &MLTAL) {
773 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
774 // The ConceptDecl as a ContextDecl ensures that, when evaluating constraints
775 // on transformed lambdas, we don't have extra outer template arguments.
776 if (ParentConcept)
777 EvaluationContext.emplace(
779 else
780 EvaluationContext.emplace(
783
784 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
785 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
786 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
787 if (!SubstitutedArgs) {
788 Satisfaction.IsSatisfied = false;
789 return ExprEmpty();
790 }
791
792 // Make sure that concepts are not evaluated in the context they are used,
793 // i.e they should not have access to the current class object or its
794 // non-public members.
795 std::optional<Sema::ContextRAII> ConceptContext;
796 if (ParentConcept)
797 ConceptContext.emplace(S, ParentConcept->getDeclContext());
798
799 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
800 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
801 Constraint.getConstraintExpr(), *SubstitutedArgs);
802
803 if (SubstitutedAtomicExpr.isInvalid())
804 return ExprError();
805
806 if (SubstitutedAtomicExpr.isUnset())
807 // Evaluator has decided satisfaction without yielding an expression.
808 return ExprEmpty();
809
810 // We don't have the ability to evaluate this, since it contains a
811 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
812 // we'd potentially pick up a different overload, and cause confusing
813 // diagnostics. SO, add a failure detail that will cause us to make this
814 // overload set not viable.
815 if (SubstitutedAtomicExpr.get()->containsErrors()) {
816 Satisfaction.IsSatisfied = false;
817 Satisfaction.ContainsErrors = true;
818
819 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
820 Satisfaction.Details.emplace_back(
822 SubstitutedAtomicExpr.get()->getBeginLoc(),
823 allocateStringFromConceptDiagnostic(S, Msg)});
824 return SubstitutedAtomicExpr;
825 }
826
827 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
828 Satisfaction.IsSatisfied = true;
829 Satisfaction.ContainsErrors = false;
830 return SubstitutedAtomicExpr;
831 }
832
834 Expr::EvalResult EvalResult;
835 EvalResult.Diag = &EvaluationDiags;
836 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
837 S.Context) ||
838 !EvaluationDiags.empty()) {
839 // C++2a [temp.constr.atomic]p1
840 // ...E shall be a constant expression of type bool.
841 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
842 diag::err_non_constant_constraint_expression)
843 << SubstitutedAtomicExpr.get()->getSourceRange();
844 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
845 S.Diag(PDiag.first, PDiag.second);
846 return ExprError();
847 }
848
849 assert(EvalResult.Val.isInt() &&
850 "evaluating bool expression didn't produce int");
851 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
852 if (!Satisfaction.IsSatisfied)
853 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
854
855 return SubstitutedAtomicExpr;
856}
857
858ExprResult ConstraintSatisfactionChecker::Evaluate(
859 const AtomicConstraint &Constraint,
860 const MultiLevelTemplateArgumentList &MLTAL) {
861
862 unsigned Size = Satisfaction.Details.size();
863 llvm::FoldingSetNodeID ID;
864 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
865
866 ID.AddPointer(Constraint.getConstraintExpr());
867 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
868 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
869 .VisitConstraint(Constraint);
870
871 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
873 auto &Cached = Iter->second.Satisfaction;
874 Satisfaction.ContainsErrors = Cached.ContainsErrors;
875 Satisfaction.IsSatisfied = Cached.IsSatisfied;
876 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
877 Cached.Details.begin(), Cached.Details.end());
878 return Iter->second.SubstExpr;
879 }
880
881 ExprResult E = EvaluateSlow(Constraint, MLTAL);
882
884 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
885 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
886 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
887 Satisfaction.Details.begin() + Size,
888 Satisfaction.Details.end());
889 Cache.SubstExpr = E;
890 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
891
892 return E;
893}
894
896ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
897 const FoldExpandedConstraint &FE,
898 const MultiLevelTemplateArgumentList &MLTAL) {
899
900 Expr *Pattern = const_cast<Expr *>(FE.getPattern());
901
903 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
904 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
905 bool Expand = true;
906 bool RetainExpansion = false;
907 UnsignedOrNone NumExpansions(std::nullopt);
909 Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
910 /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
911 NumExpansions, /*Diagnose=*/false) ||
912 !Expand || RetainExpansion)
913 return std::nullopt;
914
915 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)
916 return std::nullopt;
917 return NumExpansions;
918}
919
920ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
921 const FoldExpandedConstraint &Constraint,
922 const MultiLevelTemplateArgumentList &MLTAL) {
923
924 bool Conjunction = Constraint.getFoldOperator() ==
926 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
927
928 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
929 // FIXME: Is PackSubstitutionIndex correct?
930 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
931 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
932 SubstitutionInTemplateArguments(
933 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
934 MLTAL, SubstitutedOutermost);
935 if (!SubstitutedArgs) {
936 Satisfaction.IsSatisfied = false;
937 return ExprError();
938 }
939
941 UnsignedOrNone NumExpansions =
942 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
943 if (!NumExpansions)
944 return ExprEmpty();
945
946 if (*NumExpansions == 0) {
947 Satisfaction.IsSatisfied = Conjunction;
948 return ExprEmpty();
949 }
950
951 for (unsigned I = 0; I < *NumExpansions; I++) {
952 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
953 Satisfaction.IsSatisfied = false;
954 Satisfaction.ContainsErrors = false;
956 ConstraintSatisfactionChecker(S, Template, TopLevelConceptId,
957 TemplateNameLoc, UnsignedOrNone(I),
958 Satisfaction,
959 /*BuildExpression=*/false)
960 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
961 if (BuildExpression) {
962 if (Out.isUnset() || !Expr.isUsable())
963 Out = Expr;
964 else
965 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
966 Conjunction ? BinaryOperatorKind::BO_LAnd
967 : BinaryOperatorKind::BO_LOr,
969 Constraint.getBeginLoc(),
971 }
972 if (!Conjunction && Satisfaction.IsSatisfied) {
973 Satisfaction.Details.erase(Satisfaction.Details.begin() +
974 EffectiveDetailEndIndex,
975 Satisfaction.Details.end());
976 break;
977 }
978 if (Satisfaction.IsSatisfied != Conjunction)
979 return Out;
980 }
981
982 return Out;
983}
984
985ExprResult ConstraintSatisfactionChecker::Evaluate(
986 const FoldExpandedConstraint &Constraint,
987 const MultiLevelTemplateArgumentList &MLTAL) {
988
989 llvm::FoldingSetNodeID ID;
990 ID.AddPointer(Constraint.getPattern());
991 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
992
993 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
995
996 auto &Cached = Iter->second.Satisfaction;
997 Satisfaction.ContainsErrors = Cached.ContainsErrors;
998 Satisfaction.IsSatisfied = Cached.IsSatisfied;
999 Satisfaction.Details.insert(Satisfaction.Details.end(),
1000 Cached.Details.begin(), Cached.Details.end());
1001 return Iter->second.SubstExpr;
1002 }
1003
1004 unsigned Size = Satisfaction.Details.size();
1005
1006 ExprResult E = EvaluateSlow(Constraint, MLTAL);
1008 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1009 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1010 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1011 Satisfaction.Details.begin() + Size,
1012 Satisfaction.Details.end());
1013 Cache.SubstExpr = E;
1014 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1015 return E;
1016}
1017
1018ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1019 const ConceptIdConstraint &Constraint,
1020 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
1021 const ConceptReference *ConceptId = Constraint.getConceptId();
1022
1023 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
1024 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1025 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1026
1027 if (!SubstitutedArgs) {
1028 Satisfaction.IsSatisfied = false;
1029 // FIXME: diagnostics?
1030 return ExprError();
1031 }
1032
1033 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
1034
1035 const ASTTemplateArgumentListInfo *Ori =
1036 ConceptId->getTemplateArgsAsWritten();
1037 TemplateDeductionInfo Info(TemplateNameLoc);
1038 Sema::SFINAETrap Trap(S, Info);
1041 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
1042
1043 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
1044
1045 // There's a concern that even with the same concept, they may not have the
1046 // same ConceptReference, if they come from modules.
1047 if (TopLevelConceptId &&
1048 ConceptId->getNamedConcept().getAsTemplateDecl() ==
1049 TopLevelConceptId->getNamedConcept().getAsTemplateDecl()) {
1050 for (auto &A : Ori->arguments())
1051 OutArgs.addArgument(A);
1052 } else if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs,
1053 OutArgs) ||
1054 Trap.hasErrorOccurred()) {
1055 Satisfaction.IsSatisfied = false;
1056 if (!Trap.hasErrorOccurred())
1057 return ExprError();
1058
1061 Info.takeSFINAEDiagnostic(SubstDiag);
1062 // FIXME: This is an unfortunate consequence of there
1063 // being no serialization code for PartialDiagnostics and the fact
1064 // that serializing them would likely take a lot more storage than
1065 // just storing them as strings. We would still like, in the
1066 // future, to serialize the proper PartialDiagnostic as serializing
1067 // it as a string defeats the purpose of the diagnostic mechanism.
1068 Satisfaction.Details.insert(
1069 Satisfaction.Details.begin() + Size,
1071 SubstDiag.first,
1072 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
1073 return ExprError();
1074 }
1075
1076 CXXScopeSpec SS;
1077 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
1078
1079 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1080 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
1081 ConceptId->getFoundDecl(),
1082 ConceptId->getNamedConcept().getAsTemplateDecl(), &OutArgs,
1083 /*DoCheckConstraintSatisfaction=*/false);
1084
1085 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
1086 return ExprError();
1087
1088 if (Size != Satisfaction.Details.size()) {
1089 Satisfaction.Details.insert(
1090 Satisfaction.Details.begin() + Size,
1092 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
1093 ->getConceptReference()));
1094 }
1095 return SubstitutedConceptId;
1096}
1097
1098ExprResult ConstraintSatisfactionChecker::Evaluate(
1099 const ConceptIdConstraint &Constraint,
1100 const MultiLevelTemplateArgumentList &MLTAL) {
1101
1102 const ConceptReference *ConceptId = Constraint.getConceptId();
1103 Sema::InstantiatingTemplate InstTemplate(
1104 S, ConceptId->getBeginLoc(),
1106 ConceptId->getNamedConcept().getAsTemplateDecl(),
1107 // We may have empty template arguments when checking non-dependent
1108 // nested constraint expressions.
1109 // In such cases, non-SFINAE errors would have already been diagnosed
1110 // during parameter mapping substitution, so the instantiating template
1111 // arguments are less useful here.
1112 MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
1114 Constraint.getSourceRange());
1115 if (InstTemplate.isInvalid())
1116 return ExprError();
1117
1118 unsigned Size = Satisfaction.Details.size();
1119
1120 llvm::SaveAndRestore PushConceptDecl(
1121 ParentConcept,
1123
1124 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
1125
1126 if (E.isInvalid()) {
1127 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1128 return E;
1129 }
1130
1131 // ConceptIdConstraint is only relevant for diagnostics,
1132 // so if the normalized constraint is satisfied, we should not
1133 // substitute into the constraint.
1134 if (Satisfaction.IsSatisfied)
1135 return E;
1136
1137 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
1138 llvm::FoldingSetNodeID ID;
1139 ID.AddPointer(Constraint.getConceptId());
1140 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
1141 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1142 .VisitConstraint(Constraint);
1143
1144 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
1146
1147 auto &Cached = Iter->second.Satisfaction;
1148 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1149 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1150 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1151 Cached.Details.begin(), Cached.Details.end());
1152 return Iter->second.SubstExpr;
1153 }
1154
1155 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1156 if (CE.isInvalid())
1157 return E;
1159 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1160 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1161 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1162 Satisfaction.Details.begin() + Size,
1163 Satisfaction.Details.end());
1164 Cache.SubstExpr = CE;
1165 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1166 return CE;
1167}
1168
1169ExprResult ConstraintSatisfactionChecker::Evaluate(
1170 const CompoundConstraint &Constraint,
1171 const MultiLevelTemplateArgumentList &MLTAL) {
1172
1173 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1174
1175 bool Conjunction =
1177
1178 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1179
1180 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1181 return LHS;
1182
1183 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
1184 !Satisfaction.ContainsErrors)
1185 return LHS;
1186
1187 Satisfaction.ContainsErrors = false;
1188 Satisfaction.IsSatisfied = false;
1189
1190 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1191
1192 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
1193 !Satisfaction.ContainsErrors)
1194 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1195 EffectiveDetailEndIndex,
1196 Satisfaction.Details.end());
1197
1198 if (!BuildExpression)
1199 return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
1200
1201 if (!LHS.isUsable())
1202 return RHS;
1203
1204 if (!RHS.isUsable())
1205 return LHS;
1206
1207 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1208 Conjunction ? BinaryOperatorKind::BO_LAnd
1209 : BinaryOperatorKind::BO_LOr,
1211 Constraint.getBeginLoc(), FPOptionsOverride{});
1212}
1213
1214ExprResult ConstraintSatisfactionChecker::Evaluate(
1215 const NormalizedConstraint &Constraint,
1216 const MultiLevelTemplateArgumentList &MLTAL) {
1217 switch (Constraint.getKind()) {
1219 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1220
1222 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1223 MLTAL);
1224
1226 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1227 MLTAL);
1228
1230 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1231 }
1232 llvm_unreachable("Unknown ConstraintKind enum");
1233}
1234
1236 Sema &S, const NamedDecl *Template,
1237 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1238 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1239 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1240 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1241
1242 if (ConvertedExpr)
1243 *ConvertedExpr = nullptr;
1244
1245 if (AssociatedConstraints.empty()) {
1246 Satisfaction.IsSatisfied = true;
1247 return false;
1248 }
1249
1250 // In the general case, we can't check satisfaction if the arguments contain
1251 // unsubstituted template parameters, even if they are purely syntactic,
1252 // because they may still turn out to be invalid after substitution.
1253 // This could be permitted in cases where this substitution will still be
1254 // attempted later and diagnosed, such as function template specializations,
1255 // but that's not the case for concept specializations.
1256 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1257 Satisfaction.IsSatisfied = true;
1258 return false;
1259 }
1260
1262 if (TemplateArgsLists.getNumLevels() != 0)
1263 Args = TemplateArgsLists.getInnermost();
1264
1265 struct SynthesisContextPair {
1268 SynthesisContextPair(Sema &S, NamedDecl *Template,
1269 ArrayRef<TemplateArgument> TemplateArgs,
1270 SourceRange InstantiationRange)
1271 : Inst(S, InstantiationRange.getBegin(),
1273 TemplateArgs, InstantiationRange),
1274 NSC(S) {}
1275 };
1276 std::optional<SynthesisContextPair> SynthesisContext;
1277 if (!TopLevelConceptId)
1278 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
1279 TemplateIDRange);
1280
1281 const NormalizedConstraint *C =
1282 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1283 if (!C) {
1284 Satisfaction.IsSatisfied = false;
1285 return true;
1286 }
1287
1288 if (TopLevelConceptId)
1289 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1290 const_cast<NormalizedConstraint *>(C),
1291 Template, /*CSE=*/nullptr,
1293
1294 ExprResult Res =
1295 ConstraintSatisfactionChecker(
1296 S, Template, TopLevelConceptId, TemplateIDRange.getBegin(),
1297 S.ArgPackSubstIndex, Satisfaction,
1298 /*BuildExpression=*/ConvertedExpr != nullptr)
1299 .Evaluate(*C, TemplateArgsLists);
1300
1301 if (Res.isInvalid())
1302 return true;
1303
1304 if (Res.isUsable() && ConvertedExpr)
1305 *ConvertedExpr = Res.get();
1306
1307 return false;
1308}
1309
1312 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1313 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1314 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1315 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1316 llvm::TimeTraceScope TimeScope(
1317 "CheckConstraintSatisfaction", [TemplateIDRange, this] {
1318 return TemplateIDRange.printToString(getSourceManager());
1319 });
1320 if (AssociatedConstraints.empty()) {
1321 OutSatisfaction.IsSatisfied = true;
1322 return false;
1323 }
1324 const auto *Template = Entity.dyn_cast<const NamedDecl *>();
1325 if (!Template) {
1326 return ::CheckConstraintSatisfaction(
1327 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1328 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1329 }
1330 // Invalid templates could make their way here. Substituting them could result
1331 // in dependent expressions.
1332 if (Template->isInvalidDecl()) {
1333 OutSatisfaction.IsSatisfied = false;
1334 return true;
1335 }
1336
1337 // A list of the template argument list flattened in a predictible manner for
1338 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1339 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1340 // here.
1342 for (auto List : TemplateArgsLists)
1343 for (const TemplateArgument &Arg : List.Args)
1344 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1345
1346 const NamedDecl *Owner = Template;
1347 if (TopLevelConceptId)
1348 Owner = TopLevelConceptId->getNamedConcept().getAsTemplateDecl();
1349
1350 llvm::FoldingSetNodeID ID;
1351 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1352 void *InsertPos;
1353 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1354 OutSatisfaction = *Cached;
1355 return false;
1356 }
1357
1358 auto Satisfaction =
1359 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1361 *this, Template, AssociatedConstraints, TemplateArgsLists,
1362 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1363 OutSatisfaction = std::move(*Satisfaction);
1364 return true;
1365 }
1366
1367 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1368 // The evaluation of this constraint resulted in us trying to re-evaluate it
1369 // recursively. This isn't really possible, except we try to form a
1370 // RecoveryExpr as a part of the evaluation. If this is the case, just
1371 // return the 'cached' version (which will have the same result), and save
1372 // ourselves the extra-insert. If it ever becomes possible to legitimately
1373 // recursively check a constraint, we should skip checking the 'inner' one
1374 // above, and replace the cached version with this one, as it would be more
1375 // specific.
1376 OutSatisfaction = *Cached;
1377 return false;
1378 }
1379
1380 // Else we can simply add this satisfaction to the list.
1381 OutSatisfaction = *Satisfaction;
1382 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
1383 // invalidated it.
1384 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1385 SatisfactionCache.InsertNode(Satisfaction.release());
1386 return false;
1387}
1388
1389static ExprResult
1391 const ConceptSpecializationExpr *CSE,
1392 UnsignedOrNone SubstIndex) {
1393 Sema::SFINAETrap Trap(S);
1394 // [C++2c] [temp.constr.normal]
1395 // Otherwise, to form CE, any non-dependent concept template argument Ai
1396 // is substituted into the constraint-expression of C.
1397 // If any such substitution results in an invalid concept-id,
1398 // the program is ill-formed; no diagnostic is required.
1399
1401 Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
1402
1403 const ASTTemplateArgumentListInfo *ArgsAsWritten =
1405 if (llvm::none_of(
1406 ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {
1407 return !ArgLoc.getArgument().isDependent() &&
1408 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1409 })) {
1410 return Concept->getConstraintExpr();
1411 }
1412
1414 Concept, Concept->getLexicalDeclContext(),
1415 /*Final=*/false, CSE->getTemplateArguments(),
1416 /*RelativeToPrimary=*/true,
1417 /*Pattern=*/nullptr,
1418 /*ForConstraintInstantiation=*/true);
1419 return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),
1420 MLTAL);
1421}
1422
1423bool Sema::SetupConstraintScope(
1424 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1425 const MultiLevelTemplateArgumentList &MLTAL,
1427 assert(!isLambdaCallOperator(FD) &&
1428 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1429 "instantiations");
1430 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1431 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1433 *this, FD->getPointOfInstantiation(),
1434 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1435 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1436 SourceRange());
1437 if (Inst.isInvalid())
1438 return true;
1439
1440 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1441 // 'instantiated' parameters and adds it to the context. For the case where
1442 // this function is a template being instantiated NOW, we also need to add
1443 // the list of current template arguments to the list so that they also can
1444 // be picked out of the map.
1445 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1446 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1447 /*Final=*/false);
1448 if (addInstantiatedParametersToScope(
1449 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1450 return true;
1451 }
1452
1453 // If this is a member function, make sure we get the parameters that
1454 // reference the original primary template.
1455 if (FunctionTemplateDecl *FromMemTempl =
1456 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1457 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1458 Scope, MLTAL))
1459 return true;
1460 }
1461
1462 return false;
1463 }
1464
1467 FunctionDecl *InstantiatedFrom =
1471
1473 *this, FD->getPointOfInstantiation(),
1474 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1475 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1476 SourceRange());
1477 if (Inst.isInvalid())
1478 return true;
1479
1480 // Case where this was not a template, but instantiated as a
1481 // child-function.
1482 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1483 return true;
1484 }
1485
1486 return false;
1487}
1488
1489// This function collects all of the template arguments for the purposes of
1490// constraint-instantiation and checking.
1491std::optional<MultiLevelTemplateArgumentList>
1492Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1493 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1495 MultiLevelTemplateArgumentList MLTAL;
1496
1497 // Collect the list of template arguments relative to the 'primary' template.
1498 // We need the entire list, since the constraint is completely uninstantiated
1499 // at this point.
1500 MLTAL =
1502 /*Final=*/false, /*Innermost=*/std::nullopt,
1503 /*RelativeToPrimary=*/true,
1504 /*Pattern=*/nullptr,
1505 /*ForConstraintInstantiation=*/true);
1506 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1507 if (isLambdaCallOperator(FD))
1508 return MLTAL;
1509 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1510 return std::nullopt;
1511
1512 return MLTAL;
1513}
1514
1516 ConstraintSatisfaction &Satisfaction,
1517 SourceLocation UsageLoc,
1518 bool ForOverloadResolution) {
1519 // Don't check constraints if the function is dependent. Also don't check if
1520 // this is a function template specialization, as the call to
1521 // CheckFunctionTemplateConstraints after this will check it
1522 // better.
1523 if (FD->isDependentContext() ||
1524 FD->getTemplatedKind() ==
1526 Satisfaction.IsSatisfied = true;
1527 return false;
1528 }
1529
1530 // A lambda conversion operator has the same constraints as the call operator
1531 // and constraints checking relies on whether we are in a lambda call operator
1532 // (and may refer to its parameters), so check the call operator instead.
1533 // Note that the declarations outside of the lambda should also be
1534 // considered. Turning on the 'ForOverloadResolution' flag results in the
1535 // LocalInstantiationScope not looking into its parents, but we can still
1536 // access Decls from the parents while building a lambda RAII scope later.
1537 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1538 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1539 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1540 Satisfaction, UsageLoc,
1541 /*ShouldAddDeclsFromParentScope=*/true);
1542
1543 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1544
1545 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1546 if (isLambdaCallOperator(CtxToSave))
1547 CtxToSave = CtxToSave->getParent()->getParent();
1548 else
1549 CtxToSave = CtxToSave->getNonTransparentContext();
1550 }
1551
1552 ContextRAII SavedContext{*this, CtxToSave};
1553 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1554 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1555 SetupConstraintCheckingTemplateArgumentsAndScope(
1556 const_cast<FunctionDecl *>(FD), {}, Scope);
1557
1558 if (!MLTAL)
1559 return true;
1560
1561 Qualifiers ThisQuals;
1562 CXXRecordDecl *Record = nullptr;
1563 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1564 ThisQuals = Method->getMethodQualifiers();
1565 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1566 }
1567 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1568
1570 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1571 ForOverloadResolution);
1572
1574 FD, FD->getTrailingRequiresClause(), *MLTAL,
1575 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1576 Satisfaction);
1577}
1578
1580 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
1581 const Expr *ConstrExpr) {
1583 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
1584 /*Innermost=*/std::nullopt,
1585 /*RelativeToPrimary=*/true,
1586 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
1587 /*SkipForSpecialization*/ false);
1588
1589 if (MLTAL.getNumSubstitutedLevels() == 0)
1590 return ConstrExpr;
1591
1592 // Set up a dummy 'instantiation' scope in the case of reference to function
1593 // parameters that the surrounding function hasn't been instantiated yet. Note
1594 // this may happen while we're comparing two templates' constraint
1595 // equivalence.
1596 std::optional<LocalInstantiationScope> ScopeForParameters;
1597 if (const NamedDecl *ND = DeclInfo.getDecl();
1598 ND && ND->isFunctionOrFunctionTemplate()) {
1599 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1600 const FunctionDecl *FD = ND->getAsFunction();
1602 Template && Template->getInstantiatedFromMemberTemplate())
1603 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1604 for (auto *PVD : FD->parameters()) {
1605 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1606 continue;
1607 if (!PVD->isParameterPack()) {
1608 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1609 continue;
1610 }
1611 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1612 // to avoid building SubstTemplateTypeParmPackTypes for
1613 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1614 // otherwise reference the AssociatedDecl of the template arguments, which
1615 // is, in this case, the template declaration.
1616 //
1617 // However, as we are in the process of comparing potential
1618 // re-declarations, the canonical declaration is the declaration itself at
1619 // this point. So if we didn't expand these packs, we would end up with an
1620 // incorrect profile difference because we will be profiling the
1621 // canonical types!
1622 //
1623 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1624 // that we can eliminate the Scope in the cases where the declarations are
1625 // not necessarily instantiated. It would also benefit the noexcept
1626 // specifier comparison.
1627 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1628 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1629 }
1630 }
1631
1632 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1633
1634 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1635 // essential for having an injected class as the canonical type for a template
1636 // specialization type at the rebuilding stage. This guarantees that, for
1637 // out-of-line definitions, injected class name types and their equivalent
1638 // template specializations can be profiled to the same value, which makes it
1639 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1640 // perceived identical.
1641 std::optional<Sema::ContextRAII> ContextScope;
1642 const DeclContext *DC = [&] {
1643 if (!DeclInfo.getDecl())
1644 return DeclInfo.getDeclContext();
1645 return DeclInfo.getDecl()->getFriendObjectKind()
1646 ? DeclInfo.getLexicalDeclContext()
1647 : DeclInfo.getDeclContext();
1648 }();
1649 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1650 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1651 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1652 /*NewThisContext=*/false);
1653 }
1654 EnterExpressionEvaluationContext UnevaluatedContext(
1658 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1659 if (!SubstConstr.isUsable())
1660 return nullptr;
1661 return SubstConstr.get();
1662}
1663
1665 const Expr *OldConstr,
1667 const Expr *NewConstr) {
1668 if (OldConstr == NewConstr)
1669 return true;
1670 // C++ [temp.constr.decl]p4
1671 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1672 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1673 Sema::SFINAETrap _(*this);
1674 if (const Expr *SubstConstr =
1676 OldConstr))
1677 OldConstr = SubstConstr;
1678 else
1679 return false;
1680 if (const Expr *SubstConstr =
1682 NewConstr))
1683 NewConstr = SubstConstr;
1684 else
1685 return false;
1686 }
1687
1688 llvm::FoldingSetNodeID ID1, ID2;
1689 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1690 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1691 return ID1 == ID2;
1692}
1693
1695 assert(FD->getFriendObjectKind() && "Must be a friend!");
1696
1697 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1698 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1699 // non-function-template.
1700 assert(FD->getDescribedFunctionTemplate() &&
1701 "Non-function templates don't need to be checked");
1702
1705
1706 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1707 for (const AssociatedConstraint &AC : ACs)
1708 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1709 AC.ConstraintExpr))
1710 return true;
1711
1712 return false;
1713}
1714
1716 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1717 SourceRange TemplateIDRange) {
1718 ConstraintSatisfaction Satisfaction;
1719 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1720 TD->getAssociatedConstraints(AssociatedConstraints);
1721 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1722 TemplateIDRange, Satisfaction))
1723 return true;
1724
1725 if (!Satisfaction.IsSatisfied) {
1726 SmallString<128> TemplateArgString;
1727 TemplateArgString = " ";
1728 TemplateArgString += getTemplateArgumentBindingsText(
1729 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1730 TemplateArgsLists.getInnermost().size());
1731
1732 Diag(TemplateIDRange.getBegin(),
1733 diag::err_template_arg_list_constraints_not_satisfied)
1735 << TemplateArgString << TemplateIDRange;
1736 DiagnoseUnsatisfiedConstraint(Satisfaction);
1737 return true;
1738 }
1739 return false;
1740}
1741
1743 Sema &SemaRef, SourceLocation PointOfInstantiation,
1745 ConstraintSatisfaction &Satisfaction) {
1747 Template->getAssociatedConstraints(TemplateAC);
1748 if (TemplateAC.empty()) {
1749 Satisfaction.IsSatisfied = true;
1750 return false;
1751 }
1752
1754
1755 FunctionDecl *FD = Template->getTemplatedDecl();
1756 // Collect the list of template arguments relative to the 'primary'
1757 // template. We need the entire list, since the constraint is completely
1758 // uninstantiated at this point.
1759
1761 {
1762 // getTemplateInstantiationArgs uses this instantiation context to find out
1763 // template arguments for uninstantiated functions.
1764 // We don't want this RAII object to persist, because there would be
1765 // otherwise duplicate diagnostic notes.
1767 SemaRef, PointOfInstantiation,
1769 PointOfInstantiation);
1770 if (Inst.isInvalid())
1771 return true;
1772 MLTAL = SemaRef.getTemplateInstantiationArgs(
1773 /*D=*/FD, FD,
1774 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1775 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1776 }
1777
1778 Sema::ContextRAII SavedContext(SemaRef, FD);
1779 return SemaRef.CheckConstraintSatisfaction(
1780 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1781}
1782
1784 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1785 ArrayRef<TemplateArgument> TemplateArgs,
1786 ConstraintSatisfaction &Satisfaction) {
1787 // In most cases we're not going to have constraints, so check for that first.
1788 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1789
1790 if (!Template)
1791 return ::CheckFunctionConstraintsWithoutInstantiation(
1792 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1793 TemplateArgs, Satisfaction);
1794
1795 // Note - code synthesis context for the constraints check is created
1796 // inside CheckConstraintsSatisfaction.
1798 Template->getAssociatedConstraints(TemplateAC);
1799 if (TemplateAC.empty()) {
1800 Satisfaction.IsSatisfied = true;
1801 return false;
1802 }
1803
1804 // Enter the scope of this instantiation. We don't use
1805 // PushDeclContext because we don't have a scope.
1806 Sema::ContextRAII savedContext(*this, Decl);
1808
1809 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1810 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1811 Scope);
1812
1813 if (!MLTAL)
1814 return true;
1815
1816 Qualifiers ThisQuals;
1817 CXXRecordDecl *Record = nullptr;
1818 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1819 ThisQuals = Method->getMethodQualifiers();
1820 Record = Method->getParent();
1821 }
1822
1823 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1824 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1825 Scope);
1826
1827 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1828 PointOfInstantiation, Satisfaction);
1829}
1830
1833 bool First) {
1834 assert(!Req->isSatisfied() &&
1835 "Diagnose() can only be used on an unsatisfied requirement");
1836 switch (Req->getSatisfactionStatus()) {
1838 llvm_unreachable("Diagnosing a dependent requirement");
1839 break;
1841 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1842 if (!SubstDiag->DiagMessage.empty())
1843 S.Diag(SubstDiag->DiagLoc,
1844 diag::note_expr_requirement_expr_substitution_error)
1845 << (int)First << SubstDiag->SubstitutedEntity
1846 << SubstDiag->DiagMessage;
1847 else
1848 S.Diag(SubstDiag->DiagLoc,
1849 diag::note_expr_requirement_expr_unknown_substitution_error)
1850 << (int)First << SubstDiag->SubstitutedEntity;
1851 break;
1852 }
1854 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1855 << (int)First << Req->getExpr();
1856 break;
1858 auto *SubstDiag =
1860 if (!SubstDiag->DiagMessage.empty())
1861 S.Diag(SubstDiag->DiagLoc,
1862 diag::note_expr_requirement_type_requirement_substitution_error)
1863 << (int)First << SubstDiag->SubstitutedEntity
1864 << SubstDiag->DiagMessage;
1865 else
1866 S.Diag(
1867 SubstDiag->DiagLoc,
1868 diag::
1869 note_expr_requirement_type_requirement_unknown_substitution_error)
1870 << (int)First << SubstDiag->SubstitutedEntity;
1871 break;
1872 }
1874 ConceptSpecializationExpr *ConstraintExpr =
1876 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1877 break;
1878 }
1880 llvm_unreachable("We checked this above");
1881 }
1882}
1883
1886 bool First) {
1887 assert(!Req->isSatisfied() &&
1888 "Diagnose() can only be used on an unsatisfied requirement");
1889 switch (Req->getSatisfactionStatus()) {
1891 llvm_unreachable("Diagnosing a dependent requirement");
1892 return;
1894 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1895 if (!SubstDiag->DiagMessage.empty())
1896 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1897 << (int)First << SubstDiag->SubstitutedEntity
1898 << SubstDiag->DiagMessage;
1899 else
1900 S.Diag(SubstDiag->DiagLoc,
1901 diag::note_type_requirement_unknown_substitution_error)
1902 << (int)First << SubstDiag->SubstitutedEntity;
1903 return;
1904 }
1905 default:
1906 llvm_unreachable("Unknown satisfaction status");
1907 return;
1908 }
1909}
1910
1913 SourceLocation Loc, bool First) {
1914 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1915 S.Diag(
1916 Loc,
1917 diag::
1918 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1919 << (int)First
1920 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1921 << Concept->getNamedConcept().getAsTemplateDecl();
1922 } else {
1923 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1924 << (int)First << Concept;
1925 }
1926}
1927
1930 bool First, concepts::NestedRequirement *Req = nullptr);
1931
1934 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1935 for (auto &Record : Records) {
1937 Loc = {};
1939 }
1940}
1941
1951
1953 const Expr *SubstExpr,
1954 bool First) {
1955 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1956 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1957 switch (BO->getOpcode()) {
1958 // These two cases will in practice only be reached when using fold
1959 // expressions with || and &&, since otherwise the || and && will have been
1960 // broken down into atomic constraints during satisfaction checking.
1961 case BO_LOr:
1962 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1965 /*First=*/false);
1966 return;
1967 case BO_LAnd: {
1968 bool LHSSatisfied =
1969 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1970 if (LHSSatisfied) {
1971 // LHS is true, so RHS must be false.
1973 return;
1974 }
1975 // LHS is false
1977
1978 // RHS might also be false
1979 bool RHSSatisfied =
1980 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1981 if (!RHSSatisfied)
1983 /*First=*/false);
1984 return;
1985 }
1986 case BO_GE:
1987 case BO_LE:
1988 case BO_GT:
1989 case BO_LT:
1990 case BO_EQ:
1991 case BO_NE:
1992 if (BO->getLHS()->getType()->isIntegerType() &&
1993 BO->getRHS()->getType()->isIntegerType()) {
1994 Expr::EvalResult SimplifiedLHS;
1995 Expr::EvalResult SimplifiedRHS;
1996 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1998 /*InConstantContext=*/true);
1999 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
2001 /*InConstantContext=*/true);
2002 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
2003 S.Diag(SubstExpr->getBeginLoc(),
2004 diag::note_atomic_constraint_evaluated_to_false_elaborated)
2005 << (int)First << SubstExpr
2006 << toString(SimplifiedLHS.Val.getInt(), 10)
2007 << BinaryOperator::getOpcodeStr(BO->getOpcode())
2008 << toString(SimplifiedRHS.Val.getInt(), 10);
2009 return;
2010 }
2011 }
2012 break;
2013
2014 default:
2015 break;
2016 }
2017 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
2018 // FIXME: RequiresExpr should store dependent diagnostics.
2019 for (concepts::Requirement *Req : RE->getRequirements())
2020 if (!Req->isDependent() && !Req->isSatisfied()) {
2021 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2023 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
2025 else
2028 break;
2029 }
2030 return;
2031 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
2032 // Drill down concept ids treated as atomic constraints
2034 return;
2035 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
2036 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
2037 assert(TTE->getNumArgs() == 2);
2038 S.Diag(SubstExpr->getSourceRange().getBegin(),
2039 diag::note_is_deducible_constraint_evaluated_to_false)
2040 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2041 return;
2042 }
2043
2044 S.Diag(SubstExpr->getSourceRange().getBegin(),
2045 diag::note_atomic_constraint_evaluated_to_false)
2046 << (int)First << SubstExpr;
2047 S.DiagnoseTypeTraitDetails(SubstExpr);
2048}
2049
2053 if (auto *Diag =
2054 Record
2055 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
2056 if (Req)
2057 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
2058 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
2059 else
2060 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2061 << Diag->second;
2062 return;
2063 }
2064 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
2065 if (Loc.isInvalid())
2066 Loc = Concept->getBeginLoc();
2068 return;
2069 }
2072}
2073
2075 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
2076 bool First) {
2077
2078 assert(!Satisfaction.IsSatisfied &&
2079 "Attempted to diagnose a satisfied constraint");
2080 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
2081}
2082
2084 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
2085
2086 const ASTConstraintSatisfaction &Satisfaction =
2087 ConstraintExpr->getSatisfaction();
2088
2089 assert(!Satisfaction.IsSatisfied &&
2090 "Attempted to diagnose a satisfied constraint");
2091
2092 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
2093 ConstraintExpr->getBeginLoc(), First);
2094}
2095
2096namespace {
2097
2098class SubstituteParameterMappings {
2099 Sema &SemaRef;
2100
2101 const MultiLevelTemplateArgumentList *MLTAL;
2102 const ASTTemplateArgumentListInfo *ArgsAsWritten;
2103
2104 // When normalizing a fold constraint, e.g.
2105 // C<Pack1, Pack2...> && ...
2106 // we want the TreeTransform to expand only Pack2 but not Pack1,
2107 // since Pack1 will be expanded during the evaluation of the fold expression.
2108 // This flag helps rewrite any non-PackExpansion packs into "expanded"
2109 // parameters.
2110 bool RemovePacksForFoldExpr;
2111
2112 SubstituteParameterMappings(Sema &SemaRef,
2113 const MultiLevelTemplateArgumentList *MLTAL,
2114 const ASTTemplateArgumentListInfo *ArgsAsWritten,
2115 bool RemovePacksForFoldExpr)
2116 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2117 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2118
2119 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
2120
2121 bool substitute(NormalizedConstraintWithParamMapping &N);
2122
2123 bool substitute(ConceptIdConstraint &CC);
2124
2125public:
2126 SubstituteParameterMappings(Sema &SemaRef,
2127 bool RemovePacksForFoldExpr = false)
2128 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
2129 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2130
2131 bool substitute(NormalizedConstraint &N);
2132};
2133
2134void SubstituteParameterMappings::buildParameterMapping(
2136 TemplateParameterList *TemplateParams =
2137 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
2138
2139 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2140 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2141
2144 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2145 /*OnlyDeduced=*/false,
2146 /*Depth=*/0, OccurringIndices);
2147
2149 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2150 /*Depth=*/0, OccurringIndicesForSubsumption);
2151
2152 } else if (N.getKind() ==
2155 static_cast<FoldExpandedConstraint &>(N).getPattern(),
2156 /*OnlyDeduced=*/false,
2157 /*Depth=*/0, OccurringIndices);
2159 auto *Args = static_cast<ConceptIdConstraint &>(N)
2160 .getConceptId()
2161 ->getTemplateArgsAsWritten();
2162 if (Args)
2163 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2164 /*Depth=*/0, OccurringIndices);
2165 }
2166
2167 // If a parameter is only referenced in a default template argument,
2168 // we need to add it to the mapping explicitly.
2169 {
2171 for (unsigned I = TemplateParams->getMinRequiredArguments();
2172 I < TemplateParams->size(); ++I) {
2173 const NamedDecl *Param = TemplateParams->getParam(I);
2174 if (Param->isParameterPack())
2175 break;
2176 const TemplateArgument *Arg =
2178 assert(Arg && "expected a default argument");
2179 DefaultArgs.emplace_back(std::move(*Arg));
2180 }
2181 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*OnlyDeduced=*/false,
2182 /*Depth=*/0, OccurringIndices);
2183 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*OnlyDeduced=*/false,
2184 /*Depth=*/0,
2185 OccurringIndicesForSubsumption);
2186 }
2187
2188 unsigned Size = OccurringIndices.count();
2189 // When the constraint is independent of any template parameters,
2190 // we build an empty mapping so that we can distinguish these cases
2191 // from cases where no mapping exists at all, e.g. when there are only atomic
2192 // constraints.
2193 TemplateArgumentLoc *TempArgs =
2194 new (SemaRef.Context) TemplateArgumentLoc[Size];
2196 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2197 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2198 ? ArgsAsWritten->arguments()[I].getLocation()
2199 : SourceLocation();
2200 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
2201 // can't assert Loc.isValid() now.
2202 if (OccurringIndices[I]) {
2203 NamedDecl *Param = TemplateParams->begin()[I];
2204 new (&(TempArgs)[J]) TemplateArgumentLoc(
2205 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2206 UsedParams.push_back(Param);
2207 J++;
2208 }
2209 }
2210 auto *UsedList = TemplateParameterList::Create(
2211 SemaRef.Context, TemplateParams->getTemplateLoc(),
2212 TemplateParams->getLAngleLoc(), UsedParams,
2213 /*RAngleLoc=*/SourceLocation(),
2214 /*RequiresClause=*/nullptr);
2216 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2217 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
2218}
2219
2220bool SubstituteParameterMappings::substitute(
2222 if (!N.hasParameterMapping())
2223 buildParameterMapping(N);
2224
2225 // If the parameter mapping is empty, there is nothing to substitute.
2226 if (N.getParameterMapping().empty())
2227 return false;
2228
2229 SourceLocation InstLocBegin, InstLocEnd;
2230 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2231 if (Arguments.empty()) {
2232 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2233 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2234 } else {
2235 auto SR = Arguments[0].getSourceRange();
2236 InstLocBegin = SR.getBegin();
2237 InstLocEnd = SR.getEnd();
2238 }
2239 Sema::NonSFINAEContext _(SemaRef);
2241 SemaRef, InstLocBegin,
2243 const_cast<NamedDecl *>(N.getConstraintDecl()),
2244 {InstLocBegin, InstLocEnd});
2245 if (Inst.isInvalid())
2246 return true;
2247
2248 // TransformTemplateArguments is unable to preserve the source location of a
2249 // pack. The SourceLocation is necessary for the instantiation location.
2250 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2251 // which is wrong.
2252 TemplateArgumentListInfo SubstArgs;
2254 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2256 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs))
2257 return true;
2259 auto *TD =
2262 TD->getLocation(), SubstArgs,
2263 /*DefaultArguments=*/{},
2264 /*PartialTemplateArgs=*/false, CTAI))
2265 return true;
2266
2267 TemplateArgumentLoc *TempArgs =
2268 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2269
2270 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2271 SourceLocation Loc;
2272 // If this is an empty pack, we have no corresponding SubstArgs.
2273 if (I < SubstArgs.size())
2274 Loc = SubstArgs.arguments()[I].getLocation();
2275
2276 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2277 CTAI.SugaredConverted[I], QualType(), Loc);
2278 }
2279
2280 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2281 CTAI.SugaredConverted.size());
2285 return false;
2286}
2287
2288bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2289 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2290
2291 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2292 return true;
2293
2294 auto *CSE = CC.getConceptSpecializationExpr();
2295 assert(CSE);
2296 assert(!CC.getBeginLoc().isInvalid());
2297
2298 SourceLocation InstLocBegin, InstLocEnd;
2299 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2300 Arguments.empty()) {
2301 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2302 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2303 } else {
2304 auto SR = Arguments[0].getSourceRange();
2305 InstLocBegin = SR.getBegin();
2306 InstLocEnd = SR.getEnd();
2307 }
2308 Sema::NonSFINAEContext _(SemaRef);
2309 // This is useful for name lookup across modules; see Sema::getLookupModules.
2311 SemaRef, InstLocBegin,
2313 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2314 {InstLocBegin, InstLocEnd});
2315 if (Inst.isInvalid())
2316 return true;
2317
2319 // TransformTemplateArguments is unable to preserve the source location of a
2320 // pack. The SourceLocation is necessary for the instantiation location.
2321 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2322 // which is wrong.
2324 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2325 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2326 CSE->getTemplateArgsAsWritten();
2328 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out))
2329 return true;
2331 if (SemaRef.CheckTemplateArgumentList(CSE->getConceptDecl(),
2332 CSE->getConceptNameInfo().getLoc(), Out,
2333 /*DefaultArgs=*/{},
2334 /*PartialTemplateArgs=*/false, CTAI,
2335 /*UpdateArgsWithConversions=*/false))
2336 return true;
2337 auto TemplateArgs = *MLTAL;
2338 TemplateArgs.replaceOutermostTemplateArguments(CSE->getConceptDecl(),
2339 CTAI.SugaredConverted);
2340 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2341 RemovePacksForFoldExpr)
2342 .substitute(CC.getNormalizedConstraint());
2343}
2344
2345bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2346 switch (N.getKind()) {
2348 if (!MLTAL) {
2349 assert(!ArgsAsWritten);
2350 return false;
2351 }
2352 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2353 }
2355 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2356 if (!MLTAL) {
2357 llvm::SaveAndRestore _1(RemovePacksForFoldExpr, true);
2358 assert(!ArgsAsWritten);
2359 return substitute(FE.getNormalizedPattern());
2360 }
2361 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2362 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2363 return SubstituteParameterMappings(SemaRef, /*RemovePacksForFoldExpr=*/true)
2364 .substitute(FE.getNormalizedPattern());
2365 }
2367 auto &CC = static_cast<ConceptIdConstraint &>(N);
2368 if (MLTAL) {
2369 assert(ArgsAsWritten);
2370 return substitute(CC);
2371 }
2372 assert(!ArgsAsWritten);
2374 // Make sure that lambdas within template arguments live in a
2375 // dependent context such that they are assured to be transformed during
2376 // constraint evaluation.
2379 /*LambdaContextDecl=*/
2381 CSE->getSpecializationDecl()));
2384 if (RemovePacksForFoldExpr) {
2386 ArrayRef<TemplateArgumentLoc> InputArgLoc =
2388 if (AdjustConstraints(SemaRef, /*TemplateDepth=*/0,
2389 /*RemoveNonPackExpansionPacks=*/true)
2390 .TransformTemplateArguments(InputArgLoc.begin(),
2391 InputArgLoc.end(), OutArgs))
2392 return true;
2394 // Repack the packs.
2395 if (SemaRef.CheckTemplateArgumentList(
2396 Concept, Concept->getTemplateParameters(), Concept->getBeginLoc(),
2397 OutArgs,
2398 /*DefaultArguments=*/{},
2399 /*PartialTemplateArgs=*/false, CTAI))
2400 return true;
2401 InnerArgs = std::move(CTAI.SugaredConverted);
2402 }
2403
2405 Concept, Concept->getLexicalDeclContext(),
2406 /*Final=*/true, InnerArgs,
2407 /*RelativeToPrimary=*/true,
2408 /*Pattern=*/nullptr,
2409 /*ForConstraintInstantiation=*/true);
2410 MLTAL.setRetainInnerDepths();
2411
2412 return SubstituteParameterMappings(SemaRef, &MLTAL,
2414 RemovePacksForFoldExpr)
2415 .substitute(CC.getNormalizedConstraint());
2416 }
2418 auto &Compound = static_cast<CompoundConstraint &>(N);
2419 if (substitute(Compound.getLHS()))
2420 return true;
2421 return substitute(Compound.getRHS());
2422 }
2423 }
2424 llvm_unreachable("Unknown ConstraintKind enum");
2425}
2426
2427} // namespace
2428
2429NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2430 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2431 assert(ACs.size() != 0);
2432 auto *Conjunction =
2433 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2434 if (!Conjunction)
2435 return nullptr;
2436 for (unsigned I = 1; I < ACs.size(); ++I) {
2437 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2438 ACs[I].ArgPackSubstIndex);
2439 if (!Next)
2440 return nullptr;
2442 Conjunction, Next);
2443 }
2444 return Conjunction;
2445}
2446
2447NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2448 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2449 assert(E != nullptr);
2450
2451 // C++ [temp.constr.normal]p1.1
2452 // [...]
2453 // - The normal form of an expression (E) is the normal form of E.
2454 // [...]
2455 E = E->IgnoreParenImpCasts();
2456
2457 llvm::FoldingSetNodeID ID;
2458 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2459 return nullptr;
2460 }
2461 SatisfactionStackRAII StackRAII(S, D, ID);
2462
2463 // C++2a [temp.param]p4:
2464 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2465 // Fold expression is considered atomic constraints per current wording.
2466 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2467
2468 if (LogicalBinOp BO = E) {
2469 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2470 if (!LHS)
2471 return nullptr;
2472 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2473 if (!RHS)
2474 return nullptr;
2475
2477 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2478 }
2479 if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2480 // C++ [temp.constr.normal]p1.1
2481 // [...]
2482 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2483 // where C names a concept, is the normal form of the
2484 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2485 // respective template parameters in the parameter mappings in each atomic
2486 // constraint. If any such substitution results in an invalid type or
2487 // expression, the program is ill-formed; no diagnostic is required.
2488 // [...]
2489 NormalizedConstraint *SubNF;
2490 if (ExprResult Res =
2491 SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);
2492 Res.isUsable())
2493 // Use canonical declarations to merge ConceptDecls across different
2494 // modules.
2495 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2496 S, CSE->getConceptDecl()->getCanonicalDecl(),
2497 AssociatedConstraint(Res.get(), SubstIndex));
2498 else
2499 return nullptr;
2501 CSE->getConceptReference(), SubNF, D,
2502 CSE, SubstIndex);
2503 }
2504 if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2505 FE && S.getLangOpts().CPlusPlus26 &&
2506 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2507 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2508
2509 // Normalize fold expressions in C++26.
2510
2512 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2515
2516 if (FE->getInit()) {
2517 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2518 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2519 if (!LHS || !RHS)
2520 return nullptr;
2521
2522 if (FE->isRightFold())
2524 FE->getPattern(), D, Kind, LHS);
2525 else
2527 FE->getPattern(), D, Kind, RHS);
2528
2530 S.getASTContext(), LHS,
2531 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2532 : CCK_Disjunction),
2533 RHS);
2534 }
2535 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2536 if (!Sub)
2537 return nullptr;
2539 D, Kind, Sub);
2540 }
2541 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2542}
2543
2545 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2546 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2547 if (!ConstrainedDeclOrNestedReq) {
2548 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2549 *this, nullptr, AssociatedConstraints);
2550 if (!Normalized ||
2551 SubstituteParameterMappings(*this).substitute(*Normalized))
2552 return nullptr;
2553
2554 return Normalized;
2555 }
2556
2557 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2558 const NamedDecl *ND =
2559 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2560 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2561 if (CacheEntry == NormalizationCache.end()) {
2562 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2563 *this, ND, AssociatedConstraints);
2564 if (!Normalized) {
2565 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);
2566 return nullptr;
2567 }
2568 // substitute() can invalidate iterators of NormalizationCache.
2569 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2570 CacheEntry =
2571 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2572 .first;
2573 if (Failed)
2574 return nullptr;
2575 }
2576 return CacheEntry->second;
2577}
2578
2581
2582 // [C++26] [temp.constr.fold]
2583 // Two fold expanded constraints are compatible for subsumption
2584 // if their respective constraints both contain an equivalent unexpanded pack.
2585
2588 APacks);
2590 BPacks);
2591
2592 for (const UnexpandedParameterPack &APack : APacks) {
2593 auto ADI = getDepthAndIndex(APack);
2594 if (!ADI)
2595 continue;
2596 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2597 return getDepthAndIndex(BPack) == ADI;
2598 });
2599 if (It != BPacks.end())
2600 return true;
2601 }
2602 return false;
2603}
2604
2607 const NamedDecl *D2,
2609 bool &Result) {
2610#ifndef NDEBUG
2611 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2612 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2614 return Kind == FunctionDecl::TK_NonTemplate ||
2616 };
2617 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2618 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2619 "use non-instantiated function declaration for constraints partial "
2620 "ordering");
2621 }
2622#endif
2623
2624 if (AC1.empty()) {
2625 Result = AC2.empty();
2626 return false;
2627 }
2628 if (AC2.empty()) {
2629 // TD1 has associated constraints and TD2 does not.
2630 Result = true;
2631 return false;
2632 }
2633
2634 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2635 auto CacheEntry = SubsumptionCache.find(Key);
2636 if (CacheEntry != SubsumptionCache.end()) {
2637 Result = CacheEntry->second;
2638 return false;
2639 }
2640
2641 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
2642 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
2643
2644 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2645 if (Depth2 > Depth1) {
2646 AC1[I].ConstraintExpr =
2647 AdjustConstraints(*this, Depth2 - Depth1)
2648 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2649 .get();
2650 } else if (Depth1 > Depth2) {
2651 AC2[I].ConstraintExpr =
2652 AdjustConstraints(*this, Depth1 - Depth2)
2653 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2654 .get();
2655 }
2656 }
2657
2658 SubsumptionChecker SC(*this);
2659 // Associated declarations are used as a cache key in the event they were
2660 // normalized earlier during concept checking. However we cannot reuse these
2661 // cached results if any of the template depths have been adjusted.
2662 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2663 if (Depth2 > Depth1)
2664 DeclAC1 = nullptr;
2665 else if (Depth1 > Depth2)
2666 DeclAC2 = nullptr;
2667 std::optional<bool> Subsumes = SC.Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2668 if (!Subsumes) {
2669 // Normalization failed
2670 return true;
2671 }
2672 Result = *Subsumes;
2673 SubsumptionCache.try_emplace(Key, *Subsumes);
2674 return false;
2675}
2676
2680 if (isSFINAEContext())
2681 // No need to work here because our notes would be discarded.
2682 return false;
2683
2684 if (AC1.empty() || AC2.empty())
2685 return false;
2686
2687 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2688 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2689 const AtomicConstraint &B) {
2691 return false;
2692 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2693 if (EA == EB)
2694 return true;
2695
2696 // Not the same source level expression - are the expressions
2697 // identical?
2698 llvm::FoldingSetNodeID IDA, IDB;
2699 EA->Profile(IDA, Context, /*Canonical=*/true);
2700 EB->Profile(IDB, Context, /*Canonical=*/true);
2701 if (IDA != IDB)
2702 return false;
2703
2704 AmbiguousAtomic1 = EA;
2705 AmbiguousAtomic2 = EB;
2706 return true;
2707 };
2708
2709 {
2710 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2711 if (!Normalized1)
2712 return false;
2713
2714 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2715 if (!Normalized2)
2716 return false;
2717
2718 SubsumptionChecker SC(*this);
2719
2720 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2721 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2722
2723 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2724 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2725 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2726
2727 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2728 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2729 // Same result - no ambiguity was caused by identical atomic expressions.
2730 return false;
2731 }
2732 // A different result! Some ambiguous atomic constraint(s) caused a difference
2733 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2734
2735 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2736 << AmbiguousAtomic1->getSourceRange();
2737 Diag(AmbiguousAtomic2->getBeginLoc(),
2738 diag::note_ambiguous_atomic_constraints_similar_expression)
2739 << AmbiguousAtomic2->getSourceRange();
2740 return true;
2741}
2742
2743//
2744//
2745// ------------------------ Subsumption -----------------------------------
2746//
2747//
2749 SubsumptionCallable Callable)
2750 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2751
2752uint16_t SubsumptionChecker::getNewLiteralId() {
2753 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2754 "too many constraints!");
2755 return NextID++;
2756}
2757
2758auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2759 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2760 // C++ [temp.constr.order] p2
2761 // - an atomic constraint A subsumes another atomic constraint B
2762 // if and only if the A and B are identical [...]
2763 //
2764 // C++ [temp.constr.atomic] p2
2765 // Two atomic constraints are identical if they are formed from the
2766 // same expression and the targets of the parameter mappings are
2767 // equivalent according to the rules for expressions [...]
2768
2769 // Because subsumption of atomic constraints is an identity
2770 // relationship that does not require further analysis
2771 // We cache the results such that if an atomic constraint literal
2772 // subsumes another, their literal will be the same
2773
2774 llvm::FoldingSetNodeID ID;
2775 ID.AddBoolean(Ori->hasParameterMapping());
2776 if (Ori->hasParameterMapping()) {
2777 const auto &Mapping = Ori->getParameterMapping();
2779 Ori->mappingOccurenceListForSubsumption();
2780 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2781 if (Indexes[Idx])
2782 SemaRef.getASTContext()
2783 .getCanonicalTemplateArgument(TAL.getArgument())
2784 .Profile(ID, SemaRef.getASTContext());
2785 }
2786 }
2787 auto It = Elems.find(ID);
2788 if (It == Elems.end()) {
2789 It = Elems
2790 .insert({ID,
2791 MappedAtomicConstraint{
2792 Ori, {getNewLiteralId(), Literal::Atomic}}})
2793 .first;
2794 ReverseMap[It->second.ID.Value] = Ori;
2795 }
2796 return It->getSecond().ID;
2797}
2798
2799auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2800 auto &Elems = FoldMap[Ori->getPattern()];
2801
2802 FoldExpendedConstraintKey K;
2803 K.Kind = Ori->getFoldOperator();
2804
2805 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2806 return K.Kind == Other.Kind;
2807 });
2808 if (It == Elems.end()) {
2809 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2810 It = Elems.insert(Elems.end(), std::move(K));
2811 ReverseMap[It->ID.Value] = Ori;
2812 }
2813 return It->ID;
2814}
2815
2816auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2817 return SubsumptionChecker::Normalize<CNFFormula>(C);
2818}
2819auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2820 return SubsumptionChecker::Normalize<DNFFormula>(C);
2821}
2822
2823///
2824/// \brief SubsumptionChecker::Normalize
2825///
2826/// Normalize a formula to Conjunctive Normal Form or
2827/// Disjunctive normal form.
2828///
2829/// Each Atomic (and Fold Expanded) constraint gets represented by
2830/// a single id to reduce space.
2831///
2832/// To minimize risks of exponential blow up, if two atomic
2833/// constraints subsumes each other (same constraint and mapping),
2834/// they are represented by the same literal.
2835///
2836template <typename FormulaType>
2837FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2838 FormulaType Res;
2839
2840 auto Add = [&, this](Clause C) {
2841 // Sort each clause and remove duplicates for faster comparisons.
2842 llvm::sort(C);
2843 C.erase(llvm::unique(C), C.end());
2844 AddUniqueClauseToFormula(Res, std::move(C));
2845 };
2846
2847 switch (NC.getKind()) {
2849 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2850
2852 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2853
2855 return Normalize<FormulaType>(
2856 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2857
2859 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2860 FormulaType Left, Right;
2861 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2862 Left = Normalize<FormulaType>(Compound.getLHS());
2863 Right = Normalize<FormulaType>(Compound.getRHS());
2864 });
2865
2866 if (Compound.getCompoundKind() == FormulaType::Kind) {
2867 unsigned SizeLeft = Left.size();
2868 Res = std::move(Left);
2869 Res.reserve(SizeLeft + Right.size());
2870 std::for_each(std::make_move_iterator(Right.begin()),
2871 std::make_move_iterator(Right.end()), Add);
2872 return Res;
2873 }
2874
2875 Res.reserve(Left.size() * Right.size());
2876 for (const auto &LTransform : Left) {
2877 for (const auto &RTransform : Right) {
2878 Clause Combined;
2879 Combined.reserve(LTransform.size() + RTransform.size());
2880 llvm::copy(LTransform, std::back_inserter(Combined));
2881 llvm::copy(RTransform, std::back_inserter(Combined));
2882 Add(std::move(Combined));
2883 }
2884 }
2885 return Res;
2886 }
2887 }
2888 llvm_unreachable("Unknown ConstraintKind enum");
2889}
2890
2891void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2892 for (auto &Other : F) {
2893 if (llvm::equal(C, Other))
2894 return;
2895 }
2896 F.push_back(C);
2897}
2898
2900 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2902 const NormalizedConstraint *PNormalized =
2903 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2904 if (!PNormalized)
2905 return std::nullopt;
2906
2907 const NormalizedConstraint *QNormalized =
2908 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2909 if (!QNormalized)
2910 return std::nullopt;
2911
2912 return Subsumes(PNormalized, QNormalized);
2913}
2914
2916 const NormalizedConstraint *Q) {
2917
2918 DNFFormula DNFP = DNF(*P);
2919 CNFFormula CNFQ = CNF(*Q);
2920 return Subsumes(DNFP, CNFQ);
2921}
2922
2923bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2924 const CNFFormula &QCNF) {
2925 for (const auto &Pi : PDNF) {
2926 for (const auto &Qj : QCNF) {
2927 // C++ [temp.constr.order] p2
2928 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2929 // and only if there exists an atomic constraint Pia in Pi for which
2930 // there exists an atomic constraint, Qjb, in Qj such that Pia
2931 // subsumes Qjb.
2932 if (!DNFSubsumes(Pi, Qj))
2933 return false;
2934 }
2935 }
2936 return true;
2937}
2938
2939bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2940
2941 return llvm::any_of(P, [&](Literal LP) {
2942 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2943 });
2944}
2945
2947 const FoldExpandedConstraint *B) {
2948 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2949 A, B};
2950
2951 auto It = FoldSubsumptionCache.find(Key);
2952 if (It == FoldSubsumptionCache.end()) {
2953 // C++ [temp.constr.order]
2954 // a fold expanded constraint A subsumes another fold expanded
2955 // constraint B if they are compatible for subsumption, have the same
2956 // fold-operator, and the constraint of A subsumes that of B.
2957 bool DoesSubsume =
2958 A->getFoldOperator() == B->getFoldOperator() &&
2961 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2962 }
2963 return It->second;
2964}
2965
2966bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2967 if (A.Kind != B.Kind)
2968 return false;
2969 switch (A.Kind) {
2970 case Literal::Atomic:
2971 if (!Callable)
2972 return A.Value == B.Value;
2973 return Callable(
2974 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2975 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2976 case Literal::FoldExpanded:
2977 return Subsumes(
2978 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2979 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2980 }
2981 llvm_unreachable("unknown literal kind");
2982}
2983
2984namespace {
2985
2986class DumpNormalizedConstraint {
2987 raw_ostream &OS;
2988 const PrintingPolicy &PP;
2989 TextNodeDumper TD;
2990
2991public:
2992 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2993 : OS(OS), PP(Context.getPrintingPolicy()),
2994 TD(OS, Context, /*ShowColors=*/false) {}
2995
2996 void dump(const NormalizedConstraint &N) {
2997 TD.AddChild([&] { Traverse(N); });
2998 }
2999
3000private:
3001 void Traverse(const NormalizedConstraint &N) {
3002 switch (N.getKind()) {
3003 case NormalizedConstraint::ConstraintKind::Compound:
3004 VisitCompound(static_cast<const CompoundConstraint &>(N));
3005 break;
3006 case NormalizedConstraint::ConstraintKind::Atomic:
3007 VisitAtomic(static_cast<const AtomicConstraint &>(N));
3008 break;
3009 case NormalizedConstraint::ConstraintKind::ConceptId:
3010 VisitConceptId(static_cast<const ConceptIdConstraint &>(N));
3011 break;
3012 case NormalizedConstraint::ConstraintKind::FoldExpanded:
3013 VisitFoldExpanded(static_cast<const FoldExpandedConstraint &>(N));
3014 break;
3015 }
3016 }
3017
3018 void WriteNodeHeader(const NormalizedConstraint &N, StringRef Kind) {
3019 OS << Kind;
3020 TD.dumpPointer(&N);
3022 }
3023
3024 void WritePackIndex(const NormalizedConstraintWithParamMapping &N) {
3025 if (auto Idx = N.getPackSubstitutionIndex())
3026 OS << " SubstIndex=" << *Idx;
3027 }
3028
3029 void VisitCompound(const CompoundConstraint &C) {
3030 WriteNodeHeader(C, "CompoundConstraint");
3031 OS << " "
3032 << (C.getCompoundKind() == NormalizedConstraint::CCK_Conjunction
3033 ? "Conjunction"
3034 : "Disjunction");
3035 TD.AddChild([&] { Traverse(C.getLHS()); });
3036 TD.AddChild([&] { Traverse(C.getRHS()); });
3037 }
3038
3039 void VisitAtomic(const AtomicConstraint &A) {
3040 WriteNodeHeader(A, "AtomicConstraint");
3041 WritePackIndex(A);
3042 OS << " ";
3043 A.getConstraintExpr()->printPretty(OS, /*Helper=*/nullptr, PP);
3044 WriteParameterMapping(A);
3045 }
3046
3047 void VisitConceptId(const ConceptIdConstraint &C) {
3048 WriteNodeHeader(C, "ConceptIdConstraint");
3049 WritePackIndex(C);
3050 OS << " ";
3051 if (auto *CSE = C.getConceptSpecializationExpr()) {
3052 CSE->printPretty(OS, /*Helper=*/nullptr, PP);
3053 } else {
3054 C.getConceptId()->print(OS, PP);
3055 }
3056 WriteParameterMapping(C);
3057 TD.AddChild([&] { Traverse(C.getNormalizedConstraint()); });
3058 }
3059
3060 void VisitFoldExpanded(const FoldExpandedConstraint &F) {
3061 WriteNodeHeader(F, "FoldExpandedConstraint");
3062 OS << " "
3063 << (F.getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3064 ? "And"
3065 : "Or");
3066 WritePackIndex(F);
3067 OS << " ";
3068 F.getPattern()->printPretty(OS, /*Helper=*/nullptr, PP);
3069 WriteParameterMapping(F);
3070 TD.AddChild([&] { Traverse(F.getNormalizedPattern()); });
3071 }
3072
3073 void WriteParameterMapping(const NormalizedConstraintWithParamMapping &N) {
3074 if (!N.hasParameterMapping() || N.mappingOccurenceList().none())
3075 return;
3076 TD.AddChild([this, Indexes(N.mappingOccurenceList()),
3077 IndexesForSub(N.mappingOccurenceListForSubsumption()),
3078 Mapping(N.getParameterMapping()),
3079 TPL(N.getUsedTemplateParamList())] {
3080 OS << "ParameterMapping";
3081 WriteOccurenceList("Indexes", Indexes);
3082 WriteOccurenceList("IndexesForSubsumption", IndexesForSub);
3083 unsigned Slot = 0;
3084 for (unsigned ParamIndex : Indexes.set_bits()) {
3085 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3086 assert(TPL && Slot < TPL->size());
3087 const NamedDecl *Param = TPL->getParam(Slot);
3088 OS << "#" << ParamIndex << ": <";
3089 Param->print(OS, PP);
3090 OS << "> -> ";
3091 Mapping[Slot].getArgument().print(PP, OS,
3092 /*IncludeType=*/false);
3093 TD.AddChild([this, Slot, Mapping] {
3094 const TemplateArgument &TA = Mapping[Slot].getArgument();
3095 OS << "TemplateArgument " << TA.getKindName();
3096 TD.dumpPointer(&TA);
3097 });
3098 });
3099 ++Slot;
3100 }
3101 });
3102 }
3103
3104 void WriteOccurenceList(StringRef Label,
3106 if (BV.none())
3107 return;
3108 OS << " " << Label << "={"
3109 << llvm::join(
3110 llvm::map_range(
3111 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3112 [](unsigned I) { return llvm::to_string(I); }),
3113 ", ")
3114 << '}';
3115 }
3116};
3117
3118} // namespace
3119
3120LLVM_DUMP_METHOD void NormalizedConstraint::dump(ASTContext &Context) const {
3121 dump(llvm::errs(), Context);
3122}
3123
3124LLVM_DUMP_METHOD void NormalizedConstraint::dump(llvm::raw_ostream &OS,
3125 ASTContext &Context) const {
3126 return DumpNormalizedConstraint(OS, Context).dump(*this);
3127}
This file provides AST data structures related to concepts.
This file provides some common utility functions for processing Lambda related AST Constructs.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
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.
Result
Implement __builtin_bit_cast and related operations.
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)
static bool PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base, const MultiLevelTemplateArgumentList &TemplateArgs, TypeSourceInfo *&Out, UnexpandedInfo &Info)
APSInt & getInt()
Definition APValue.h:511
bool isInt() const
Definition APValue.h:488
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
const TemplateArgument * getDefaultTemplateArgumentOrNone(const NamedDecl *P) const
Return the default argument of a template parameter, if one exists.
CanQualType BoolTy
llvm::StringRef backupStr(llvm::StringRef S) const
Definition ASTContext.h:906
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:6954
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:7085
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4058
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2189
StringRef getOpcodeStr() const
Definition Expr.h:4124
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:5109
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2151
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2972
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:76
void Adopt(NestedNameSpecifierLoc Other)
Adopt an existing nested-name-specifier (with source-range information).
Definition DeclSpec.cpp:103
Expr * getCallee()
Definition Expr.h:3110
arg_range arguments()
Definition Expr.h:3215
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
TemplateName 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
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptDecl * getConceptDecl() const
ConceptReference * getConceptReference() const
const ImplicitConceptSpecializationDecl * getSpecializationDecl() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
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:1466
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
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()
NamedDecl * getFoundDecl()
Get the NamedDecl through which this reference occurred.
Definition Expr.h:1401
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
Definition Expr.h:1494
DeclarationNameInfo getNameInfo() const
Definition Expr.h:1362
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
Definition Expr.h:1417
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:494
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
Definition Expr.h:1383
ValueDecl * getDecl()
Definition Expr.h:1358
const TemplateArgumentLoc * getTemplateArgs() const
Retrieve the template arguments provided as part of this template-id.
Definition Expr.h:1457
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1488
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:1243
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition DeclBase.h:1136
bool isParameterPack() const
Whether this declaration is a parameter pack.
Definition DeclBase.cpp:266
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:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:935
SourceLocation getInnerLocStart() const
Return start of source range ignoring outer template declarations.
Definition Decl.h:822
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition Decl.h:855
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:809
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition Expr.h:113
@ SE_NoSideEffects
Strictly evaluate the expression.
Definition Expr.h:692
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:178
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:448
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:195
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3101
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:247
bool isPRValue() const
Definition Expr.h:286
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:283
QualType getType() const
Definition Expr.h:145
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:2058
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4236
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4577
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2904
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition Decl.cpp:4356
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4372
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4300
TemplatedKind
The kind of templated function a FunctionDecl can be.
Definition Decl.h:2063
@ TK_FunctionTemplateSpecialization
Definition Decl.h:2074
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition Decl.cpp:4187
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4260
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4208
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:2081
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:377
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:181
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
Definition Template.h:277
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
Definition Template.h:218
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
Definition Template.h:129
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
Definition Template.h:135
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
Definition Template.h:259
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
Definition Template.h:281
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo)
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:938
QualType getCanonicalType() const
Definition TypeBase.h:8554
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
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:13758
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8470
A RAII object to temporarily push a declaration context.
Definition Sema.h:3533
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition Sema.h:12547
const DeclContext * getDeclContext() const
Definition Sema.h:12301
const NamedDecl * getDecl() const
Definition Sema.h:12293
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12297
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:864
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:15112
ASTContext & Context
Definition Sema.h:1305
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:933
void DiagnoseTypeTraitDetails(const Expr *E)
If E represents a built-in type trait, or a known standard type trait, try to print more information ...
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions, bool Diagnose=true)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
ASTContext & getASTContext() const
Definition Sema.h:936
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:14981
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:929
@ ReuseLambdaContextDecl
Definition Sema.h:7050
void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)
Collect the set of unexpanded parameter packs within the given template argument.
bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out)
TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const
Definition Sema.h:11863
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1340
llvm::DenseMap< llvm::FoldingSetNodeID, TemplateArgumentLoc > * CurrentCachedTemplateArgs
Cache the instantiation results of template parameter mappings within concepts.
Definition Sema.h:15119
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, const DeclContext *DC=nullptr, bool Final=false, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false, bool ForDefaultArgumentSubstitution=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)
Check whether the given function decl's trailing requires clause is satisfied, if any.
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
SourceManager & getSourceManager() const
Definition Sema.h:934
bool isSFINAEContext() const
Definition Sema.h:13796
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13752
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14937
void PopSatisfactionStackEntry()
Definition Sema.h:14943
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:6760
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6739
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition Sema.h:14945
bool IsAtLeastAsConstrained(const NamedDecl *D1, MutableArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, MutableArrayRef< AssociatedConstraint > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(const NamedDecl *D1, ArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, ArrayRef< AssociatedConstraint > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
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:4560
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
std::string printToString(const SourceManager &SM) const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
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:355
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.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
bool isNull() const
Determine whether this template name is NULL.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
unsigned getMinRequiredArguments() const
Returns the minimum number of arguments needed to form a template specialization.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() const
void dumpPointer(const void *Ptr)
void dumpSourceRange(SourceRange R)
void AddChild(Fn DoAddChild)
Add a child of the current node. Calls DoAddChild without arguments.
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:104
tok::TokenKind getKind() const
Definition Token.h:99
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:1879
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2867
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:9080
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2859
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2469
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2877
bool isFunctionType() const
Definition TypeBase.h:8735
QualType desugar() const
Definition Type.cpp:4207
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...
__inline void unsigned int _2
uint32_t Literal
Literals are represented as positive integers.
Definition CNFFormula.h:35
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool Sub(InterpState &S, CodePtr OpPC)
Definition Interp.h:448
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:419
Top level wrappers for InstallAPI frontend operations.
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:152
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:244
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:906
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
OptionalUnsigned< unsigned > UnsignedOrNone
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:586
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:136
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1774
#define false
Definition stdbool.h:26
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:666
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:668
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:650
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
void dump(ASTContext &Context) const
SourceLocation getBeginLoc() const
llvm::SmallBitVector OccurenceList
Definition SemaConcept.h:51
constexpr underlying_type toInternalRepresentation() const
SmallVector< TemplateArgument, 4 > SugaredConverted
The checked, converted argument will be added to the end of these vectors.
Definition Sema.h:12082
A stack object to be created when performing template instantiation.
Definition Sema.h:13401