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 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
389 if (!Constraint.hasParameterMapping()) {
390 for (const auto &List : TemplateArgs)
391 for (const TemplateArgument &Arg : List.Args)
393 ID, SemaRef.Context);
394 return;
395 }
396
397 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
398 Constraint.getParameterMapping();
399 for (auto &ArgLoc : Mapping) {
400 TemplateArgument Canonical =
401 SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());
402 // We don't want sugars to impede the profile of cache.
403 UsedTemplateArgs.push_back(Canonical);
404 TraverseTemplateArgument(Canonical);
405 }
406
407 for (auto &Used : UsedTemplateArgs) {
408 llvm::FoldingSetNodeID R;
409 Used.Profile(R, SemaRef.Context);
410 ID.AddNodeID(R);
411 }
412 }
413};
414
415class ConstraintSatisfactionChecker {
416 Sema &S;
417 const NamedDecl *Template;
418 SourceLocation TemplateNameLoc;
419 UnsignedOrNone PackSubstitutionIndex;
420
421 ConstraintSatisfaction &Satisfaction;
422
423private:
425 EvaluateAtomicConstraint(const Expr *AtomicExpr,
426 const MultiLevelTemplateArgumentList &MLTAL);
427
428 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
429 const FoldExpandedConstraint &FE,
430 const MultiLevelTemplateArgumentList &MLTAL);
431
432 // XXX: It is SLOW! Use it very carefully.
433 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
434 const NormalizedConstraintWithParamMapping &Constraint,
435 const MultiLevelTemplateArgumentList &MLTAL,
436 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
437
438 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
439 const MultiLevelTemplateArgumentList &MLTAL);
440
441 ExprResult Evaluate(const AtomicConstraint &Constraint,
442 const MultiLevelTemplateArgumentList &MLTAL);
443
444 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
445 const MultiLevelTemplateArgumentList &MLTAL);
446
447 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
448 const MultiLevelTemplateArgumentList &MLTAL);
449
450 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
451 const MultiLevelTemplateArgumentList &MLTAL,
452 unsigned int Size);
453
454 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
455 const MultiLevelTemplateArgumentList &MLTAL);
456
457 ExprResult Evaluate(const CompoundConstraint &Constraint,
458 const MultiLevelTemplateArgumentList &MLTAL);
459
460public:
461 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
462 SourceLocation TemplateNameLoc,
463 UnsignedOrNone PackSubstitutionIndex,
464 ConstraintSatisfaction &Satisfaction)
465 : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),
466 PackSubstitutionIndex(PackSubstitutionIndex),
467 Satisfaction(Satisfaction) {}
468
469 ExprResult Evaluate(const NormalizedConstraint &Constraint,
470 const MultiLevelTemplateArgumentList &MLTAL);
471};
472
473StringRef allocateStringFromConceptDiagnostic(const Sema &S,
474 const PartialDiagnostic Diag) {
475 SmallString<128> DiagString;
476 DiagString = ": ";
477 Diag.EmitToString(S.getDiagnostics(), DiagString);
478 return S.getASTContext().backupStr(DiagString);
479}
480
481} // namespace
482
483ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
484 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
485 EnterExpressionEvaluationContext ConstantEvaluated(
488
489 llvm::FoldingSetNodeID ID;
490 if (Template &&
492 Satisfaction.IsSatisfied = false;
493 Satisfaction.ContainsErrors = true;
494 return ExprEmpty();
495 }
496 SatisfactionStackRAII StackRAII(S, Template, ID);
497
498 // Atomic constraint - substitute arguments and check satisfaction.
499 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
500 {
501 TemplateDeductionInfo Info(TemplateNameLoc);
505 // FIXME: improve const-correctness of InstantiatingTemplate
506 const_cast<NamedDecl *>(Template), Info, AtomicExpr->getSourceRange());
507 if (Inst.isInvalid())
508 return ExprError();
509
510 // We do not want error diagnostics escaping here.
511 Sema::SFINAETrap Trap(S);
512 SubstitutedExpression =
513 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
514
515 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
516 // C++2a [temp.constr.atomic]p1
517 // ...If substitution results in an invalid type or expression, the
518 // constraint is not satisfied.
519 if (!Trap.hasErrorOccurred())
520 // A non-SFINAE error has occurred as a result of this
521 // substitution.
522 return ExprError();
523
526 Info.takeSFINAEDiagnostic(SubstDiag);
527 // FIXME: This is an unfortunate consequence of there
528 // being no serialization code for PartialDiagnostics and the fact
529 // that serializing them would likely take a lot more storage than
530 // just storing them as strings. We would still like, in the
531 // future, to serialize the proper PartialDiagnostic as serializing
532 // it as a string defeats the purpose of the diagnostic mechanism.
533 Satisfaction.Details.emplace_back(
535 SubstDiag.first,
536 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
537 Satisfaction.IsSatisfied = false;
538 return ExprEmpty();
539 }
540 }
541
542 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
543 return ExprError();
544
545 // [temp.constr.atomic]p3: To determine if an atomic constraint is
546 // satisfied, the parameter mapping and template arguments are first
547 // substituted into its expression. If substitution results in an
548 // invalid type or expression, the constraint is not satisfied.
549 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
550 // and E shall be a constant expression of type bool.
551 //
552 // Perform the L to R Value conversion if necessary. We do so for all
553 // non-PRValue categories, else we fail to extend the lifetime of
554 // temporaries, and that fails the constant expression check.
555 if (!SubstitutedExpression.get()->isPRValue())
556 SubstitutedExpression = ImplicitCastExpr::Create(
557 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
558 SubstitutedExpression.get(),
559 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
560
561 return SubstitutedExpression;
562}
563
564std::optional<MultiLevelTemplateArgumentList>
565ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
566 const NormalizedConstraintWithParamMapping &Constraint,
568 llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {
569
570 if (!Constraint.hasParameterMapping())
571 return std::move(MLTAL);
572
573 // The mapping is empty, meaning no template arguments are needed for
574 // evaluation.
575 if (Constraint.getParameterMapping().empty())
577
578 TemplateDeductionInfo Info(Constraint.getBeginLoc());
580 S, Constraint.getBeginLoc(),
582 // FIXME: improve const-correctness of InstantiatingTemplate
583 const_cast<NamedDecl *>(Template), Info, Constraint.getSourceRange());
584 if (Inst.isInvalid())
585 return std::nullopt;
586
587 Sema::SFINAETrap Trap(S);
588
589 TemplateArgumentListInfo SubstArgs;
591 S, Constraint.getPackSubstitutionIndex()
592 ? Constraint.getPackSubstitutionIndex()
593 : PackSubstitutionIndex);
594
596 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
597 SubstArgs, /*BuildPackExpansionTypes=*/true)) {
598 Satisfaction.IsSatisfied = false;
599 return std::nullopt;
600 }
601
603 auto *TD = const_cast<TemplateDecl *>(
606 TD->getLocation(), SubstArgs,
607 /*DefaultArguments=*/{},
608 /*PartialTemplateArgs=*/false, CTAI))
609 return std::nullopt;
611 Constraint.mappingOccurenceList();
612 // The empty MLTAL situation should only occur when evaluating non-dependent
613 // constraints.
614 if (MLTAL.getNumSubstitutedLevels())
615 SubstitutedOutermost =
616 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
617 unsigned Offset = 0;
618 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
620 if (Used[I])
622 CTAI.SugaredConverted[MappedIndex++]);
623 if (I < SubstitutedOutermost.size()) {
624 SubstitutedOutermost[I] = Arg;
625 Offset = I + 1;
626 } else {
627 SubstitutedOutermost.push_back(Arg);
628 Offset = SubstitutedOutermost.size();
629 }
630 }
631 if (Offset < SubstitutedOutermost.size())
632 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
633
634 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
635 SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,
636 /*Final=*/false);
637 return std::move(SubstitutedTemplateArgs);
638}
639
640ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
641 const AtomicConstraint &Constraint,
642 const MultiLevelTemplateArgumentList &MLTAL) {
643
644 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
645 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
646 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
647 if (!SubstitutedArgs) {
648 Satisfaction.IsSatisfied = false;
649 return ExprEmpty();
650 }
651
652 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
653 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
654 Constraint.getConstraintExpr(), *SubstitutedArgs);
655
656 if (SubstitutedAtomicExpr.isInvalid())
657 return ExprError();
658
659 if (SubstitutedAtomicExpr.isUnset())
660 // Evaluator has decided satisfaction without yielding an expression.
661 return ExprEmpty();
662
663 // We don't have the ability to evaluate this, since it contains a
664 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
665 // we'd potentially pick up a different overload, and cause confusing
666 // diagnostics. SO, add a failure detail that will cause us to make this
667 // overload set not viable.
668 if (SubstitutedAtomicExpr.get()->containsErrors()) {
669 Satisfaction.IsSatisfied = false;
670 Satisfaction.ContainsErrors = true;
671
672 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
673 Satisfaction.Details.emplace_back(
675 SubstitutedAtomicExpr.get()->getBeginLoc(),
676 allocateStringFromConceptDiagnostic(S, Msg)});
677 return SubstitutedAtomicExpr;
678 }
679
680 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
681 Satisfaction.IsSatisfied = true;
682 Satisfaction.ContainsErrors = false;
683 return SubstitutedAtomicExpr;
684 }
685
686 EnterExpressionEvaluationContext ConstantEvaluated(
689 Expr::EvalResult EvalResult;
690 EvalResult.Diag = &EvaluationDiags;
691 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
692 S.Context) ||
693 !EvaluationDiags.empty()) {
694 // C++2a [temp.constr.atomic]p1
695 // ...E shall be a constant expression of type bool.
696 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
697 diag::err_non_constant_constraint_expression)
698 << SubstitutedAtomicExpr.get()->getSourceRange();
699 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
700 S.Diag(PDiag.first, PDiag.second);
701 return ExprError();
702 }
703
704 assert(EvalResult.Val.isInt() &&
705 "evaluating bool expression didn't produce int");
706 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
707 if (!Satisfaction.IsSatisfied)
708 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
709
710 return SubstitutedAtomicExpr;
711}
712
713ExprResult ConstraintSatisfactionChecker::Evaluate(
714 const AtomicConstraint &Constraint,
715 const MultiLevelTemplateArgumentList &MLTAL) {
716
717 unsigned Size = Satisfaction.Details.size();
718 llvm::FoldingSetNodeID ID;
719 UnsignedOrNone OuterPackSubstIndex =
720 Constraint.getPackSubstitutionIndex()
721 ? Constraint.getPackSubstitutionIndex()
722 : PackSubstitutionIndex;
723
724 ID.AddPointer(Constraint.getConstraintExpr());
725 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
726 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
727 .VisitConstraint(Constraint);
728
729 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
731 auto &Cached = Iter->second.Satisfaction;
732 Satisfaction.ContainsErrors = Cached.ContainsErrors;
733 Satisfaction.IsSatisfied = Cached.IsSatisfied;
734 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
735 Cached.Details.begin(), Cached.Details.end());
736 return Iter->second.SubstExpr;
737 }
738
739 ExprResult E = EvaluateSlow(Constraint, MLTAL);
740
742 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
743 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
744 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
745 Satisfaction.Details.begin() + Size,
746 Satisfaction.Details.end());
747 Cache.SubstExpr = E;
748 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
749
750 return E;
751}
752
754ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
755 const FoldExpandedConstraint &FE,
756 const MultiLevelTemplateArgumentList &MLTAL) {
757
758 // We should ignore errors in the presence of packs of different size.
759 Sema::SFINAETrap Trap(S);
760
761 Expr *Pattern = const_cast<Expr *>(FE.getPattern());
762
764 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
765 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
766 bool Expand = true;
767 bool RetainExpansion = false;
768 UnsignedOrNone NumExpansions(std::nullopt);
770 Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
771 /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
772 NumExpansions) ||
773 !Expand || RetainExpansion)
774 return std::nullopt;
775
776 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) {
777 S.Diag(Pattern->getExprLoc(),
778 clang::diag::err_fold_expression_limit_exceeded)
779 << *NumExpansions << S.getLangOpts().BracketDepth
780 << Pattern->getSourceRange();
781 S.Diag(Pattern->getExprLoc(), diag::note_bracket_depth);
782 return std::nullopt;
783 }
784 return NumExpansions;
785}
786
787ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
788 const FoldExpandedConstraint &Constraint,
789 const MultiLevelTemplateArgumentList &MLTAL) {
790
791 bool Conjunction = Constraint.getFoldOperator() ==
793 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
794
795 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
796 // FIXME: Is PackSubstitutionIndex correct?
797 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
798 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
799 SubstitutionInTemplateArguments(
800 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
801 MLTAL, SubstitutedOutermost);
802 if (!SubstitutedArgs) {
803 Satisfaction.IsSatisfied = false;
804 return ExprError();
805 }
806
808 UnsignedOrNone NumExpansions =
809 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
810 if (!NumExpansions)
811 return ExprEmpty();
812
813 if (*NumExpansions == 0) {
814 Satisfaction.IsSatisfied = Conjunction;
815 return ExprEmpty();
816 }
817
818 for (unsigned I = 0; I < *NumExpansions; I++) {
819 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
820 Satisfaction.IsSatisfied = false;
821 Satisfaction.ContainsErrors = false;
823 ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,
824 UnsignedOrNone(I), Satisfaction)
825 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
826 if (Expr.isUsable()) {
827 if (Out.isUnset())
828 Out = Expr;
829 else
830 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
831 Conjunction ? BinaryOperatorKind::BO_LAnd
832 : BinaryOperatorKind::BO_LOr,
834 Constraint.getBeginLoc(),
836 } else {
837 assert(!Satisfaction.IsSatisfied);
838 }
839 if (!Conjunction && Satisfaction.IsSatisfied) {
840 Satisfaction.Details.erase(Satisfaction.Details.begin() +
841 EffectiveDetailEndIndex,
842 Satisfaction.Details.end());
843 break;
844 }
845 if (Satisfaction.IsSatisfied != Conjunction)
846 return Out;
847 }
848
849 return Out;
850}
851
852ExprResult ConstraintSatisfactionChecker::Evaluate(
853 const FoldExpandedConstraint &Constraint,
854 const MultiLevelTemplateArgumentList &MLTAL) {
855
856 llvm::FoldingSetNodeID ID;
857 ID.AddPointer(Constraint.getPattern());
858 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
859
860 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
862
863 auto &Cached = Iter->second.Satisfaction;
864 Satisfaction.ContainsErrors = Cached.ContainsErrors;
865 Satisfaction.IsSatisfied = Cached.IsSatisfied;
866 Satisfaction.Details.insert(Satisfaction.Details.end(),
867 Cached.Details.begin(), Cached.Details.end());
868 return Iter->second.SubstExpr;
869 }
870
871 unsigned Size = Satisfaction.Details.size();
872
873 ExprResult E = EvaluateSlow(Constraint, MLTAL);
875 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
876 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
877 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
878 Satisfaction.Details.begin() + Size,
879 Satisfaction.Details.end());
880 Cache.SubstExpr = E;
881 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
882 return E;
883}
884
885ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
886 const ConceptIdConstraint &Constraint,
887 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
888 const ConceptReference *ConceptId = Constraint.getConceptId();
889
890 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
891 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
892 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
893
894 if (!SubstitutedArgs) {
895 Satisfaction.IsSatisfied = false;
896 // FIXME: diagnostics?
897 return ExprError();
898 }
899
900 Sema::SFINAETrap Trap(S);
902 S, Constraint.getPackSubstitutionIndex()
903 ? Constraint.getPackSubstitutionIndex()
904 : PackSubstitutionIndex);
905
906 const ASTTemplateArgumentListInfo *Ori =
907 ConceptId->getTemplateArgsAsWritten();
908 TemplateDeductionInfo Info(TemplateNameLoc);
911 const_cast<NamedDecl *>(Template), Info, Constraint.getSourceRange());
912
913 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
914 if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, OutArgs) ||
915 Trap.hasErrorOccurred()) {
916 Satisfaction.IsSatisfied = false;
917 if (!Trap.hasErrorOccurred())
918 return ExprError();
919
922 Info.takeSFINAEDiagnostic(SubstDiag);
923 // FIXME: This is an unfortunate consequence of there
924 // being no serialization code for PartialDiagnostics and the fact
925 // that serializing them would likely take a lot more storage than
926 // just storing them as strings. We would still like, in the
927 // future, to serialize the proper PartialDiagnostic as serializing
928 // it as a string defeats the purpose of the diagnostic mechanism.
929 Satisfaction.Details.insert(
930 Satisfaction.Details.begin() + Size,
932 SubstDiag.first,
933 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
934 return ExprError();
935 }
936
937 CXXScopeSpec SS;
938 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
939
940 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
941 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
942 ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs,
943 /*DoCheckConstraintSatisfaction=*/false);
944
945 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
946 return ExprError();
947
948 if (Size != Satisfaction.Details.size()) {
949 Satisfaction.Details.insert(
950 Satisfaction.Details.begin() + Size,
952 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
954 }
955 return SubstitutedConceptId;
956}
957
958ExprResult ConstraintSatisfactionChecker::Evaluate(
959 const ConceptIdConstraint &Constraint,
960 const MultiLevelTemplateArgumentList &MLTAL) {
961
962 const ConceptReference *ConceptId = Constraint.getConceptId();
963
964 UnsignedOrNone OuterPackSubstIndex =
965 Constraint.getPackSubstitutionIndex()
966 ? Constraint.getPackSubstitutionIndex()
967 : PackSubstitutionIndex;
968
969 Sema::InstantiatingTemplate InstTemplate(
970 S, ConceptId->getBeginLoc(),
972 ConceptId->getNamedConcept(),
973 // We may have empty template arguments when checking non-dependent
974 // nested constraint expressions.
975 // In such cases, non-SFINAE errors would have already been diagnosed
976 // during parameter mapping substitution, so the instantiating template
977 // arguments are less useful here.
978 MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
980 Constraint.getSourceRange());
981 if (InstTemplate.isInvalid())
982 return ExprError();
983
984 unsigned Size = Satisfaction.Details.size();
985
986 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
987
988 if (!E.isUsable()) {
989 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
990 return E;
991 }
992
993 // ConceptIdConstraint is only relevant for diagnostics,
994 // so if the normalized constraint is satisfied, we should not
995 // substitute into the constraint.
996 if (Satisfaction.IsSatisfied)
997 return E;
998
999 llvm::FoldingSetNodeID ID;
1000 ID.AddPointer(Constraint.getConceptId());
1001 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
1002 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1003 .VisitConstraint(Constraint);
1004
1005 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
1007
1008 auto &Cached = Iter->second.Satisfaction;
1009 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1010 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1011 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1012 Cached.Details.begin(), Cached.Details.end());
1013 return Iter->second.SubstExpr;
1014 }
1015
1016 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1017 if (CE.isInvalid())
1018 return E;
1020 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1021 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1022 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1023 Satisfaction.Details.begin() + Size,
1024 Satisfaction.Details.end());
1025 Cache.SubstExpr = CE;
1026 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1027 return CE;
1028}
1029
1030ExprResult ConstraintSatisfactionChecker::Evaluate(
1031 const CompoundConstraint &Constraint,
1032 const MultiLevelTemplateArgumentList &MLTAL) {
1033
1034 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1035
1036 bool Conjunction =
1038
1039 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1040
1041 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1042 return LHS;
1043
1044 if (!Conjunction && LHS.isUsable() && Satisfaction.IsSatisfied &&
1045 !Satisfaction.ContainsErrors)
1046 return LHS;
1047
1048 Satisfaction.ContainsErrors = false;
1049 Satisfaction.IsSatisfied = false;
1050
1051 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1052
1053 if (RHS.isUsable() && Satisfaction.IsSatisfied &&
1054 !Satisfaction.ContainsErrors)
1055 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1056 EffectiveDetailEndIndex,
1057 Satisfaction.Details.end());
1058
1059 if (!LHS.isUsable())
1060 return RHS;
1061
1062 if (!RHS.isUsable())
1063 return LHS;
1064
1065 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1066 Conjunction ? BinaryOperatorKind::BO_LAnd
1067 : BinaryOperatorKind::BO_LOr,
1069 Constraint.getBeginLoc(), FPOptionsOverride{});
1070}
1071
1072ExprResult ConstraintSatisfactionChecker::Evaluate(
1073 const NormalizedConstraint &Constraint,
1074 const MultiLevelTemplateArgumentList &MLTAL) {
1075 switch (Constraint.getKind()) {
1077 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1078
1080 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1081 MLTAL);
1082
1084 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1085 MLTAL);
1086
1088 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1089 }
1090 llvm_unreachable("Unknown ConstraintKind enum");
1091}
1092
1094 Sema &S, const NamedDecl *Template,
1095 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1096 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1097 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1098 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1099
1100 if (ConvertedExpr)
1101 *ConvertedExpr = nullptr;
1102
1103 if (AssociatedConstraints.empty()) {
1104 Satisfaction.IsSatisfied = true;
1105 return false;
1106 }
1107
1108 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1109 // No need to check satisfaction for dependent constraint expressions.
1110 Satisfaction.IsSatisfied = true;
1111 return false;
1112 }
1113
1115 if (TemplateArgsLists.getNumLevels() != 0)
1116 Args = TemplateArgsLists.getInnermost();
1117
1118 std::optional<Sema::InstantiatingTemplate> SynthesisContext;
1119 if (!TopLevelConceptId) {
1120 SynthesisContext.emplace(S, TemplateIDRange.getBegin(),
1122 const_cast<NamedDecl *>(Template), Args,
1123 TemplateIDRange);
1124 }
1125
1126 const NormalizedConstraint *C =
1127 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1128 if (!C) {
1129 Satisfaction.IsSatisfied = false;
1130 return true;
1131 }
1132
1133 if (TopLevelConceptId)
1134 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1135 const_cast<NormalizedConstraint *>(C),
1136 Template, /*CSE=*/nullptr,
1138
1139 ExprResult Res =
1140 ConstraintSatisfactionChecker(S, Template, TemplateIDRange.getBegin(),
1141 S.ArgPackSubstIndex, Satisfaction)
1142 .Evaluate(*C, TemplateArgsLists);
1143
1144 if (Res.isInvalid())
1145 return true;
1146
1147 if (Res.isUsable() && ConvertedExpr)
1148 *ConvertedExpr = Res.get();
1149
1150 return false;
1151}
1152
1155 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1156 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1157 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1158 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1159 if (AssociatedConstraints.empty()) {
1160 OutSatisfaction.IsSatisfied = true;
1161 return false;
1162 }
1163 const auto *Template = Entity.dyn_cast<const NamedDecl *>();
1164 if (!Template) {
1165 return ::CheckConstraintSatisfaction(
1166 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1167 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1168 }
1169 // Invalid templates could make their way here. Substituting them could result
1170 // in dependent expressions.
1171 if (Template->isInvalidDecl()) {
1172 OutSatisfaction.IsSatisfied = false;
1173 return true;
1174 }
1175
1176 // A list of the template argument list flattened in a predictible manner for
1177 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1178 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1179 // here.
1181 for (auto List : TemplateArgsLists)
1182 for (const TemplateArgument &Arg : List.Args)
1183 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1184
1185 const NamedDecl *Owner = Template;
1186 if (TopLevelConceptId)
1187 Owner = TopLevelConceptId->getNamedConcept();
1188
1189 llvm::FoldingSetNodeID ID;
1190 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1191 void *InsertPos;
1192 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1193 OutSatisfaction = *Cached;
1194 return false;
1195 }
1196
1197 auto Satisfaction =
1198 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1200 *this, Template, AssociatedConstraints, TemplateArgsLists,
1201 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1202 OutSatisfaction = std::move(*Satisfaction);
1203 return true;
1204 }
1205
1206 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1207 // The evaluation of this constraint resulted in us trying to re-evaluate it
1208 // recursively. This isn't really possible, except we try to form a
1209 // RecoveryExpr as a part of the evaluation. If this is the case, just
1210 // return the 'cached' version (which will have the same result), and save
1211 // ourselves the extra-insert. If it ever becomes possible to legitimately
1212 // recursively check a constraint, we should skip checking the 'inner' one
1213 // above, and replace the cached version with this one, as it would be more
1214 // specific.
1215 OutSatisfaction = *Cached;
1216 return false;
1217 }
1218
1219 // Else we can simply add this satisfaction to the list.
1220 OutSatisfaction = *Satisfaction;
1221 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
1222 // invalidated it.
1223 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1224 SatisfactionCache.InsertNode(Satisfaction.release());
1225 return false;
1226}
1227
1228static ExprResult
1230 const ConceptSpecializationExpr *CSE,
1231 UnsignedOrNone SubstIndex) {
1232
1233 // [C++2c] [temp.constr.normal]
1234 // Otherwise, to form CE, any non-dependent concept template argument Ai
1235 // is substituted into the constraint-expression of C.
1236 // If any such substitution results in an invalid concept-id,
1237 // the program is ill-formed; no diagnostic is required.
1238
1240 Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
1241
1242 const ASTTemplateArgumentListInfo *ArgsAsWritten =
1244 if (llvm::none_of(
1245 ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {
1246 return !ArgLoc.getArgument().isDependent() &&
1247 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1248 })) {
1249 return Concept->getConstraintExpr();
1250 }
1251
1253 Concept, Concept->getLexicalDeclContext(),
1254 /*Final=*/false, CSE->getTemplateArguments(),
1255 /*RelativeToPrimary=*/true,
1256 /*Pattern=*/nullptr,
1257 /*ForConstraintInstantiation=*/true);
1258 return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),
1259 MLTAL);
1260}
1261
1263 const ConceptSpecializationExpr *ConstraintExpr,
1264 ConstraintSatisfaction &Satisfaction) {
1265
1267 *this, nullptr, ConstraintExpr, ArgPackSubstIndex);
1268 if (!Res.isUsable())
1269 return true;
1270
1272 Constraints.emplace_back(Res.get());
1273
1274 MultiLevelTemplateArgumentList MLTAL(ConstraintExpr->getNamedConcept(),
1275 ConstraintExpr->getTemplateArguments(),
1276 true);
1277
1279 ConstraintExpr->getNamedConcept(), Constraints, MLTAL,
1280 ConstraintExpr->getSourceRange(), Satisfaction,
1281 ConstraintExpr->getConceptReference());
1282}
1283
1284bool Sema::SetupConstraintScope(
1285 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1286 const MultiLevelTemplateArgumentList &MLTAL,
1288 assert(!isLambdaCallOperator(FD) &&
1289 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1290 "instantiations");
1291 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1292 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1293 InstantiatingTemplate Inst(
1294 *this, FD->getPointOfInstantiation(),
1296 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1297 SourceRange());
1298 if (Inst.isInvalid())
1299 return true;
1300
1301 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1302 // 'instantiated' parameters and adds it to the context. For the case where
1303 // this function is a template being instantiated NOW, we also need to add
1304 // the list of current template arguments to the list so that they also can
1305 // be picked out of the map.
1306 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1307 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1308 /*Final=*/false);
1309 if (addInstantiatedParametersToScope(
1310 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1311 return true;
1312 }
1313
1314 // If this is a member function, make sure we get the parameters that
1315 // reference the original primary template.
1316 if (FunctionTemplateDecl *FromMemTempl =
1317 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1318 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1319 Scope, MLTAL))
1320 return true;
1321 }
1322
1323 return false;
1324 }
1325
1328 FunctionDecl *InstantiatedFrom =
1332
1334 *this, FD->getPointOfInstantiation(),
1335 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1336 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1337 SourceRange());
1338 if (Inst.isInvalid())
1339 return true;
1340
1341 // Case where this was not a template, but instantiated as a
1342 // child-function.
1343 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1344 return true;
1345 }
1346
1347 return false;
1348}
1349
1350// This function collects all of the template arguments for the purposes of
1351// constraint-instantiation and checking.
1352std::optional<MultiLevelTemplateArgumentList>
1353Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1354 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1356 MultiLevelTemplateArgumentList MLTAL;
1357
1358 // Collect the list of template arguments relative to the 'primary' template.
1359 // We need the entire list, since the constraint is completely uninstantiated
1360 // at this point.
1361 MLTAL =
1363 /*Final=*/false, /*Innermost=*/std::nullopt,
1364 /*RelativeToPrimary=*/true,
1365 /*Pattern=*/nullptr,
1366 /*ForConstraintInstantiation=*/true);
1367 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1368 if (isLambdaCallOperator(FD))
1369 return MLTAL;
1370 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1371 return std::nullopt;
1372
1373 return MLTAL;
1374}
1375
1377 ConstraintSatisfaction &Satisfaction,
1378 SourceLocation UsageLoc,
1379 bool ForOverloadResolution) {
1380 // Don't check constraints if the function is dependent. Also don't check if
1381 // this is a function template specialization, as the call to
1382 // CheckFunctionTemplateConstraints after this will check it
1383 // better.
1384 if (FD->isDependentContext() ||
1385 FD->getTemplatedKind() ==
1387 Satisfaction.IsSatisfied = true;
1388 return false;
1389 }
1390
1391 // A lambda conversion operator has the same constraints as the call operator
1392 // and constraints checking relies on whether we are in a lambda call operator
1393 // (and may refer to its parameters), so check the call operator instead.
1394 // Note that the declarations outside of the lambda should also be
1395 // considered. Turning on the 'ForOverloadResolution' flag results in the
1396 // LocalInstantiationScope not looking into its parents, but we can still
1397 // access Decls from the parents while building a lambda RAII scope later.
1398 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1399 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1400 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1401 Satisfaction, UsageLoc,
1402 /*ShouldAddDeclsFromParentScope=*/true);
1403
1404 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1405
1406 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1407 if (isLambdaCallOperator(CtxToSave))
1408 CtxToSave = CtxToSave->getParent()->getParent();
1409 else
1410 CtxToSave = CtxToSave->getNonTransparentContext();
1411 }
1412
1413 ContextRAII SavedContext{*this, CtxToSave};
1414 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1415 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1416 SetupConstraintCheckingTemplateArgumentsAndScope(
1417 const_cast<FunctionDecl *>(FD), {}, Scope);
1418
1419 if (!MLTAL)
1420 return true;
1421
1422 Qualifiers ThisQuals;
1423 CXXRecordDecl *Record = nullptr;
1424 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1425 ThisQuals = Method->getMethodQualifiers();
1426 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1427 }
1428 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1429
1431 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1432 ForOverloadResolution);
1433
1435 FD, FD->getTrailingRequiresClause(), *MLTAL,
1436 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1437 Satisfaction);
1438}
1439
1441 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
1442 const Expr *ConstrExpr) {
1444 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
1445 /*Innermost=*/std::nullopt,
1446 /*RelativeToPrimary=*/true,
1447 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
1448 /*SkipForSpecialization*/ false);
1449
1450 if (MLTAL.getNumSubstitutedLevels() == 0)
1451 return ConstrExpr;
1452
1453 Sema::SFINAETrap SFINAE(S);
1454
1456 S, DeclInfo.getLocation(),
1458 const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
1459 if (Inst.isInvalid())
1460 return nullptr;
1461
1462 // Set up a dummy 'instantiation' scope in the case of reference to function
1463 // parameters that the surrounding function hasn't been instantiated yet. Note
1464 // this may happen while we're comparing two templates' constraint
1465 // equivalence.
1466 std::optional<LocalInstantiationScope> ScopeForParameters;
1467 if (const NamedDecl *ND = DeclInfo.getDecl();
1468 ND && ND->isFunctionOrFunctionTemplate()) {
1469 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1470 const FunctionDecl *FD = ND->getAsFunction();
1472 Template && Template->getInstantiatedFromMemberTemplate())
1473 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1474 for (auto *PVD : FD->parameters()) {
1475 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1476 continue;
1477 if (!PVD->isParameterPack()) {
1478 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1479 continue;
1480 }
1481 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1482 // to avoid building SubstTemplateTypeParmPackTypes for
1483 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1484 // otherwise reference the AssociatedDecl of the template arguments, which
1485 // is, in this case, the template declaration.
1486 //
1487 // However, as we are in the process of comparing potential
1488 // re-declarations, the canonical declaration is the declaration itself at
1489 // this point. So if we didn't expand these packs, we would end up with an
1490 // incorrect profile difference because we will be profiling the
1491 // canonical types!
1492 //
1493 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1494 // that we can eliminate the Scope in the cases where the declarations are
1495 // not necessarily instantiated. It would also benefit the noexcept
1496 // specifier comparison.
1497 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1498 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1499 }
1500 }
1501
1502 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1503
1504 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1505 // essential for having an injected class as the canonical type for a template
1506 // specialization type at the rebuilding stage. This guarantees that, for
1507 // out-of-line definitions, injected class name types and their equivalent
1508 // template specializations can be profiled to the same value, which makes it
1509 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1510 // perceived identical.
1511 std::optional<Sema::ContextRAII> ContextScope;
1512 const DeclContext *DC = [&] {
1513 if (!DeclInfo.getDecl())
1514 return DeclInfo.getDeclContext();
1515 return DeclInfo.getDecl()->getFriendObjectKind()
1516 ? DeclInfo.getLexicalDeclContext()
1517 : DeclInfo.getDeclContext();
1518 }();
1519 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1520 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1521 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1522 /*NewThisContext=*/false);
1523 }
1524 EnterExpressionEvaluationContext UnevaluatedContext(
1528 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1529 if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
1530 return nullptr;
1531 return SubstConstr.get();
1532}
1533
1535 const Expr *OldConstr,
1537 const Expr *NewConstr) {
1538 if (OldConstr == NewConstr)
1539 return true;
1540 // C++ [temp.constr.decl]p4
1541 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1542 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1543 if (const Expr *SubstConstr =
1545 OldConstr))
1546 OldConstr = SubstConstr;
1547 else
1548 return false;
1549 if (const Expr *SubstConstr =
1551 NewConstr))
1552 NewConstr = SubstConstr;
1553 else
1554 return false;
1555 }
1556
1557 llvm::FoldingSetNodeID ID1, ID2;
1558 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1559 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1560 return ID1 == ID2;
1561}
1562
1564 assert(FD->getFriendObjectKind() && "Must be a friend!");
1565
1566 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1567 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1568 // non-function-template.
1569 assert(FD->getDescribedFunctionTemplate() &&
1570 "Non-function templates don't need to be checked");
1571
1574
1575 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1576 for (const AssociatedConstraint &AC : ACs)
1577 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1578 AC.ConstraintExpr))
1579 return true;
1580
1581 return false;
1582}
1583
1585 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1586 SourceRange TemplateIDRange) {
1587 ConstraintSatisfaction Satisfaction;
1588 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1589 TD->getAssociatedConstraints(AssociatedConstraints);
1590 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1591 TemplateIDRange, Satisfaction))
1592 return true;
1593
1594 if (!Satisfaction.IsSatisfied) {
1595 SmallString<128> TemplateArgString;
1596 TemplateArgString = " ";
1597 TemplateArgString += getTemplateArgumentBindingsText(
1598 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1599 TemplateArgsLists.getInnermost().size());
1600
1601 Diag(TemplateIDRange.getBegin(),
1602 diag::err_template_arg_list_constraints_not_satisfied)
1604 << TemplateArgString << TemplateIDRange;
1605 DiagnoseUnsatisfiedConstraint(Satisfaction);
1606 return true;
1607 }
1608 return false;
1609}
1610
1612 Sema &SemaRef, SourceLocation PointOfInstantiation,
1614 ConstraintSatisfaction &Satisfaction) {
1616 Template->getAssociatedConstraints(TemplateAC);
1617 if (TemplateAC.empty()) {
1618 Satisfaction.IsSatisfied = true;
1619 return false;
1620 }
1621
1623
1624 FunctionDecl *FD = Template->getTemplatedDecl();
1625 // Collect the list of template arguments relative to the 'primary'
1626 // template. We need the entire list, since the constraint is completely
1627 // uninstantiated at this point.
1628
1630 {
1631 // getTemplateInstantiationArgs uses this instantiation context to find out
1632 // template arguments for uninstantiated functions.
1633 // We don't want this RAII object to persist, because there would be
1634 // otherwise duplicate diagnostic notes.
1636 SemaRef, PointOfInstantiation,
1638 PointOfInstantiation);
1639 if (Inst.isInvalid())
1640 return true;
1641 MLTAL = SemaRef.getTemplateInstantiationArgs(
1642 /*D=*/FD, FD,
1643 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1644 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1645 }
1646
1647 Sema::ContextRAII SavedContext(SemaRef, FD);
1648 return SemaRef.CheckConstraintSatisfaction(
1649 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1650}
1651
1653 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1654 ArrayRef<TemplateArgument> TemplateArgs,
1655 ConstraintSatisfaction &Satisfaction) {
1656 // In most cases we're not going to have constraints, so check for that first.
1657 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1658
1659 if (!Template)
1660 return ::CheckFunctionConstraintsWithoutInstantiation(
1661 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1662 TemplateArgs, Satisfaction);
1663
1664 // Note - code synthesis context for the constraints check is created
1665 // inside CheckConstraintsSatisfaction.
1667 Template->getAssociatedConstraints(TemplateAC);
1668 if (TemplateAC.empty()) {
1669 Satisfaction.IsSatisfied = true;
1670 return false;
1671 }
1672
1673 // Enter the scope of this instantiation. We don't use
1674 // PushDeclContext because we don't have a scope.
1675 Sema::ContextRAII savedContext(*this, Decl);
1677
1678 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1679 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1680 Scope);
1681
1682 if (!MLTAL)
1683 return true;
1684
1685 Qualifiers ThisQuals;
1686 CXXRecordDecl *Record = nullptr;
1687 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1688 ThisQuals = Method->getMethodQualifiers();
1689 Record = Method->getParent();
1690 }
1691
1692 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1693 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1694 Scope);
1695
1696 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1697 PointOfInstantiation, Satisfaction);
1698}
1699
1702 bool First) {
1703 assert(!Req->isSatisfied() &&
1704 "Diagnose() can only be used on an unsatisfied requirement");
1705 switch (Req->getSatisfactionStatus()) {
1707 llvm_unreachable("Diagnosing a dependent requirement");
1708 break;
1710 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1711 if (!SubstDiag->DiagMessage.empty())
1712 S.Diag(SubstDiag->DiagLoc,
1713 diag::note_expr_requirement_expr_substitution_error)
1714 << (int)First << SubstDiag->SubstitutedEntity
1715 << SubstDiag->DiagMessage;
1716 else
1717 S.Diag(SubstDiag->DiagLoc,
1718 diag::note_expr_requirement_expr_unknown_substitution_error)
1719 << (int)First << SubstDiag->SubstitutedEntity;
1720 break;
1721 }
1723 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1724 << (int)First << Req->getExpr();
1725 break;
1727 auto *SubstDiag =
1729 if (!SubstDiag->DiagMessage.empty())
1730 S.Diag(SubstDiag->DiagLoc,
1731 diag::note_expr_requirement_type_requirement_substitution_error)
1732 << (int)First << SubstDiag->SubstitutedEntity
1733 << SubstDiag->DiagMessage;
1734 else
1735 S.Diag(
1736 SubstDiag->DiagLoc,
1737 diag::
1738 note_expr_requirement_type_requirement_unknown_substitution_error)
1739 << (int)First << SubstDiag->SubstitutedEntity;
1740 break;
1741 }
1743 ConceptSpecializationExpr *ConstraintExpr =
1745 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1746 break;
1747 }
1749 llvm_unreachable("We checked this above");
1750 }
1751}
1752
1755 bool First) {
1756 assert(!Req->isSatisfied() &&
1757 "Diagnose() can only be used on an unsatisfied requirement");
1758 switch (Req->getSatisfactionStatus()) {
1760 llvm_unreachable("Diagnosing a dependent requirement");
1761 return;
1763 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1764 if (!SubstDiag->DiagMessage.empty())
1765 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1766 << (int)First << SubstDiag->SubstitutedEntity
1767 << SubstDiag->DiagMessage;
1768 else
1769 S.Diag(SubstDiag->DiagLoc,
1770 diag::note_type_requirement_unknown_substitution_error)
1771 << (int)First << SubstDiag->SubstitutedEntity;
1772 return;
1773 }
1774 default:
1775 llvm_unreachable("Unknown satisfaction status");
1776 return;
1777 }
1778}
1779
1782 SourceLocation Loc, bool First) {
1783 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1784 S.Diag(
1785 Loc,
1786 diag::
1787 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1788 << (int)First
1789 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1790 << Concept->getNamedConcept();
1791 } else {
1792 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1793 << (int)First << Concept;
1794 }
1795}
1796
1799 bool First, concepts::NestedRequirement *Req = nullptr);
1800
1803 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1804 for (auto &Record : Records) {
1806 Loc = {};
1808 }
1809}
1810
1820
1822 const Expr *SubstExpr,
1823 bool First) {
1824 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1825 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1826 switch (BO->getOpcode()) {
1827 // These two cases will in practice only be reached when using fold
1828 // expressions with || and &&, since otherwise the || and && will have been
1829 // broken down into atomic constraints during satisfaction checking.
1830 case BO_LOr:
1831 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1834 /*First=*/false);
1835 return;
1836 case BO_LAnd: {
1837 bool LHSSatisfied =
1838 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1839 if (LHSSatisfied) {
1840 // LHS is true, so RHS must be false.
1842 return;
1843 }
1844 // LHS is false
1846
1847 // RHS might also be false
1848 bool RHSSatisfied =
1849 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1850 if (!RHSSatisfied)
1852 /*First=*/false);
1853 return;
1854 }
1855 case BO_GE:
1856 case BO_LE:
1857 case BO_GT:
1858 case BO_LT:
1859 case BO_EQ:
1860 case BO_NE:
1861 if (BO->getLHS()->getType()->isIntegerType() &&
1862 BO->getRHS()->getType()->isIntegerType()) {
1863 Expr::EvalResult SimplifiedLHS;
1864 Expr::EvalResult SimplifiedRHS;
1865 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1867 /*InConstantContext=*/true);
1868 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1870 /*InConstantContext=*/true);
1871 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1872 S.Diag(SubstExpr->getBeginLoc(),
1873 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1874 << (int)First << SubstExpr
1875 << toString(SimplifiedLHS.Val.getInt(), 10)
1876 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1877 << toString(SimplifiedRHS.Val.getInt(), 10);
1878 return;
1879 }
1880 }
1881 break;
1882
1883 default:
1884 break;
1885 }
1886 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1887 // FIXME: RequiresExpr should store dependent diagnostics.
1888 for (concepts::Requirement *Req : RE->getRequirements())
1889 if (!Req->isDependent() && !Req->isSatisfied()) {
1890 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1892 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1894 else
1897 break;
1898 }
1899 return;
1900 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1901 // Drill down concept ids treated as atomic constraints
1903 return;
1904 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1905 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1906 assert(TTE->getNumArgs() == 2);
1907 S.Diag(SubstExpr->getSourceRange().getBegin(),
1908 diag::note_is_deducible_constraint_evaluated_to_false)
1909 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1910 return;
1911 }
1912
1913 S.Diag(SubstExpr->getSourceRange().getBegin(),
1914 diag::note_atomic_constraint_evaluated_to_false)
1915 << (int)First << SubstExpr;
1916 S.DiagnoseTypeTraitDetails(SubstExpr);
1917}
1918
1922 if (auto *Diag =
1923 Record
1924 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1925 if (Req)
1926 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
1927 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
1928 else
1929 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1930 << Diag->second;
1931 return;
1932 }
1933 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
1934 if (Loc.isInvalid())
1935 Loc = Concept->getBeginLoc();
1937 return;
1938 }
1941}
1942
1944 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
1945 bool First) {
1946
1947 assert(!Satisfaction.IsSatisfied &&
1948 "Attempted to diagnose a satisfied constraint");
1949 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
1950}
1951
1953 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
1954
1955 const ASTConstraintSatisfaction &Satisfaction =
1956 ConstraintExpr->getSatisfaction();
1957
1958 assert(!Satisfaction.IsSatisfied &&
1959 "Attempted to diagnose a satisfied constraint");
1960
1961 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
1962 ConstraintExpr->getBeginLoc(), First);
1963}
1964
1965namespace {
1966
1967class SubstituteParameterMappings {
1968 Sema &SemaRef;
1969
1970 const MultiLevelTemplateArgumentList *MLTAL;
1971 const ASTTemplateArgumentListInfo *ArgsAsWritten;
1972
1973 bool InFoldExpr;
1974
1975 SubstituteParameterMappings(Sema &SemaRef,
1976 const MultiLevelTemplateArgumentList *MLTAL,
1977 const ASTTemplateArgumentListInfo *ArgsAsWritten,
1978 bool InFoldExpr)
1979 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
1980 InFoldExpr(InFoldExpr) {}
1981
1982 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
1983
1984 bool substitute(NormalizedConstraintWithParamMapping &N);
1985
1986 bool substitute(ConceptIdConstraint &CC);
1987
1988public:
1989 SubstituteParameterMappings(Sema &SemaRef, bool InFoldExpr = false)
1990 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
1991 InFoldExpr(InFoldExpr) {}
1992
1993 bool substitute(NormalizedConstraint &N);
1994};
1995
1996void SubstituteParameterMappings::buildParameterMapping(
1998 TemplateParameterList *TemplateParams =
1999 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
2000
2001 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2002 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2003
2006 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2007 /*OnlyDeduced=*/false,
2008 /*Depth=*/0, OccurringIndices);
2009
2011 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2012 /*Depth=*/0, OccurringIndicesForSubsumption);
2013
2014 } else if (N.getKind() ==
2017 static_cast<FoldExpandedConstraint &>(N).getPattern(),
2018 /*OnlyDeduced=*/false,
2019 /*Depth=*/0, OccurringIndices);
2021 auto *Args = static_cast<ConceptIdConstraint &>(N)
2022 .getConceptId()
2023 ->getTemplateArgsAsWritten();
2024 if (Args)
2025 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2026 /*Depth=*/0, OccurringIndices);
2027 }
2028 unsigned Size = OccurringIndices.count();
2029 // When the constraint is independent of any template parameters,
2030 // we build an empty mapping so that we can distinguish these cases
2031 // from cases where no mapping exists at all, e.g. when there are only atomic
2032 // constraints.
2033 TemplateArgumentLoc *TempArgs =
2034 new (SemaRef.Context) TemplateArgumentLoc[Size];
2036 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2037 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2038 ? ArgsAsWritten->arguments()[I].getLocation()
2039 : SourceLocation();
2040 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
2041 // can't assert Loc.isValid() now.
2042 if (OccurringIndices[I]) {
2043 NamedDecl *Param = TemplateParams->begin()[I];
2044 new (&(TempArgs)[J]) TemplateArgumentLoc(
2045 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2046 UsedParams.push_back(Param);
2047 J++;
2048 }
2049 }
2050 auto *UsedList = TemplateParameterList::Create(
2051 SemaRef.Context, TemplateParams->getTemplateLoc(),
2052 TemplateParams->getLAngleLoc(), UsedParams,
2053 /*RAngleLoc=*/SourceLocation(),
2054 /*RequiresClause=*/nullptr);
2056 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2057 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
2058}
2059
2060bool SubstituteParameterMappings::substitute(
2062 if (!N.hasParameterMapping())
2063 buildParameterMapping(N);
2064
2065 // If the parameter mapping is empty, there is nothing to substitute.
2066 if (N.getParameterMapping().empty())
2067 return false;
2068
2069 SourceLocation InstLocBegin, InstLocEnd;
2070 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2071 if (Arguments.empty()) {
2072 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2073 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2074 } else {
2075 auto SR = Arguments[0].getSourceRange();
2076 InstLocBegin = SR.getBegin();
2077 InstLocEnd = SR.getEnd();
2078 }
2080 SemaRef, InstLocBegin,
2082 const_cast<NamedDecl *>(N.getConstraintDecl()),
2083 {InstLocBegin, InstLocEnd});
2084 if (Inst.isInvalid())
2085 return true;
2086
2087 // TransformTemplateArguments is unable to preserve the source location of a
2088 // pack. The SourceLocation is necessary for the instantiation location.
2089 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2090 // which is wrong.
2091 TemplateArgumentListInfo SubstArgs;
2093 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs,
2094 /*BuildPackExpansionTypes=*/!InFoldExpr))
2095 return true;
2097 auto *TD =
2100 TD->getLocation(), SubstArgs,
2101 /*DefaultArguments=*/{},
2102 /*PartialTemplateArgs=*/false, CTAI))
2103 return true;
2104
2105 TemplateArgumentLoc *TempArgs =
2106 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2107
2108 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2109 SourceLocation Loc;
2110 // If this is an empty pack, we have no corresponding SubstArgs.
2111 if (I < SubstArgs.size())
2112 Loc = SubstArgs.arguments()[I].getLocation();
2113
2114 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2115 CTAI.SugaredConverted[I], QualType(), Loc);
2116 }
2117
2118 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2119 CTAI.SugaredConverted.size());
2123 return false;
2124}
2125
2126bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2127 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2128
2129 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2130 return true;
2131
2132 auto *CSE = CC.getConceptSpecializationExpr();
2133 assert(CSE);
2134 assert(!CC.getBeginLoc().isInvalid());
2135
2136 SourceLocation InstLocBegin, InstLocEnd;
2137 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2138 Arguments.empty()) {
2139 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2140 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2141 } else {
2142 auto SR = Arguments[0].getSourceRange();
2143 InstLocBegin = SR.getBegin();
2144 InstLocEnd = SR.getEnd();
2145 }
2146 // This is useful for name lookup across modules; see Sema::getLookupModules.
2148 SemaRef, InstLocBegin,
2150 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2151 {InstLocBegin, InstLocEnd});
2152 if (Inst.isInvalid())
2153 return true;
2154
2156 // TransformTemplateArguments is unable to preserve the source location of a
2157 // pack. The SourceLocation is necessary for the instantiation location.
2158 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2159 // which is wrong.
2160 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2161 CSE->getTemplateArgsAsWritten();
2163 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out,
2164 /*BuildPackExpansionTypes=*/!InFoldExpr))
2165 return true;
2167 if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(),
2168 CSE->getConceptNameInfo().getLoc(), Out,
2169 /*DefaultArgs=*/{},
2170 /*PartialTemplateArgs=*/false, CTAI,
2171 /*UpdateArgsWithConversions=*/false))
2172 return true;
2173 auto TemplateArgs = *MLTAL;
2174 TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(),
2175 CTAI.SugaredConverted);
2176 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2177 InFoldExpr)
2178 .substitute(CC.getNormalizedConstraint());
2179}
2180
2181bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2182 switch (N.getKind()) {
2184 if (!MLTAL) {
2185 assert(!ArgsAsWritten);
2186 return false;
2187 }
2188 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2189 }
2191 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2192 if (!MLTAL) {
2193 llvm::SaveAndRestore _1(InFoldExpr, true);
2194 assert(!ArgsAsWritten);
2195 return substitute(FE.getNormalizedPattern());
2196 }
2197 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2198 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2199 return SubstituteParameterMappings(SemaRef, /*InFoldExpr=*/true)
2200 .substitute(FE.getNormalizedPattern());
2201 }
2203 auto &CC = static_cast<ConceptIdConstraint &>(N);
2204 if (MLTAL) {
2205 assert(ArgsAsWritten);
2206 return substitute(CC);
2207 }
2208 assert(!ArgsAsWritten);
2212 Concept, Concept->getLexicalDeclContext(),
2213 /*Final=*/true, CSE->getTemplateArguments(),
2214 /*RelativeToPrimary=*/true,
2215 /*Pattern=*/nullptr,
2216 /*ForConstraintInstantiation=*/true);
2217
2218 return SubstituteParameterMappings(
2219 SemaRef, &MLTAL, CSE->getTemplateArgsAsWritten(), InFoldExpr)
2220 .substitute(CC.getNormalizedConstraint());
2221 }
2223 auto &Compound = static_cast<CompoundConstraint &>(N);
2224 if (substitute(Compound.getLHS()))
2225 return true;
2226 return substitute(Compound.getRHS());
2227 }
2228 }
2229 llvm_unreachable("Unknown ConstraintKind enum");
2230}
2231
2232} // namespace
2233
2234NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2235 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2236 assert(ACs.size() != 0);
2237 auto *Conjunction =
2238 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2239 if (!Conjunction)
2240 return nullptr;
2241 for (unsigned I = 1; I < ACs.size(); ++I) {
2242 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2243 ACs[I].ArgPackSubstIndex);
2244 if (!Next)
2245 return nullptr;
2247 Conjunction, Next);
2248 }
2249 return Conjunction;
2250}
2251
2252NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2253 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2254 assert(E != nullptr);
2255
2256 // C++ [temp.constr.normal]p1.1
2257 // [...]
2258 // - The normal form of an expression (E) is the normal form of E.
2259 // [...]
2260 E = E->IgnoreParenImpCasts();
2261
2262 llvm::FoldingSetNodeID ID;
2263 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2264 return nullptr;
2265 }
2266 SatisfactionStackRAII StackRAII(S, D, ID);
2267
2268 // C++2a [temp.param]p4:
2269 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2270 // Fold expression is considered atomic constraints per current wording.
2271 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2272
2273 if (LogicalBinOp BO = E) {
2274 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2275 if (!LHS)
2276 return nullptr;
2277 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2278 if (!RHS)
2279 return nullptr;
2280
2282 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2283 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2284 NormalizedConstraint *SubNF;
2285 {
2286 Sema::InstantiatingTemplate Inst(
2287 S, CSE->getExprLoc(),
2288 Sema::InstantiatingTemplate::ConstraintNormalization{},
2289 // FIXME: improve const-correctness of InstantiatingTemplate
2290 const_cast<NamedDecl *>(D), CSE->getSourceRange());
2291 if (Inst.isInvalid())
2292 return nullptr;
2293 // C++ [temp.constr.normal]p1.1
2294 // [...]
2295 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2296 // where C names a concept, is the normal form of the
2297 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2298 // respective template parameters in the parameter mappings in each atomic
2299 // constraint. If any such substitution results in an invalid type or
2300 // expression, the program is ill-formed; no diagnostic is required.
2301 // [...]
2302
2303 // Use canonical declarations to merge ConceptDecls across
2304 // different modules.
2305 ConceptDecl *CD = CSE->getNamedConcept()->getCanonicalDecl();
2306
2307 ExprResult Res =
2308 SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);
2309 if (!Res.isUsable())
2310 return nullptr;
2311
2312 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2313 S, CD, AssociatedConstraint(Res.get(), SubstIndex));
2314
2315 if (!SubNF)
2316 return nullptr;
2317 }
2318
2320 CSE->getConceptReference(), SubNF, D,
2321 CSE, SubstIndex);
2322
2323 } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2324 FE && S.getLangOpts().CPlusPlus26 &&
2325 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2326 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2327
2328 // Normalize fold expressions in C++26.
2329
2331 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2334
2335 if (FE->getInit()) {
2336 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2337 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2338 if (!LHS || !RHS)
2339 return nullptr;
2340
2341 if (FE->isRightFold())
2343 FE->getPattern(), D, Kind, LHS);
2344 else
2346 FE->getPattern(), D, Kind, RHS);
2347
2349 S.getASTContext(), LHS,
2350 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2351 : CCK_Disjunction),
2352 RHS);
2353 }
2354 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2355 if (!Sub)
2356 return nullptr;
2358 D, Kind, Sub);
2359 }
2360 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2361}
2362
2364 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2365 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2366 if (!ConstrainedDeclOrNestedReq) {
2367 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2368 *this, nullptr, AssociatedConstraints);
2369 if (!Normalized ||
2370 SubstituteParameterMappings(*this).substitute(*Normalized))
2371 return nullptr;
2372
2373 return Normalized;
2374 }
2375
2376 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2377 const NamedDecl *ND =
2378 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2379 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2380 if (CacheEntry == NormalizationCache.end()) {
2381 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2382 *this, ND, AssociatedConstraints);
2383 CacheEntry =
2384 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2385 .first;
2386 if (!Normalized ||
2387 SubstituteParameterMappings(*this).substitute(*Normalized))
2388 return nullptr;
2389 }
2390 return CacheEntry->second;
2391}
2392
2395
2396 // [C++26] [temp.constr.fold]
2397 // Two fold expanded constraints are compatible for subsumption
2398 // if their respective constraints both contain an equivalent unexpanded pack.
2399
2402 APacks);
2404 BPacks);
2405
2406 for (const UnexpandedParameterPack &APack : APacks) {
2407 auto ADI = getDepthAndIndex(APack);
2408 if (!ADI)
2409 continue;
2410 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2411 return getDepthAndIndex(BPack) == ADI;
2412 });
2413 if (It != BPacks.end())
2414 return true;
2415 }
2416 return false;
2417}
2418
2421 const NamedDecl *D2,
2423 bool &Result) {
2424#ifndef NDEBUG
2425 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2426 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2428 return Kind == FunctionDecl::TK_NonTemplate ||
2430 };
2431 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2432 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2433 "use non-instantiated function declaration for constraints partial "
2434 "ordering");
2435 }
2436#endif
2437
2438 if (AC1.empty()) {
2439 Result = AC2.empty();
2440 return false;
2441 }
2442 if (AC2.empty()) {
2443 // TD1 has associated constraints and TD2 does not.
2444 Result = true;
2445 return false;
2446 }
2447
2448 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2449 auto CacheEntry = SubsumptionCache.find(Key);
2450 if (CacheEntry != SubsumptionCache.end()) {
2451 Result = CacheEntry->second;
2452 return false;
2453 }
2454
2455 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
2456 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
2457
2458 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2459 if (Depth2 > Depth1) {
2460 AC1[I].ConstraintExpr =
2461 AdjustConstraintDepth(*this, Depth2 - Depth1)
2462 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2463 .get();
2464 } else if (Depth1 > Depth2) {
2465 AC2[I].ConstraintExpr =
2466 AdjustConstraintDepth(*this, Depth1 - Depth2)
2467 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2468 .get();
2469 }
2470 }
2471
2472 SubsumptionChecker SC(*this);
2473 std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2);
2474 if (!Subsumes) {
2475 // Normalization failed
2476 return true;
2477 }
2478 Result = *Subsumes;
2479 SubsumptionCache.try_emplace(Key, *Subsumes);
2480 return false;
2481}
2482
2486 if (isSFINAEContext())
2487 // No need to work here because our notes would be discarded.
2488 return false;
2489
2490 if (AC1.empty() || AC2.empty())
2491 return false;
2492
2493 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2494 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2495 const AtomicConstraint &B) {
2497 return false;
2498 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2499 if (EA == EB)
2500 return true;
2501
2502 // Not the same source level expression - are the expressions
2503 // identical?
2504 llvm::FoldingSetNodeID IDA, IDB;
2505 EA->Profile(IDA, Context, /*Canonical=*/true);
2506 EB->Profile(IDB, Context, /*Canonical=*/true);
2507 if (IDA != IDB)
2508 return false;
2509
2510 AmbiguousAtomic1 = EA;
2511 AmbiguousAtomic2 = EB;
2512 return true;
2513 };
2514
2515 {
2516 // The subsumption checks might cause diagnostics
2517 SFINAETrap Trap(*this);
2518 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2519 if (!Normalized1)
2520 return false;
2521
2522 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2523 if (!Normalized2)
2524 return false;
2525
2526 SubsumptionChecker SC(*this);
2527
2528 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2529 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2530
2531 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2532 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2533 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2534
2535 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2536 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2537 // Same result - no ambiguity was caused by identical atomic expressions.
2538 return false;
2539 }
2540 // A different result! Some ambiguous atomic constraint(s) caused a difference
2541 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2542
2543 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2544 << AmbiguousAtomic1->getSourceRange();
2545 Diag(AmbiguousAtomic2->getBeginLoc(),
2546 diag::note_ambiguous_atomic_constraints_similar_expression)
2547 << AmbiguousAtomic2->getSourceRange();
2548 return true;
2549}
2550
2551//
2552//
2553// ------------------------ Subsumption -----------------------------------
2554//
2555//
2557 SubsumptionCallable Callable)
2558 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2559
2560uint16_t SubsumptionChecker::getNewLiteralId() {
2561 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2562 "too many constraints!");
2563 return NextID++;
2564}
2565
2566auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2567 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2568 // C++ [temp.constr.order] p2
2569 // - an atomic constraint A subsumes another atomic constraint B
2570 // if and only if the A and B are identical [...]
2571 //
2572 // C++ [temp.constr.atomic] p2
2573 // Two atomic constraints are identical if they are formed from the
2574 // same expression and the targets of the parameter mappings are
2575 // equivalent according to the rules for expressions [...]
2576
2577 // Because subsumption of atomic constraints is an identity
2578 // relationship that does not require further analysis
2579 // We cache the results such that if an atomic constraint literal
2580 // subsumes another, their literal will be the same
2581
2582 llvm::FoldingSetNodeID ID;
2583 ID.AddBoolean(Ori->hasParameterMapping());
2584 if (Ori->hasParameterMapping()) {
2585 const auto &Mapping = Ori->getParameterMapping();
2587 Ori->mappingOccurenceListForSubsumption();
2588 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2589 if (Indexes[Idx])
2590 SemaRef.getASTContext()
2591 .getCanonicalTemplateArgument(TAL.getArgument())
2592 .Profile(ID, SemaRef.getASTContext());
2593 }
2594 }
2595 auto It = Elems.find(ID);
2596 if (It == Elems.end()) {
2597 It = Elems
2598 .insert({ID,
2599 MappedAtomicConstraint{
2600 Ori, {getNewLiteralId(), Literal::Atomic}}})
2601 .first;
2602 ReverseMap[It->second.ID.Value] = Ori;
2603 }
2604 return It->getSecond().ID;
2605}
2606
2607auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2608 auto &Elems = FoldMap[Ori->getPattern()];
2609
2610 FoldExpendedConstraintKey K;
2611 K.Kind = Ori->getFoldOperator();
2612
2613 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2614 return K.Kind == Other.Kind;
2615 });
2616 if (It == Elems.end()) {
2617 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2618 It = Elems.insert(Elems.end(), std::move(K));
2619 ReverseMap[It->ID.Value] = Ori;
2620 }
2621 return It->ID;
2622}
2623
2624auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2625 return SubsumptionChecker::Normalize<CNFFormula>(C);
2626}
2627auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2628 return SubsumptionChecker::Normalize<DNFFormula>(C);
2629}
2630
2631///
2632/// \brief SubsumptionChecker::Normalize
2633///
2634/// Normalize a formula to Conjunctive Normal Form or
2635/// Disjunctive normal form.
2636///
2637/// Each Atomic (and Fold Expanded) constraint gets represented by
2638/// a single id to reduce space.
2639///
2640/// To minimize risks of exponential blow up, if two atomic
2641/// constraints subsumes each other (same constraint and mapping),
2642/// they are represented by the same literal.
2643///
2644template <typename FormulaType>
2645FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2646 FormulaType Res;
2647
2648 auto Add = [&, this](Clause C) {
2649 // Sort each clause and remove duplicates for faster comparisons.
2650 llvm::sort(C);
2651 C.erase(llvm::unique(C), C.end());
2652 AddUniqueClauseToFormula(Res, std::move(C));
2653 };
2654
2655 switch (NC.getKind()) {
2657 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2658
2660 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2661
2663 return Normalize<FormulaType>(
2664 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2665
2667 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2668 FormulaType Left, Right;
2669 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2670 Left = Normalize<FormulaType>(Compound.getLHS());
2671 Right = Normalize<FormulaType>(Compound.getRHS());
2672 });
2673
2674 if (Compound.getCompoundKind() == FormulaType::Kind) {
2675 Res = std::move(Left);
2676 Res.reserve(Left.size() + Right.size());
2677 std::for_each(std::make_move_iterator(Right.begin()),
2678 std::make_move_iterator(Right.end()), Add);
2679 return Res;
2680 }
2681
2682 Res.reserve(Left.size() * Right.size());
2683 for (const auto &LTransform : Left) {
2684 for (const auto &RTransform : Right) {
2685 Clause Combined;
2686 Combined.reserve(LTransform.size() + RTransform.size());
2687 llvm::copy(LTransform, std::back_inserter(Combined));
2688 llvm::copy(RTransform, std::back_inserter(Combined));
2689 Add(std::move(Combined));
2690 }
2691 }
2692 return Res;
2693 }
2694 }
2695 llvm_unreachable("Unknown ConstraintKind enum");
2696}
2697
2698void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2699 for (auto &Other : F) {
2700 if (llvm::equal(C, Other))
2701 return;
2702 }
2703 F.push_back(C);
2704}
2705
2707 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2709 const NormalizedConstraint *PNormalized =
2710 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2711 if (!PNormalized)
2712 return std::nullopt;
2713
2714 const NormalizedConstraint *QNormalized =
2715 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2716 if (!QNormalized)
2717 return std::nullopt;
2718
2719 return Subsumes(PNormalized, QNormalized);
2720}
2721
2723 const NormalizedConstraint *Q) {
2724
2725 DNFFormula DNFP = DNF(*P);
2726 CNFFormula CNFQ = CNF(*Q);
2727 return Subsumes(DNFP, CNFQ);
2728}
2729
2730bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2731 const CNFFormula &QCNF) {
2732 for (const auto &Pi : PDNF) {
2733 for (const auto &Qj : QCNF) {
2734 // C++ [temp.constr.order] p2
2735 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2736 // and only if there exists an atomic constraint Pia in Pi for which
2737 // there exists an atomic constraint, Qjb, in Qj such that Pia
2738 // subsumes Qjb.
2739 if (!DNFSubsumes(Pi, Qj))
2740 return false;
2741 }
2742 }
2743 return true;
2744}
2745
2746bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2747
2748 return llvm::any_of(P, [&](Literal LP) {
2749 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2750 });
2751}
2752
2754 const FoldExpandedConstraint *B) {
2755 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2756 A, B};
2757
2758 auto It = FoldSubsumptionCache.find(Key);
2759 if (It == FoldSubsumptionCache.end()) {
2760 // C++ [temp.constr.order]
2761 // a fold expanded constraint A subsumes another fold expanded
2762 // constraint B if they are compatible for subsumption, have the same
2763 // fold-operator, and the constraint of A subsumes that of B.
2764 bool DoesSubsume =
2765 A->getFoldOperator() == B->getFoldOperator() &&
2768 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2769 }
2770 return It->second;
2771}
2772
2773bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2774 if (A.Kind != B.Kind)
2775 return false;
2776 switch (A.Kind) {
2777 case Literal::Atomic:
2778 if (!Callable)
2779 return A.Value == B.Value;
2780 return Callable(
2781 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2782 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2783 case Literal::FoldExpanded:
2784 return Subsumes(
2785 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2786 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2787 }
2788 llvm_unreachable("unknown literal kind");
2789}
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
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition SemaBase.cpp:61
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition SemaBase.cpp:33
RAII object used to change the argument pack substitution index within a Sema object.
Definition Sema.h:13597
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8416
A RAII object to temporarily push a declaration context.
Definition Sema.h:3476
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition Sema.h:12404
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition Sema.h:12437
SourceLocation getLocation() const
Definition Sema.h:12178
const DeclContext * getDeclContext() const
Definition Sema.h:12174
const NamedDecl * getDecl() const
Definition Sema.h:12166
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12170
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:14941
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 ...
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:14800
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:6993
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:11736
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1314
std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const
Determines whether we are currently in a context where template argument substitution failures are no...
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)
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13591
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14760
void PopSatisfactionStackEntry()
Definition Sema.h:14766
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:6711
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6690
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition Sema.h:14768
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
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.
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.
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:425
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:398
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
@ 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:11954
A stack object to be created when performing template instantiation.
Definition Sema.h:13240
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition Sema.h:13400
constexpr unsigned toInternalRepresentation() const