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::FoldingSetNodeIDRef, 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;
611 Satisfaction.Details.begin(),
612 Satisfaction.Details.begin() + PreviousDetailsSize);
613 Details.append(Cached.Details.begin(), Cached.Details.end());
614 std::swap(Details, Satisfaction.Details);
615 return &Iter->second;
616 }
617
618 ExprResult cache(ExprResult E) {
620 auto &Satisfaction = Checker.Satisfaction;
621 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
622 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
623 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
624 Satisfaction.Details.begin() +
625 PreviousDetailsSize,
626 Satisfaction.Details.end());
627 Cache.SubstExpr = E;
628 Checker.S.UnsubstitutedConstraintSatisfactionCache.try_emplace(
629 ID.Intern(Checker.S.BumpAlloc), std::move(Cache));
630 return E;
631 }
632 };
633
634private:
635 template <class Constraint>
636 UnsignedOrNone getOuterPackIndex(const Constraint &C) const {
637 return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex()
638 : PackSubstitutionIndex;
639 }
640
641 StringRef allocateStringFromConceptDiagnostic(const PartialDiagnostic &Diag) {
642 SmallString<128> DiagString;
643 DiagString = ": ";
644 Diag.EmitToString(S.getDiagnostics(), DiagString);
645 return S.getASTContext().backupStr(DiagString);
646 }
647
648 void consumeSFINAEFailure(TemplateDeductionInfo &Info,
649 ConstraintSatisfaction &Satisfaction) {
652 Info.takeSFINAEDiagnostic(SubstDiag);
653 // FIXME: This is an unfortunate consequence of there
654 // being no serialization code for PartialDiagnostics and the fact
655 // that serializing them would likely take a lot more storage than
656 // just storing them as strings. We would still like, in the
657 // future, to serialize the proper PartialDiagnostic as serializing
658 // it as a string defeats the purpose of the diagnostic mechanism.
659 Satisfaction.Details.emplace_back(
660 new (S.Context) ConstraintSubstitutionDiagnostic{
661 SubstDiag.first,
662 allocateStringFromConceptDiagnostic(SubstDiag.second)});
663 }
664
666 EvaluateAtomicConstraint(const Expr *AtomicExpr,
667 const MultiLevelTemplateArgumentList &MLTAL);
668
669 // XXX: It is SLOW! Use it very carefully.
670 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
671 const NormalizedConstraintWithParamMapping &Constraint,
673 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
674
675 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
676 const MultiLevelTemplateArgumentList &MLTAL);
677
678 ExprResult Evaluate(const AtomicConstraint &Constraint,
679 const MultiLevelTemplateArgumentList &MLTAL);
680
681 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
682 const MultiLevelTemplateArgumentList &MLTAL);
683
684 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
685 const MultiLevelTemplateArgumentList &MLTAL);
686
687 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
689 unsigned int Size);
690
691 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
692 const MultiLevelTemplateArgumentList &MLTAL);
693
694 ExprResult Evaluate(const CompoundConstraint &Constraint,
695 const MultiLevelTemplateArgumentList &MLTAL);
696
697public:
699 const ConceptReference *TopLevelConceptId,
700 SourceLocation TemplateNameLoc,
701 UnsignedOrNone PackSubstitutionIndex,
702 ConstraintSatisfaction &Satisfaction,
703 bool BuildExpression)
704 : S(SemaRef), Template(Template), TopLevelConceptId(TopLevelConceptId),
705 TemplateNameLoc(TemplateNameLoc),
706 PackSubstitutionIndex(PackSubstitutionIndex),
707 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
708
709 ExprResult Evaluate(const NormalizedConstraint &Constraint,
710 const MultiLevelTemplateArgumentList &MLTAL);
711};
712
713} // namespace clang
714
715ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
716 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
717 llvm::FoldingSetNodeID ID;
718 if (Template &&
719 DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, &MLTAL)) {
720 Satisfaction.IsSatisfied = false;
721 Satisfaction.ContainsErrors = true;
722 return ExprEmpty();
723 }
724 SatisfactionStackRAII StackRAII(S, Template, ID);
725
726 // Atomic constraint - substitute arguments and check satisfaction.
727 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
728 {
729 TemplateDeductionInfo Info(TemplateNameLoc);
730 Sema::InstantiatingTemplate Inst(
731 S, AtomicExpr->getBeginLoc(),
732 Sema::InstantiatingTemplate::ConstraintSubstitution{},
733 // FIXME: improve const-correctness of InstantiatingTemplate
734 const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());
735 if (Inst.isInvalid())
736 return ExprError();
737
738 // We do not want error diagnostics escaping here.
739 Sema::SFINAETrap Trap(S, Info);
740 SubstitutedExpression =
741 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
742
743 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
744 // C++2a [temp.constr.atomic]p1
745 // ...If substitution results in an invalid type or expression, the
746 // constraint is not satisfied.
747 if (!Trap.hasErrorOccurred())
748 // A non-SFINAE error has occurred as a result of this
749 // substitution.
750 return ExprError();
751 consumeSFINAEFailure(Info, Satisfaction);
752 return ExprEmpty();
753 }
754 }
755
756 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
757 return ExprError();
758
759 // [temp.constr.atomic]p3: To determine if an atomic constraint is
760 // satisfied, the parameter mapping and template arguments are first
761 // substituted into its expression. If substitution results in an
762 // invalid type or expression, the constraint is not satisfied.
763 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
764 // and E shall be a constant expression of type bool.
765 //
766 // Perform the L to R Value conversion if necessary. We do so for all
767 // non-PRValue categories, else we fail to extend the lifetime of
768 // temporaries, and that fails the constant expression check.
769 if (!SubstitutedExpression.get()->isPRValue())
770 SubstitutedExpression = ImplicitCastExpr::Create(
771 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
772 SubstitutedExpression.get(),
773 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
774
775 return SubstitutedExpression;
776}
777
778std::optional<MultiLevelTemplateArgumentList>
779ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
780 const NormalizedConstraintWithParamMapping &Constraint,
782 llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {
783
784 if (!Constraint.hasParameterMapping()) {
785 if (MLTAL.getNumSubstitutedLevels())
786 SubstitutedOutermost.assign(MLTAL.getOutermost());
787 return MLTAL;
788 }
789
790 // The mapping is empty, meaning no template arguments are needed for
791 // evaluation.
792 if (Constraint.getParameterMapping().empty())
793 return MultiLevelTemplateArgumentList();
794
795 TemplateDeductionInfo Info(Constraint.getBeginLoc());
796 Sema::SFINAETrap Trap(S, Info);
797 Sema::InstantiatingTemplate Inst(
798 S, Constraint.getBeginLoc(),
799 Sema::InstantiatingTemplate::ConstraintSubstitution{},
800 // FIXME: improve const-correctness of InstantiatingTemplate
801 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
802 if (Inst.isInvalid())
803 return std::nullopt;
804
805 TemplateArgumentListInfo SubstArgs;
806 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
807
808 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
809 &CachedTemplateArgs);
810
811 // We don't want the template argument substitution into parameter
812 // mappings to preserve the outer depths.
813 if (S.SubstTemplateArgumentsInParameterMapping(
814 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
815 SubstArgs)) {
816 Satisfaction.IsSatisfied = false;
817 if (Trap.hasErrorOccurred())
818 consumeSFINAEFailure(Info, Satisfaction);
819 return std::nullopt;
820 }
821
822 Sema::CheckTemplateArgumentInfo CTAI;
823 auto *TD = const_cast<TemplateDecl *>(
825 if (S.CheckTemplateArgumentList(TD, Constraint.getUsedTemplateParamList(),
826 TD->getLocation(), SubstArgs,
827 /*DefaultArguments=*/{},
828 /*PartialTemplateArgs=*/false, CTAI))
829 return std::nullopt;
831 Constraint.mappingOccurenceList();
832 // The empty MLTAL situation should only occur when evaluating non-dependent
833 // constraints.
834 if (MLTAL.getNumSubstitutedLevels())
835 SubstitutedOutermost =
836 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
837 unsigned Offset = 0;
838 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
839 TemplateArgument Arg;
840 if (Used[I])
841 Arg = S.Context.getCanonicalTemplateArgument(
842 CTAI.SugaredConverted[MappedIndex++]);
843 if (I < SubstitutedOutermost.size()) {
844 SubstitutedOutermost[I] = Arg;
845 Offset = I + 1;
846 } else {
847 SubstitutedOutermost.push_back(Arg);
848 Offset = SubstitutedOutermost.size();
849 }
850 }
851 if (Offset < SubstitutedOutermost.size())
852 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
853
854 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
855 SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,
856 /*Final=*/false);
857 return std::move(SubstitutedTemplateArgs);
858}
859
860ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
861 const AtomicConstraint &Constraint,
862 const MultiLevelTemplateArgumentList &MLTAL) {
863 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
864 // The ConceptDecl as a ContextDecl ensures that, when evaluating constraints
865 // on transformed lambdas, we don't have extra outer template arguments.
866 if (ParentConcept)
867 EvaluationContext.emplace(
869 else
870 EvaluationContext.emplace(
873
874 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
875 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
876 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
877 if (!SubstitutedArgs) {
878 Satisfaction.IsSatisfied = false;
879 return ExprError();
880 }
881
882 // Make sure that concepts are not evaluated in the context they are used,
883 // i.e they should not have access to the current class object or its
884 // non-public members.
885 std::optional<Sema::ContextRAII> ConceptContext;
886 if (ParentConcept)
887 ConceptContext.emplace(S, ParentConcept->getDeclContext());
888
889 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
890 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
891 Constraint.getConstraintExpr(), *SubstitutedArgs);
892
893 if (SubstitutedAtomicExpr.isInvalid())
894 return ExprError();
895
896 if (SubstitutedAtomicExpr.isUnset())
897 // Evaluator has decided satisfaction without yielding an expression.
898 return ExprEmpty();
899
900 // We don't have the ability to evaluate this, since it contains a
901 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
902 // we'd potentially pick up a different overload, and cause confusing
903 // diagnostics. SO, add a failure detail that will cause us to make this
904 // overload set not viable.
905 if (SubstitutedAtomicExpr.get()->containsErrors()) {
906 Satisfaction.IsSatisfied = false;
907 Satisfaction.ContainsErrors = true;
908
909 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
910 Satisfaction.Details.emplace_back(
911 new (S.Context) ConstraintSubstitutionDiagnostic{
912 SubstitutedAtomicExpr.get()->getBeginLoc(),
913 allocateStringFromConceptDiagnostic(Msg)});
914 return SubstitutedAtomicExpr;
915 }
916
917 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
918 Satisfaction.IsSatisfied = true;
919 Satisfaction.ContainsErrors = false;
920 return SubstitutedAtomicExpr;
921 }
922
923 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
924 Expr::EvalResult EvalResult;
925 EvalResult.Diag = &EvaluationDiags;
926 EvalProxy SProxy(S);
927 if (!SubstitutedAtomicExpr.get()->EvaluateAsMandatedConstantExpr(
928 EvalResult, S.Context, SProxy) ||
929 !EvaluationDiags.empty()) {
930 // C++2a [temp.constr.atomic]p1
931 // ...E shall be a constant expression of type bool.
932 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
933 diag::err_non_constant_constraint_expression)
934 << SubstitutedAtomicExpr.get()->getSourceRange();
935 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
936 S.Diag(PDiag.first, PDiag.second);
937 return ExprError();
938 }
939
940 assert(EvalResult.Val.isInt() &&
941 "evaluating bool expression didn't produce int");
942 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
943 if (!Satisfaction.IsSatisfied)
944 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
945
946 return SubstitutedAtomicExpr;
947}
948
949ExprResult ConstraintSatisfactionChecker::Evaluate(
950 const AtomicConstraint &Constraint,
951 const MultiLevelTemplateArgumentList &MLTAL) {
952
953 ParameterMappingInstantiationCache PMCache(*this, Constraint, MLTAL,
954 getOuterPackIndex(Constraint));
955
956 if (auto *V = PMCache.available())
957 return V->SubstExpr;
958
959 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
960}
961
962ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
963 const FoldExpandedConstraint &Constraint,
964 const MultiLevelTemplateArgumentList &MLTAL) {
965
966 bool Conjunction = Constraint.getFoldOperator() ==
968 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
969
970 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
971 // FIXME: Is PackSubstitutionIndex correct?
972 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
973 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
974 SubstitutionInTemplateArguments(
975 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
976 MLTAL, SubstitutedOutermost);
977 if (!SubstitutedArgs) {
978 Satisfaction.IsSatisfied = false;
979 return ExprError();
980 }
981
982 UnsignedOrNone NumExpansions(std::nullopt);
983 {
984 Sema::InstantiatingTemplate InstTemplate(
985 S, TemplateNameLoc,
986 Sema::InstantiatingTemplate::ConstraintSubstitution{},
987 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
988 NumExpansions = S.EvaluateFoldExpandedConstraintSize(
989 Constraint.getPattern(), *SubstitutedArgs);
990 }
991 if (!NumExpansions)
992 return ExprEmpty();
993
994 if (*NumExpansions == 0) {
995 Satisfaction.IsSatisfied = Conjunction;
996 return ExprEmpty();
997 }
998
1000 for (unsigned I = 0; I < *NumExpansions; I++) {
1001 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
1002 Satisfaction.IsSatisfied = false;
1003 Satisfaction.ContainsErrors = false;
1004 ExprResult Expr =
1005 ConstraintSatisfactionChecker(S, Template, TopLevelConceptId,
1006 TemplateNameLoc, UnsignedOrNone(I),
1007 Satisfaction,
1008 /*BuildExpression=*/false)
1009 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
1010 if (BuildExpression) {
1011 if (Out.isUnset() || !Expr.isUsable())
1012 Out = Expr;
1013 else
1014 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
1015 Conjunction ? BinaryOperatorKind::BO_LAnd
1016 : BinaryOperatorKind::BO_LOr,
1017 S.Context.BoolTy, VK_PRValue, OK_Ordinary,
1018 Constraint.getBeginLoc(),
1019 FPOptionsOverride{});
1020 }
1021 if (!Conjunction && Satisfaction.IsSatisfied) {
1022 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1023 EffectiveDetailEndIndex,
1024 Satisfaction.Details.end());
1025 break;
1026 }
1027 if (Satisfaction.IsSatisfied != Conjunction)
1028 return Out;
1029 }
1030
1031 return Out;
1032}
1033
1034ExprResult ConstraintSatisfactionChecker::Evaluate(
1035 const FoldExpandedConstraint &Constraint,
1036 const MultiLevelTemplateArgumentList &MLTAL) {
1037
1038 ParameterMappingInstantiationCache PMCache(*this, Constraint, MLTAL,
1039 /*PackIndex=*/std::nullopt);
1040
1041 if (auto *V = PMCache.available())
1042 return V->SubstExpr;
1043
1044 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
1045}
1046
1047ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1048 const ConceptIdConstraint &Constraint,
1049 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
1050 const ConceptReference *ConceptId = Constraint.getConceptId();
1051
1052 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
1053 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1054 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1055
1056 if (!SubstitutedArgs) {
1057 Satisfaction.IsSatisfied = false;
1058 return ExprError();
1059 }
1060
1061 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
1062
1063 const ASTTemplateArgumentListInfo *Ori =
1064 ConceptId->getTemplateArgsAsWritten();
1065 TemplateDeductionInfo Info(TemplateNameLoc);
1066 Sema::SFINAETrap Trap(S, Info);
1067 Sema::InstantiatingTemplate _2(
1068 S, TemplateNameLoc, Sema::InstantiatingTemplate::ConstraintSubstitution{},
1069 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
1070
1071 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
1072
1073 // There's a concern that even with the same concept, they may not have the
1074 // same ConceptReference, if they come from modules.
1075 if (TopLevelConceptId &&
1076 ConceptId->getNamedConcept().getAsTemplateDecl() ==
1077 TopLevelConceptId->getNamedConcept().getAsTemplateDecl()) {
1078 for (auto &A : Ori->arguments())
1079 OutArgs.addArgument(A);
1080 } else if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs,
1081 OutArgs) ||
1082 Trap.hasErrorOccurred()) {
1083 Satisfaction.IsSatisfied = false;
1084 if (Trap.hasErrorOccurred())
1085 consumeSFINAEFailure(Info, Satisfaction);
1086 return ExprError();
1087 }
1088
1089 CXXScopeSpec SS;
1090 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
1091
1092 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1093 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
1094 ConceptId->getFoundDecl(),
1095 ConceptId->getNamedConcept().getAsTemplateDecl(), &OutArgs,
1096 /*DoCheckConstraintSatisfaction=*/false);
1097
1098 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
1099 return ExprError();
1100
1101 if (Size != Satisfaction.Details.size()) {
1102 Satisfaction.Details.insert(
1103 Satisfaction.Details.begin() + Size,
1105 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
1106 ->getConceptReference()));
1107 }
1108 return SubstitutedConceptId;
1109}
1110
1111ExprResult ConstraintSatisfactionChecker::Evaluate(
1112 const ConceptIdConstraint &Constraint,
1113 const MultiLevelTemplateArgumentList &MLTAL) {
1114
1115 const ConceptReference *ConceptId = Constraint.getConceptId();
1116 Sema::InstantiatingTemplate InstTemplate(
1117 S, ConceptId->getBeginLoc(),
1118 Sema::InstantiatingTemplate::ConstraintsCheck{},
1119 ConceptId->getNamedConcept().getAsTemplateDecl(),
1120 // We may have empty template arguments when checking non-dependent
1121 // nested constraint expressions.
1122 // In such cases, non-SFINAE errors would have already been diagnosed
1123 // during parameter mapping substitution, so the instantiating template
1124 // arguments are less useful here.
1125 MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
1126 : ArrayRef<TemplateArgument>{},
1127 Constraint.getSourceRange());
1128 if (InstTemplate.isInvalid())
1129 return ExprError();
1130
1131 unsigned Size = Satisfaction.Details.size();
1132
1133 llvm::SaveAndRestore PushConceptDecl(
1134 ParentConcept,
1136
1137 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
1138
1139 if (E.isInvalid()) {
1140 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1141 return E;
1142 }
1143
1144 // ConceptIdConstraint is only relevant for diagnostics,
1145 // so if the normalized constraint is satisfied, we should not
1146 // substitute into the constraint.
1147 if (Satisfaction.IsSatisfied)
1148 return E;
1149
1150 ParameterMappingInstantiationCache PMCache(
1151 *this, Constraint, MLTAL, getOuterPackIndex(Constraint), Size);
1152
1153 if (auto *V = PMCache.available())
1154 return V->SubstExpr;
1155
1156 return PMCache.cache(EvaluateSlow(Constraint, MLTAL, Size));
1157}
1158
1159ExprResult ConstraintSatisfactionChecker::Evaluate(
1160 const CompoundConstraint &Constraint,
1161 const MultiLevelTemplateArgumentList &MLTAL) {
1162
1163 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1164
1165 bool Conjunction =
1167
1168 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1169
1170 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1171 return LHS;
1172
1173 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
1174 !Satisfaction.ContainsErrors)
1175 return LHS;
1176
1177 Satisfaction.ContainsErrors = false;
1178 Satisfaction.IsSatisfied = false;
1179
1180 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1181
1182 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
1183 !Satisfaction.ContainsErrors)
1184 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1185 EffectiveDetailEndIndex,
1186 Satisfaction.Details.end());
1187
1188 if (!BuildExpression)
1189 return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
1190
1191 if (!LHS.isUsable())
1192 return RHS;
1193
1194 if (!RHS.isUsable())
1195 return LHS;
1196
1197 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1198 Conjunction ? BinaryOperatorKind::BO_LAnd
1199 : BinaryOperatorKind::BO_LOr,
1200 S.Context.BoolTy, VK_PRValue, OK_Ordinary,
1201 Constraint.getBeginLoc(), FPOptionsOverride{});
1202}
1203
1204ExprResult ConstraintSatisfactionChecker::Evaluate(
1205 const NormalizedConstraint &Constraint,
1206 const MultiLevelTemplateArgumentList &MLTAL) {
1207 switch (Constraint.getKind()) {
1209 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1210
1212 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1213 MLTAL);
1214
1216 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1217 MLTAL);
1218
1220 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1221 }
1222 llvm_unreachable("Unknown ConstraintKind enum");
1223}
1224
1226 Sema &S, const NamedDecl *Template,
1227 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1228 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1229 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1230 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1231
1232 if (ConvertedExpr)
1233 *ConvertedExpr = nullptr;
1234
1235 if (AssociatedConstraints.empty()) {
1236 Satisfaction.IsSatisfied = true;
1237 return false;
1238 }
1239
1240 // In the general case, we can't check satisfaction if the arguments contain
1241 // unsubstituted template parameters, even if they are purely syntactic,
1242 // because they may still turn out to be invalid after substitution.
1243 // This could be permitted in cases where this substitution will still be
1244 // attempted later and diagnosed, such as function template specializations,
1245 // but that's not the case for concept specializations.
1246 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1247 Satisfaction.IsSatisfied = true;
1248 return false;
1249 }
1250
1252 if (TemplateArgsLists.getNumLevels() != 0)
1253 Args = TemplateArgsLists.getInnermost();
1254
1255 struct SynthesisContextPair {
1258 SynthesisContextPair(Sema &S, NamedDecl *Template,
1259 ArrayRef<TemplateArgument> TemplateArgs,
1260 SourceRange InstantiationRange)
1261 : Inst(S, InstantiationRange.getBegin(),
1263 TemplateArgs, InstantiationRange),
1264 NSC(S) {}
1265 };
1266 std::optional<SynthesisContextPair> SynthesisContext;
1267 if (!TopLevelConceptId)
1268 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
1269 TemplateIDRange);
1270
1271 const NormalizedConstraint *C =
1272 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1273 if (!C) {
1274 Satisfaction.IsSatisfied = false;
1275 return true;
1276 }
1277
1278 if (TopLevelConceptId)
1279 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1280 const_cast<NormalizedConstraint *>(C),
1281 Template, /*CSE=*/nullptr,
1283
1284 ExprResult Res =
1286 S, Template, TopLevelConceptId, TemplateIDRange.getBegin(),
1287 S.ArgPackSubstIndex, Satisfaction,
1288 /*BuildExpression=*/ConvertedExpr != nullptr)
1289 .Evaluate(*C, TemplateArgsLists);
1290
1291 if (Res.isUsable() && ConvertedExpr)
1292 *ConvertedExpr = Res.get();
1293
1294 return false;
1295}
1296
1299 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1300 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1301 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1302 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1303 llvm::TimeTraceScope TimeScope(
1304 "CheckConstraintSatisfaction", [TemplateIDRange, this] {
1305 return TemplateIDRange.printToString(getSourceManager());
1306 });
1307 if (AssociatedConstraints.empty()) {
1308 OutSatisfaction.IsSatisfied = true;
1309 return false;
1310 }
1311 const auto *Template = dyn_cast_if_present<const NamedDecl *>(Entity);
1312 if (!Template) {
1313 return ::CheckConstraintSatisfaction(
1314 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1315 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1316 }
1317 // Invalid templates could make their way here. Substituting them could result
1318 // in dependent expressions.
1319 if (Template->isInvalidDecl()) {
1320 OutSatisfaction.IsSatisfied = false;
1321 return true;
1322 }
1323
1324 // A list of the template argument list flattened in a predictible manner for
1325 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1326 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1327 // here.
1329 for (auto List : TemplateArgsLists)
1330 for (const TemplateArgument &Arg : List.Args)
1331 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1332
1333 const NamedDecl *Owner = Template;
1334 if (TopLevelConceptId)
1335 Owner = TopLevelConceptId->getNamedConcept().getAsTemplateDecl();
1336
1337 llvm::FoldingSetNodeID ID;
1338 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1339 if (auto *Cached = SatisfactionCache.lookup(ID)) {
1340 OutSatisfaction = *Cached;
1341 return false;
1342 }
1343
1344 auto Satisfaction = std::make_unique<ConstraintSatisfaction>();
1346 *this, Template, AssociatedConstraints, TemplateArgsLists,
1347 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1348 OutSatisfaction = std::move(*Satisfaction);
1349 return true;
1350 }
1351
1352 // Else we can simply add this satisfaction to the list.
1353 OutSatisfaction = *Satisfaction;
1354 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1355 auto [Iter, Inserted] =
1356 SatisfactionCache.try_emplace(ID.Intern(BumpAlloc), nullptr);
1357 if (Inserted)
1358 Iter->second = Satisfaction.release();
1359 return false;
1360}
1361
1362static ExprResult
1364 const ConceptSpecializationExpr *CSE,
1365 UnsignedOrNone SubstIndex) {
1366 Sema::SFINAETrap Trap(S);
1367 // [C++2c] [temp.constr.normal]
1368 // Otherwise, to form CE, any non-dependent concept template argument Ai
1369 // is substituted into the constraint-expression of C.
1370 // If any such substitution results in an invalid concept-id,
1371 // the program is ill-formed; no diagnostic is required.
1372
1374 Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
1375
1376 const ASTTemplateArgumentListInfo *ArgsAsWritten =
1378 if (llvm::none_of(
1379 ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {
1380 return !ArgLoc.getArgument().isDependent() &&
1381 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1382 })) {
1383 return Concept->getConstraintExpr();
1384 }
1385
1387 Concept, Concept->getLexicalDeclContext(),
1388 /*Final=*/false, CSE->getTemplateArguments(),
1389 /*RelativeToPrimary=*/true,
1390 /*Pattern=*/nullptr,
1391 /*ForConstraintInstantiation=*/true);
1392 return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),
1393 MLTAL);
1394}
1395
1396bool Sema::SetupConstraintScope(
1397 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1398 const MultiLevelTemplateArgumentList &MLTAL,
1400 assert(!isLambdaCallOperator(FD) &&
1401 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1402 "instantiations");
1403 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1404 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1406 *this, FD->getPointOfInstantiation(),
1407 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1408 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1409 SourceRange());
1410 if (Inst.isInvalid())
1411 return true;
1412
1413 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1414 // 'instantiated' parameters and adds it to the context. For the case where
1415 // this function is a template being instantiated NOW, we also need to add
1416 // the list of current template arguments to the list so that they also can
1417 // be picked out of the map.
1418 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1419 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1420 /*Final=*/false);
1421 if (addInstantiatedParametersToScope(
1422 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1423 return true;
1424 }
1425
1426 // If this is a member function, make sure we get the parameters that
1427 // reference the original primary template.
1428 if (FunctionTemplateDecl *FromMemTempl =
1429 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1430 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1431 Scope, MLTAL))
1432 return true;
1433 }
1434
1435 return false;
1436 }
1437
1440 FunctionDecl *InstantiatedFrom =
1444
1446 *this, FD->getPointOfInstantiation(),
1447 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1448 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1449 SourceRange());
1450 if (Inst.isInvalid())
1451 return true;
1452
1453 // Case where this was not a template, but instantiated as a
1454 // child-function.
1455 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1456 return true;
1457 }
1458
1459 return false;
1460}
1461
1462// This function collects all of the template arguments for the purposes of
1463// constraint-instantiation and checking.
1464std::optional<MultiLevelTemplateArgumentList>
1465Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1466 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1468 MultiLevelTemplateArgumentList MLTAL;
1469
1470 // Collect the list of template arguments relative to the 'primary' template.
1471 // We need the entire list, since the constraint is completely uninstantiated
1472 // at this point.
1473 MLTAL =
1475 /*Final=*/false, /*Innermost=*/std::nullopt,
1476 /*RelativeToPrimary=*/true,
1477 /*Pattern=*/nullptr,
1478 /*ForConstraintInstantiation=*/true);
1479 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1480 if (isLambdaCallOperator(FD))
1481 return MLTAL;
1482 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1483 return std::nullopt;
1484
1485 return MLTAL;
1486}
1487
1489 ConstraintSatisfaction &Satisfaction,
1490 SourceLocation UsageLoc,
1491 bool ForOverloadResolution) {
1492 // Don't check constraints if the function is dependent. Also don't check if
1493 // this is a function template specialization, as the call to
1494 // CheckFunctionTemplateConstraints after this will check it
1495 // better.
1496 if (FD->isDependentContext() ||
1497 FD->getTemplatedKind() ==
1499 Satisfaction.IsSatisfied = true;
1500 return false;
1501 }
1502
1503 // A lambda conversion operator has the same constraints as the call operator
1504 // and constraints checking relies on whether we are in a lambda call operator
1505 // (and may refer to its parameters), so check the call operator instead.
1506 // Note that the declarations outside of the lambda should also be
1507 // considered. Turning on the 'ForOverloadResolution' flag results in the
1508 // LocalInstantiationScope not looking into its parents, but we can still
1509 // access Decls from the parents while building a lambda RAII scope later.
1510 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1511 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1512 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1513 Satisfaction, UsageLoc,
1514 /*ShouldAddDeclsFromParentScope=*/true);
1515
1516 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1517
1518 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1519 if (isLambdaCallOperator(CtxToSave))
1520 CtxToSave = CtxToSave->getParent()->getParent();
1521 else
1522 CtxToSave = CtxToSave->getNonTransparentContext();
1523 }
1524
1525 ContextRAII SavedContext{*this, CtxToSave};
1526 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1527 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1528 SetupConstraintCheckingTemplateArgumentsAndScope(
1529 const_cast<FunctionDecl *>(FD), {}, Scope);
1530
1531 if (!MLTAL)
1532 return true;
1533
1534 Qualifiers ThisQuals;
1535 CXXRecordDecl *Record = nullptr;
1536 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1537 ThisQuals = Method->getMethodQualifiers();
1538 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1539 }
1540 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1541
1543 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1544 ForOverloadResolution);
1545
1547 FD, FD->getTrailingRequiresClause(), *MLTAL,
1548 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1549 Satisfaction);
1550}
1551
1553 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
1554 const Expr *ConstrExpr) {
1556 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
1557 /*Innermost=*/std::nullopt,
1558 /*RelativeToPrimary=*/true,
1559 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
1560 /*SkipForSpecialization*/ false);
1561
1562 if (MLTAL.getNumSubstitutedLevels() == 0)
1563 return ConstrExpr;
1564
1565 // Set up a dummy 'instantiation' scope in the case of reference to function
1566 // parameters that the surrounding function hasn't been instantiated yet. Note
1567 // this may happen while we're comparing two templates' constraint
1568 // equivalence.
1569 std::optional<LocalInstantiationScope> ScopeForParameters;
1570 if (const NamedDecl *ND = DeclInfo.getDecl();
1571 ND && ND->isFunctionOrFunctionTemplate()) {
1572 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1573 const FunctionDecl *FD = ND->getAsFunction();
1575 Template && Template->getInstantiatedFromMemberTemplate())
1576 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1577 for (auto *PVD : FD->parameters()) {
1578 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1579 continue;
1580 if (!PVD->isParameterPack()) {
1581 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1582 continue;
1583 }
1584 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1585 // to avoid building SubstTemplateTypeParmPackTypes for
1586 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1587 // otherwise reference the AssociatedDecl of the template arguments, which
1588 // is, in this case, the template declaration.
1589 //
1590 // However, as we are in the process of comparing potential
1591 // re-declarations, the canonical declaration is the declaration itself at
1592 // this point. So if we didn't expand these packs, we would end up with an
1593 // incorrect profile difference because we will be profiling the
1594 // canonical types!
1595 //
1596 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1597 // that we can eliminate the Scope in the cases where the declarations are
1598 // not necessarily instantiated. It would also benefit the noexcept
1599 // specifier comparison.
1600 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1601 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1602 }
1603 }
1604
1605 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1606
1607 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1608 // essential for having an injected class as the canonical type for a template
1609 // specialization type at the rebuilding stage. This guarantees that, for
1610 // out-of-line definitions, injected class name types and their equivalent
1611 // template specializations can be profiled to the same value, which makes it
1612 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1613 // perceived identical.
1614 std::optional<Sema::ContextRAII> ContextScope;
1615 const DeclContext *DC = [&] {
1616 if (!DeclInfo.getDecl())
1617 return DeclInfo.getDeclContext();
1618 return DeclInfo.getDecl()->getFriendObjectKind()
1619 ? DeclInfo.getLexicalDeclContext()
1620 : DeclInfo.getDeclContext();
1621 }();
1622 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1623 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1624 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1625 /*NewThisContext=*/false);
1626 }
1627 EnterExpressionEvaluationContext UnevaluatedContext(
1631 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1632 if (!SubstConstr.isUsable())
1633 return nullptr;
1634 return SubstConstr.get();
1635}
1636
1638 const Expr *OldConstr,
1640 const Expr *NewConstr) {
1641 if (OldConstr == NewConstr)
1642 return true;
1643 // C++ [temp.constr.decl]p4
1644 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1645 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1646 Sema::SFINAETrap _(*this);
1647 if (const Expr *SubstConstr =
1649 OldConstr))
1650 OldConstr = SubstConstr;
1651 else
1652 return false;
1653 if (const Expr *SubstConstr =
1655 NewConstr))
1656 NewConstr = SubstConstr;
1657 else
1658 return false;
1659 }
1660
1661 llvm::FoldingSetNodeID ID1, ID2;
1662 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1663 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1664 return ID1 == ID2;
1665}
1666
1668 assert(FD->getFriendObjectKind() && "Must be a friend!");
1669
1670 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1671 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1672 // non-function-template.
1673 assert(FD->getDescribedFunctionTemplate() &&
1674 "Non-function templates don't need to be checked");
1675
1678
1679 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1680 for (const AssociatedConstraint &AC : ACs)
1681 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1682 AC.ConstraintExpr))
1683 return true;
1684
1685 return false;
1686}
1687
1689 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1690 SourceRange TemplateIDRange) {
1691 ConstraintSatisfaction Satisfaction;
1692 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1693 TD->getAssociatedConstraints(AssociatedConstraints);
1694 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1695 TemplateIDRange, Satisfaction) ||
1696 !Satisfaction.IsSatisfied) {
1697 SmallString<128> TemplateArgString;
1698 TemplateArgString = " ";
1699 TemplateArgString += getTemplateArgumentBindingsText(
1700 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1701 TemplateArgsLists.getInnermost().size());
1702
1703 Diag(TemplateIDRange.getBegin(),
1704 diag::err_template_arg_list_constraints_not_satisfied)
1706 << TemplateArgString << TemplateIDRange;
1707 DiagnoseUnsatisfiedConstraint(Satisfaction);
1708 return true;
1709 }
1710 return false;
1711}
1712
1714 Sema &SemaRef, SourceLocation PointOfInstantiation,
1716 ConstraintSatisfaction &Satisfaction) {
1718 Template->getAssociatedConstraints(TemplateAC);
1719 if (TemplateAC.empty()) {
1720 Satisfaction.IsSatisfied = true;
1721 return false;
1722 }
1723
1725
1726 FunctionDecl *FD = Template->getTemplatedDecl();
1727 // Collect the list of template arguments relative to the 'primary'
1728 // template. We need the entire list, since the constraint is completely
1729 // uninstantiated at this point.
1730
1732 {
1733 // getTemplateInstantiationArgs uses this instantiation context to find out
1734 // template arguments for uninstantiated functions.
1735 // We don't want this RAII object to persist, because there would be
1736 // otherwise duplicate diagnostic notes.
1738 SemaRef, PointOfInstantiation,
1740 PointOfInstantiation);
1741 if (Inst.isInvalid())
1742 return true;
1743 MLTAL = SemaRef.getTemplateInstantiationArgs(
1744 /*D=*/FD, FD,
1745 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1746 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1747 }
1748
1749 Sema::ContextRAII SavedContext(SemaRef, FD);
1750 return SemaRef.CheckConstraintSatisfaction(
1751 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1752}
1753
1755 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1756 ArrayRef<TemplateArgument> TemplateArgs,
1757 ConstraintSatisfaction &Satisfaction) {
1758 // In most cases we're not going to have constraints, so check for that first.
1759 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1760
1761 if (!Template)
1762 return ::CheckFunctionConstraintsWithoutInstantiation(
1763 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1764 TemplateArgs, Satisfaction);
1765
1766 // Note - code synthesis context for the constraints check is created
1767 // inside CheckConstraintsSatisfaction.
1769 Template->getAssociatedConstraints(TemplateAC);
1770 if (TemplateAC.empty()) {
1771 Satisfaction.IsSatisfied = true;
1772 return false;
1773 }
1774
1775 // Enter the scope of this instantiation. We don't use
1776 // PushDeclContext because we don't have a scope.
1777 Sema::ContextRAII savedContext(*this, Decl);
1779
1780 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1781 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1782 Scope);
1783
1784 if (!MLTAL)
1785 return true;
1786
1787 Qualifiers ThisQuals;
1788 CXXRecordDecl *Record = nullptr;
1789 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1790 ThisQuals = Method->getMethodQualifiers();
1791 Record = Method->getParent();
1792 }
1793
1794 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1795 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1796 Scope);
1797
1798 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1799 PointOfInstantiation, Satisfaction);
1800}
1801
1804 bool First) {
1805 assert(!Req->isSatisfied() &&
1806 "Diagnose() can only be used on an unsatisfied requirement");
1807 switch (Req->getSatisfactionStatus()) {
1809 llvm_unreachable("Diagnosing a dependent requirement");
1810 break;
1812 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1813 if (!SubstDiag->DiagMessage.empty())
1814 S.Diag(SubstDiag->DiagLoc,
1815 diag::note_expr_requirement_expr_substitution_error)
1816 << (int)First << SubstDiag->SubstitutedEntity
1817 << SubstDiag->DiagMessage;
1818 else
1819 S.Diag(SubstDiag->DiagLoc,
1820 diag::note_expr_requirement_expr_unknown_substitution_error)
1821 << (int)First << SubstDiag->SubstitutedEntity;
1822 break;
1823 }
1825 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1826 << (int)First << Req->getExpr();
1827 break;
1829 auto *SubstDiag =
1831 if (!SubstDiag->DiagMessage.empty())
1832 S.Diag(SubstDiag->DiagLoc,
1833 diag::note_expr_requirement_type_requirement_substitution_error)
1834 << (int)First << SubstDiag->SubstitutedEntity
1835 << SubstDiag->DiagMessage;
1836 else
1837 S.Diag(
1838 SubstDiag->DiagLoc,
1839 diag::
1840 note_expr_requirement_type_requirement_unknown_substitution_error)
1841 << (int)First << SubstDiag->SubstitutedEntity;
1842 break;
1843 }
1845 ConceptSpecializationExpr *ConstraintExpr =
1847 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1848 break;
1849 }
1851 llvm_unreachable("We checked this above");
1852 }
1853}
1854
1857 bool First) {
1858 assert(!Req->isSatisfied() &&
1859 "Diagnose() can only be used on an unsatisfied requirement");
1860 switch (Req->getSatisfactionStatus()) {
1862 llvm_unreachable("Diagnosing a dependent requirement");
1863 return;
1865 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1866 if (!SubstDiag->DiagMessage.empty())
1867 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1868 << (int)First << SubstDiag->SubstitutedEntity
1869 << SubstDiag->DiagMessage;
1870 else
1871 S.Diag(SubstDiag->DiagLoc,
1872 diag::note_type_requirement_unknown_substitution_error)
1873 << (int)First << SubstDiag->SubstitutedEntity;
1874 return;
1875 }
1876 default:
1877 llvm_unreachable("Unknown satisfaction status");
1878 return;
1879 }
1880}
1881
1884 SourceLocation Loc, bool First) {
1885 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1886 S.Diag(
1887 Loc,
1888 diag::
1889 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1890 << (int)First
1891 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1892 << Concept->getNamedConcept().getAsTemplateDecl();
1893 } else {
1894 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1895 << (int)First << Concept;
1896 }
1897}
1898
1901 bool First, concepts::NestedRequirement *Req = nullptr);
1902
1905 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1906 for (auto &Record : Records) {
1908 Loc = {};
1910 }
1911}
1912
1922
1924 const Expr *SubstExpr,
1925 bool First) {
1926 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1927 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1928 switch (BO->getOpcode()) {
1929 // These two cases will in practice only be reached when using fold
1930 // expressions with || and &&, since otherwise the || and && will have been
1931 // broken down into atomic constraints during satisfaction checking.
1932 case BO_LOr:
1933 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1936 /*First=*/false);
1937 return;
1938 case BO_LAnd: {
1939 bool LHSSatisfied =
1940 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1941 if (LHSSatisfied) {
1942 // LHS is true, so RHS must be false.
1944 return;
1945 }
1946 // LHS is false
1948
1949 // RHS might also be false
1950 bool RHSSatisfied =
1951 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1952 if (!RHSSatisfied)
1954 /*First=*/false);
1955 return;
1956 }
1957 case BO_GE:
1958 case BO_LE:
1959 case BO_GT:
1960 case BO_LT:
1961 case BO_EQ:
1962 case BO_NE:
1963 if (BO->getLHS()->getType()->isIntegerType() &&
1964 BO->getRHS()->getType()->isIntegerType()) {
1965 Expr::EvalResult SimplifiedLHS;
1966 Expr::EvalResult SimplifiedRHS;
1967 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1969 /*InConstantContext=*/true);
1970 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1972 /*InConstantContext=*/true);
1973 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1974 S.Diag(SubstExpr->getBeginLoc(),
1975 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1976 << (int)First << SubstExpr
1977 << toString(SimplifiedLHS.Val.getInt(), 10)
1978 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1979 << toString(SimplifiedRHS.Val.getInt(), 10);
1980 return;
1981 }
1982 }
1983 break;
1984
1985 default:
1986 break;
1987 }
1988 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1990 return;
1991 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1992 // Drill down concept ids treated as atomic constraints
1994 return;
1995 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1996 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1997 assert(TTE->getNumArgs() == 2);
1998 S.Diag(SubstExpr->getSourceRange().getBegin(),
1999 diag::note_is_deducible_constraint_evaluated_to_false)
2000 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2001 return;
2002 }
2003
2004 S.Diag(SubstExpr->getSourceRange().getBegin(),
2005 diag::note_atomic_constraint_evaluated_to_false)
2006 << (int)First << SubstExpr;
2007 S.DiagnoseTypeTraitDetails(SubstExpr);
2008}
2009
2013 if (auto *Diag = dyn_cast<const ConstraintSubstitutionDiagnostic *>(Record)) {
2014 if (Req)
2015 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
2016 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
2017 else
2018 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2019 << Diag->second;
2020 return;
2021 }
2022 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
2023 if (Loc.isInvalid())
2024 Loc = Concept->getBeginLoc();
2026 return;
2027 }
2030}
2031
2033 // FIXME: RequiresExpr should store dependent diagnostics.
2034 for (concepts::Requirement *Req : RE->getRequirements())
2035 if (!Req->isDependent() && !Req->isSatisfied()) {
2036 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2038 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
2040 else
2043 break;
2044 }
2045}
2046
2048 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
2049 bool First) {
2050
2051 assert(!Satisfaction.IsSatisfied &&
2052 "Attempted to diagnose a satisfied constraint");
2053 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
2054}
2055
2057 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
2058
2059 const ASTConstraintSatisfaction &Satisfaction =
2060 ConstraintExpr->getSatisfaction();
2061
2062 assert(!Satisfaction.isSatisfied() &&
2063 "Attempted to diagnose a satisfied constraint");
2064
2065 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
2066 ConstraintExpr->getBeginLoc(), First);
2067}
2068
2069namespace clang {
2070
2071class SubstituteParameterMappings {
2072 Sema &SemaRef;
2073
2074 const MultiLevelTemplateArgumentList *MLTAL;
2075 const ASTTemplateArgumentListInfo *ArgsAsWritten;
2076
2077 // When normalizing a fold constraint, e.g.
2078 // C<Pack1, Pack2...> && ...
2079 // we want the TreeTransform to expand only Pack2 but not Pack1,
2080 // since Pack1 will be expanded during the evaluation of the fold expression.
2081 // This flag helps rewrite any non-PackExpansion packs into "expanded"
2082 // parameters.
2083 bool RemovePacksForFoldExpr;
2084
2085 SubstituteParameterMappings(Sema &SemaRef,
2086 const MultiLevelTemplateArgumentList *MLTAL,
2087 const ASTTemplateArgumentListInfo *ArgsAsWritten,
2088 bool RemovePacksForFoldExpr)
2089 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2090 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2091
2092 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
2093
2094 bool substitute(NormalizedConstraintWithParamMapping &N);
2095
2096 bool substitute(ConceptIdConstraint &CC);
2097
2098public:
2100 bool RemovePacksForFoldExpr = false)
2101 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
2102 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2103
2104 bool substitute(NormalizedConstraint &N);
2105};
2106
2107} // namespace clang
2108
2109void SubstituteParameterMappings::buildParameterMapping(
2111 TemplateParameterList *TemplateParams =
2112 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
2113
2114 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2115 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2116
2118 SemaRef.MarkUsedTemplateParameters(
2119 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2120 /*OnlyDeduced=*/false,
2121 /*Depth=*/0, OccurringIndices);
2122
2123 SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(
2124 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2125 /*Depth=*/0, OccurringIndicesForSubsumption);
2126
2127 } else if (N.getKind() ==
2129 SemaRef.MarkUsedTemplateParameters(
2130 static_cast<FoldExpandedConstraint &>(N).getPattern(),
2131 /*OnlyDeduced=*/false,
2132 /*Depth=*/0, OccurringIndices);
2134 auto *Args = static_cast<ConceptIdConstraint &>(N)
2135 .getConceptId()
2136 ->getTemplateArgsAsWritten();
2137 if (Args)
2138 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2139 /*Depth=*/0, OccurringIndices);
2140 }
2141
2142 // If a parameter is only referenced in a default template argument,
2143 // we need to add it to the mapping explicitly.
2144 {
2145 llvm::SmallVector<TemplateArgument> DefaultArgs;
2146 for (unsigned I = TemplateParams->getMinRequiredArguments();
2147 I < TemplateParams->size(); ++I) {
2148 const NamedDecl *Param = TemplateParams->getParam(I);
2149 if (Param->isParameterPack())
2150 break;
2151 const TemplateArgument *Arg =
2152 SemaRef.getASTContext().getDefaultTemplateArgumentOrNone(Param);
2153 assert(Arg && "expected a default argument");
2154 DefaultArgs.emplace_back(std::move(*Arg));
2155 }
2156 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*OnlyDeduced=*/false,
2157 /*Depth=*/0, OccurringIndices);
2158 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*OnlyDeduced=*/false,
2159 /*Depth=*/0,
2160 OccurringIndicesForSubsumption);
2161 }
2162
2163 unsigned Size = OccurringIndices.count();
2164 // When the constraint is independent of any template parameters,
2165 // we build an empty mapping so that we can distinguish these cases
2166 // from cases where no mapping exists at all, e.g. when there are only atomic
2167 // constraints.
2168 TemplateArgumentLoc *TempArgs =
2169 new (SemaRef.Context) TemplateArgumentLoc[Size];
2170 llvm::SmallVector<NamedDecl *> UsedParams;
2171 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2172 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2173 ? ArgsAsWritten->arguments()[I].getLocation()
2174 : SourceLocation();
2175 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
2176 // can't assert Loc.isValid() now.
2177 if (OccurringIndices[I]) {
2178 NamedDecl *Param = TemplateParams->begin()[I];
2179 new (&(TempArgs)[J]) TemplateArgumentLoc(
2180 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2181 UsedParams.push_back(Param);
2182 J++;
2183 }
2184 }
2185 auto *UsedList = TemplateParameterList::Create(
2186 SemaRef.Context, TemplateParams->getTemplateLoc(),
2187 TemplateParams->getLAngleLoc(), UsedParams,
2188 /*RAngleLoc=*/SourceLocation(),
2189 /*RequiresClause=*/nullptr);
2191 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2192 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
2193}
2194
2195bool SubstituteParameterMappings::substitute(
2197 if (!N.hasParameterMapping())
2198 buildParameterMapping(N);
2199
2200 // If the parameter mapping is empty, there is nothing to substitute.
2201 if (N.getParameterMapping().empty())
2202 return false;
2203
2204 SourceLocation InstLocBegin, InstLocEnd;
2205 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2206 if (Arguments.empty()) {
2207 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2208 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2209 } else {
2210 auto SR = Arguments[0].getSourceRange();
2211 InstLocBegin = SR.getBegin();
2212 InstLocEnd = SR.getEnd();
2213 }
2214 Sema::NonSFINAEContext _(SemaRef);
2215 Sema::InstantiatingTemplate Inst(
2216 SemaRef, InstLocBegin,
2217 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2218 const_cast<NamedDecl *>(N.getConstraintDecl()),
2219 {InstLocBegin, InstLocEnd});
2220 if (Inst.isInvalid())
2221 return true;
2222
2223 // TransformTemplateArguments is unable to preserve the source location of a
2224 // pack. The SourceLocation is necessary for the instantiation location.
2225 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2226 // which is wrong.
2227 TemplateArgumentListInfo SubstArgs;
2228 llvm::SaveAndRestore<decltype(SemaRef.CurrentCachedTemplateArgs)>
2229 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2230 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2231 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs))
2232 return true;
2233 Sema::CheckTemplateArgumentInfo CTAI;
2234 auto *TD =
2235 const_cast<TemplateDecl *>(cast<TemplateDecl>(N.getConstraintDecl()));
2236 if (SemaRef.CheckTemplateArgumentList(TD, N.getUsedTemplateParamList(),
2237 TD->getLocation(), SubstArgs,
2238 /*DefaultArguments=*/{},
2239 /*PartialTemplateArgs=*/false, CTAI))
2240 return true;
2241
2242 TemplateArgumentLoc *TempArgs =
2243 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2244
2245 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2246 SourceLocation Loc;
2247 // If this is an empty pack, we have no corresponding SubstArgs.
2248 if (I < SubstArgs.size())
2249 Loc = SubstArgs.arguments()[I].getLocation();
2250
2251 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2252 CTAI.SugaredConverted[I], QualType(), Loc);
2253 }
2254
2255 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2256 CTAI.SugaredConverted.size());
2260 return false;
2261}
2262
2263bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2264 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2265
2266 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2267 return true;
2268
2269 auto *CSE = CC.getConceptSpecializationExpr();
2270 assert(CSE);
2271 assert(!CC.getBeginLoc().isInvalid());
2272
2273 SourceLocation InstLocBegin, InstLocEnd;
2274 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2275 Arguments.empty()) {
2276 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2277 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2278 } else {
2279 auto SR = Arguments[0].getSourceRange();
2280 InstLocBegin = SR.getBegin();
2281 InstLocEnd = SR.getEnd();
2282 }
2283 Sema::NonSFINAEContext _(SemaRef);
2284 // This is useful for name lookup across modules; see Sema::getLookupModules.
2285 Sema::InstantiatingTemplate Inst(
2286 SemaRef, InstLocBegin,
2287 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2288 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2289 {InstLocBegin, InstLocEnd});
2290 if (Inst.isInvalid())
2291 return true;
2292
2293 TemplateArgumentListInfo Out;
2294 // TransformTemplateArguments is unable to preserve the source location of a
2295 // pack. The SourceLocation is necessary for the instantiation location.
2296 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2297 // which is wrong.
2298 llvm::SaveAndRestore<decltype(SemaRef.CurrentCachedTemplateArgs)>
2299 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2300 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2301 CSE->getTemplateArgsAsWritten();
2302 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2303 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out))
2304 return true;
2305 Sema::CheckTemplateArgumentInfo CTAI;
2306 if (SemaRef.CheckTemplateArgumentList(CSE->getConceptDecl(),
2307 CSE->getConceptNameInfo().getLoc(), Out,
2308 /*DefaultArgs=*/{},
2309 /*PartialTemplateArgs=*/false, CTAI,
2310 /*UpdateArgsWithConversions=*/false))
2311 return true;
2312 auto TemplateArgs = *MLTAL;
2313 TemplateArgs.replaceOutermostTemplateArguments(CSE->getConceptDecl(),
2314 CTAI.SugaredConverted);
2315 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2316 RemovePacksForFoldExpr)
2317 .substitute(CC.getNormalizedConstraint());
2318}
2319
2320bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2321 switch (N.getKind()) {
2323 if (!MLTAL) {
2324 assert(!ArgsAsWritten);
2325 return false;
2326 }
2327 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2328 }
2330 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2331 if (!MLTAL) {
2332 llvm::SaveAndRestore _1(RemovePacksForFoldExpr, true);
2333 assert(!ArgsAsWritten);
2334 return substitute(FE.getNormalizedPattern());
2335 }
2336 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2337 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2338 return SubstituteParameterMappings(SemaRef, /*RemovePacksForFoldExpr=*/true)
2339 .substitute(FE.getNormalizedPattern());
2340 }
2342 auto &CC = static_cast<ConceptIdConstraint &>(N);
2343 if (MLTAL) {
2344 assert(ArgsAsWritten);
2345 return substitute(CC);
2346 }
2347 assert(!ArgsAsWritten);
2349 // Make sure that lambdas within template arguments live in a
2350 // dependent context such that they are assured to be transformed during
2351 // constraint evaluation.
2354 /*LambdaContextDecl=*/
2356 CSE->getSpecializationDecl()));
2359 if (RemovePacksForFoldExpr) {
2361 ArrayRef<TemplateArgumentLoc> InputArgLoc =
2363 if (AdjustConstraints(SemaRef, /*TemplateDepth=*/0,
2364 /*RemoveNonPackExpansionPacks=*/true)
2365 .TransformTemplateArguments(InputArgLoc.begin(),
2366 InputArgLoc.end(), OutArgs))
2367 return true;
2369 // Repack the packs.
2370 if (SemaRef.CheckTemplateArgumentList(
2371 Concept, Concept->getTemplateParameters(), Concept->getBeginLoc(),
2372 OutArgs,
2373 /*DefaultArguments=*/{},
2374 /*PartialTemplateArgs=*/false, CTAI))
2375 return true;
2376 InnerArgs = std::move(CTAI.SugaredConverted);
2377 }
2378
2379 MultiLevelTemplateArgumentList MLTAL = SemaRef.getTemplateInstantiationArgs(
2380 Concept, Concept->getLexicalDeclContext(),
2381 /*Final=*/true, InnerArgs,
2382 /*RelativeToPrimary=*/true,
2383 /*Pattern=*/nullptr,
2384 /*ForConstraintInstantiation=*/true);
2385 MLTAL.setRetainInnerDepths();
2386
2387 return SubstituteParameterMappings(SemaRef, &MLTAL,
2389 RemovePacksForFoldExpr)
2390 .substitute(CC.getNormalizedConstraint());
2391 }
2393 auto &Compound = static_cast<CompoundConstraint &>(N);
2394 if (substitute(Compound.getLHS()))
2395 return true;
2396 return substitute(Compound.getRHS());
2397 }
2398 }
2399 llvm_unreachable("Unknown ConstraintKind enum");
2400}
2401
2402NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2403 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2404 assert(ACs.size() != 0);
2405 auto *Conjunction =
2406 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2407 if (!Conjunction)
2408 return nullptr;
2409 for (unsigned I = 1; I < ACs.size(); ++I) {
2410 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2411 ACs[I].ArgPackSubstIndex);
2412 if (!Next)
2413 return nullptr;
2415 Conjunction, Next);
2416 }
2417 return Conjunction;
2418}
2419
2420NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2421 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2422 assert(E != nullptr);
2423
2424 // C++ [temp.constr.normal]p1.1
2425 // [...]
2426 // - The normal form of an expression (E) is the normal form of E.
2427 // [...]
2428 E = E->IgnoreParenImpCasts();
2429
2430 llvm::FoldingSetNodeID ID;
2431 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2432 return nullptr;
2433 }
2434 SatisfactionStackRAII StackRAII(S, D, ID);
2435
2436 // C++2a [temp.param]p4:
2437 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2438 // Fold expression is considered atomic constraints per current wording.
2439 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2440
2441 if (LogicalBinOp BO = E) {
2442 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2443 if (!LHS)
2444 return nullptr;
2445 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2446 if (!RHS)
2447 return nullptr;
2448
2450 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2451 }
2452 if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2453 // C++ [temp.constr.normal]p1.1
2454 // [...]
2455 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2456 // where C names a concept, is the normal form of the
2457 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2458 // respective template parameters in the parameter mappings in each atomic
2459 // constraint. If any such substitution results in an invalid type or
2460 // expression, the program is ill-formed; no diagnostic is required.
2461 // [...]
2462 NormalizedConstraint *SubNF;
2463 if (ExprResult Res =
2464 SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);
2465 Res.isUsable())
2466 // Use canonical declarations to merge ConceptDecls across different
2467 // modules.
2468 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2469 S, CSE->getConceptDecl()->getCanonicalDecl(),
2470 AssociatedConstraint(Res.get(), SubstIndex));
2471 else
2472 return nullptr;
2474 CSE->getConceptReference(), SubNF, D,
2475 CSE, SubstIndex);
2476 }
2477 if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2478 FE && S.getLangOpts().CPlusPlus26 &&
2479 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2480 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2481
2482 // Normalize fold expressions in C++26.
2483
2485 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2488
2489 if (FE->getInit()) {
2490 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2491 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2492 if (!LHS || !RHS)
2493 return nullptr;
2494
2495 if (FE->isRightFold())
2497 FE->getPattern(), D, Kind, LHS);
2498 else
2500 FE->getPattern(), D, Kind, RHS);
2501
2503 S.getASTContext(), LHS,
2504 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2505 : CCK_Disjunction),
2506 RHS);
2507 }
2508 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2509 if (!Sub)
2510 return nullptr;
2511 return FoldExpandedConstraint::Create(S.getASTContext(), FE->getPattern(),
2512 D, Kind, Sub);
2513 }
2514 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2515}
2516
2518 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2519 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2520 if (!ConstrainedDeclOrNestedReq) {
2521 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2522 *this, nullptr, AssociatedConstraints);
2523 if (!Normalized ||
2524 SubstituteParameterMappings(*this).substitute(*Normalized))
2525 return nullptr;
2526
2527 return Normalized;
2528 }
2529
2530 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2531 const NamedDecl *ND = dyn_cast<const NamedDecl *>(ConstrainedDeclOrNestedReq);
2532 // The normal form only depends on the constraint expressions, and the
2533 // members of all specializations of a class template share the
2534 // (uninstantiated) constraint expressions of the member they were
2535 // instantiated from. Cache the normal form of each expression to not
2536 // normalize the same expression once per class template specialization.
2537 NormalizedConstraint *Normalized = nullptr;
2538 for (const AssociatedConstraint &AC : AssociatedConstraints) {
2539 std::pair<const Expr *, unsigned> Key(
2540 AC.ConstraintExpr, AC.ArgPackSubstIndex.toInternalRepresentation());
2542 if (auto It = NormalizedConstraintExprCache.find(Key);
2543 It != NormalizedConstraintExprCache.end()) {
2544 Next = It->second;
2545 } else {
2546 Next = NormalizedConstraint::fromAssociatedConstraints(*this, ND, AC);
2547 // substitute() can invalidate iterators of NormalizedConstraintExprCache.
2548 if (Next && SubstituteParameterMappings(*this).substitute(*Next))
2549 Next = nullptr;
2550 NormalizedConstraintExprCache.try_emplace(Key, Next);
2551 }
2552 if (!Next)
2553 return nullptr;
2554 Normalized =
2555 Normalized
2557 : Next;
2558 }
2559 return Normalized;
2560}
2561
2564
2565 // [C++26] [temp.constr.fold]
2566 // Two fold expanded constraints are compatible for subsumption
2567 // if their respective constraints both contain an equivalent unexpanded pack.
2568
2571 APacks);
2573 BPacks);
2574
2575 for (const UnexpandedParameterPack &APack : APacks) {
2576 auto ADI = getDepthAndIndex(APack);
2577 if (!ADI)
2578 continue;
2579 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2580 return getDepthAndIndex(BPack) == ADI;
2581 });
2582 if (It != BPacks.end())
2583 return true;
2584 }
2585 return false;
2586}
2587
2590 const NamedDecl *D2,
2592 bool &Result) {
2593#ifndef NDEBUG
2594 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2595 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2597 return Kind == FunctionDecl::TK_NonTemplate ||
2601 ->getOverloadedOperator() == OO_Spaceship);
2602 };
2603 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2604 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2605 "use non-instantiated function declaration for constraints partial "
2606 "ordering");
2607 }
2608#endif
2609
2610 if (AC1.empty()) {
2611 Result = AC2.empty();
2612 return false;
2613 }
2614 if (AC2.empty()) {
2615 // TD1 has associated constraints and TD2 does not.
2616 Result = true;
2617 return false;
2618 }
2619
2620 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2621 auto CacheEntry = SubsumptionCache.find(Key);
2622 if (CacheEntry != SubsumptionCache.end()) {
2623 Result = CacheEntry->second;
2624 return false;
2625 }
2626
2627 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
2628 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
2629
2630 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2631 if (Depth2 > Depth1) {
2632 AC1[I].ConstraintExpr =
2633 AdjustConstraints(*this, Depth2 - Depth1)
2634 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2635 .get();
2636 } else if (Depth1 > Depth2) {
2637 AC2[I].ConstraintExpr =
2638 AdjustConstraints(*this, Depth1 - Depth2)
2639 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2640 .get();
2641 }
2642 }
2643
2644 SubsumptionChecker SC(*this);
2645 // Associated declarations are used as a cache key in the event they were
2646 // normalized earlier during concept checking. However we cannot reuse these
2647 // cached results if any of the template depths have been adjusted.
2648 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2649 if (Depth2 > Depth1)
2650 DeclAC1 = nullptr;
2651 else if (Depth1 > Depth2)
2652 DeclAC2 = nullptr;
2653 std::optional<bool> Subsumes = SC.Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2654 if (!Subsumes) {
2655 // Normalization failed
2656 return true;
2657 }
2658 Result = *Subsumes;
2659 SubsumptionCache.try_emplace(Key, *Subsumes);
2660 return false;
2661}
2662
2666 if (isSFINAEContext())
2667 // No need to work here because our notes would be discarded.
2668 return false;
2669
2670 if (AC1.empty() || AC2.empty())
2671 return false;
2672
2673 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2674 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2675 const AtomicConstraint &B) {
2677 return false;
2678 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2679 if (EA == EB)
2680 return true;
2681
2682 // Not the same source level expression - are the expressions
2683 // identical?
2684 llvm::FoldingSetNodeID IDA, IDB;
2685 EA->Profile(IDA, Context, /*Canonical=*/true);
2686 EB->Profile(IDB, Context, /*Canonical=*/true);
2687 if (IDA != IDB)
2688 return false;
2689
2690 AmbiguousAtomic1 = EA;
2691 AmbiguousAtomic2 = EB;
2692 return true;
2693 };
2694
2695 {
2696 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2697 if (!Normalized1)
2698 return false;
2699
2700 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2701 if (!Normalized2)
2702 return false;
2703
2704 SubsumptionChecker SC(*this);
2705
2706 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2707 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2708
2709 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2710 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2711 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2712
2713 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2714 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2715 // Same result - no ambiguity was caused by identical atomic expressions.
2716 return false;
2717 }
2718 // A different result! Some ambiguous atomic constraint(s) caused a difference
2719 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2720
2721 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2722 << AmbiguousAtomic1->getSourceRange();
2723 Diag(AmbiguousAtomic2->getBeginLoc(),
2724 diag::note_ambiguous_atomic_constraints_similar_expression)
2725 << AmbiguousAtomic2->getSourceRange();
2726 return true;
2727}
2728
2729//
2730//
2731// ------------------------ Subsumption -----------------------------------
2732//
2733//
2735 SubsumptionCallable Callable)
2736 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2737
2738uint16_t SubsumptionChecker::getNewLiteralId() {
2739 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2740 "too many constraints!");
2741 return NextID++;
2742}
2743
2744auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2745 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2746 // C++ [temp.constr.order] p2
2747 // - an atomic constraint A subsumes another atomic constraint B
2748 // if and only if the A and B are identical [...]
2749 //
2750 // C++ [temp.constr.atomic] p2
2751 // Two atomic constraints are identical if they are formed from the
2752 // same expression and the targets of the parameter mappings are
2753 // equivalent according to the rules for expressions [...]
2754
2755 // Because subsumption of atomic constraints is an identity
2756 // relationship that does not require further analysis
2757 // We cache the results such that if an atomic constraint literal
2758 // subsumes another, their literal will be the same
2759
2760 llvm::FoldingSetNodeID ID;
2761 ID.AddBoolean(Ori->hasParameterMapping());
2762 if (Ori->hasParameterMapping()) {
2763 const auto &Mapping = Ori->getParameterMapping();
2765 Ori->mappingOccurenceListForSubsumption();
2766 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2767 if (Indexes[Idx])
2768 SemaRef.getASTContext()
2769 .getCanonicalTemplateArgument(TAL.getArgument())
2770 .Profile(ID, SemaRef.getASTContext());
2771 }
2772 }
2773 auto It = Elems.find(ID);
2774 if (It == Elems.end()) {
2775 It = Elems
2776 .insert({ID,
2777 MappedAtomicConstraint{
2778 Ori, {getNewLiteralId(), Literal::Atomic}}})
2779 .first;
2780 ReverseMap[It->second.ID.Value] = Ori;
2781 }
2782 return It->getSecond().ID;
2783}
2784
2785auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2786 auto &Elems = FoldMap[Ori->getPattern()];
2787
2788 FoldExpendedConstraintKey K;
2789 K.Kind = Ori->getFoldOperator();
2790
2791 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2792 return K.Kind == Other.Kind;
2793 });
2794 if (It == Elems.end()) {
2795 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2796 It = Elems.insert(Elems.end(), std::move(K));
2797 ReverseMap[It->ID.Value] = Ori;
2798 }
2799 return It->ID;
2800}
2801
2802auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2803 return SubsumptionChecker::Normalize<CNFFormula>(C);
2804}
2805auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2806 return SubsumptionChecker::Normalize<DNFFormula>(C);
2807}
2808
2809///
2810/// \brief SubsumptionChecker::Normalize
2811///
2812/// Normalize a formula to Conjunctive Normal Form or
2813/// Disjunctive normal form.
2814///
2815/// Each Atomic (and Fold Expanded) constraint gets represented by
2816/// a single id to reduce space.
2817///
2818/// To minimize risks of exponential blow up, if two atomic
2819/// constraints subsumes each other (same constraint and mapping),
2820/// they are represented by the same literal.
2821///
2822template <typename FormulaType>
2823FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2824 FormulaType Res;
2825
2826 auto Add = [&, this](Clause C) {
2827 // Sort each clause and remove duplicates for faster comparisons.
2828 llvm::sort(C);
2829 C.erase(llvm::unique(C), C.end());
2830 AddUniqueClauseToFormula(Res, std::move(C));
2831 };
2832
2833 switch (NC.getKind()) {
2835 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2836
2838 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2839
2841 return Normalize<FormulaType>(
2842 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2843
2845 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2846 FormulaType Left, Right;
2847 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2848 Left = Normalize<FormulaType>(Compound.getLHS());
2849 Right = Normalize<FormulaType>(Compound.getRHS());
2850 });
2851
2852 if (Compound.getCompoundKind() == FormulaType::Kind) {
2853 unsigned SizeLeft = Left.size();
2854 Res = std::move(Left);
2855 Res.reserve(SizeLeft + Right.size());
2856 std::for_each(std::make_move_iterator(Right.begin()),
2857 std::make_move_iterator(Right.end()), Add);
2858 return Res;
2859 }
2860
2861 Res.reserve(Left.size() * Right.size());
2862 for (const auto &LTransform : Left) {
2863 for (const auto &RTransform : Right) {
2864 Clause Combined;
2865 Combined.reserve(LTransform.size() + RTransform.size());
2866 llvm::copy(LTransform, std::back_inserter(Combined));
2867 llvm::copy(RTransform, std::back_inserter(Combined));
2868 Add(std::move(Combined));
2869 }
2870 }
2871 return Res;
2872 }
2873 }
2874 llvm_unreachable("Unknown ConstraintKind enum");
2875}
2876
2877void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2878 for (auto &Other : F) {
2879 if (llvm::equal(C, Other))
2880 return;
2881 }
2882 F.push_back(C);
2883}
2884
2886 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2888 const NormalizedConstraint *PNormalized =
2889 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2890 if (!PNormalized)
2891 return std::nullopt;
2892
2893 const NormalizedConstraint *QNormalized =
2894 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2895 if (!QNormalized)
2896 return std::nullopt;
2897
2898 return Subsumes(PNormalized, QNormalized);
2899}
2900
2902 const NormalizedConstraint *Q) {
2903
2904 DNFFormula DNFP = DNF(*P);
2905 CNFFormula CNFQ = CNF(*Q);
2906 return Subsumes(DNFP, CNFQ);
2907}
2908
2909bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2910 const CNFFormula &QCNF) {
2911 for (const auto &Pi : PDNF) {
2912 for (const auto &Qj : QCNF) {
2913 // C++ [temp.constr.order] p2
2914 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2915 // and only if there exists an atomic constraint Pia in Pi for which
2916 // there exists an atomic constraint, Qjb, in Qj such that Pia
2917 // subsumes Qjb.
2918 if (!DNFSubsumes(Pi, Qj))
2919 return false;
2920 }
2921 }
2922 return true;
2923}
2924
2925bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2926
2927 return llvm::any_of(P, [&](Literal LP) {
2928 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2929 });
2930}
2931
2933 const FoldExpandedConstraint *B) {
2934 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2935 A, B};
2936
2937 auto It = FoldSubsumptionCache.find(Key);
2938 if (It == FoldSubsumptionCache.end()) {
2939 // C++ [temp.constr.order]
2940 // a fold expanded constraint A subsumes another fold expanded
2941 // constraint B if they are compatible for subsumption, have the same
2942 // fold-operator, and the constraint of A subsumes that of B.
2943 bool DoesSubsume =
2944 A->getFoldOperator() == B->getFoldOperator() &&
2947 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2948 }
2949 return It->second;
2950}
2951
2952bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2953 if (A.Kind != B.Kind)
2954 return false;
2955 switch (A.Kind) {
2956 case Literal::Atomic:
2957 if (!Callable)
2958 return A.Value == B.Value;
2959 return Callable(
2960 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2961 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2962 case Literal::FoldExpanded:
2963 return Subsumes(
2964 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2965 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2966 }
2967 llvm_unreachable("unknown literal kind");
2968}
2969
2970namespace {
2971
2972class DumpNormalizedConstraint {
2973 raw_ostream &OS;
2974 const PrintingPolicy &PP;
2975 TextNodeDumper TD;
2976
2977public:
2978 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2979 : OS(OS), PP(Context.getPrintingPolicy()),
2980 TD(OS, Context, /*ShowColors=*/false) {}
2981
2982 void dump(const NormalizedConstraint &N) {
2983 TD.AddChild([&] { Traverse(N); });
2984 }
2985
2986private:
2987 void Traverse(const NormalizedConstraint &N) {
2988 switch (N.getKind()) {
2989 case NormalizedConstraint::ConstraintKind::Compound:
2990 VisitCompound(static_cast<const CompoundConstraint &>(N));
2991 break;
2992 case NormalizedConstraint::ConstraintKind::Atomic:
2993 VisitAtomic(static_cast<const AtomicConstraint &>(N));
2994 break;
2995 case NormalizedConstraint::ConstraintKind::ConceptId:
2996 VisitConceptId(static_cast<const ConceptIdConstraint &>(N));
2997 break;
2998 case NormalizedConstraint::ConstraintKind::FoldExpanded:
2999 VisitFoldExpanded(static_cast<const FoldExpandedConstraint &>(N));
3000 break;
3001 }
3002 }
3003
3004 void WriteNodeHeader(const NormalizedConstraint &N, StringRef Kind) {
3005 OS << Kind;
3006 TD.dumpPointer(&N);
3008 }
3009
3010 void WritePackIndex(const NormalizedConstraintWithParamMapping &N) {
3011 if (auto Idx = N.getPackSubstitutionIndex())
3012 OS << " SubstIndex=" << *Idx;
3013 }
3014
3015 void VisitCompound(const CompoundConstraint &C) {
3016 WriteNodeHeader(C, "CompoundConstraint");
3017 OS << " "
3018 << (C.getCompoundKind() == NormalizedConstraint::CCK_Conjunction
3019 ? "Conjunction"
3020 : "Disjunction");
3021 TD.AddChild([&] { Traverse(C.getLHS()); });
3022 TD.AddChild([&] { Traverse(C.getRHS()); });
3023 }
3024
3025 void VisitAtomic(const AtomicConstraint &A) {
3026 WriteNodeHeader(A, "AtomicConstraint");
3027 WritePackIndex(A);
3028 OS << " ";
3029 A.getConstraintExpr()->printPretty(OS, /*Helper=*/nullptr, PP);
3030 WriteParameterMapping(A);
3031 }
3032
3033 void VisitConceptId(const ConceptIdConstraint &C) {
3034 WriteNodeHeader(C, "ConceptIdConstraint");
3035 WritePackIndex(C);
3036 OS << " ";
3037 if (auto *CSE = C.getConceptSpecializationExpr()) {
3038 CSE->printPretty(OS, /*Helper=*/nullptr, PP);
3039 } else {
3040 C.getConceptId()->print(OS, PP);
3041 }
3042 WriteParameterMapping(C);
3043 TD.AddChild([&] { Traverse(C.getNormalizedConstraint()); });
3044 }
3045
3046 void VisitFoldExpanded(const FoldExpandedConstraint &F) {
3047 WriteNodeHeader(F, "FoldExpandedConstraint");
3048 OS << " "
3049 << (F.getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3050 ? "And"
3051 : "Or");
3052 WritePackIndex(F);
3053 OS << " ";
3054 F.getPattern()->printPretty(OS, /*Helper=*/nullptr, PP);
3055 WriteParameterMapping(F);
3056 TD.AddChild([&] { Traverse(F.getNormalizedPattern()); });
3057 }
3058
3059 void WriteParameterMapping(const NormalizedConstraintWithParamMapping &N) {
3060 if (!N.hasParameterMapping() || N.mappingOccurenceList().none())
3061 return;
3062 TD.AddChild([this, Indexes(N.mappingOccurenceList()),
3063 IndexesForSub(N.mappingOccurenceListForSubsumption()),
3064 Mapping(N.getParameterMapping()),
3065 TPL(N.getUsedTemplateParamList())] {
3066 OS << "ParameterMapping";
3067 WriteOccurenceList("Indexes", Indexes);
3068 WriteOccurenceList("IndexesForSubsumption", IndexesForSub);
3069 unsigned Slot = 0;
3070 for (unsigned ParamIndex : Indexes.set_bits()) {
3071 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3072 assert(TPL && Slot < TPL->size());
3073 const NamedDecl *Param = TPL->getParam(Slot);
3074 OS << "#" << ParamIndex << ": <";
3075 Param->print(OS, PP);
3076 OS << "> -> ";
3077 Mapping[Slot].getArgument().print(PP, OS,
3078 /*IncludeType=*/false);
3079 TD.AddChild([this, Slot, Mapping] {
3080 const TemplateArgument &TA = Mapping[Slot].getArgument();
3081 OS << "TemplateArgument " << TA.getKindName();
3082 TD.dumpPointer(&TA);
3083 });
3084 });
3085 ++Slot;
3086 }
3087 });
3088 }
3089
3090 void WriteOccurenceList(StringRef Label,
3092 if (BV.none())
3093 return;
3094 OS << " " << Label << "={"
3095 << llvm::join(
3096 llvm::map_range(
3097 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3098 [](unsigned I) { return llvm::to_string(I); }),
3099 ", ")
3100 << '}';
3101 }
3102};
3103
3104} // namespace
3105
3106LLVM_DUMP_METHOD void NormalizedConstraint::dump(ASTContext &Context) const {
3107 dump(llvm::errs(), Context);
3108}
3109
3110LLVM_DUMP_METHOD void NormalizedConstraint::dump(llvm::raw_ostream &OS,
3111 ASTContext &Context) const {
3112 return DumpNormalizedConstraint(OS, Context).dump(*this);
3113}
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
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:75
ArrayRef< UnsatisfiedConstraintRecord > records() const
Definition ASTConcept.h:99
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:7014
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:127
const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const
Definition ASTConcept.h:167
NamedDecl * getFoundDecl() const
Definition ASTConcept.h:194
const DeclarationNameInfo & getConceptNameInfo() const
Definition ASTConcept.h:171
SourceLocation getBeginLoc() const LLVM_READONLY
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition ASTConcept.h:200
TemplateName getNamedConcept() const
Definition ASTConcept.h:198
SourceLocation getTemplateKWLoc() const
Definition ASTConcept.h:177
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
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C, const NamedDecl *ConstraintOwner, ArrayRef< TemplateArgument > TemplateArgs)
llvm::SmallVector< UnsatisfiedConstraintRecord, 1 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
Definition ASTConcept.h:55
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1467
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2121
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:1244
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition DeclBase.h:1137
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:448
DeclContext * getDeclContext()
Definition DeclBase.h:457
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:936
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:4257
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4598
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:4377
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4393
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4321
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:4208
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4281
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4229
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:13896
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:3633
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition Sema.h:12680
const DeclContext * getDeclContext() const
Definition Sema.h:12434
const NamedDecl * getDecl() const
Definition Sema.h:12426
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12430
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:862
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:1331
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:934
friend class SubstituteParameterMappings
Definition Sema.h:15289
llvm::PointerUnion< const NamedDecl *, const concepts::NestedRequirement * > ConstrainedDeclOrNestedRequirement
Definition Sema.h:15160
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:927
@ 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:11996
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1366
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:932
bool isSFINAEContext() const
Definition Sema.h:13934
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13890
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:15116
void PopSatisfactionStackEntry()
Definition Sema.h:15122
@ 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:15124
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...
llvm::BumpPtrAllocator BumpAlloc
Definition Sema.h:1276
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:4375
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:426
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:397
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:242
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:584
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:844
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1787
#define false
Definition stdbool.h:26
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:12215
A stack object to be created when performing template instantiation.
Definition Sema.h:13539