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