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