clang 24.0.0git
SemaConcept.cpp
Go to the documentation of this file.
1//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for C++ constraints and concepts.
10//
11//===----------------------------------------------------------------------===//
12
14#include "TreeTransform.h"
16#include "clang/AST/ASTLambda.h"
17#include "clang/AST/DeclCXX.h"
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 ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
281 NonTypeTemplateParmDecl *NTTP =
282 dyn_cast<NonTypeTemplateParmDecl>(E->getDecl());
283 if (!NTTP)
284 return inherited::TransformDeclRefExpr(E);
285
286 assert(E->getTemplateArgs() == nullptr &&
287 "Template arguments for NTTP decl?");
288 auto *TSI = inherited::TransformType(NTTP->getTypeSourceInfo());
289 if (!TSI)
290 return ExprError();
291
293 SemaRef.getASTContext(), NTTP->getDeclContext(),
294 NTTP->getInnerLocStart(), NTTP->getLocation(),
295 NTTP->getDepth() + TemplateDepth, NTTP->getPosition(),
296 NTTP->getIdentifier(), TSI->getType(), NTTP->isParameterPack(), TSI);
297
298 return DeclRefExpr::Create(
299 SemaRef.getASTContext(), E->getQualifierLoc(),
301 E->getNameInfo(), TSI->getType(), E->getValueKind(), D,
302 /*TemplateArgs=*/nullptr, E->isNonOdrUse());
303 }
304};
305} // namespace
306
307namespace {
308
309// FIXME: Convert it to DynamicRecursiveASTVisitor
310class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
311 using inherited = RecursiveASTVisitor<HashParameterMapping>;
312 friend inherited;
313
314 Sema &SemaRef;
315 const MultiLevelTemplateArgumentList &TemplateArgs;
316 llvm::FoldingSetNodeID &ID;
317 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
318
319 UnsignedOrNone OuterPackSubstIndex;
320
321 bool shouldVisitTemplateInstantiations() const { return true; }
322
323public:
324 HashParameterMapping(Sema &SemaRef,
325 const MultiLevelTemplateArgumentList &TemplateArgs,
326 llvm::FoldingSetNodeID &ID,
327 UnsignedOrNone OuterPackSubstIndex)
328 : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),
329 OuterPackSubstIndex(OuterPackSubstIndex) {}
330
331 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
332 // A lambda expression can introduce template parameters that don't have
333 // corresponding template arguments yet.
334 if (T->getDepth() >= TemplateArgs.getNumLevels())
335 return true;
336
337 // There might not be a corresponding template argument before substituting
338 // into the parameter mapping, e.g. a sizeof... expression.
339 if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
340 return true;
341
342 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
343
344 // In concept parameter mapping for fold expressions, packs that aren't
345 // expanded in place are treated as having non-pack dependency, so that
346 // a PackExpansionType won't prevent expanding the packs outside the
347 // TreeTransform. However we still need to check the pack at this point.
348 if ((T->isParameterPack() ||
349 (T->getDecl() && T->getDecl()->isTemplateParameterPack())) &&
350 SemaRef.ArgPackSubstIndex) {
351 assert(Arg.getKind() == TemplateArgument::Pack &&
352 "Missing argument pack");
353
354 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
355 }
356
357 UsedTemplateArgs.push_back(
359 return true;
360 }
361
362 bool VisitDeclRefExpr(DeclRefExpr *E) {
363 NamedDecl *D = E->getDecl();
364 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
365 if (!NTTP)
366 return TraverseDecl(D);
367
368 if (NTTP->getDepth() >= TemplateArgs.getNumLevels())
369 return true;
370
371 if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), NTTP->getIndex()))
372 return true;
373
374 TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
375 if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
376 assert(Arg.getKind() == TemplateArgument::Pack &&
377 "Missing argument pack");
378 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
379 }
380
381 UsedTemplateArgs.push_back(
383 return true;
384 }
385
386 bool VisitTypedefType(TypedefType *TT) {
387 return inherited::TraverseType(TT->desugar());
388 }
389
390 bool TraverseDecl(Decl *D) {
391 if (auto *VD = dyn_cast<ValueDecl>(D)) {
392 if (auto *Var = dyn_cast<VarDecl>(VD))
393 TraverseStmt(Var->getInit());
394 return TraverseType(VD->getType());
395 }
396
397 return inherited::TraverseDecl(D);
398 }
399
400 bool TraverseCallExpr(CallExpr *CE) {
401 inherited::TraverseStmt(CE->getCallee());
402
403 for (Expr *Arg : CE->arguments())
404 inherited::TraverseStmt(Arg);
405
406 return true;
407 }
408
409 bool TraverseCXXThisExpr(CXXThisExpr *E) {
410 return inherited::TraverseType(E->getType());
411 }
412
413 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
414 // We don't care about TypeLocs. So traverse Types instead.
415 return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);
416 }
417
418 bool TraverseDependentNameType(const DependentNameType *T,
419 bool /*TraverseQualifier*/) {
420 return TraverseNestedNameSpecifier(T->getQualifier());
421 }
422
423 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
424 // T's parent can be dependent while T doesn't have any template arguments.
425 // We should have already traversed its qualifier.
426 // FIXME: Add an assert to catch cases where we failed to profile the
427 // concept.
428 return true;
429 }
430
431 bool TraverseUnresolvedUsingType(UnresolvedUsingType *T,
432 bool TraverseQualifier) {
433 // Sometimes the written type doesn't contain a qualifier which contains
434 // necessary template arguments, whereas the declaration does.
435 if (NestedNameSpecifier NNS = T->getDecl()->getQualifier();
436 TraverseQualifier && NNS)
437 return inherited::TraverseNestedNameSpecifier(NNS);
438 return inherited::TraverseUnresolvedUsingType(T, TraverseQualifier);
439 }
440
441 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
442 bool TraverseQualifier) {
443 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
444 }
445
446 bool TraverseTemplateArgument(const TemplateArgument &Arg) {
448 // Act as if we are fully expanding this pack, if it is a PackExpansion.
449 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
450 llvm::SaveAndRestore<UnsignedOrNone> _2(OuterPackSubstIndex,
451 std::nullopt);
452 return inherited::TraverseTemplateArgument(Arg);
453 }
454
455 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
456 return inherited::TraverseTemplateArgument(Arg);
457 }
458
459 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
460 return TraverseDecl(SOPE->getPack());
461 }
462
463 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
464 return inherited::TraverseStmt(E->getReplacement());
465 }
466
467 bool TraverseTemplateName(TemplateName Template) {
468 if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
469 Template.getAsTemplateDecl());
470 TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
471 if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
472 TTP->getPosition()))
473 return true;
474
475 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
476 if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
477 assert(Arg.getKind() == TemplateArgument::Pack &&
478 "Missing argument pack");
479 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
480 }
481 assert(!Arg.getAsTemplate().isNull() &&
482 "Null template template argument");
483 UsedTemplateArgs.push_back(
485 }
486 return inherited::TraverseTemplateName(Template);
487 }
488
489 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
490 if (!Constraint.hasParameterMapping()) {
491 for (const auto &List : TemplateArgs)
492 for (const TemplateArgument &Arg : List.Args)
494 ID, SemaRef.Context);
495 return;
496 }
497
498 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
499 Constraint.getParameterMapping();
500 for (auto &ArgLoc : Mapping) {
501 TemplateArgument Canonical =
502 SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());
503 // We don't want sugars to impede the profile of cache.
504 UsedTemplateArgs.push_back(Canonical);
505 TraverseTemplateArgument(Canonical);
506 }
507
508 for (auto &Used : UsedTemplateArgs) {
509 llvm::FoldingSetNodeID R;
510 Used.Profile(R, SemaRef.Context);
511 ID.AddNodeID(R);
512 }
513 }
514};
515
516class ConstraintSatisfactionChecker {
517 Sema &S;
518 const NamedDecl *Template;
519 const ConceptReference *TopLevelConceptId;
520 SourceLocation TemplateNameLoc;
521 UnsignedOrNone PackSubstitutionIndex;
522 ConstraintSatisfaction &Satisfaction;
523 bool BuildExpression;
524
525 // The closest concept declaration when evaluating atomic constraints.
526 ConceptDecl *ParentConcept = nullptr;
527
528 // This is for TemplateInstantiator to not instantiate the same template
529 // parameter mapping many times, in order to improve substitution performance.
530 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
531 CachedTemplateArgs;
532
533private:
534 template <class Constraint>
535 UnsignedOrNone getOuterPackIndex(const Constraint &C) const {
536 return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex()
537 : PackSubstitutionIndex;
538 }
539
541 EvaluateAtomicConstraint(const Expr *AtomicExpr,
542 const MultiLevelTemplateArgumentList &MLTAL);
543
544 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
545 const FoldExpandedConstraint &FE,
546 const MultiLevelTemplateArgumentList &MLTAL);
547
548 // XXX: It is SLOW! Use it very carefully.
549 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
550 const NormalizedConstraintWithParamMapping &Constraint,
551 const MultiLevelTemplateArgumentList &MLTAL,
552 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
553
554 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
555 const MultiLevelTemplateArgumentList &MLTAL);
556
557 ExprResult Evaluate(const AtomicConstraint &Constraint,
558 const MultiLevelTemplateArgumentList &MLTAL);
559
560 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
561 const MultiLevelTemplateArgumentList &MLTAL);
562
563 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
564 const MultiLevelTemplateArgumentList &MLTAL);
565
566 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
567 const MultiLevelTemplateArgumentList &MLTAL,
568 unsigned int Size);
569
570 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
571 const MultiLevelTemplateArgumentList &MLTAL);
572
573 ExprResult Evaluate(const CompoundConstraint &Constraint,
574 const MultiLevelTemplateArgumentList &MLTAL);
575
576public:
577 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
578 const ConceptReference *TopLevelConceptId,
579 SourceLocation TemplateNameLoc,
580 UnsignedOrNone PackSubstitutionIndex,
581 ConstraintSatisfaction &Satisfaction,
582 bool BuildExpression)
583 : S(SemaRef), Template(Template), TopLevelConceptId(TopLevelConceptId),
584 TemplateNameLoc(TemplateNameLoc),
585 PackSubstitutionIndex(PackSubstitutionIndex),
586 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
587
588 ExprResult Evaluate(const NormalizedConstraint &Constraint,
589 const MultiLevelTemplateArgumentList &MLTAL);
590};
591
592StringRef allocateStringFromConceptDiagnostic(const Sema &S,
593 const PartialDiagnostic Diag) {
594 SmallString<128> DiagString;
595 DiagString = ": ";
596 Diag.EmitToString(S.getDiagnostics(), DiagString);
597 return S.getASTContext().backupStr(DiagString);
598}
599
600} // namespace
601
602ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
603 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
604 llvm::FoldingSetNodeID ID;
605 if (Template &&
607 Satisfaction.IsSatisfied = false;
608 Satisfaction.ContainsErrors = true;
609 return ExprEmpty();
610 }
611 SatisfactionStackRAII StackRAII(S, Template, ID);
612
613 // Atomic constraint - substitute arguments and check satisfaction.
614 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
615 {
616 TemplateDeductionInfo Info(TemplateNameLoc);
620 // FIXME: improve const-correctness of InstantiatingTemplate
621 const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());
622 if (Inst.isInvalid())
623 return ExprError();
624
625 // We do not want error diagnostics escaping here.
626 Sema::SFINAETrap Trap(S, Info);
627 SubstitutedExpression =
628 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
629
630 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
631 // C++2a [temp.constr.atomic]p1
632 // ...If substitution results in an invalid type or expression, the
633 // constraint is not satisfied.
634 if (!Trap.hasErrorOccurred())
635 // A non-SFINAE error has occurred as a result of this
636 // substitution.
637 return ExprError();
638
641 Info.takeSFINAEDiagnostic(SubstDiag);
642 // FIXME: This is an unfortunate consequence of there
643 // being no serialization code for PartialDiagnostics and the fact
644 // that serializing them would likely take a lot more storage than
645 // just storing them as strings. We would still like, in the
646 // future, to serialize the proper PartialDiagnostic as serializing
647 // it as a string defeats the purpose of the diagnostic mechanism.
648 Satisfaction.Details.emplace_back(
650 SubstDiag.first,
651 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
652 Satisfaction.IsSatisfied = false;
653 return ExprEmpty();
654 }
655 }
656
657 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
658 return ExprError();
659
660 // [temp.constr.atomic]p3: To determine if an atomic constraint is
661 // satisfied, the parameter mapping and template arguments are first
662 // substituted into its expression. If substitution results in an
663 // invalid type or expression, the constraint is not satisfied.
664 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
665 // and E shall be a constant expression of type bool.
666 //
667 // Perform the L to R Value conversion if necessary. We do so for all
668 // non-PRValue categories, else we fail to extend the lifetime of
669 // temporaries, and that fails the constant expression check.
670 if (!SubstitutedExpression.get()->isPRValue())
671 SubstitutedExpression = ImplicitCastExpr::Create(
672 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
673 SubstitutedExpression.get(),
674 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
675
676 return SubstitutedExpression;
677}
678
679std::optional<MultiLevelTemplateArgumentList>
680ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
681 const NormalizedConstraintWithParamMapping &Constraint,
683 llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {
684
685 if (!Constraint.hasParameterMapping()) {
686 if (MLTAL.getNumSubstitutedLevels())
687 SubstitutedOutermost.assign(MLTAL.getOutermost());
688 return MLTAL;
689 }
690
691 // The mapping is empty, meaning no template arguments are needed for
692 // evaluation.
693 if (Constraint.getParameterMapping().empty())
695
696 TemplateDeductionInfo Info(Constraint.getBeginLoc());
697 Sema::SFINAETrap Trap(S, Info);
699 S, Constraint.getBeginLoc(),
701 // FIXME: improve const-correctness of InstantiatingTemplate
702 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
703 if (Inst.isInvalid())
704 return std::nullopt;
705
706 TemplateArgumentListInfo SubstArgs;
707 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
708
709 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
710 &CachedTemplateArgs);
711
712 // We don't want the template argument substitution into parameter
713 // mappings to preserve the outer depths.
715 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
716 SubstArgs)) {
717 Satisfaction.IsSatisfied = false;
718 return std::nullopt;
719 }
720
722 auto *TD = const_cast<TemplateDecl *>(
725 TD->getLocation(), SubstArgs,
726 /*DefaultArguments=*/{},
727 /*PartialTemplateArgs=*/false, CTAI))
728 return std::nullopt;
730 Constraint.mappingOccurenceList();
731 // The empty MLTAL situation should only occur when evaluating non-dependent
732 // constraints.
733 if (MLTAL.getNumSubstitutedLevels())
734 SubstitutedOutermost =
735 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
736 unsigned Offset = 0;
737 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
739 if (Used[I])
741 CTAI.SugaredConverted[MappedIndex++]);
742 if (I < SubstitutedOutermost.size()) {
743 SubstitutedOutermost[I] = Arg;
744 Offset = I + 1;
745 } else {
746 SubstitutedOutermost.push_back(Arg);
747 Offset = SubstitutedOutermost.size();
748 }
749 }
750 if (Offset < SubstitutedOutermost.size())
751 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
752
753 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
754 SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,
755 /*Final=*/false);
756 return std::move(SubstitutedTemplateArgs);
757}
758
759ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
760 const AtomicConstraint &Constraint,
761 const MultiLevelTemplateArgumentList &MLTAL) {
762 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
763 // The ConceptDecl as a ContextDecl ensures that, when evaluating constraints
764 // on transformed lambdas, we don't have extra outer template arguments.
765 if (ParentConcept)
766 EvaluationContext.emplace(
768 else
769 EvaluationContext.emplace(
772
773 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
774 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
775 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
776 if (!SubstitutedArgs) {
777 Satisfaction.IsSatisfied = false;
778 return ExprEmpty();
779 }
780
781 // Make sure that concepts are not evaluated in the context they are used,
782 // i.e they should not have access to the current class object or its
783 // non-public members.
784 std::optional<Sema::ContextRAII> ConceptContext;
785 if (ParentConcept)
786 ConceptContext.emplace(S, ParentConcept->getDeclContext());
787
788 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
789 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
790 Constraint.getConstraintExpr(), *SubstitutedArgs);
791
792 if (SubstitutedAtomicExpr.isInvalid())
793 return ExprError();
794
795 if (SubstitutedAtomicExpr.isUnset())
796 // Evaluator has decided satisfaction without yielding an expression.
797 return ExprEmpty();
798
799 // We don't have the ability to evaluate this, since it contains a
800 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
801 // we'd potentially pick up a different overload, and cause confusing
802 // diagnostics. SO, add a failure detail that will cause us to make this
803 // overload set not viable.
804 if (SubstitutedAtomicExpr.get()->containsErrors()) {
805 Satisfaction.IsSatisfied = false;
806 Satisfaction.ContainsErrors = true;
807
808 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
809 Satisfaction.Details.emplace_back(
811 SubstitutedAtomicExpr.get()->getBeginLoc(),
812 allocateStringFromConceptDiagnostic(S, Msg)});
813 return SubstitutedAtomicExpr;
814 }
815
816 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
817 Satisfaction.IsSatisfied = true;
818 Satisfaction.ContainsErrors = false;
819 return SubstitutedAtomicExpr;
820 }
821
823 Expr::EvalResult EvalResult;
824 EvalResult.Diag = &EvaluationDiags;
825 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
826 S.Context) ||
827 !EvaluationDiags.empty()) {
828 // C++2a [temp.constr.atomic]p1
829 // ...E shall be a constant expression of type bool.
830 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
831 diag::err_non_constant_constraint_expression)
832 << SubstitutedAtomicExpr.get()->getSourceRange();
833 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
834 S.Diag(PDiag.first, PDiag.second);
835 return ExprError();
836 }
837
838 assert(EvalResult.Val.isInt() &&
839 "evaluating bool expression didn't produce int");
840 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
841 if (!Satisfaction.IsSatisfied)
842 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
843
844 return SubstitutedAtomicExpr;
845}
846
847ExprResult ConstraintSatisfactionChecker::Evaluate(
848 const AtomicConstraint &Constraint,
849 const MultiLevelTemplateArgumentList &MLTAL) {
850
851 unsigned Size = Satisfaction.Details.size();
852 llvm::FoldingSetNodeID ID;
853 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
854
855 ID.AddPointer(Constraint.getConstraintExpr());
856 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
857 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
858 .VisitConstraint(Constraint);
859
860 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
862 auto &Cached = Iter->second.Satisfaction;
863 Satisfaction.ContainsErrors = Cached.ContainsErrors;
864 Satisfaction.IsSatisfied = Cached.IsSatisfied;
865 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
866 Cached.Details.begin(), Cached.Details.end());
867 return Iter->second.SubstExpr;
868 }
869
870 ExprResult E = EvaluateSlow(Constraint, MLTAL);
871
873 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
874 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
875 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
876 Satisfaction.Details.begin() + Size,
877 Satisfaction.Details.end());
878 Cache.SubstExpr = E;
879 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
880
881 return E;
882}
883
885ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
886 const FoldExpandedConstraint &FE,
887 const MultiLevelTemplateArgumentList &MLTAL) {
888
889 Expr *Pattern = const_cast<Expr *>(FE.getPattern());
890
892 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
893 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
894 bool Expand = true;
895 bool RetainExpansion = false;
896 UnsignedOrNone NumExpansions(std::nullopt);
898 Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
899 /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
900 NumExpansions, /*Diagnose=*/false) ||
901 !Expand || RetainExpansion)
902 return std::nullopt;
903
904 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)
905 return std::nullopt;
906 return NumExpansions;
907}
908
909ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
910 const FoldExpandedConstraint &Constraint,
911 const MultiLevelTemplateArgumentList &MLTAL) {
912
913 bool Conjunction = Constraint.getFoldOperator() ==
915 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
916
917 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
918 // FIXME: Is PackSubstitutionIndex correct?
919 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
920 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
921 SubstitutionInTemplateArguments(
922 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
923 MLTAL, SubstitutedOutermost);
924 if (!SubstitutedArgs) {
925 Satisfaction.IsSatisfied = false;
926 return ExprError();
927 }
928
930 UnsignedOrNone NumExpansions =
931 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
932 if (!NumExpansions)
933 return ExprEmpty();
934
935 if (*NumExpansions == 0) {
936 Satisfaction.IsSatisfied = Conjunction;
937 return ExprEmpty();
938 }
939
940 for (unsigned I = 0; I < *NumExpansions; I++) {
941 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
942 Satisfaction.IsSatisfied = false;
943 Satisfaction.ContainsErrors = false;
945 ConstraintSatisfactionChecker(S, Template, TopLevelConceptId,
946 TemplateNameLoc, UnsignedOrNone(I),
947 Satisfaction,
948 /*BuildExpression=*/false)
949 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
950 if (BuildExpression) {
951 if (Out.isUnset() || !Expr.isUsable())
952 Out = Expr;
953 else
954 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
955 Conjunction ? BinaryOperatorKind::BO_LAnd
956 : BinaryOperatorKind::BO_LOr,
958 Constraint.getBeginLoc(),
960 }
961 if (!Conjunction && Satisfaction.IsSatisfied) {
962 Satisfaction.Details.erase(Satisfaction.Details.begin() +
963 EffectiveDetailEndIndex,
964 Satisfaction.Details.end());
965 break;
966 }
967 if (Satisfaction.IsSatisfied != Conjunction)
968 return Out;
969 }
970
971 return Out;
972}
973
974ExprResult ConstraintSatisfactionChecker::Evaluate(
975 const FoldExpandedConstraint &Constraint,
976 const MultiLevelTemplateArgumentList &MLTAL) {
977
978 llvm::FoldingSetNodeID ID;
979 ID.AddPointer(Constraint.getPattern());
980 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
981
982 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
984
985 auto &Cached = Iter->second.Satisfaction;
986 Satisfaction.ContainsErrors = Cached.ContainsErrors;
987 Satisfaction.IsSatisfied = Cached.IsSatisfied;
988 Satisfaction.Details.insert(Satisfaction.Details.end(),
989 Cached.Details.begin(), Cached.Details.end());
990 return Iter->second.SubstExpr;
991 }
992
993 unsigned Size = Satisfaction.Details.size();
994
995 ExprResult E = EvaluateSlow(Constraint, MLTAL);
997 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
998 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
999 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1000 Satisfaction.Details.begin() + Size,
1001 Satisfaction.Details.end());
1002 Cache.SubstExpr = E;
1003 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1004 return E;
1005}
1006
1007ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1008 const ConceptIdConstraint &Constraint,
1009 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
1010 const ConceptReference *ConceptId = Constraint.getConceptId();
1011
1012 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
1013 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1014 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1015
1016 if (!SubstitutedArgs) {
1017 Satisfaction.IsSatisfied = false;
1018 // FIXME: diagnostics?
1019 return ExprError();
1020 }
1021
1022 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
1023
1024 const ASTTemplateArgumentListInfo *Ori =
1025 ConceptId->getTemplateArgsAsWritten();
1026 TemplateDeductionInfo Info(TemplateNameLoc);
1027 Sema::SFINAETrap Trap(S, Info);
1030 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
1031
1032 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
1033
1034 // There's a concern that even with the same concept, they may not have the
1035 // same ConceptReference, if they come from modules.
1036 if (TopLevelConceptId &&
1037 ConceptId->getNamedConcept() == TopLevelConceptId->getNamedConcept()) {
1038 for (auto &A : Ori->arguments())
1039 OutArgs.addArgument(A);
1040 } else if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs,
1041 OutArgs) ||
1042 Trap.hasErrorOccurred()) {
1043 Satisfaction.IsSatisfied = false;
1044 if (!Trap.hasErrorOccurred())
1045 return ExprError();
1046
1049 Info.takeSFINAEDiagnostic(SubstDiag);
1050 // FIXME: This is an unfortunate consequence of there
1051 // being no serialization code for PartialDiagnostics and the fact
1052 // that serializing them would likely take a lot more storage than
1053 // just storing them as strings. We would still like, in the
1054 // future, to serialize the proper PartialDiagnostic as serializing
1055 // it as a string defeats the purpose of the diagnostic mechanism.
1056 Satisfaction.Details.insert(
1057 Satisfaction.Details.begin() + Size,
1059 SubstDiag.first,
1060 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
1061 return ExprError();
1062 }
1063
1064 CXXScopeSpec SS;
1065 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
1066
1067 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1068 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
1069 ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs,
1070 /*DoCheckConstraintSatisfaction=*/false);
1071
1072 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
1073 return ExprError();
1074
1075 if (Size != Satisfaction.Details.size()) {
1076 Satisfaction.Details.insert(
1077 Satisfaction.Details.begin() + Size,
1079 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
1080 ->getConceptReference()));
1081 }
1082 return SubstitutedConceptId;
1083}
1084
1085ExprResult ConstraintSatisfactionChecker::Evaluate(
1086 const ConceptIdConstraint &Constraint,
1087 const MultiLevelTemplateArgumentList &MLTAL) {
1088
1089 const ConceptReference *ConceptId = Constraint.getConceptId();
1090 Sema::InstantiatingTemplate InstTemplate(
1091 S, ConceptId->getBeginLoc(),
1093 ConceptId->getNamedConcept(),
1094 // We may have empty template arguments when checking non-dependent
1095 // nested constraint expressions.
1096 // In such cases, non-SFINAE errors would have already been diagnosed
1097 // during parameter mapping substitution, so the instantiating template
1098 // arguments are less useful here.
1099 MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
1101 Constraint.getSourceRange());
1102 if (InstTemplate.isInvalid())
1103 return ExprError();
1104
1105 unsigned Size = Satisfaction.Details.size();
1106
1107 llvm::SaveAndRestore PushConceptDecl(
1108 ParentConcept, cast<ConceptDecl>(ConceptId->getNamedConcept()));
1109
1110 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
1111
1112 if (E.isInvalid()) {
1113 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1114 return E;
1115 }
1116
1117 // ConceptIdConstraint is only relevant for diagnostics,
1118 // so if the normalized constraint is satisfied, we should not
1119 // substitute into the constraint.
1120 if (Satisfaction.IsSatisfied)
1121 return E;
1122
1123 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
1124 llvm::FoldingSetNodeID ID;
1125 ID.AddPointer(Constraint.getConceptId());
1126 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
1127 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1128 .VisitConstraint(Constraint);
1129
1130 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
1132
1133 auto &Cached = Iter->second.Satisfaction;
1134 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1135 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1136 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1137 Cached.Details.begin(), Cached.Details.end());
1138 return Iter->second.SubstExpr;
1139 }
1140
1141 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1142 if (CE.isInvalid())
1143 return E;
1145 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1146 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1147 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1148 Satisfaction.Details.begin() + Size,
1149 Satisfaction.Details.end());
1150 Cache.SubstExpr = CE;
1151 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1152 return CE;
1153}
1154
1155ExprResult ConstraintSatisfactionChecker::Evaluate(
1156 const CompoundConstraint &Constraint,
1157 const MultiLevelTemplateArgumentList &MLTAL) {
1158
1159 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1160
1161 bool Conjunction =
1163
1164 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1165
1166 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1167 return LHS;
1168
1169 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
1170 !Satisfaction.ContainsErrors)
1171 return LHS;
1172
1173 Satisfaction.ContainsErrors = false;
1174 Satisfaction.IsSatisfied = false;
1175
1176 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1177
1178 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
1179 !Satisfaction.ContainsErrors)
1180 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1181 EffectiveDetailEndIndex,
1182 Satisfaction.Details.end());
1183
1184 if (!BuildExpression)
1185 return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
1186
1187 if (!LHS.isUsable())
1188 return RHS;
1189
1190 if (!RHS.isUsable())
1191 return LHS;
1192
1193 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1194 Conjunction ? BinaryOperatorKind::BO_LAnd
1195 : BinaryOperatorKind::BO_LOr,
1197 Constraint.getBeginLoc(), FPOptionsOverride{});
1198}
1199
1200ExprResult ConstraintSatisfactionChecker::Evaluate(
1201 const NormalizedConstraint &Constraint,
1202 const MultiLevelTemplateArgumentList &MLTAL) {
1203 switch (Constraint.getKind()) {
1205 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1206
1208 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1209 MLTAL);
1210
1212 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1213 MLTAL);
1214
1216 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1217 }
1218 llvm_unreachable("Unknown ConstraintKind enum");
1219}
1220
1222 Sema &S, const NamedDecl *Template,
1223 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1224 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1225 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1226 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1227
1228 if (ConvertedExpr)
1229 *ConvertedExpr = nullptr;
1230
1231 if (AssociatedConstraints.empty()) {
1232 Satisfaction.IsSatisfied = true;
1233 return false;
1234 }
1235
1236 // In the general case, we can't check satisfaction if the arguments contain
1237 // unsubstituted template parameters, even if they are purely syntactic,
1238 // because they may still turn out to be invalid after substitution.
1239 // This could be permitted in cases where this substitution will still be
1240 // attempted later and diagnosed, such as function template specializations,
1241 // but that's not the case for concept specializations.
1242 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1243 Satisfaction.IsSatisfied = true;
1244 return false;
1245 }
1246
1248 if (TemplateArgsLists.getNumLevels() != 0)
1249 Args = TemplateArgsLists.getInnermost();
1250
1251 struct SynthesisContextPair {
1254 SynthesisContextPair(Sema &S, NamedDecl *Template,
1255 ArrayRef<TemplateArgument> TemplateArgs,
1256 SourceRange InstantiationRange)
1257 : Inst(S, InstantiationRange.getBegin(),
1259 TemplateArgs, InstantiationRange),
1260 NSC(S) {}
1261 };
1262 std::optional<SynthesisContextPair> SynthesisContext;
1263 if (!TopLevelConceptId)
1264 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
1265 TemplateIDRange);
1266
1267 const NormalizedConstraint *C =
1268 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1269 if (!C) {
1270 Satisfaction.IsSatisfied = false;
1271 return true;
1272 }
1273
1274 if (TopLevelConceptId)
1275 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1276 const_cast<NormalizedConstraint *>(C),
1277 Template, /*CSE=*/nullptr,
1279
1280 ExprResult Res =
1281 ConstraintSatisfactionChecker(
1282 S, Template, TopLevelConceptId, TemplateIDRange.getBegin(),
1283 S.ArgPackSubstIndex, Satisfaction,
1284 /*BuildExpression=*/ConvertedExpr != nullptr)
1285 .Evaluate(*C, TemplateArgsLists);
1286
1287 if (Res.isInvalid())
1288 return true;
1289
1290 if (Res.isUsable() && ConvertedExpr)
1291 *ConvertedExpr = Res.get();
1292
1293 return false;
1294}
1295
1298 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1299 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1300 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1301 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1302 llvm::TimeTraceScope TimeScope(
1303 "CheckConstraintSatisfaction", [TemplateIDRange, this] {
1304 return TemplateIDRange.printToString(getSourceManager());
1305 });
1306 if (AssociatedConstraints.empty()) {
1307 OutSatisfaction.IsSatisfied = true;
1308 return false;
1309 }
1310 const auto *Template = Entity.dyn_cast<const NamedDecl *>();
1311 if (!Template) {
1312 return ::CheckConstraintSatisfaction(
1313 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1314 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1315 }
1316 // Invalid templates could make their way here. Substituting them could result
1317 // in dependent expressions.
1318 if (Template->isInvalidDecl()) {
1319 OutSatisfaction.IsSatisfied = false;
1320 return true;
1321 }
1322
1323 // A list of the template argument list flattened in a predictible manner for
1324 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1325 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1326 // here.
1328 for (auto List : TemplateArgsLists)
1329 for (const TemplateArgument &Arg : List.Args)
1330 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1331
1332 const NamedDecl *Owner = Template;
1333 if (TopLevelConceptId)
1334 Owner = TopLevelConceptId->getNamedConcept();
1335
1336 llvm::FoldingSetNodeID ID;
1337 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1338 void *InsertPos;
1339 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1340 OutSatisfaction = *Cached;
1341 return false;
1342 }
1343
1344 auto Satisfaction =
1345 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1347 *this, Template, AssociatedConstraints, TemplateArgsLists,
1348 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1349 OutSatisfaction = std::move(*Satisfaction);
1350 return true;
1351 }
1352
1353 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1354 // The evaluation of this constraint resulted in us trying to re-evaluate it
1355 // recursively. This isn't really possible, except we try to form a
1356 // RecoveryExpr as a part of the evaluation. If this is the case, just
1357 // return the 'cached' version (which will have the same result), and save
1358 // ourselves the extra-insert. If it ever becomes possible to legitimately
1359 // recursively check a constraint, we should skip checking the 'inner' one
1360 // above, and replace the cached version with this one, as it would be more
1361 // specific.
1362 OutSatisfaction = *Cached;
1363 return false;
1364 }
1365
1366 // Else we can simply add this satisfaction to the list.
1367 OutSatisfaction = *Satisfaction;
1368 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
1369 // invalidated it.
1370 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1371 SatisfactionCache.InsertNode(Satisfaction.release());
1372 return false;
1373}
1374
1375static ExprResult
1377 const ConceptSpecializationExpr *CSE,
1378 UnsignedOrNone SubstIndex) {
1379 Sema::SFINAETrap Trap(S);
1380 // [C++2c] [temp.constr.normal]
1381 // Otherwise, to form CE, any non-dependent concept template argument Ai
1382 // is substituted into the constraint-expression of C.
1383 // If any such substitution results in an invalid concept-id,
1384 // the program is ill-formed; no diagnostic is required.
1385
1387 Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
1388
1389 const ASTTemplateArgumentListInfo *ArgsAsWritten =
1391 if (llvm::none_of(
1392 ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {
1393 return !ArgLoc.getArgument().isDependent() &&
1394 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1395 })) {
1396 return Concept->getConstraintExpr();
1397 }
1398
1400 Concept, Concept->getLexicalDeclContext(),
1401 /*Final=*/false, CSE->getTemplateArguments(),
1402 /*RelativeToPrimary=*/true,
1403 /*Pattern=*/nullptr,
1404 /*ForConstraintInstantiation=*/true);
1405 return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),
1406 MLTAL);
1407}
1408
1409bool Sema::SetupConstraintScope(
1410 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1411 const MultiLevelTemplateArgumentList &MLTAL,
1413 assert(!isLambdaCallOperator(FD) &&
1414 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1415 "instantiations");
1416 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1417 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1419 *this, FD->getPointOfInstantiation(),
1420 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1421 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1422 SourceRange());
1423 if (Inst.isInvalid())
1424 return true;
1425
1426 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1427 // 'instantiated' parameters and adds it to the context. For the case where
1428 // this function is a template being instantiated NOW, we also need to add
1429 // the list of current template arguments to the list so that they also can
1430 // be picked out of the map.
1431 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1432 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1433 /*Final=*/false);
1434 if (addInstantiatedParametersToScope(
1435 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1436 return true;
1437 }
1438
1439 // If this is a member function, make sure we get the parameters that
1440 // reference the original primary template.
1441 if (FunctionTemplateDecl *FromMemTempl =
1442 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1443 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1444 Scope, MLTAL))
1445 return true;
1446 }
1447
1448 return false;
1449 }
1450
1453 FunctionDecl *InstantiatedFrom =
1457
1459 *this, FD->getPointOfInstantiation(),
1460 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1461 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1462 SourceRange());
1463 if (Inst.isInvalid())
1464 return true;
1465
1466 // Case where this was not a template, but instantiated as a
1467 // child-function.
1468 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1469 return true;
1470 }
1471
1472 return false;
1473}
1474
1475// This function collects all of the template arguments for the purposes of
1476// constraint-instantiation and checking.
1477std::optional<MultiLevelTemplateArgumentList>
1478Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1479 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1481 MultiLevelTemplateArgumentList MLTAL;
1482
1483 // Collect the list of template arguments relative to the 'primary' template.
1484 // We need the entire list, since the constraint is completely uninstantiated
1485 // at this point.
1486 MLTAL =
1488 /*Final=*/false, /*Innermost=*/std::nullopt,
1489 /*RelativeToPrimary=*/true,
1490 /*Pattern=*/nullptr,
1491 /*ForConstraintInstantiation=*/true);
1492 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1493 if (isLambdaCallOperator(FD))
1494 return MLTAL;
1495 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1496 return std::nullopt;
1497
1498 return MLTAL;
1499}
1500
1502 ConstraintSatisfaction &Satisfaction,
1503 SourceLocation UsageLoc,
1504 bool ForOverloadResolution) {
1505 // Don't check constraints if the function is dependent. Also don't check if
1506 // this is a function template specialization, as the call to
1507 // CheckFunctionTemplateConstraints after this will check it
1508 // better.
1509 if (FD->isDependentContext() ||
1510 FD->getTemplatedKind() ==
1512 Satisfaction.IsSatisfied = true;
1513 return false;
1514 }
1515
1516 // A lambda conversion operator has the same constraints as the call operator
1517 // and constraints checking relies on whether we are in a lambda call operator
1518 // (and may refer to its parameters), so check the call operator instead.
1519 // Note that the declarations outside of the lambda should also be
1520 // considered. Turning on the 'ForOverloadResolution' flag results in the
1521 // LocalInstantiationScope not looking into its parents, but we can still
1522 // access Decls from the parents while building a lambda RAII scope later.
1523 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1524 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1525 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1526 Satisfaction, UsageLoc,
1527 /*ShouldAddDeclsFromParentScope=*/true);
1528
1529 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1530
1531 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1532 if (isLambdaCallOperator(CtxToSave))
1533 CtxToSave = CtxToSave->getParent()->getParent();
1534 else
1535 CtxToSave = CtxToSave->getNonTransparentContext();
1536 }
1537
1538 ContextRAII SavedContext{*this, CtxToSave};
1539 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1540 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1541 SetupConstraintCheckingTemplateArgumentsAndScope(
1542 const_cast<FunctionDecl *>(FD), {}, Scope);
1543
1544 if (!MLTAL)
1545 return true;
1546
1547 Qualifiers ThisQuals;
1548 CXXRecordDecl *Record = nullptr;
1549 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1550 ThisQuals = Method->getMethodQualifiers();
1551 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1552 }
1553 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1554
1556 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1557 ForOverloadResolution);
1558
1560 FD, FD->getTrailingRequiresClause(), *MLTAL,
1561 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1562 Satisfaction);
1563}
1564
1566 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
1567 const Expr *ConstrExpr) {
1569 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
1570 /*Innermost=*/std::nullopt,
1571 /*RelativeToPrimary=*/true,
1572 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
1573 /*SkipForSpecialization*/ false);
1574
1575 if (MLTAL.getNumSubstitutedLevels() == 0)
1576 return ConstrExpr;
1577
1578 // Set up a dummy 'instantiation' scope in the case of reference to function
1579 // parameters that the surrounding function hasn't been instantiated yet. Note
1580 // this may happen while we're comparing two templates' constraint
1581 // equivalence.
1582 std::optional<LocalInstantiationScope> ScopeForParameters;
1583 if (const NamedDecl *ND = DeclInfo.getDecl();
1584 ND && ND->isFunctionOrFunctionTemplate()) {
1585 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1586 const FunctionDecl *FD = ND->getAsFunction();
1588 Template && Template->getInstantiatedFromMemberTemplate())
1589 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1590 for (auto *PVD : FD->parameters()) {
1591 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1592 continue;
1593 if (!PVD->isParameterPack()) {
1594 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1595 continue;
1596 }
1597 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1598 // to avoid building SubstTemplateTypeParmPackTypes for
1599 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1600 // otherwise reference the AssociatedDecl of the template arguments, which
1601 // is, in this case, the template declaration.
1602 //
1603 // However, as we are in the process of comparing potential
1604 // re-declarations, the canonical declaration is the declaration itself at
1605 // this point. So if we didn't expand these packs, we would end up with an
1606 // incorrect profile difference because we will be profiling the
1607 // canonical types!
1608 //
1609 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1610 // that we can eliminate the Scope in the cases where the declarations are
1611 // not necessarily instantiated. It would also benefit the noexcept
1612 // specifier comparison.
1613 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1614 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1615 }
1616 }
1617
1618 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1619
1620 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1621 // essential for having an injected class as the canonical type for a template
1622 // specialization type at the rebuilding stage. This guarantees that, for
1623 // out-of-line definitions, injected class name types and their equivalent
1624 // template specializations can be profiled to the same value, which makes it
1625 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1626 // perceived identical.
1627 std::optional<Sema::ContextRAII> ContextScope;
1628 const DeclContext *DC = [&] {
1629 if (!DeclInfo.getDecl())
1630 return DeclInfo.getDeclContext();
1631 return DeclInfo.getDecl()->getFriendObjectKind()
1632 ? DeclInfo.getLexicalDeclContext()
1633 : DeclInfo.getDeclContext();
1634 }();
1635 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1636 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1637 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1638 /*NewThisContext=*/false);
1639 }
1640 EnterExpressionEvaluationContext UnevaluatedContext(
1644 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1645 if (!SubstConstr.isUsable())
1646 return nullptr;
1647 return SubstConstr.get();
1648}
1649
1651 const Expr *OldConstr,
1653 const Expr *NewConstr) {
1654 if (OldConstr == NewConstr)
1655 return true;
1656 // C++ [temp.constr.decl]p4
1657 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1658 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1659 Sema::SFINAETrap _(*this);
1660 if (const Expr *SubstConstr =
1662 OldConstr))
1663 OldConstr = SubstConstr;
1664 else
1665 return false;
1666 if (const Expr *SubstConstr =
1668 NewConstr))
1669 NewConstr = SubstConstr;
1670 else
1671 return false;
1672 }
1673
1674 llvm::FoldingSetNodeID ID1, ID2;
1675 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1676 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1677 return ID1 == ID2;
1678}
1679
1681 assert(FD->getFriendObjectKind() && "Must be a friend!");
1682
1683 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1684 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1685 // non-function-template.
1686 assert(FD->getDescribedFunctionTemplate() &&
1687 "Non-function templates don't need to be checked");
1688
1691
1692 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1693 for (const AssociatedConstraint &AC : ACs)
1694 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1695 AC.ConstraintExpr))
1696 return true;
1697
1698 return false;
1699}
1700
1702 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1703 SourceRange TemplateIDRange) {
1704 ConstraintSatisfaction Satisfaction;
1705 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1706 TD->getAssociatedConstraints(AssociatedConstraints);
1707 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1708 TemplateIDRange, Satisfaction))
1709 return true;
1710
1711 if (!Satisfaction.IsSatisfied) {
1712 SmallString<128> TemplateArgString;
1713 TemplateArgString = " ";
1714 TemplateArgString += getTemplateArgumentBindingsText(
1715 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1716 TemplateArgsLists.getInnermost().size());
1717
1718 Diag(TemplateIDRange.getBegin(),
1719 diag::err_template_arg_list_constraints_not_satisfied)
1721 << TemplateArgString << TemplateIDRange;
1722 DiagnoseUnsatisfiedConstraint(Satisfaction);
1723 return true;
1724 }
1725 return false;
1726}
1727
1729 Sema &SemaRef, SourceLocation PointOfInstantiation,
1731 ConstraintSatisfaction &Satisfaction) {
1733 Template->getAssociatedConstraints(TemplateAC);
1734 if (TemplateAC.empty()) {
1735 Satisfaction.IsSatisfied = true;
1736 return false;
1737 }
1738
1740
1741 FunctionDecl *FD = Template->getTemplatedDecl();
1742 // Collect the list of template arguments relative to the 'primary'
1743 // template. We need the entire list, since the constraint is completely
1744 // uninstantiated at this point.
1745
1747 {
1748 // getTemplateInstantiationArgs uses this instantiation context to find out
1749 // template arguments for uninstantiated functions.
1750 // We don't want this RAII object to persist, because there would be
1751 // otherwise duplicate diagnostic notes.
1753 SemaRef, PointOfInstantiation,
1755 PointOfInstantiation);
1756 if (Inst.isInvalid())
1757 return true;
1758 MLTAL = SemaRef.getTemplateInstantiationArgs(
1759 /*D=*/FD, FD,
1760 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1761 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1762 }
1763
1764 Sema::ContextRAII SavedContext(SemaRef, FD);
1765 return SemaRef.CheckConstraintSatisfaction(
1766 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1767}
1768
1770 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1771 ArrayRef<TemplateArgument> TemplateArgs,
1772 ConstraintSatisfaction &Satisfaction) {
1773 // In most cases we're not going to have constraints, so check for that first.
1774 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1775
1776 if (!Template)
1777 return ::CheckFunctionConstraintsWithoutInstantiation(
1778 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1779 TemplateArgs, Satisfaction);
1780
1781 // Note - code synthesis context for the constraints check is created
1782 // inside CheckConstraintsSatisfaction.
1784 Template->getAssociatedConstraints(TemplateAC);
1785 if (TemplateAC.empty()) {
1786 Satisfaction.IsSatisfied = true;
1787 return false;
1788 }
1789
1790 // Enter the scope of this instantiation. We don't use
1791 // PushDeclContext because we don't have a scope.
1792 Sema::ContextRAII savedContext(*this, Decl);
1794
1795 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1796 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1797 Scope);
1798
1799 if (!MLTAL)
1800 return true;
1801
1802 Qualifiers ThisQuals;
1803 CXXRecordDecl *Record = nullptr;
1804 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1805 ThisQuals = Method->getMethodQualifiers();
1806 Record = Method->getParent();
1807 }
1808
1809 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1810 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1811 Scope);
1812
1813 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1814 PointOfInstantiation, Satisfaction);
1815}
1816
1819 bool First) {
1820 assert(!Req->isSatisfied() &&
1821 "Diagnose() can only be used on an unsatisfied requirement");
1822 switch (Req->getSatisfactionStatus()) {
1824 llvm_unreachable("Diagnosing a dependent requirement");
1825 break;
1827 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1828 if (!SubstDiag->DiagMessage.empty())
1829 S.Diag(SubstDiag->DiagLoc,
1830 diag::note_expr_requirement_expr_substitution_error)
1831 << (int)First << SubstDiag->SubstitutedEntity
1832 << SubstDiag->DiagMessage;
1833 else
1834 S.Diag(SubstDiag->DiagLoc,
1835 diag::note_expr_requirement_expr_unknown_substitution_error)
1836 << (int)First << SubstDiag->SubstitutedEntity;
1837 break;
1838 }
1840 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1841 << (int)First << Req->getExpr();
1842 break;
1844 auto *SubstDiag =
1846 if (!SubstDiag->DiagMessage.empty())
1847 S.Diag(SubstDiag->DiagLoc,
1848 diag::note_expr_requirement_type_requirement_substitution_error)
1849 << (int)First << SubstDiag->SubstitutedEntity
1850 << SubstDiag->DiagMessage;
1851 else
1852 S.Diag(
1853 SubstDiag->DiagLoc,
1854 diag::
1855 note_expr_requirement_type_requirement_unknown_substitution_error)
1856 << (int)First << SubstDiag->SubstitutedEntity;
1857 break;
1858 }
1860 ConceptSpecializationExpr *ConstraintExpr =
1862 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1863 break;
1864 }
1866 llvm_unreachable("We checked this above");
1867 }
1868}
1869
1872 bool First) {
1873 assert(!Req->isSatisfied() &&
1874 "Diagnose() can only be used on an unsatisfied requirement");
1875 switch (Req->getSatisfactionStatus()) {
1877 llvm_unreachable("Diagnosing a dependent requirement");
1878 return;
1880 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1881 if (!SubstDiag->DiagMessage.empty())
1882 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1883 << (int)First << SubstDiag->SubstitutedEntity
1884 << SubstDiag->DiagMessage;
1885 else
1886 S.Diag(SubstDiag->DiagLoc,
1887 diag::note_type_requirement_unknown_substitution_error)
1888 << (int)First << SubstDiag->SubstitutedEntity;
1889 return;
1890 }
1891 default:
1892 llvm_unreachable("Unknown satisfaction status");
1893 return;
1894 }
1895}
1896
1899 SourceLocation Loc, bool First) {
1900 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1901 S.Diag(
1902 Loc,
1903 diag::
1904 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1905 << (int)First
1906 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1907 << Concept->getNamedConcept();
1908 } else {
1909 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1910 << (int)First << Concept;
1911 }
1912}
1913
1916 bool First, concepts::NestedRequirement *Req = nullptr);
1917
1920 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1921 for (auto &Record : Records) {
1923 Loc = {};
1925 }
1926}
1927
1937
1939 const Expr *SubstExpr,
1940 bool First) {
1941 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1942 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1943 switch (BO->getOpcode()) {
1944 // These two cases will in practice only be reached when using fold
1945 // expressions with || and &&, since otherwise the || and && will have been
1946 // broken down into atomic constraints during satisfaction checking.
1947 case BO_LOr:
1948 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1951 /*First=*/false);
1952 return;
1953 case BO_LAnd: {
1954 bool LHSSatisfied =
1955 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1956 if (LHSSatisfied) {
1957 // LHS is true, so RHS must be false.
1959 return;
1960 }
1961 // LHS is false
1963
1964 // RHS might also be false
1965 bool RHSSatisfied =
1966 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1967 if (!RHSSatisfied)
1969 /*First=*/false);
1970 return;
1971 }
1972 case BO_GE:
1973 case BO_LE:
1974 case BO_GT:
1975 case BO_LT:
1976 case BO_EQ:
1977 case BO_NE:
1978 if (BO->getLHS()->getType()->isIntegerType() &&
1979 BO->getRHS()->getType()->isIntegerType()) {
1980 Expr::EvalResult SimplifiedLHS;
1981 Expr::EvalResult SimplifiedRHS;
1982 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1984 /*InConstantContext=*/true);
1985 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1987 /*InConstantContext=*/true);
1988 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1989 S.Diag(SubstExpr->getBeginLoc(),
1990 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1991 << (int)First << SubstExpr
1992 << toString(SimplifiedLHS.Val.getInt(), 10)
1993 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1994 << toString(SimplifiedRHS.Val.getInt(), 10);
1995 return;
1996 }
1997 }
1998 break;
1999
2000 default:
2001 break;
2002 }
2003 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
2004 // FIXME: RequiresExpr should store dependent diagnostics.
2005 for (concepts::Requirement *Req : RE->getRequirements())
2006 if (!Req->isDependent() && !Req->isSatisfied()) {
2007 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2009 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
2011 else
2014 break;
2015 }
2016 return;
2017 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
2018 // Drill down concept ids treated as atomic constraints
2020 return;
2021 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
2022 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
2023 assert(TTE->getNumArgs() == 2);
2024 S.Diag(SubstExpr->getSourceRange().getBegin(),
2025 diag::note_is_deducible_constraint_evaluated_to_false)
2026 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2027 return;
2028 }
2029
2030 S.Diag(SubstExpr->getSourceRange().getBegin(),
2031 diag::note_atomic_constraint_evaluated_to_false)
2032 << (int)First << SubstExpr;
2033 S.DiagnoseTypeTraitDetails(SubstExpr);
2034}
2035
2039 if (auto *Diag =
2040 Record
2041 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
2042 if (Req)
2043 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
2044 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
2045 else
2046 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2047 << Diag->second;
2048 return;
2049 }
2050 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
2051 if (Loc.isInvalid())
2052 Loc = Concept->getBeginLoc();
2054 return;
2055 }
2058}
2059
2061 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
2062 bool First) {
2063
2064 assert(!Satisfaction.IsSatisfied &&
2065 "Attempted to diagnose a satisfied constraint");
2066 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
2067}
2068
2070 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
2071
2072 const ASTConstraintSatisfaction &Satisfaction =
2073 ConstraintExpr->getSatisfaction();
2074
2075 assert(!Satisfaction.IsSatisfied &&
2076 "Attempted to diagnose a satisfied constraint");
2077
2078 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
2079 ConstraintExpr->getBeginLoc(), First);
2080}
2081
2082namespace {
2083
2084class SubstituteParameterMappings {
2085 Sema &SemaRef;
2086
2087 const MultiLevelTemplateArgumentList *MLTAL;
2088 const ASTTemplateArgumentListInfo *ArgsAsWritten;
2089
2090 // When normalizing a fold constraint, e.g.
2091 // C<Pack1, Pack2...> && ...
2092 // we want the TreeTransform to expand only Pack2 but not Pack1,
2093 // since Pack1 will be expanded during the evaluation of the fold expression.
2094 // This flag helps rewrite any non-PackExpansion packs into "expanded"
2095 // parameters.
2096 bool RemovePacksForFoldExpr;
2097
2098 SubstituteParameterMappings(Sema &SemaRef,
2099 const MultiLevelTemplateArgumentList *MLTAL,
2100 const ASTTemplateArgumentListInfo *ArgsAsWritten,
2101 bool RemovePacksForFoldExpr)
2102 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2103 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2104
2105 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
2106
2107 bool substitute(NormalizedConstraintWithParamMapping &N);
2108
2109 bool substitute(ConceptIdConstraint &CC);
2110
2111public:
2112 SubstituteParameterMappings(Sema &SemaRef,
2113 bool RemovePacksForFoldExpr = false)
2114 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
2115 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2116
2117 bool substitute(NormalizedConstraint &N);
2118};
2119
2120void SubstituteParameterMappings::buildParameterMapping(
2122 TemplateParameterList *TemplateParams =
2123 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
2124
2125 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2126 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2127
2130 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2131 /*OnlyDeduced=*/false,
2132 /*Depth=*/0, OccurringIndices);
2133
2135 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2136 /*Depth=*/0, OccurringIndicesForSubsumption);
2137
2138 } else if (N.getKind() ==
2141 static_cast<FoldExpandedConstraint &>(N).getPattern(),
2142 /*OnlyDeduced=*/false,
2143 /*Depth=*/0, OccurringIndices);
2145 auto *Args = static_cast<ConceptIdConstraint &>(N)
2146 .getConceptId()
2147 ->getTemplateArgsAsWritten();
2148 if (Args)
2149 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2150 /*Depth=*/0, OccurringIndices);
2151 }
2152
2153 // If a parameter is only referenced in a default template argument,
2154 // we need to add it to the mapping explicitly.
2155 {
2157 for (unsigned I = TemplateParams->getMinRequiredArguments();
2158 I < TemplateParams->size(); ++I) {
2159 const NamedDecl *Param = TemplateParams->getParam(I);
2160 if (Param->isParameterPack())
2161 break;
2162 const TemplateArgument *Arg =
2164 assert(Arg && "expected a default argument");
2165 DefaultArgs.emplace_back(std::move(*Arg));
2166 }
2167 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0,
2168 OccurringIndices);
2169 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0,
2170 OccurringIndicesForSubsumption);
2171 }
2172
2173 unsigned Size = OccurringIndices.count();
2174 // When the constraint is independent of any template parameters,
2175 // we build an empty mapping so that we can distinguish these cases
2176 // from cases where no mapping exists at all, e.g. when there are only atomic
2177 // constraints.
2178 TemplateArgumentLoc *TempArgs =
2179 new (SemaRef.Context) TemplateArgumentLoc[Size];
2181 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2182 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2183 ? ArgsAsWritten->arguments()[I].getLocation()
2184 : SourceLocation();
2185 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
2186 // can't assert Loc.isValid() now.
2187 if (OccurringIndices[I]) {
2188 NamedDecl *Param = TemplateParams->begin()[I];
2189 new (&(TempArgs)[J]) TemplateArgumentLoc(
2190 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2191 UsedParams.push_back(Param);
2192 J++;
2193 }
2194 }
2195 auto *UsedList = TemplateParameterList::Create(
2196 SemaRef.Context, TemplateParams->getTemplateLoc(),
2197 TemplateParams->getLAngleLoc(), UsedParams,
2198 /*RAngleLoc=*/SourceLocation(),
2199 /*RequiresClause=*/nullptr);
2201 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2202 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
2203}
2204
2205bool SubstituteParameterMappings::substitute(
2207 if (!N.hasParameterMapping())
2208 buildParameterMapping(N);
2209
2210 // If the parameter mapping is empty, there is nothing to substitute.
2211 if (N.getParameterMapping().empty())
2212 return false;
2213
2214 SourceLocation InstLocBegin, InstLocEnd;
2215 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2216 if (Arguments.empty()) {
2217 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2218 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2219 } else {
2220 auto SR = Arguments[0].getSourceRange();
2221 InstLocBegin = SR.getBegin();
2222 InstLocEnd = SR.getEnd();
2223 }
2224 Sema::NonSFINAEContext _(SemaRef);
2226 SemaRef, InstLocBegin,
2228 const_cast<NamedDecl *>(N.getConstraintDecl()),
2229 {InstLocBegin, InstLocEnd});
2230 if (Inst.isInvalid())
2231 return true;
2232
2233 // TransformTemplateArguments is unable to preserve the source location of a
2234 // pack. The SourceLocation is necessary for the instantiation location.
2235 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2236 // which is wrong.
2237 TemplateArgumentListInfo SubstArgs;
2239 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2241 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs))
2242 return true;
2244 auto *TD =
2247 TD->getLocation(), SubstArgs,
2248 /*DefaultArguments=*/{},
2249 /*PartialTemplateArgs=*/false, CTAI))
2250 return true;
2251
2252 TemplateArgumentLoc *TempArgs =
2253 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2254
2255 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2256 SourceLocation Loc;
2257 // If this is an empty pack, we have no corresponding SubstArgs.
2258 if (I < SubstArgs.size())
2259 Loc = SubstArgs.arguments()[I].getLocation();
2260
2261 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2262 CTAI.SugaredConverted[I], QualType(), Loc);
2263 }
2264
2265 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2266 CTAI.SugaredConverted.size());
2270 return false;
2271}
2272
2273bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2274 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2275
2276 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2277 return true;
2278
2279 auto *CSE = CC.getConceptSpecializationExpr();
2280 assert(CSE);
2281 assert(!CC.getBeginLoc().isInvalid());
2282
2283 SourceLocation InstLocBegin, InstLocEnd;
2284 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2285 Arguments.empty()) {
2286 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2287 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2288 } else {
2289 auto SR = Arguments[0].getSourceRange();
2290 InstLocBegin = SR.getBegin();
2291 InstLocEnd = SR.getEnd();
2292 }
2293 Sema::NonSFINAEContext _(SemaRef);
2294 // This is useful for name lookup across modules; see Sema::getLookupModules.
2296 SemaRef, InstLocBegin,
2298 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2299 {InstLocBegin, InstLocEnd});
2300 if (Inst.isInvalid())
2301 return true;
2302
2304 // TransformTemplateArguments is unable to preserve the source location of a
2305 // pack. The SourceLocation is necessary for the instantiation location.
2306 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2307 // which is wrong.
2309 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2310 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2311 CSE->getTemplateArgsAsWritten();
2313 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out))
2314 return true;
2316 if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(),
2317 CSE->getConceptNameInfo().getLoc(), Out,
2318 /*DefaultArgs=*/{},
2319 /*PartialTemplateArgs=*/false, CTAI,
2320 /*UpdateArgsWithConversions=*/false))
2321 return true;
2322 auto TemplateArgs = *MLTAL;
2323 TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(),
2324 CTAI.SugaredConverted);
2325 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2326 RemovePacksForFoldExpr)
2327 .substitute(CC.getNormalizedConstraint());
2328}
2329
2330bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2331 switch (N.getKind()) {
2333 if (!MLTAL) {
2334 assert(!ArgsAsWritten);
2335 return false;
2336 }
2337 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2338 }
2340 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2341 if (!MLTAL) {
2342 llvm::SaveAndRestore _1(RemovePacksForFoldExpr, true);
2343 assert(!ArgsAsWritten);
2344 return substitute(FE.getNormalizedPattern());
2345 }
2346 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2347 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2348 return SubstituteParameterMappings(SemaRef, /*RemovePacksForFoldExpr=*/true)
2349 .substitute(FE.getNormalizedPattern());
2350 }
2352 auto &CC = static_cast<ConceptIdConstraint &>(N);
2353 if (MLTAL) {
2354 assert(ArgsAsWritten);
2355 return substitute(CC);
2356 }
2357 assert(!ArgsAsWritten);
2359 // Make sure that lambdas within template arguments live in a
2360 // dependent context such that they are assured to be transformed during
2361 // constraint evaluation.
2364 /*LambdaContextDecl=*/
2366 CSE->getSpecializationDecl()));
2369 if (RemovePacksForFoldExpr) {
2371 ArrayRef<TemplateArgumentLoc> InputArgLoc =
2373 if (AdjustConstraints(SemaRef, /*TemplateDepth=*/0,
2374 /*RemoveNonPackExpansionPacks=*/true)
2375 .TransformTemplateArguments(InputArgLoc.begin(),
2376 InputArgLoc.end(), OutArgs))
2377 return true;
2379 // Repack the packs.
2380 if (SemaRef.CheckTemplateArgumentList(
2381 Concept, Concept->getTemplateParameters(), Concept->getBeginLoc(),
2382 OutArgs,
2383 /*DefaultArguments=*/{},
2384 /*PartialTemplateArgs=*/false, CTAI))
2385 return true;
2386 InnerArgs = std::move(CTAI.SugaredConverted);
2387 }
2388
2390 Concept, Concept->getLexicalDeclContext(),
2391 /*Final=*/true, InnerArgs,
2392 /*RelativeToPrimary=*/true,
2393 /*Pattern=*/nullptr,
2394 /*ForConstraintInstantiation=*/true);
2395 MLTAL.setRetainInnerDepths();
2396
2397 return SubstituteParameterMappings(SemaRef, &MLTAL,
2399 RemovePacksForFoldExpr)
2400 .substitute(CC.getNormalizedConstraint());
2401 }
2403 auto &Compound = static_cast<CompoundConstraint &>(N);
2404 if (substitute(Compound.getLHS()))
2405 return true;
2406 return substitute(Compound.getRHS());
2407 }
2408 }
2409 llvm_unreachable("Unknown ConstraintKind enum");
2410}
2411
2412} // namespace
2413
2414NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2415 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2416 assert(ACs.size() != 0);
2417 auto *Conjunction =
2418 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2419 if (!Conjunction)
2420 return nullptr;
2421 for (unsigned I = 1; I < ACs.size(); ++I) {
2422 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2423 ACs[I].ArgPackSubstIndex);
2424 if (!Next)
2425 return nullptr;
2427 Conjunction, Next);
2428 }
2429 return Conjunction;
2430}
2431
2432NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2433 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2434 assert(E != nullptr);
2435
2436 // C++ [temp.constr.normal]p1.1
2437 // [...]
2438 // - The normal form of an expression (E) is the normal form of E.
2439 // [...]
2440 E = E->IgnoreParenImpCasts();
2441
2442 llvm::FoldingSetNodeID ID;
2443 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2444 return nullptr;
2445 }
2446 SatisfactionStackRAII StackRAII(S, D, ID);
2447
2448 // C++2a [temp.param]p4:
2449 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2450 // Fold expression is considered atomic constraints per current wording.
2451 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2452
2453 if (LogicalBinOp BO = E) {
2454 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2455 if (!LHS)
2456 return nullptr;
2457 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2458 if (!RHS)
2459 return nullptr;
2460
2462 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2463 }
2464 if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2465 // C++ [temp.constr.normal]p1.1
2466 // [...]
2467 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2468 // where C names a concept, is the normal form of the
2469 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2470 // respective template parameters in the parameter mappings in each atomic
2471 // constraint. If any such substitution results in an invalid type or
2472 // expression, the program is ill-formed; no diagnostic is required.
2473 // [...]
2474 NormalizedConstraint *SubNF;
2475 if (ExprResult Res =
2476 SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);
2477 Res.isUsable())
2478 // Use canonical declarations to merge ConceptDecls across different
2479 // modules.
2480 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2481 S, CSE->getNamedConcept()->getCanonicalDecl(),
2482 AssociatedConstraint(Res.get(), SubstIndex));
2483 else
2484 return nullptr;
2486 CSE->getConceptReference(), SubNF, D,
2487 CSE, SubstIndex);
2488 }
2489 if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2490 FE && S.getLangOpts().CPlusPlus26 &&
2491 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2492 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2493
2494 // Normalize fold expressions in C++26.
2495
2497 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2500
2501 if (FE->getInit()) {
2502 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2503 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2504 if (!LHS || !RHS)
2505 return nullptr;
2506
2507 if (FE->isRightFold())
2509 FE->getPattern(), D, Kind, LHS);
2510 else
2512 FE->getPattern(), D, Kind, RHS);
2513
2515 S.getASTContext(), LHS,
2516 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2517 : CCK_Disjunction),
2518 RHS);
2519 }
2520 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2521 if (!Sub)
2522 return nullptr;
2524 D, Kind, Sub);
2525 }
2526 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2527}
2528
2530 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2531 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2532 if (!ConstrainedDeclOrNestedReq) {
2533 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2534 *this, nullptr, AssociatedConstraints);
2535 if (!Normalized ||
2536 SubstituteParameterMappings(*this).substitute(*Normalized))
2537 return nullptr;
2538
2539 return Normalized;
2540 }
2541
2542 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2543 const NamedDecl *ND =
2544 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2545 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2546 if (CacheEntry == NormalizationCache.end()) {
2547 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2548 *this, ND, AssociatedConstraints);
2549 if (!Normalized) {
2550 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);
2551 return nullptr;
2552 }
2553 // substitute() can invalidate iterators of NormalizationCache.
2554 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2555 CacheEntry =
2556 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2557 .first;
2558 if (Failed)
2559 return nullptr;
2560 }
2561 return CacheEntry->second;
2562}
2563
2566
2567 // [C++26] [temp.constr.fold]
2568 // Two fold expanded constraints are compatible for subsumption
2569 // if their respective constraints both contain an equivalent unexpanded pack.
2570
2573 APacks);
2575 BPacks);
2576
2577 for (const UnexpandedParameterPack &APack : APacks) {
2578 auto ADI = getDepthAndIndex(APack);
2579 if (!ADI)
2580 continue;
2581 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2582 return getDepthAndIndex(BPack) == ADI;
2583 });
2584 if (It != BPacks.end())
2585 return true;
2586 }
2587 return false;
2588}
2589
2592 const NamedDecl *D2,
2594 bool &Result) {
2595#ifndef NDEBUG
2596 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2597 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2599 return Kind == FunctionDecl::TK_NonTemplate ||
2601 };
2602 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2603 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2604 "use non-instantiated function declaration for constraints partial "
2605 "ordering");
2606 }
2607#endif
2608
2609 if (AC1.empty()) {
2610 Result = AC2.empty();
2611 return false;
2612 }
2613 if (AC2.empty()) {
2614 // TD1 has associated constraints and TD2 does not.
2615 Result = true;
2616 return false;
2617 }
2618
2619 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2620 auto CacheEntry = SubsumptionCache.find(Key);
2621 if (CacheEntry != SubsumptionCache.end()) {
2622 Result = CacheEntry->second;
2623 return false;
2624 }
2625
2626 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
2627 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
2628
2629 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2630 if (Depth2 > Depth1) {
2631 AC1[I].ConstraintExpr =
2632 AdjustConstraints(*this, Depth2 - Depth1)
2633 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2634 .get();
2635 } else if (Depth1 > Depth2) {
2636 AC2[I].ConstraintExpr =
2637 AdjustConstraints(*this, Depth1 - Depth2)
2638 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2639 .get();
2640 }
2641 }
2642
2643 SubsumptionChecker SC(*this);
2644 // Associated declarations are used as a cache key in the event they were
2645 // normalized earlier during concept checking. However we cannot reuse these
2646 // cached results if any of the template depths have been adjusted.
2647 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2648 if (Depth2 > Depth1)
2649 DeclAC1 = nullptr;
2650 else if (Depth1 > Depth2)
2651 DeclAC2 = nullptr;
2652 std::optional<bool> Subsumes = SC.Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2653 if (!Subsumes) {
2654 // Normalization failed
2655 return true;
2656 }
2657 Result = *Subsumes;
2658 SubsumptionCache.try_emplace(Key, *Subsumes);
2659 return false;
2660}
2661
2665 if (isSFINAEContext())
2666 // No need to work here because our notes would be discarded.
2667 return false;
2668
2669 if (AC1.empty() || AC2.empty())
2670 return false;
2671
2672 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2673 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2674 const AtomicConstraint &B) {
2676 return false;
2677 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2678 if (EA == EB)
2679 return true;
2680
2681 // Not the same source level expression - are the expressions
2682 // identical?
2683 llvm::FoldingSetNodeID IDA, IDB;
2684 EA->Profile(IDA, Context, /*Canonical=*/true);
2685 EB->Profile(IDB, Context, /*Canonical=*/true);
2686 if (IDA != IDB)
2687 return false;
2688
2689 AmbiguousAtomic1 = EA;
2690 AmbiguousAtomic2 = EB;
2691 return true;
2692 };
2693
2694 {
2695 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2696 if (!Normalized1)
2697 return false;
2698
2699 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2700 if (!Normalized2)
2701 return false;
2702
2703 SubsumptionChecker SC(*this);
2704
2705 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2706 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2707
2708 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2709 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2710 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2711
2712 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2713 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2714 // Same result - no ambiguity was caused by identical atomic expressions.
2715 return false;
2716 }
2717 // A different result! Some ambiguous atomic constraint(s) caused a difference
2718 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2719
2720 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2721 << AmbiguousAtomic1->getSourceRange();
2722 Diag(AmbiguousAtomic2->getBeginLoc(),
2723 diag::note_ambiguous_atomic_constraints_similar_expression)
2724 << AmbiguousAtomic2->getSourceRange();
2725 return true;
2726}
2727
2728//
2729//
2730// ------------------------ Subsumption -----------------------------------
2731//
2732//
2734 SubsumptionCallable Callable)
2735 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2736
2737uint16_t SubsumptionChecker::getNewLiteralId() {
2738 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2739 "too many constraints!");
2740 return NextID++;
2741}
2742
2743auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2744 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2745 // C++ [temp.constr.order] p2
2746 // - an atomic constraint A subsumes another atomic constraint B
2747 // if and only if the A and B are identical [...]
2748 //
2749 // C++ [temp.constr.atomic] p2
2750 // Two atomic constraints are identical if they are formed from the
2751 // same expression and the targets of the parameter mappings are
2752 // equivalent according to the rules for expressions [...]
2753
2754 // Because subsumption of atomic constraints is an identity
2755 // relationship that does not require further analysis
2756 // We cache the results such that if an atomic constraint literal
2757 // subsumes another, their literal will be the same
2758
2759 llvm::FoldingSetNodeID ID;
2760 ID.AddBoolean(Ori->hasParameterMapping());
2761 if (Ori->hasParameterMapping()) {
2762 const auto &Mapping = Ori->getParameterMapping();
2764 Ori->mappingOccurenceListForSubsumption();
2765 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2766 if (Indexes[Idx])
2767 SemaRef.getASTContext()
2768 .getCanonicalTemplateArgument(TAL.getArgument())
2769 .Profile(ID, SemaRef.getASTContext());
2770 }
2771 }
2772 auto It = Elems.find(ID);
2773 if (It == Elems.end()) {
2774 It = Elems
2775 .insert({ID,
2776 MappedAtomicConstraint{
2777 Ori, {getNewLiteralId(), Literal::Atomic}}})
2778 .first;
2779 ReverseMap[It->second.ID.Value] = Ori;
2780 }
2781 return It->getSecond().ID;
2782}
2783
2784auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2785 auto &Elems = FoldMap[Ori->getPattern()];
2786
2787 FoldExpendedConstraintKey K;
2788 K.Kind = Ori->getFoldOperator();
2789
2790 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2791 return K.Kind == Other.Kind;
2792 });
2793 if (It == Elems.end()) {
2794 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2795 It = Elems.insert(Elems.end(), std::move(K));
2796 ReverseMap[It->ID.Value] = Ori;
2797 }
2798 return It->ID;
2799}
2800
2801auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2802 return SubsumptionChecker::Normalize<CNFFormula>(C);
2803}
2804auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2805 return SubsumptionChecker::Normalize<DNFFormula>(C);
2806}
2807
2808///
2809/// \brief SubsumptionChecker::Normalize
2810///
2811/// Normalize a formula to Conjunctive Normal Form or
2812/// Disjunctive normal form.
2813///
2814/// Each Atomic (and Fold Expanded) constraint gets represented by
2815/// a single id to reduce space.
2816///
2817/// To minimize risks of exponential blow up, if two atomic
2818/// constraints subsumes each other (same constraint and mapping),
2819/// they are represented by the same literal.
2820///
2821template <typename FormulaType>
2822FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2823 FormulaType Res;
2824
2825 auto Add = [&, this](Clause C) {
2826 // Sort each clause and remove duplicates for faster comparisons.
2827 llvm::sort(C);
2828 C.erase(llvm::unique(C), C.end());
2829 AddUniqueClauseToFormula(Res, std::move(C));
2830 };
2831
2832 switch (NC.getKind()) {
2834 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2835
2837 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2838
2840 return Normalize<FormulaType>(
2841 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2842
2844 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2845 FormulaType Left, Right;
2846 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2847 Left = Normalize<FormulaType>(Compound.getLHS());
2848 Right = Normalize<FormulaType>(Compound.getRHS());
2849 });
2850
2851 if (Compound.getCompoundKind() == FormulaType::Kind) {
2852 unsigned SizeLeft = Left.size();
2853 Res = std::move(Left);
2854 Res.reserve(SizeLeft + Right.size());
2855 std::for_each(std::make_move_iterator(Right.begin()),
2856 std::make_move_iterator(Right.end()), Add);
2857 return Res;
2858 }
2859
2860 Res.reserve(Left.size() * Right.size());
2861 for (const auto &LTransform : Left) {
2862 for (const auto &RTransform : Right) {
2863 Clause Combined;
2864 Combined.reserve(LTransform.size() + RTransform.size());
2865 llvm::copy(LTransform, std::back_inserter(Combined));
2866 llvm::copy(RTransform, std::back_inserter(Combined));
2867 Add(std::move(Combined));
2868 }
2869 }
2870 return Res;
2871 }
2872 }
2873 llvm_unreachable("Unknown ConstraintKind enum");
2874}
2875
2876void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2877 for (auto &Other : F) {
2878 if (llvm::equal(C, Other))
2879 return;
2880 }
2881 F.push_back(C);
2882}
2883
2885 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2887 const NormalizedConstraint *PNormalized =
2888 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2889 if (!PNormalized)
2890 return std::nullopt;
2891
2892 const NormalizedConstraint *QNormalized =
2893 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2894 if (!QNormalized)
2895 return std::nullopt;
2896
2897 return Subsumes(PNormalized, QNormalized);
2898}
2899
2901 const NormalizedConstraint *Q) {
2902
2903 DNFFormula DNFP = DNF(*P);
2904 CNFFormula CNFQ = CNF(*Q);
2905 return Subsumes(DNFP, CNFQ);
2906}
2907
2908bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2909 const CNFFormula &QCNF) {
2910 for (const auto &Pi : PDNF) {
2911 for (const auto &Qj : QCNF) {
2912 // C++ [temp.constr.order] p2
2913 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2914 // and only if there exists an atomic constraint Pia in Pi for which
2915 // there exists an atomic constraint, Qjb, in Qj such that Pia
2916 // subsumes Qjb.
2917 if (!DNFSubsumes(Pi, Qj))
2918 return false;
2919 }
2920 }
2921 return true;
2922}
2923
2924bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2925
2926 return llvm::any_of(P, [&](Literal LP) {
2927 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2928 });
2929}
2930
2932 const FoldExpandedConstraint *B) {
2933 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2934 A, B};
2935
2936 auto It = FoldSubsumptionCache.find(Key);
2937 if (It == FoldSubsumptionCache.end()) {
2938 // C++ [temp.constr.order]
2939 // a fold expanded constraint A subsumes another fold expanded
2940 // constraint B if they are compatible for subsumption, have the same
2941 // fold-operator, and the constraint of A subsumes that of B.
2942 bool DoesSubsume =
2943 A->getFoldOperator() == B->getFoldOperator() &&
2946 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2947 }
2948 return It->second;
2949}
2950
2951bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2952 if (A.Kind != B.Kind)
2953 return false;
2954 switch (A.Kind) {
2955 case Literal::Atomic:
2956 if (!Callable)
2957 return A.Value == B.Value;
2958 return Callable(
2959 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2960 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2961 case Literal::FoldExpanded:
2962 return Subsumes(
2963 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2964 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2965 }
2966 llvm_unreachable("unknown literal kind");
2967}
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.
Result
Implement __builtin_bit_cast and related operations.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Records Records
Definition MachO.h:40
llvm::MachO::Record Record
Definition MachO.h:31
Defines and computes precedence levels for binary/ternary operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc, bool First, concepts::NestedRequirement *Req=nullptr)
static ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)
static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)
static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, const Expr *SubstExpr, bool First)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList *MLTAL=nullptr)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId=nullptr)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)
static bool CheckFunctionConstraintsWithoutInstantiation(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
static bool PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base, const MultiLevelTemplateArgumentList &TemplateArgs, TypeSourceInfo *&Out, UnexpandedInfo &Info)
APSInt & getInt()
Definition APValue.h:511
bool isInt() const
Definition APValue.h:488
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
const TemplateArgument * getDefaultTemplateArgumentOrNone(const NamedDecl *P) const
Return the default argument of a template parameter, if one exists.
CanQualType BoolTy
llvm::StringRef backupStr(llvm::StringRef S) const
Definition ASTContext.h:890
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:6940
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:7071
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4044
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2187
StringRef getOpcodeStr() const
Definition Expr.h:4110
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:5105
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2149
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2968
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:76
void Adopt(NestedNameSpecifierLoc Other)
Adopt an existing nested-name-specifier (with source-range information).
Definition DeclSpec.cpp:103
Expr * getCallee()
Definition Expr.h:3096
arg_range arguments()
Definition Expr.h:3201
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
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptReference * getConceptReference() const
const ImplicitConceptSpecializationDecl * getSpecializationDecl() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
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:1466
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getNonTransparentContext()
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
Definition Expr.h:1480
DeclarationNameInfo getNameInfo() const
Definition Expr.h:1348
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
Definition Expr.h:1403
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:494
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
Definition Expr.h:1369
ValueDecl * getDecl()
Definition Expr.h:1344
const TemplateArgumentLoc * getTemplateArgs() const
Retrieve the template arguments provided as part of this template-id.
Definition Expr.h:1443
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1474
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
Definition DeclBase.h:1243
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition DeclBase.h:1136
bool isParameterPack() const
Whether this declaration is a parameter pack.
Definition DeclBase.cpp:266
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:935
SourceLocation getInnerLocStart() const
Return start of source range ignoring outer template declarations.
Definition Decl.h:822
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition Decl.h:855
TypeSourceInfo * getTypeSourceInfo() const
Definition Decl.h:809
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:678
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:177
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:447
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:3099
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:283
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:2029
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4171
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4512
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2814
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition Decl.cpp:4291
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4307
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4235
TemplatedKind
The kind of templated function a FunctionDecl can be.
Definition Decl.h:2034
@ TK_FunctionTemplateSpecialization
Definition Decl.h:2045
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition Decl.cpp:4122
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4195
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4143
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:2079
const TypeClass * getTypePtr() const
Definition TypeLoc.h:526
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Definition Template.h:377
Data structure that captures multiple levels of template argument lists for use in template instantia...
Definition Template.h:76
bool hasTemplateArgument(unsigned Depth, unsigned Index) const
Determine whether there is a non-NULL template argument at the given depth and index.
Definition Template.h:181
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
Definition Template.h:277
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
Definition Template.h:218
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
Definition Template.h:129
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
Definition Template.h:135
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
Definition Template.h:259
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
Definition Template.h:281
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo)
unsigned getPosition() const
Get the position of the template parameter within its parameter list.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getIndex() const
Get the index of the template parameter within its parameter list.
unsigned getDepth() const
Get the nesting depth of the template parameter.
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:8499
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:13801
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8535
A RAII object to temporarily push a declaration context.
Definition Sema.h:3532
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition Sema.h:12595
const DeclContext * getDeclContext() const
Definition Sema.h:12349
const NamedDecl * getDecl() const
Definition Sema.h:12341
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12345
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:869
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:15150
ASTContext & Context
Definition Sema.h:1310
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:938
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:941
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:15019
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:934
@ ReuseLambdaContextDecl
Definition Sema.h:7114
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:11911
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1343
llvm::DenseMap< llvm::FoldingSetNodeID, TemplateArgumentLoc > * CurrentCachedTemplateArgs
Cache the instantiation results of template parameter mappings within concepts.
Definition Sema.h:15157
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
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:939
bool isSFINAEContext() const
Definition Sema.h:13839
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13795
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14975
void PopSatisfactionStackEntry()
Definition Sema.h:14981
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:6824
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6803
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition Sema.h:14983
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:4509
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.
NamedDecl * getParam(unsigned Idx)
unsigned getMinRequiredArguments() const
Returns the minimum number of arguments needed to form a template specialization.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() const
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:1875
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2854
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:9019
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2846
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2465
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2864
bool isFunctionType() const
Definition TypeBase.h:8680
QualType desugar() const
Definition Type.cpp:4177
UnresolvedUsingTypenameDecl * getDecl() const
Definition TypeBase.h:6119
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
Definition DeclCXX.h:4095
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...
__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:436
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:407
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:152
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.
OptionalUnsigned< unsigned > UnsignedOrNone
@ 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:136
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1774
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:652
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:654
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:640
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
constexpr underlying_type toInternalRepresentation() const
SmallVector< TemplateArgument, 4 > SugaredConverted
The checked, converted argument will be added to the end of these vectors.
Definition Sema.h:12130
A stack object to be created when performing template instantiation.
Definition Sema.h:13436