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