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