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