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.
204 const NamedDecl *ND) {
205 // FIXME: This is a very expensive way to calculate this.
207 return MLTAL.getNumLevels();
208}
209
210namespace {
211class AdjustConstraints : public TreeTransform<AdjustConstraints> {
212 unsigned TemplateDepth = 0;
213
214 bool RemoveNonPackExpansionPacks = false;
215
216public:
217 using inherited = TreeTransform<AdjustConstraints>;
218 AdjustConstraints(Sema &SemaRef, unsigned TemplateDepth,
219 bool RemoveNonPackExpansionPacks = false)
220 : inherited(SemaRef), TemplateDepth(TemplateDepth),
221 RemoveNonPackExpansionPacks(RemoveNonPackExpansionPacks) {}
222
223 ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
224 UnsignedOrNone NumExpansions) {
225 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc, NumExpansions);
226 }
227
228 TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
229 SourceLocation EllipsisLoc,
230 UnsignedOrNone NumExpansions) {
231 if (!RemoveNonPackExpansionPacks)
232 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc,
233 NumExpansions);
234 return Pattern;
235 }
236
237 bool PreparePackForExpansion(TemplateArgumentLoc In, bool Uneval,
238 TemplateArgumentLoc &Out, UnexpandedInfo &Info) {
239 if (!RemoveNonPackExpansionPacks)
240 return inherited::PreparePackForExpansion(In, Uneval, Out, Info);
241 assert(In.getArgument().isPackExpansion());
242 Out = In;
243 Info.Expand = false;
244 return false;
245 }
246
247 using inherited::TransformTemplateTypeParmType;
248 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
249 TemplateTypeParmTypeLoc TL, bool) {
250 const TemplateTypeParmType *T = TL.getTypePtr();
251
252 TemplateTypeParmDecl *NewTTPDecl = nullptr;
253 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
254 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
255 TransformDecl(TL.getNameLoc(), OldTTPDecl));
256
257 QualType Result = getSema().Context.getTemplateTypeParmType(
258 T->getDepth() + TemplateDepth, T->getIndex(),
259 RemoveNonPackExpansionPacks ? false : T->isParameterPack(), NewTTPDecl);
260 TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
261 NewTL.setNameLoc(TL.getNameLoc());
262 return Result;
263 }
264
265 bool AlreadyTransformed(QualType T) {
266 if (T.isNull())
267 return true;
268
271 return false;
272 return true;
273 }
274};
275} // namespace
276
277namespace {
278
279// FIXME: Convert it to DynamicRecursiveASTVisitor
280class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
281 using inherited = RecursiveASTVisitor<HashParameterMapping>;
282 friend inherited;
283
284 Sema &SemaRef;
285 const MultiLevelTemplateArgumentList &TemplateArgs;
286 llvm::FoldingSetNodeID &ID;
287 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
288
289 UnsignedOrNone OuterPackSubstIndex;
290
291 bool shouldVisitTemplateInstantiations() const { return true; }
292
293public:
294 HashParameterMapping(Sema &SemaRef,
295 const MultiLevelTemplateArgumentList &TemplateArgs,
296 llvm::FoldingSetNodeID &ID,
297 UnsignedOrNone OuterPackSubstIndex)
298 : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),
299 OuterPackSubstIndex(OuterPackSubstIndex) {}
300
301 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
302 // A lambda expression can introduce template parameters that don't have
303 // corresponding template arguments yet.
304 if (T->getDepth() >= TemplateArgs.getNumLevels())
305 return true;
306
307 // There might not be a corresponding template argument before substituting
308 // into the parameter mapping, e.g. a sizeof... expression.
309 if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
310 return true;
311
312 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
313
314 // In concept parameter mapping for fold expressions, packs that aren't
315 // expanded in place are treated as having non-pack dependency, so that
316 // a PackExpansionType won't prevent expanding the packs outside the
317 // TreeTransform. However we still need to check the pack at this point.
318 if ((T->isParameterPack() ||
319 (T->getDecl() && T->getDecl()->isTemplateParameterPack())) &&
320 SemaRef.ArgPackSubstIndex) {
321 assert(Arg.getKind() == TemplateArgument::Pack &&
322 "Missing argument pack");
323
324 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
325 }
326
327 UsedTemplateArgs.push_back(
329 return true;
330 }
331
332 bool VisitDeclRefExpr(DeclRefExpr *E) {
333 NamedDecl *D = E->getDecl();
334 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
335 if (!NTTP)
336 return TraverseDecl(D);
337
338 if (NTTP->getDepth() >= TemplateArgs.getNumLevels())
339 return true;
340
341 if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), NTTP->getIndex()))
342 return true;
343
344 TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
345 if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
346 assert(Arg.getKind() == TemplateArgument::Pack &&
347 "Missing argument pack");
348 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
349 }
350
351 UsedTemplateArgs.push_back(
353 return true;
354 }
355
356 bool VisitTypedefType(TypedefType *TT) {
357 return inherited::TraverseType(TT->desugar());
358 }
359
360 bool TraverseDecl(Decl *D) {
361 if (auto *VD = dyn_cast<ValueDecl>(D)) {
362 if (auto *Var = dyn_cast<VarDecl>(VD))
363 TraverseStmt(Var->getInit());
364 return TraverseType(VD->getType());
365 }
366
367 return inherited::TraverseDecl(D);
368 }
369
370 bool TraverseCallExpr(CallExpr *CE) {
371 inherited::TraverseStmt(CE->getCallee());
372
373 for (Expr *Arg : CE->arguments())
374 inherited::TraverseStmt(Arg);
375
376 return true;
377 }
378
379 bool TraverseCXXThisExpr(CXXThisExpr *E) {
380 return inherited::TraverseType(E->getType());
381 }
382
383 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
384 // We don't care about TypeLocs. So traverse Types instead.
385 return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);
386 }
387
388 bool TraverseDependentNameType(const DependentNameType *T,
389 bool /*TraverseQualifier*/) {
390 return TraverseNestedNameSpecifier(T->getQualifier());
391 }
392
393 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
394 // T's parent can be dependent while T doesn't have any template arguments.
395 // We should have already traversed its qualifier.
396 // FIXME: Add an assert to catch cases where we failed to profile the
397 // concept.
398 return true;
399 }
400
401 bool TraverseUnresolvedUsingType(UnresolvedUsingType *T,
402 bool TraverseQualifier) {
403 // Sometimes the written type doesn't contain a qualifier which contains
404 // necessary template arguments, whereas the declaration does.
405 if (NestedNameSpecifier NNS = T->getDecl()->getQualifier();
406 TraverseQualifier && NNS)
407 return inherited::TraverseNestedNameSpecifier(NNS);
408 return inherited::TraverseUnresolvedUsingType(T, TraverseQualifier);
409 }
410
411 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
412 bool TraverseQualifier) {
413 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
414 }
415
416 bool TraverseTemplateArgument(const TemplateArgument &Arg) {
418 // Act as if we are fully expanding this pack, if it is a PackExpansion.
419 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
420 llvm::SaveAndRestore<UnsignedOrNone> _2(OuterPackSubstIndex,
421 std::nullopt);
422 return inherited::TraverseTemplateArgument(Arg);
423 }
424
425 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
426 return inherited::TraverseTemplateArgument(Arg);
427 }
428
429 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
430 return TraverseDecl(SOPE->getPack());
431 }
432
433 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
434 return inherited::TraverseStmt(E->getReplacement());
435 }
436
437 bool TraverseTemplateName(TemplateName Template) {
438 if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
439 Template.getAsTemplateDecl());
440 TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
441 if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
442 TTP->getPosition()))
443 return true;
444
445 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
446 if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
447 assert(Arg.getKind() == TemplateArgument::Pack &&
448 "Missing argument pack");
449 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
450 }
451 assert(!Arg.getAsTemplate().isNull() &&
452 "Null template template argument");
453 UsedTemplateArgs.push_back(
455 }
456 return inherited::TraverseTemplateName(Template);
457 }
458
459 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
460 if (!Constraint.hasParameterMapping()) {
461 for (const auto &List : TemplateArgs)
462 for (const TemplateArgument &Arg : List.Args)
464 ID, SemaRef.Context);
465 return;
466 }
467
468 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
469 Constraint.getParameterMapping();
470 for (auto &ArgLoc : Mapping) {
471 TemplateArgument Canonical =
472 SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());
473 // We don't want sugars to impede the profile of cache.
474 UsedTemplateArgs.push_back(Canonical);
475 TraverseTemplateArgument(Canonical);
476 }
477
478 for (auto &Used : UsedTemplateArgs) {
479 llvm::FoldingSetNodeID R;
480 Used.Profile(R, SemaRef.Context);
481 ID.AddNodeID(R);
482 }
483 }
484};
485
486class ConstraintSatisfactionChecker {
487 Sema &S;
488 const NamedDecl *Template;
489 SourceLocation TemplateNameLoc;
490 UnsignedOrNone PackSubstitutionIndex;
491 ConstraintSatisfaction &Satisfaction;
492 bool BuildExpression;
493
494 // The closest concept declaration when evaluating atomic constraints.
495 ConceptDecl *ParentConcept = nullptr;
496
497 // This is for TemplateInstantiator to not instantiate the same template
498 // parameter mapping many times, in order to improve substitution performance.
499 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
500 CachedTemplateArgs;
501
502private:
503 template <class Constraint>
504 UnsignedOrNone getOuterPackIndex(const Constraint &C) const {
505 return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex()
506 : PackSubstitutionIndex;
507 }
508
510 EvaluateAtomicConstraint(const Expr *AtomicExpr,
511 const MultiLevelTemplateArgumentList &MLTAL);
512
513 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
514 const FoldExpandedConstraint &FE,
515 const MultiLevelTemplateArgumentList &MLTAL);
516
517 // XXX: It is SLOW! Use it very carefully.
518 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
519 const NormalizedConstraintWithParamMapping &Constraint,
520 const MultiLevelTemplateArgumentList &MLTAL,
521 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
522
523 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
524 const MultiLevelTemplateArgumentList &MLTAL);
525
526 ExprResult Evaluate(const AtomicConstraint &Constraint,
527 const MultiLevelTemplateArgumentList &MLTAL);
528
529 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
530 const MultiLevelTemplateArgumentList &MLTAL);
531
532 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
533 const MultiLevelTemplateArgumentList &MLTAL);
534
535 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
536 const MultiLevelTemplateArgumentList &MLTAL,
537 unsigned int Size);
538
539 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
540 const MultiLevelTemplateArgumentList &MLTAL);
541
542 ExprResult Evaluate(const CompoundConstraint &Constraint,
543 const MultiLevelTemplateArgumentList &MLTAL);
544
545public:
546 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
547 SourceLocation TemplateNameLoc,
548 UnsignedOrNone PackSubstitutionIndex,
549 ConstraintSatisfaction &Satisfaction,
550 bool BuildExpression)
551 : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),
552 PackSubstitutionIndex(PackSubstitutionIndex),
553 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
554
555 ExprResult Evaluate(const NormalizedConstraint &Constraint,
556 const MultiLevelTemplateArgumentList &MLTAL);
557};
558
559StringRef allocateStringFromConceptDiagnostic(const Sema &S,
560 const PartialDiagnostic Diag) {
561 SmallString<128> DiagString;
562 DiagString = ": ";
563 Diag.EmitToString(S.getDiagnostics(), DiagString);
564 return S.getASTContext().backupStr(DiagString);
565}
566
567} // namespace
568
569ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
570 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
571 llvm::FoldingSetNodeID ID;
572 if (Template &&
574 Satisfaction.IsSatisfied = false;
575 Satisfaction.ContainsErrors = true;
576 return ExprEmpty();
577 }
578 SatisfactionStackRAII StackRAII(S, Template, ID);
579
580 // Atomic constraint - substitute arguments and check satisfaction.
581 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
582 {
583 TemplateDeductionInfo Info(TemplateNameLoc);
587 // FIXME: improve const-correctness of InstantiatingTemplate
588 const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());
589 if (Inst.isInvalid())
590 return ExprError();
591
592 // We do not want error diagnostics escaping here.
593 Sema::SFINAETrap Trap(S, Info);
594 SubstitutedExpression =
595 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
596
597 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
598 // C++2a [temp.constr.atomic]p1
599 // ...If substitution results in an invalid type or expression, the
600 // constraint is not satisfied.
601 if (!Trap.hasErrorOccurred())
602 // A non-SFINAE error has occurred as a result of this
603 // substitution.
604 return ExprError();
605
608 Info.takeSFINAEDiagnostic(SubstDiag);
609 // FIXME: This is an unfortunate consequence of there
610 // being no serialization code for PartialDiagnostics and the fact
611 // that serializing them would likely take a lot more storage than
612 // just storing them as strings. We would still like, in the
613 // future, to serialize the proper PartialDiagnostic as serializing
614 // it as a string defeats the purpose of the diagnostic mechanism.
615 Satisfaction.Details.emplace_back(
617 SubstDiag.first,
618 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
619 Satisfaction.IsSatisfied = false;
620 return ExprEmpty();
621 }
622 }
623
624 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
625 return ExprError();
626
627 // [temp.constr.atomic]p3: To determine if an atomic constraint is
628 // satisfied, the parameter mapping and template arguments are first
629 // substituted into its expression. If substitution results in an
630 // invalid type or expression, the constraint is not satisfied.
631 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
632 // and E shall be a constant expression of type bool.
633 //
634 // Perform the L to R Value conversion if necessary. We do so for all
635 // non-PRValue categories, else we fail to extend the lifetime of
636 // temporaries, and that fails the constant expression check.
637 if (!SubstitutedExpression.get()->isPRValue())
638 SubstitutedExpression = ImplicitCastExpr::Create(
639 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
640 SubstitutedExpression.get(),
641 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
642
643 return SubstitutedExpression;
644}
645
646std::optional<MultiLevelTemplateArgumentList>
647ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
648 const NormalizedConstraintWithParamMapping &Constraint,
650 llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {
651
652 if (!Constraint.hasParameterMapping()) {
653 if (MLTAL.getNumSubstitutedLevels())
654 SubstitutedOutermost.assign(MLTAL.getOutermost());
655 return MLTAL;
656 }
657
658 // The mapping is empty, meaning no template arguments are needed for
659 // evaluation.
660 if (Constraint.getParameterMapping().empty())
662
663 TemplateDeductionInfo Info(Constraint.getBeginLoc());
664 Sema::SFINAETrap Trap(S, Info);
666 S, Constraint.getBeginLoc(),
668 // FIXME: improve const-correctness of InstantiatingTemplate
669 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
670 if (Inst.isInvalid())
671 return std::nullopt;
672
673 TemplateArgumentListInfo SubstArgs;
674 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
675
676 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
677 &CachedTemplateArgs);
678
680 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
681 SubstArgs)) {
682 Satisfaction.IsSatisfied = false;
683 return std::nullopt;
684 }
685
687 auto *TD = const_cast<TemplateDecl *>(
690 TD->getLocation(), SubstArgs,
691 /*DefaultArguments=*/{},
692 /*PartialTemplateArgs=*/false, CTAI))
693 return std::nullopt;
695 Constraint.mappingOccurenceList();
696 // The empty MLTAL situation should only occur when evaluating non-dependent
697 // constraints.
698 if (MLTAL.getNumSubstitutedLevels())
699 SubstitutedOutermost =
700 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
701 unsigned Offset = 0;
702 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
704 if (Used[I])
706 CTAI.SugaredConverted[MappedIndex++]);
707 if (I < SubstitutedOutermost.size()) {
708 SubstitutedOutermost[I] = Arg;
709 Offset = I + 1;
710 } else {
711 SubstitutedOutermost.push_back(Arg);
712 Offset = SubstitutedOutermost.size();
713 }
714 }
715 if (Offset < SubstitutedOutermost.size())
716 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
717
718 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
719 SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,
720 /*Final=*/false);
721 return std::move(SubstitutedTemplateArgs);
722}
723
724ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
725 const AtomicConstraint &Constraint,
726 const MultiLevelTemplateArgumentList &MLTAL) {
727 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
728 EvaluationContext.emplace(
731
732 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
733 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
734 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
735 if (!SubstitutedArgs) {
736 Satisfaction.IsSatisfied = false;
737 return ExprEmpty();
738 }
739
740 // Make sure that concepts are not evaluated in the context they are used,
741 // i.e they should not have access to the current class object or its
742 // non-public members.
743 std::optional<Sema::ContextRAII> ConceptContext;
744 if (ParentConcept) {
745 ConceptContext.emplace(S, ParentConcept->getDeclContext());
746 // FIXME: the evaluation context should learn to track template arguments
747 // separately from a Decl.
748 EvaluationContext.emplace(
750 /*LambdaContextDecl=*/
752 S.Context, ParentConcept->getDeclContext(),
753 ParentConcept->getBeginLoc(), SubstitutedOutermost));
754 }
755
756 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
757 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
758 Constraint.getConstraintExpr(), *SubstitutedArgs);
759
760 if (SubstitutedAtomicExpr.isInvalid())
761 return ExprError();
762
763 if (SubstitutedAtomicExpr.isUnset())
764 // Evaluator has decided satisfaction without yielding an expression.
765 return ExprEmpty();
766
767 // We don't have the ability to evaluate this, since it contains a
768 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
769 // we'd potentially pick up a different overload, and cause confusing
770 // diagnostics. SO, add a failure detail that will cause us to make this
771 // overload set not viable.
772 if (SubstitutedAtomicExpr.get()->containsErrors()) {
773 Satisfaction.IsSatisfied = false;
774 Satisfaction.ContainsErrors = true;
775
776 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
777 Satisfaction.Details.emplace_back(
779 SubstitutedAtomicExpr.get()->getBeginLoc(),
780 allocateStringFromConceptDiagnostic(S, Msg)});
781 return SubstitutedAtomicExpr;
782 }
783
784 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
785 Satisfaction.IsSatisfied = true;
786 Satisfaction.ContainsErrors = false;
787 return SubstitutedAtomicExpr;
788 }
789
791 Expr::EvalResult EvalResult;
792 EvalResult.Diag = &EvaluationDiags;
793 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
794 S.Context) ||
795 !EvaluationDiags.empty()) {
796 // C++2a [temp.constr.atomic]p1
797 // ...E shall be a constant expression of type bool.
798 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
799 diag::err_non_constant_constraint_expression)
800 << SubstitutedAtomicExpr.get()->getSourceRange();
801 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
802 S.Diag(PDiag.first, PDiag.second);
803 return ExprError();
804 }
805
806 assert(EvalResult.Val.isInt() &&
807 "evaluating bool expression didn't produce int");
808 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
809 if (!Satisfaction.IsSatisfied)
810 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
811
812 return SubstitutedAtomicExpr;
813}
814
815ExprResult ConstraintSatisfactionChecker::Evaluate(
816 const AtomicConstraint &Constraint,
817 const MultiLevelTemplateArgumentList &MLTAL) {
818
819 unsigned Size = Satisfaction.Details.size();
820 llvm::FoldingSetNodeID ID;
821 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
822
823 ID.AddPointer(Constraint.getConstraintExpr());
824 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
825 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
826 .VisitConstraint(Constraint);
827
828 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
830 auto &Cached = Iter->second.Satisfaction;
831 Satisfaction.ContainsErrors = Cached.ContainsErrors;
832 Satisfaction.IsSatisfied = Cached.IsSatisfied;
833 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
834 Cached.Details.begin(), Cached.Details.end());
835 return Iter->second.SubstExpr;
836 }
837
838 ExprResult E = EvaluateSlow(Constraint, MLTAL);
839
841 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
842 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
843 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
844 Satisfaction.Details.begin() + Size,
845 Satisfaction.Details.end());
846 Cache.SubstExpr = E;
847 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
848
849 return E;
850}
851
853ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
854 const FoldExpandedConstraint &FE,
855 const MultiLevelTemplateArgumentList &MLTAL) {
856
857 Expr *Pattern = const_cast<Expr *>(FE.getPattern());
858
860 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
861 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
862 bool Expand = true;
863 bool RetainExpansion = false;
864 UnsignedOrNone NumExpansions(std::nullopt);
866 Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
867 /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
868 NumExpansions, /*Diagnose=*/false) ||
869 !Expand || RetainExpansion)
870 return std::nullopt;
871
872 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)
873 return std::nullopt;
874 return NumExpansions;
875}
876
877ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
878 const FoldExpandedConstraint &Constraint,
879 const MultiLevelTemplateArgumentList &MLTAL) {
880
881 bool Conjunction = Constraint.getFoldOperator() ==
883 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
884
885 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
886 // FIXME: Is PackSubstitutionIndex correct?
887 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
888 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
889 SubstitutionInTemplateArguments(
890 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
891 MLTAL, SubstitutedOutermost);
892 if (!SubstitutedArgs) {
893 Satisfaction.IsSatisfied = false;
894 return ExprError();
895 }
896
898 UnsignedOrNone NumExpansions =
899 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
900 if (!NumExpansions)
901 return ExprEmpty();
902
903 if (*NumExpansions == 0) {
904 Satisfaction.IsSatisfied = Conjunction;
905 return ExprEmpty();
906 }
907
908 for (unsigned I = 0; I < *NumExpansions; I++) {
909 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
910 Satisfaction.IsSatisfied = false;
911 Satisfaction.ContainsErrors = false;
913 ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,
914 UnsignedOrNone(I), Satisfaction,
915 /*BuildExpression=*/false)
916 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
917 if (BuildExpression) {
918 if (Out.isUnset() || !Expr.isUsable())
919 Out = Expr;
920 else
921 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
922 Conjunction ? BinaryOperatorKind::BO_LAnd
923 : BinaryOperatorKind::BO_LOr,
925 Constraint.getBeginLoc(),
927 }
928 if (!Conjunction && Satisfaction.IsSatisfied) {
929 Satisfaction.Details.erase(Satisfaction.Details.begin() +
930 EffectiveDetailEndIndex,
931 Satisfaction.Details.end());
932 break;
933 }
934 if (Satisfaction.IsSatisfied != Conjunction)
935 return Out;
936 }
937
938 return Out;
939}
940
941ExprResult ConstraintSatisfactionChecker::Evaluate(
942 const FoldExpandedConstraint &Constraint,
943 const MultiLevelTemplateArgumentList &MLTAL) {
944
945 llvm::FoldingSetNodeID ID;
946 ID.AddPointer(Constraint.getPattern());
947 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
948
949 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
951
952 auto &Cached = Iter->second.Satisfaction;
953 Satisfaction.ContainsErrors = Cached.ContainsErrors;
954 Satisfaction.IsSatisfied = Cached.IsSatisfied;
955 Satisfaction.Details.insert(Satisfaction.Details.end(),
956 Cached.Details.begin(), Cached.Details.end());
957 return Iter->second.SubstExpr;
958 }
959
960 unsigned Size = Satisfaction.Details.size();
961
962 ExprResult E = EvaluateSlow(Constraint, MLTAL);
964 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
965 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
966 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
967 Satisfaction.Details.begin() + Size,
968 Satisfaction.Details.end());
969 Cache.SubstExpr = E;
970 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
971 return E;
972}
973
974ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
975 const ConceptIdConstraint &Constraint,
976 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
977 const ConceptReference *ConceptId = Constraint.getConceptId();
978
979 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
980 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
981 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
982
983 if (!SubstitutedArgs) {
984 Satisfaction.IsSatisfied = false;
985 // FIXME: diagnostics?
986 return ExprError();
987 }
988
989 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
990
991 const ASTTemplateArgumentListInfo *Ori =
992 ConceptId->getTemplateArgsAsWritten();
993 TemplateDeductionInfo Info(TemplateNameLoc);
994 Sema::SFINAETrap Trap(S, Info);
997 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
998
999 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
1000 if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, OutArgs) ||
1001 Trap.hasErrorOccurred()) {
1002 Satisfaction.IsSatisfied = false;
1003 if (!Trap.hasErrorOccurred())
1004 return ExprError();
1005
1008 Info.takeSFINAEDiagnostic(SubstDiag);
1009 // FIXME: This is an unfortunate consequence of there
1010 // being no serialization code for PartialDiagnostics and the fact
1011 // that serializing them would likely take a lot more storage than
1012 // just storing them as strings. We would still like, in the
1013 // future, to serialize the proper PartialDiagnostic as serializing
1014 // it as a string defeats the purpose of the diagnostic mechanism.
1015 Satisfaction.Details.insert(
1016 Satisfaction.Details.begin() + Size,
1018 SubstDiag.first,
1019 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
1020 return ExprError();
1021 }
1022
1023 CXXScopeSpec SS;
1024 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
1025
1026 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1027 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
1028 ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs,
1029 /*DoCheckConstraintSatisfaction=*/false);
1030
1031 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
1032 return ExprError();
1033
1034 if (Size != Satisfaction.Details.size()) {
1035 Satisfaction.Details.insert(
1036 Satisfaction.Details.begin() + Size,
1038 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
1039 ->getConceptReference()));
1040 }
1041 return SubstitutedConceptId;
1042}
1043
1044ExprResult ConstraintSatisfactionChecker::Evaluate(
1045 const ConceptIdConstraint &Constraint,
1046 const MultiLevelTemplateArgumentList &MLTAL) {
1047
1048 const ConceptReference *ConceptId = Constraint.getConceptId();
1049 Sema::InstantiatingTemplate InstTemplate(
1050 S, ConceptId->getBeginLoc(),
1052 ConceptId->getNamedConcept(),
1053 // We may have empty template arguments when checking non-dependent
1054 // nested constraint expressions.
1055 // In such cases, non-SFINAE errors would have already been diagnosed
1056 // during parameter mapping substitution, so the instantiating template
1057 // arguments are less useful here.
1058 MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
1060 Constraint.getSourceRange());
1061 if (InstTemplate.isInvalid())
1062 return ExprError();
1063
1064 unsigned Size = Satisfaction.Details.size();
1065
1066 llvm::SaveAndRestore PushConceptDecl(
1067 ParentConcept, cast<ConceptDecl>(ConceptId->getNamedConcept()));
1068
1069 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
1070
1071 if (E.isInvalid()) {
1072 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1073 return E;
1074 }
1075
1076 // ConceptIdConstraint is only relevant for diagnostics,
1077 // so if the normalized constraint is satisfied, we should not
1078 // substitute into the constraint.
1079 if (Satisfaction.IsSatisfied)
1080 return E;
1081
1082 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
1083 llvm::FoldingSetNodeID ID;
1084 ID.AddPointer(Constraint.getConceptId());
1085 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
1086 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1087 .VisitConstraint(Constraint);
1088
1089 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
1091
1092 auto &Cached = Iter->second.Satisfaction;
1093 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1094 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1095 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1096 Cached.Details.begin(), Cached.Details.end());
1097 return Iter->second.SubstExpr;
1098 }
1099
1100 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1101 if (CE.isInvalid())
1102 return E;
1104 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1105 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1106 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1107 Satisfaction.Details.begin() + Size,
1108 Satisfaction.Details.end());
1109 Cache.SubstExpr = CE;
1110 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1111 return CE;
1112}
1113
1114ExprResult ConstraintSatisfactionChecker::Evaluate(
1115 const CompoundConstraint &Constraint,
1116 const MultiLevelTemplateArgumentList &MLTAL) {
1117
1118 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1119
1120 bool Conjunction =
1122
1123 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1124
1125 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1126 return LHS;
1127
1128 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
1129 !Satisfaction.ContainsErrors)
1130 return LHS;
1131
1132 Satisfaction.ContainsErrors = false;
1133 Satisfaction.IsSatisfied = false;
1134
1135 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1136
1137 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
1138 !Satisfaction.ContainsErrors)
1139 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1140 EffectiveDetailEndIndex,
1141 Satisfaction.Details.end());
1142
1143 if (!BuildExpression)
1144 return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
1145
1146 if (!LHS.isUsable())
1147 return RHS;
1148
1149 if (!RHS.isUsable())
1150 return LHS;
1151
1152 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1153 Conjunction ? BinaryOperatorKind::BO_LAnd
1154 : BinaryOperatorKind::BO_LOr,
1156 Constraint.getBeginLoc(), FPOptionsOverride{});
1157}
1158
1159ExprResult ConstraintSatisfactionChecker::Evaluate(
1160 const NormalizedConstraint &Constraint,
1161 const MultiLevelTemplateArgumentList &MLTAL) {
1162 switch (Constraint.getKind()) {
1164 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1165
1167 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1168 MLTAL);
1169
1171 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1172 MLTAL);
1173
1175 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1176 }
1177 llvm_unreachable("Unknown ConstraintKind enum");
1178}
1179
1181 Sema &S, const NamedDecl *Template,
1182 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1183 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1184 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1185 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1186
1187 if (ConvertedExpr)
1188 *ConvertedExpr = nullptr;
1189
1190 if (AssociatedConstraints.empty()) {
1191 Satisfaction.IsSatisfied = true;
1192 return false;
1193 }
1194
1195 // In the general case, we can't check satisfaction if the arguments contain
1196 // unsubstituted template parameters, even if they are purely syntactic,
1197 // because they may still turn out to be invalid after substitution.
1198 // This could be permitted in cases where this substitution will still be
1199 // attempted later and diagnosed, such as function template specializations,
1200 // but that's not the case for concept specializations.
1201 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1202 Satisfaction.IsSatisfied = true;
1203 return false;
1204 }
1205
1207 if (TemplateArgsLists.getNumLevels() != 0)
1208 Args = TemplateArgsLists.getInnermost();
1209
1210 struct SynthesisContextPair {
1213 SynthesisContextPair(Sema &S, NamedDecl *Template,
1214 ArrayRef<TemplateArgument> TemplateArgs,
1215 SourceRange InstantiationRange)
1216 : Inst(S, InstantiationRange.getBegin(),
1218 TemplateArgs, InstantiationRange),
1219 NSC(S) {}
1220 };
1221 std::optional<SynthesisContextPair> SynthesisContext;
1222 if (!TopLevelConceptId)
1223 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
1224 TemplateIDRange);
1225
1226 const NormalizedConstraint *C =
1227 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1228 if (!C) {
1229 Satisfaction.IsSatisfied = false;
1230 return true;
1231 }
1232
1233 if (TopLevelConceptId)
1234 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1235 const_cast<NormalizedConstraint *>(C),
1236 Template, /*CSE=*/nullptr,
1238
1239 ExprResult Res = ConstraintSatisfactionChecker(
1240 S, Template, TemplateIDRange.getBegin(),
1241 S.ArgPackSubstIndex, Satisfaction,
1242 /*BuildExpression=*/ConvertedExpr != nullptr)
1243 .Evaluate(*C, TemplateArgsLists);
1244
1245 if (Res.isInvalid())
1246 return true;
1247
1248 if (Res.isUsable() && ConvertedExpr)
1249 *ConvertedExpr = Res.get();
1250
1251 return false;
1252}
1253
1256 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1257 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1258 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1259 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1260 llvm::TimeTraceScope TimeScope(
1261 "CheckConstraintSatisfaction", [TemplateIDRange, this] {
1262 return TemplateIDRange.printToString(getSourceManager());
1263 });
1264 if (AssociatedConstraints.empty()) {
1265 OutSatisfaction.IsSatisfied = true;
1266 return false;
1267 }
1268 const auto *Template = Entity.dyn_cast<const NamedDecl *>();
1269 if (!Template) {
1270 return ::CheckConstraintSatisfaction(
1271 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1272 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1273 }
1274 // Invalid templates could make their way here. Substituting them could result
1275 // in dependent expressions.
1276 if (Template->isInvalidDecl()) {
1277 OutSatisfaction.IsSatisfied = false;
1278 return true;
1279 }
1280
1281 // A list of the template argument list flattened in a predictible manner for
1282 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1283 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1284 // here.
1286 for (auto List : TemplateArgsLists)
1287 for (const TemplateArgument &Arg : List.Args)
1288 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1289
1290 const NamedDecl *Owner = Template;
1291 if (TopLevelConceptId)
1292 Owner = TopLevelConceptId->getNamedConcept();
1293
1294 llvm::FoldingSetNodeID ID;
1295 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1296 void *InsertPos;
1297 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1298 OutSatisfaction = *Cached;
1299 return false;
1300 }
1301
1302 auto Satisfaction =
1303 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1305 *this, Template, AssociatedConstraints, TemplateArgsLists,
1306 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1307 OutSatisfaction = std::move(*Satisfaction);
1308 return true;
1309 }
1310
1311 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1312 // The evaluation of this constraint resulted in us trying to re-evaluate it
1313 // recursively. This isn't really possible, except we try to form a
1314 // RecoveryExpr as a part of the evaluation. If this is the case, just
1315 // return the 'cached' version (which will have the same result), and save
1316 // ourselves the extra-insert. If it ever becomes possible to legitimately
1317 // recursively check a constraint, we should skip checking the 'inner' one
1318 // above, and replace the cached version with this one, as it would be more
1319 // specific.
1320 OutSatisfaction = *Cached;
1321 return false;
1322 }
1323
1324 // Else we can simply add this satisfaction to the list.
1325 OutSatisfaction = *Satisfaction;
1326 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
1327 // invalidated it.
1328 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1329 SatisfactionCache.InsertNode(Satisfaction.release());
1330 return false;
1331}
1332
1334 Sema &S, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex) {
1335 Sema::SFINAETrap Trap(S);
1336 // [C++2c] [temp.constr.normal]
1337 // Otherwise, to form CE, any non-dependent concept template argument Ai
1338 // is substituted into the constraint-expression of C.
1339 // If any such substitution results in an invalid concept-id,
1340 // the program is ill-formed; no diagnostic is required.
1341
1342 Expr *ConstraintExpr =
1344 Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
1345
1346 const ASTTemplateArgumentListInfo *ArgsAsWritten =
1348 if (llvm::none_of(
1349 ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {
1350 return !ArgLoc.getArgument().isDependent() &&
1351 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1352 })) {
1353 return ConstraintExpr;
1354 }
1355
1357 CSE, ConstraintExpr,
1359}
1360
1361bool Sema::SetupConstraintScope(FunctionDecl *FD,
1362 const MultiLevelTemplateArgumentList &MLTAL,
1364 assert(!isLambdaCallOperator(FD) &&
1365 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1366 "instantiations");
1367 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1368 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1370 *this, FD->getPointOfInstantiation(),
1371 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1372 FD->getTemplateSpecializationArgs()->asArray(), SourceRange());
1373 if (Inst.isInvalid())
1374 return true;
1375
1376 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1377 // 'instantiated' parameters and adds it to the context. For the case where
1378 // this function is a template being instantiated NOW, we also need to add
1379 // the list of current template arguments to the list so that they also can
1380 // be picked out of the map.
1381 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1382 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1383 /*Final=*/false);
1384 if (addInstantiatedParametersToScope(
1385 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1386 return true;
1387 }
1388
1389 // If this is a member function, make sure we get the parameters that
1390 // reference the original primary template.
1391 if (FunctionTemplateDecl *FromMemTempl =
1392 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1393 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1394 Scope, MLTAL))
1395 return true;
1396 }
1397
1398 return false;
1399 }
1400
1403 FunctionDecl *InstantiatedFrom =
1407
1409 Sema::InstantiatingTemplate::ConstraintsCheck{},
1410 InstantiatedFrom, 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(
1429 MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(FD);
1430 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1431 if (isLambdaCallOperator(FD))
1432 return MLTAL;
1433 if (SetupConstraintScope(FD, MLTAL, Scope))
1434 return std::nullopt;
1435
1436 return MLTAL;
1437}
1438
1440 ConstraintSatisfaction &Satisfaction,
1441 SourceLocation UsageLoc,
1442 bool ForOverloadResolution) {
1443 // Don't check constraints if the function is dependent. Also don't check if
1444 // this is a function template specialization, as the call to
1445 // CheckFunctionTemplateConstraints after this will check it
1446 // better.
1447 if (FD->isDependentContext() ||
1448 FD->getTemplatedKind() ==
1450 Satisfaction.IsSatisfied = true;
1451 return false;
1452 }
1453
1454 // A lambda conversion operator has the same constraints as the call operator
1455 // and constraints checking relies on whether we are in a lambda call operator
1456 // (and may refer to its parameters), so check the call operator instead.
1457 // Note that the declarations outside of the lambda should also be
1458 // considered. Turning on the 'ForOverloadResolution' flag results in the
1459 // LocalInstantiationScope not looking into its parents, but we can still
1460 // access Decls from the parents while building a lambda RAII scope later.
1461 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1462 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1463 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1464 Satisfaction, UsageLoc,
1465 /*ShouldAddDeclsFromParentScope=*/true);
1466
1467 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1468
1469 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1470 if (isLambdaCallOperator(CtxToSave))
1471 CtxToSave = CtxToSave->getParent()->getParent();
1472 else
1473 CtxToSave = CtxToSave->getNonTransparentContext();
1474 }
1475
1476 ContextRAII SavedContext{*this, CtxToSave};
1477 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1478 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1479 SetupConstraintCheckingTemplateArgumentsAndScope(
1480 const_cast<FunctionDecl *>(FD), Scope);
1481
1482 if (!MLTAL)
1483 return true;
1484
1485 Qualifiers ThisQuals;
1486 CXXRecordDecl *Record = nullptr;
1487 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1488 ThisQuals = Method->getMethodQualifiers();
1489 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1490 }
1491 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1492
1494 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1495 ForOverloadResolution);
1496
1498 FD, FD->getTrailingRequiresClause(), *MLTAL,
1499 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1500 Satisfaction);
1501}
1502
1503static const Expr *
1505 const Expr *ConstrExpr) {
1507
1508 if (MLTAL.getNumSubstitutedLevels() == 0)
1509 return ConstrExpr;
1510
1511 // Set up a dummy 'instantiation' scope in the case of reference to function
1512 // parameters that the surrounding function hasn't been instantiated yet. Note
1513 // this may happen while we're comparing two templates' constraint
1514 // equivalence.
1515 std::optional<LocalInstantiationScope> ScopeForParameters;
1516 if (ND->isFunctionOrFunctionTemplate()) {
1517 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1518 const FunctionDecl *FD = ND->getAsFunction();
1520 Template && Template->getInstantiatedFromMemberTemplate())
1521 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1522 for (auto *PVD : FD->parameters()) {
1523 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1524 continue;
1525 if (!PVD->isParameterPack()) {
1526 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1527 continue;
1528 }
1529 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1530 // to avoid building SubstTemplateTypeParmPackTypes for
1531 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1532 // otherwise reference the AssociatedDecl of the template arguments, which
1533 // is, in this case, the template declaration.
1534 //
1535 // However, as we are in the process of comparing potential
1536 // re-declarations, the canonical declaration is the declaration itself at
1537 // this point. So if we didn't expand these packs, we would end up with an
1538 // incorrect profile difference because we will be profiling the
1539 // canonical types!
1540 //
1541 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1542 // that we can eliminate the Scope in the cases where the declarations are
1543 // not necessarily instantiated. It would also benefit the noexcept
1544 // specifier comparison.
1545 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1546 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1547 }
1548 }
1549
1550 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1551
1552 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1553 // essential for having an injected class as the canonical type for a template
1554 // specialization type at the rebuilding stage. This guarantees that, for
1555 // out-of-line definitions, injected class name types and their equivalent
1556 // template specializations can be profiled to the same value, which makes it
1557 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1558 // perceived identical.
1559 std::optional<Sema::ContextRAII> ContextScope;
1560 const DeclContext *DC = ND->getFriendObjectKind()
1561 ? ND->getLexicalDeclContext()
1562 : ND->getDeclContext();
1563 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1564 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1565 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1566 /*NewThisContext=*/false);
1567 }
1568 EnterExpressionEvaluationContext UnevaluatedContext(
1572 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1573 if (!SubstConstr.isUsable())
1574 return nullptr;
1575 return SubstConstr.get();
1576}
1577
1578bool Sema::AreConstraintExpressionsEqual(const Decl *Old, const Expr *OldConstr,
1579 const Decl *New,
1580 const Expr *NewConstr) {
1581 if (OldConstr == NewConstr)
1582 return true;
1583 // C++ [temp.constr.decl]p4
1584 if (Old != New &&
1585 Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
1586 Sema::SFINAETrap _(*this);
1587 if (const Expr *SubstConstr =
1589 OldConstr))
1590 OldConstr = SubstConstr;
1591 else
1592 return false;
1593 if (const Expr *SubstConstr =
1595 NewConstr))
1596 NewConstr = SubstConstr;
1597 else
1598 return false;
1599 }
1600
1601 llvm::FoldingSetNodeID ID1, ID2;
1602 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1603 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1604 return ID1 == ID2;
1605}
1606
1608 const FunctionTemplateDecl *FTD) {
1609 assert(FTD->getFriendObjectKind() && "Must be a friend!");
1610
1612 FTD->getAssociatedConstraints(ACs);
1613
1614 const FunctionDecl *FD = FTD->getTemplatedDecl();
1615 unsigned OldTemplateDepth = FTD->getTemplateDepth();
1616 for (const AssociatedConstraint &AC : ACs)
1617 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1618 AC.ConstraintExpr))
1619 return true;
1620
1621 return false;
1622}
1623
1625 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1626 SourceRange TemplateIDRange) {
1627 ConstraintSatisfaction Satisfaction;
1628 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1629 TD->getAssociatedConstraints(AssociatedConstraints);
1630 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1631 TemplateIDRange, Satisfaction))
1632 return true;
1633
1634 if (!Satisfaction.IsSatisfied) {
1635 SmallString<128> TemplateArgString;
1636 TemplateArgString = " ";
1637 TemplateArgString += getTemplateArgumentBindingsText(
1638 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1639 TemplateArgsLists.getInnermost().size());
1640
1641 Diag(TemplateIDRange.getBegin(),
1642 diag::err_template_arg_list_constraints_not_satisfied)
1644 << TemplateArgString << TemplateIDRange;
1645 DiagnoseUnsatisfiedConstraint(Satisfaction);
1646 return true;
1647 }
1648 return false;
1649}
1650
1652 SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template,
1653 ArrayRef<TemplateArgument> TemplateArgs,
1654 ConstraintSatisfaction &Satisfaction) {
1656 Template->getAssociatedConstraints(TemplateAC);
1657 if (TemplateAC.empty()) {
1658 Satisfaction.IsSatisfied = true;
1659 return false;
1660 }
1661
1663
1666
1667 Sema::ContextRAII SavedContext(*this, Template->getTemplatedDecl());
1668 return CheckConstraintSatisfaction(Template, TemplateAC, MLTAL,
1669 PointOfInstantiation, Satisfaction);
1670}
1671
1673 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1674 ConstraintSatisfaction &Satisfaction) {
1675 // In most cases we're not going to have constraints, so check for that first.
1676 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1677 assert(Template && "Function is not a specialization");
1678
1679 // Note - code synthesis context for the constraints check is created
1680 // inside CheckConstraintsSatisfaction.
1682 Template->getAssociatedConstraints(TemplateAC);
1683 if (TemplateAC.empty()) {
1684 Satisfaction.IsSatisfied = true;
1685 return false;
1686 }
1687
1688 // Enter the scope of this instantiation. We don't use
1689 // PushDeclContext because we don't have a scope.
1690 Sema::ContextRAII savedContext(*this, Decl);
1692
1693 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1694 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, Scope);
1695
1696 if (!MLTAL)
1697 return true;
1698
1699 Qualifiers ThisQuals;
1700 CXXRecordDecl *Record = nullptr;
1701 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1702 ThisQuals = Method->getMethodQualifiers();
1703 Record = Method->getParent();
1704 }
1705
1706 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1707 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1708 Scope);
1709
1710 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1711 PointOfInstantiation, Satisfaction);
1712}
1713
1716 bool First) {
1717 assert(!Req->isSatisfied() &&
1718 "Diagnose() can only be used on an unsatisfied requirement");
1719 switch (Req->getSatisfactionStatus()) {
1721 llvm_unreachable("Diagnosing a dependent requirement");
1722 break;
1724 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1725 if (!SubstDiag->DiagMessage.empty())
1726 S.Diag(SubstDiag->DiagLoc,
1727 diag::note_expr_requirement_expr_substitution_error)
1728 << (int)First << SubstDiag->SubstitutedEntity
1729 << SubstDiag->DiagMessage;
1730 else
1731 S.Diag(SubstDiag->DiagLoc,
1732 diag::note_expr_requirement_expr_unknown_substitution_error)
1733 << (int)First << SubstDiag->SubstitutedEntity;
1734 break;
1735 }
1737 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1738 << (int)First << Req->getExpr();
1739 break;
1741 auto *SubstDiag =
1743 if (!SubstDiag->DiagMessage.empty())
1744 S.Diag(SubstDiag->DiagLoc,
1745 diag::note_expr_requirement_type_requirement_substitution_error)
1746 << (int)First << SubstDiag->SubstitutedEntity
1747 << SubstDiag->DiagMessage;
1748 else
1749 S.Diag(
1750 SubstDiag->DiagLoc,
1751 diag::
1752 note_expr_requirement_type_requirement_unknown_substitution_error)
1753 << (int)First << SubstDiag->SubstitutedEntity;
1754 break;
1755 }
1757 ConceptSpecializationExpr *ConstraintExpr =
1759 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1760 break;
1761 }
1763 llvm_unreachable("We checked this above");
1764 }
1765}
1766
1769 bool First) {
1770 assert(!Req->isSatisfied() &&
1771 "Diagnose() can only be used on an unsatisfied requirement");
1772 switch (Req->getSatisfactionStatus()) {
1774 llvm_unreachable("Diagnosing a dependent requirement");
1775 return;
1777 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1778 if (!SubstDiag->DiagMessage.empty())
1779 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1780 << (int)First << SubstDiag->SubstitutedEntity
1781 << SubstDiag->DiagMessage;
1782 else
1783 S.Diag(SubstDiag->DiagLoc,
1784 diag::note_type_requirement_unknown_substitution_error)
1785 << (int)First << SubstDiag->SubstitutedEntity;
1786 return;
1787 }
1788 default:
1789 llvm_unreachable("Unknown satisfaction status");
1790 return;
1791 }
1792}
1793
1796 SourceLocation Loc, bool First) {
1797 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1798 S.Diag(
1799 Loc,
1800 diag::
1801 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1802 << (int)First
1803 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1804 << Concept->getNamedConcept();
1805 } else {
1806 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1807 << (int)First << Concept;
1808 }
1809}
1810
1813 bool First, concepts::NestedRequirement *Req = nullptr);
1814
1817 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1818 for (auto &Record : Records) {
1820 Loc = {};
1822 }
1823}
1824
1834
1836 const Expr *SubstExpr,
1837 bool First) {
1838 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1839 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1840 switch (BO->getOpcode()) {
1841 // These two cases will in practice only be reached when using fold
1842 // expressions with || and &&, since otherwise the || and && will have been
1843 // broken down into atomic constraints during satisfaction checking.
1844 case BO_LOr:
1845 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1848 /*First=*/false);
1849 return;
1850 case BO_LAnd: {
1851 bool LHSSatisfied =
1852 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1853 if (LHSSatisfied) {
1854 // LHS is true, so RHS must be false.
1856 return;
1857 }
1858 // LHS is false
1860
1861 // RHS might also be false
1862 bool RHSSatisfied =
1863 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1864 if (!RHSSatisfied)
1866 /*First=*/false);
1867 return;
1868 }
1869 case BO_GE:
1870 case BO_LE:
1871 case BO_GT:
1872 case BO_LT:
1873 case BO_EQ:
1874 case BO_NE:
1875 if (BO->getLHS()->getType()->isIntegerType() &&
1876 BO->getRHS()->getType()->isIntegerType()) {
1877 Expr::EvalResult SimplifiedLHS;
1878 Expr::EvalResult SimplifiedRHS;
1879 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1881 /*InConstantContext=*/true);
1882 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1884 /*InConstantContext=*/true);
1885 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1886 S.Diag(SubstExpr->getBeginLoc(),
1887 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1888 << (int)First << SubstExpr
1889 << toString(SimplifiedLHS.Val.getInt(), 10)
1890 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1891 << toString(SimplifiedRHS.Val.getInt(), 10);
1892 return;
1893 }
1894 }
1895 break;
1896
1897 default:
1898 break;
1899 }
1900 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1901 // FIXME: RequiresExpr should store dependent diagnostics.
1902 for (concepts::Requirement *Req : RE->getRequirements())
1903 if (!Req->isDependent() && !Req->isSatisfied()) {
1904 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1906 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1908 else
1911 break;
1912 }
1913 return;
1914 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1915 // Drill down concept ids treated as atomic constraints
1917 return;
1918 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1919 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1920 assert(TTE->getNumArgs() == 2);
1921 S.Diag(SubstExpr->getSourceRange().getBegin(),
1922 diag::note_is_deducible_constraint_evaluated_to_false)
1923 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1924 return;
1925 }
1926
1927 S.Diag(SubstExpr->getSourceRange().getBegin(),
1928 diag::note_atomic_constraint_evaluated_to_false)
1929 << (int)First << SubstExpr;
1930 S.DiagnoseTypeTraitDetails(SubstExpr);
1931}
1932
1936 if (auto *Diag =
1937 Record
1938 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1939 if (Req)
1940 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
1941 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
1942 else
1943 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1944 << Diag->second;
1945 return;
1946 }
1947 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
1948 if (Loc.isInvalid())
1949 Loc = Concept->getBeginLoc();
1951 return;
1952 }
1955}
1956
1958 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
1959 bool First) {
1960
1961 assert(!Satisfaction.IsSatisfied &&
1962 "Attempted to diagnose a satisfied constraint");
1963 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
1964}
1965
1967 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
1968
1969 const ASTConstraintSatisfaction &Satisfaction =
1970 ConstraintExpr->getSatisfaction();
1971
1972 assert(!Satisfaction.IsSatisfied &&
1973 "Attempted to diagnose a satisfied constraint");
1974
1975 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
1976 ConstraintExpr->getBeginLoc(), First);
1977}
1978
1979namespace {
1980
1981class SubstituteParameterMappings {
1982 Sema &SemaRef;
1983
1984 const MultiLevelTemplateArgumentList *MLTAL;
1985 const ASTTemplateArgumentListInfo *ArgsAsWritten;
1986
1987 // When normalizing a fold constraint, e.g.
1988 // C<Pack1, Pack2...> && ...
1989 // we want the TreeTransform to expand only Pack2 but not Pack1,
1990 // since Pack1 will be expanded during the evaluation of the fold expression.
1991 // This flag helps rewrite any non-PackExpansion packs into "expanded"
1992 // parameters.
1993 bool RemovePacksForFoldExpr;
1994
1995 SubstituteParameterMappings(Sema &SemaRef,
1996 const MultiLevelTemplateArgumentList *MLTAL,
1997 const ASTTemplateArgumentListInfo *ArgsAsWritten,
1998 bool RemovePacksForFoldExpr)
1999 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2000 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2001
2002 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
2003
2004 bool substitute(NormalizedConstraintWithParamMapping &N);
2005
2006 bool substitute(ConceptIdConstraint &CC);
2007
2008public:
2009 SubstituteParameterMappings(Sema &SemaRef,
2010 bool RemovePacksForFoldExpr = false)
2011 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
2012 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2013
2014 bool substitute(NormalizedConstraint &N);
2015};
2016
2017void SubstituteParameterMappings::buildParameterMapping(
2019 TemplateParameterList *TemplateParams =
2020 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
2021
2022 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2023 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2024
2027 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2028 /*OnlyDeduced=*/false,
2029 /*Depth=*/0, OccurringIndices);
2030
2032 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2033 /*Depth=*/0, OccurringIndicesForSubsumption);
2034
2035 } else if (N.getKind() ==
2038 static_cast<FoldExpandedConstraint &>(N).getPattern(),
2039 /*OnlyDeduced=*/false,
2040 /*Depth=*/0, OccurringIndices);
2042 auto *Args = static_cast<ConceptIdConstraint &>(N)
2043 .getConceptId()
2044 ->getTemplateArgsAsWritten();
2045 if (Args)
2046 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2047 /*Depth=*/0, OccurringIndices);
2048 }
2049
2050 // If a parameter is only referenced in a default template argument,
2051 // we need to add it to the mapping explicitly.
2052 {
2054 for (unsigned I = TemplateParams->getMinRequiredArguments();
2055 I < TemplateParams->size(); ++I) {
2056 const NamedDecl *Param = TemplateParams->getParam(I);
2057 if (Param->isParameterPack())
2058 break;
2059 const TemplateArgument *Arg =
2061 assert(Arg && "expected a default argument");
2062 DefaultArgs.emplace_back(std::move(*Arg));
2063 }
2064 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0,
2065 OccurringIndices);
2066 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0,
2067 OccurringIndicesForSubsumption);
2068 }
2069
2070 unsigned Size = OccurringIndices.count();
2071 // When the constraint is independent of any template parameters,
2072 // we build an empty mapping so that we can distinguish these cases
2073 // from cases where no mapping exists at all, e.g. when there are only atomic
2074 // constraints.
2075 TemplateArgumentLoc *TempArgs =
2076 new (SemaRef.Context) TemplateArgumentLoc[Size];
2078 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2079 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2080 ? ArgsAsWritten->arguments()[I].getLocation()
2081 : SourceLocation();
2082 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
2083 // can't assert Loc.isValid() now.
2084 if (OccurringIndices[I]) {
2085 NamedDecl *Param = TemplateParams->begin()[I];
2086 new (&(TempArgs)[J]) TemplateArgumentLoc(
2087 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2088 UsedParams.push_back(Param);
2089 J++;
2090 }
2091 }
2092 auto *UsedList = TemplateParameterList::Create(
2093 SemaRef.Context, TemplateParams->getTemplateLoc(),
2094 TemplateParams->getLAngleLoc(), UsedParams,
2095 /*RAngleLoc=*/SourceLocation(),
2096 /*RequiresClause=*/nullptr);
2098 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2099 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
2100}
2101
2102bool SubstituteParameterMappings::substitute(
2104 if (!N.hasParameterMapping())
2105 buildParameterMapping(N);
2106
2107 // If the parameter mapping is empty, there is nothing to substitute.
2108 if (N.getParameterMapping().empty())
2109 return false;
2110
2111 SourceLocation InstLocBegin, InstLocEnd;
2112 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2113 if (Arguments.empty()) {
2114 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2115 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2116 } else {
2117 auto SR = Arguments[0].getSourceRange();
2118 InstLocBegin = SR.getBegin();
2119 InstLocEnd = SR.getEnd();
2120 }
2121 Sema::NonSFINAEContext _(SemaRef);
2123 SemaRef, InstLocBegin,
2125 const_cast<NamedDecl *>(N.getConstraintDecl()),
2126 {InstLocBegin, InstLocEnd});
2127 if (Inst.isInvalid())
2128 return true;
2129
2130 // TransformTemplateArguments is unable to preserve the source location of a
2131 // pack. The SourceLocation is necessary for the instantiation location.
2132 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2133 // which is wrong.
2134 TemplateArgumentListInfo SubstArgs;
2136 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2138 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs))
2139 return true;
2141 auto *TD =
2144 TD->getLocation(), SubstArgs,
2145 /*DefaultArguments=*/{},
2146 /*PartialTemplateArgs=*/false, CTAI))
2147 return true;
2148
2149 TemplateArgumentLoc *TempArgs =
2150 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2151
2152 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2153 SourceLocation Loc;
2154 // If this is an empty pack, we have no corresponding SubstArgs.
2155 if (I < SubstArgs.size())
2156 Loc = SubstArgs.arguments()[I].getLocation();
2157
2158 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2159 CTAI.SugaredConverted[I], QualType(), Loc);
2160 }
2161
2162 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2163 CTAI.SugaredConverted.size());
2167 return false;
2168}
2169
2170bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2171 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2172
2173 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2174 return true;
2175
2176 auto *CSE = CC.getConceptSpecializationExpr();
2177 assert(CSE);
2178 assert(!CC.getBeginLoc().isInvalid());
2179
2180 SourceLocation InstLocBegin, InstLocEnd;
2181 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2182 Arguments.empty()) {
2183 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2184 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2185 } else {
2186 auto SR = Arguments[0].getSourceRange();
2187 InstLocBegin = SR.getBegin();
2188 InstLocEnd = SR.getEnd();
2189 }
2190 Sema::NonSFINAEContext _(SemaRef);
2191 // This is useful for name lookup across modules; see Sema::getLookupModules.
2193 SemaRef, InstLocBegin,
2195 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2196 {InstLocBegin, InstLocEnd});
2197 if (Inst.isInvalid())
2198 return true;
2199
2201 // TransformTemplateArguments is unable to preserve the source location of a
2202 // pack. The SourceLocation is necessary for the instantiation location.
2203 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2204 // which is wrong.
2206 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2207 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2208 CSE->getTemplateArgsAsWritten();
2210 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out))
2211 return true;
2213 if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(),
2214 CSE->getConceptNameInfo().getLoc(), Out,
2215 /*DefaultArgs=*/{},
2216 /*PartialTemplateArgs=*/false, CTAI,
2217 /*UpdateArgsWithConversions=*/false))
2218 return true;
2219 auto TemplateArgs = *MLTAL;
2220 TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(),
2221 CTAI.SugaredConverted);
2222 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2223 RemovePacksForFoldExpr)
2224 .substitute(CC.getNormalizedConstraint());
2225}
2226
2227bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2228 switch (N.getKind()) {
2230 if (!MLTAL) {
2231 assert(!ArgsAsWritten);
2232 return false;
2233 }
2234 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2235 }
2237 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2238 if (!MLTAL) {
2239 llvm::SaveAndRestore _1(RemovePacksForFoldExpr, true);
2240 assert(!ArgsAsWritten);
2241 return substitute(FE.getNormalizedPattern());
2242 }
2243 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2244 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2245 return SubstituteParameterMappings(SemaRef, /*RemovePacksForFoldExpr=*/true)
2246 .substitute(FE.getNormalizedPattern());
2247 }
2249 auto &CC = static_cast<ConceptIdConstraint &>(N);
2250 if (MLTAL) {
2251 assert(ArgsAsWritten);
2252 return substitute(CC);
2253 }
2254 assert(!ArgsAsWritten);
2258 if (RemovePacksForFoldExpr) {
2260 ArrayRef<TemplateArgumentLoc> InputArgLoc =
2262 if (AdjustConstraints(SemaRef, /*TemplateDepth=*/0,
2263 /*RemoveNonPackExpansionPacks=*/true)
2264 .TransformTemplateArguments(InputArgLoc.begin(),
2265 InputArgLoc.end(), OutArgs))
2266 return true;
2268 // Repack the packs.
2269 if (SemaRef.CheckTemplateArgumentList(
2270 Concept, Concept->getTemplateParameters(), Concept->getBeginLoc(),
2271 OutArgs,
2272 /*DefaultArguments=*/{},
2273 /*PartialTemplateArgs=*/false, CTAI))
2274 return true;
2275 InnerArgs = std::move(CTAI.SugaredConverted);
2276 }
2277
2279 SemaRef.getTemplateInstantiationArgs(Concept, InnerArgs);
2280
2281 return SubstituteParameterMappings(SemaRef, &MLTAL,
2283 RemovePacksForFoldExpr)
2284 .substitute(CC.getNormalizedConstraint());
2285 }
2287 auto &Compound = static_cast<CompoundConstraint &>(N);
2288 if (substitute(Compound.getLHS()))
2289 return true;
2290 return substitute(Compound.getRHS());
2291 }
2292 }
2293 llvm_unreachable("Unknown ConstraintKind enum");
2294}
2295
2296} // namespace
2297
2298NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2299 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2300 assert(ACs.size() != 0);
2301 auto *Conjunction =
2302 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2303 if (!Conjunction)
2304 return nullptr;
2305 for (unsigned I = 1; I < ACs.size(); ++I) {
2306 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2307 ACs[I].ArgPackSubstIndex);
2308 if (!Next)
2309 return nullptr;
2311 Conjunction, Next);
2312 }
2313 return Conjunction;
2314}
2315
2316NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2317 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2318 assert(E != nullptr);
2319
2320 // C++ [temp.constr.normal]p1.1
2321 // [...]
2322 // - The normal form of an expression (E) is the normal form of E.
2323 // [...]
2324 E = E->IgnoreParenImpCasts();
2325
2326 llvm::FoldingSetNodeID ID;
2327 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2328 return nullptr;
2329 }
2330 SatisfactionStackRAII StackRAII(S, D, ID);
2331
2332 // C++2a [temp.param]p4:
2333 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2334 // Fold expression is considered atomic constraints per current wording.
2335 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2336
2337 if (LogicalBinOp BO = E) {
2338 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2339 if (!LHS)
2340 return nullptr;
2341 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2342 if (!RHS)
2343 return nullptr;
2344
2346 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2347 }
2348 if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2349 // C++ [temp.constr.normal]p1.1
2350 // [...]
2351 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2352 // where C names a concept, is the normal form of the
2353 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2354 // respective template parameters in the parameter mappings in each atomic
2355 // constraint. If any such substitution results in an invalid type or
2356 // expression, the program is ill-formed; no diagnostic is required.
2357 // [...]
2358 NormalizedConstraint *SubNF;
2359 if (ExprResult Res =
2360 SubstituteConceptsInConstraintExpression(S, CSE, SubstIndex);
2361 Res.isUsable())
2362 // Use canonical declarations to merge ConceptDecls across different
2363 // modules.
2364 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2365 S, CSE->getNamedConcept()->getCanonicalDecl(),
2366 AssociatedConstraint(Res.get(), SubstIndex));
2367 else
2368 return nullptr;
2370 CSE->getConceptReference(), SubNF, D,
2371 CSE, SubstIndex);
2372 }
2373 if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2374 FE && S.getLangOpts().CPlusPlus26 &&
2375 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2376 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2377
2378 // Normalize fold expressions in C++26.
2379
2381 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2384
2385 if (FE->getInit()) {
2386 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2387 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2388 if (!LHS || !RHS)
2389 return nullptr;
2390
2391 if (FE->isRightFold())
2393 FE->getPattern(), D, Kind, LHS);
2394 else
2396 FE->getPattern(), D, Kind, RHS);
2397
2399 S.getASTContext(), LHS,
2400 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2401 : CCK_Disjunction),
2402 RHS);
2403 }
2404 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2405 if (!Sub)
2406 return nullptr;
2408 D, Kind, Sub);
2409 }
2410 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2411}
2412
2414 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2415 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2416 if (!ConstrainedDeclOrNestedReq) {
2417 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2418 *this, nullptr, AssociatedConstraints);
2419 if (!Normalized ||
2420 SubstituteParameterMappings(*this).substitute(*Normalized))
2421 return nullptr;
2422
2423 return Normalized;
2424 }
2425
2426 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2427 const NamedDecl *ND =
2428 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2429 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2430 if (CacheEntry == NormalizationCache.end()) {
2431 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2432 *this, ND, AssociatedConstraints);
2433 if (!Normalized) {
2434 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);
2435 return nullptr;
2436 }
2437 // substitute() can invalidate iterators of NormalizationCache.
2438 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2439 CacheEntry =
2440 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2441 .first;
2442 if (Failed)
2443 return nullptr;
2444 }
2445 return CacheEntry->second;
2446}
2447
2450
2451 // [C++26] [temp.constr.fold]
2452 // Two fold expanded constraints are compatible for subsumption
2453 // if their respective constraints both contain an equivalent unexpanded pack.
2454
2457 APacks);
2459 BPacks);
2460
2461 for (const UnexpandedParameterPack &APack : APacks) {
2462 auto ADI = getDepthAndIndex(APack);
2463 if (!ADI)
2464 continue;
2465 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2466 return getDepthAndIndex(BPack) == ADI;
2467 });
2468 if (It != BPacks.end())
2469 return true;
2470 }
2471 return false;
2472}
2473
2476 const NamedDecl *D2,
2478 bool &Result) {
2479#ifndef NDEBUG
2480 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2481 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2483 return Kind == FunctionDecl::TK_NonTemplate ||
2485 };
2486 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2487 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2488 "use non-instantiated function declaration for constraints partial "
2489 "ordering");
2490 }
2491#endif
2492
2493 if (AC1.empty()) {
2494 Result = AC2.empty();
2495 return false;
2496 }
2497 if (AC2.empty()) {
2498 // TD1 has associated constraints and TD2 does not.
2499 Result = true;
2500 return false;
2501 }
2502
2503 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2504 auto CacheEntry = SubsumptionCache.find(Key);
2505 if (CacheEntry != SubsumptionCache.end()) {
2506 Result = CacheEntry->second;
2507 return false;
2508 }
2509
2510 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1);
2511 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2);
2512
2513 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2514 if (Depth2 > Depth1) {
2515 AC1[I].ConstraintExpr =
2516 AdjustConstraints(*this, Depth2 - Depth1)
2517 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2518 .get();
2519 } else if (Depth1 > Depth2) {
2520 AC2[I].ConstraintExpr =
2521 AdjustConstraints(*this, Depth1 - Depth2)
2522 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2523 .get();
2524 }
2525 }
2526
2527 SubsumptionChecker SC(*this);
2528 // Associated declarations are used as a cache key in the event they were
2529 // normalized earlier during concept checking. However we cannot reuse these
2530 // cached results if any of the template depths have been adjusted.
2531 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2532 if (Depth2 > Depth1)
2533 DeclAC1 = nullptr;
2534 else if (Depth1 > Depth2)
2535 DeclAC2 = nullptr;
2536 std::optional<bool> Subsumes = SC.Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2537 if (!Subsumes) {
2538 // Normalization failed
2539 return true;
2540 }
2541 Result = *Subsumes;
2542 SubsumptionCache.try_emplace(Key, *Subsumes);
2543 return false;
2544}
2545
2549 if (isSFINAEContext())
2550 // No need to work here because our notes would be discarded.
2551 return false;
2552
2553 if (AC1.empty() || AC2.empty())
2554 return false;
2555
2556 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2557 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2558 const AtomicConstraint &B) {
2560 return false;
2561 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2562 if (EA == EB)
2563 return true;
2564
2565 // Not the same source level expression - are the expressions
2566 // identical?
2567 llvm::FoldingSetNodeID IDA, IDB;
2568 EA->Profile(IDA, Context, /*Canonical=*/true);
2569 EB->Profile(IDB, Context, /*Canonical=*/true);
2570 if (IDA != IDB)
2571 return false;
2572
2573 AmbiguousAtomic1 = EA;
2574 AmbiguousAtomic2 = EB;
2575 return true;
2576 };
2577
2578 {
2579 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2580 if (!Normalized1)
2581 return false;
2582
2583 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2584 if (!Normalized2)
2585 return false;
2586
2587 SubsumptionChecker SC(*this);
2588
2589 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2590 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2591
2592 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2593 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2594 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2595
2596 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2597 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2598 // Same result - no ambiguity was caused by identical atomic expressions.
2599 return false;
2600 }
2601 // A different result! Some ambiguous atomic constraint(s) caused a difference
2602 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2603
2604 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2605 << AmbiguousAtomic1->getSourceRange();
2606 Diag(AmbiguousAtomic2->getBeginLoc(),
2607 diag::note_ambiguous_atomic_constraints_similar_expression)
2608 << AmbiguousAtomic2->getSourceRange();
2609 return true;
2610}
2611
2612//
2613//
2614// ------------------------ Subsumption -----------------------------------
2615//
2616//
2618 SubsumptionCallable Callable)
2619 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2620
2621uint16_t SubsumptionChecker::getNewLiteralId() {
2622 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2623 "too many constraints!");
2624 return NextID++;
2625}
2626
2627auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2628 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2629 // C++ [temp.constr.order] p2
2630 // - an atomic constraint A subsumes another atomic constraint B
2631 // if and only if the A and B are identical [...]
2632 //
2633 // C++ [temp.constr.atomic] p2
2634 // Two atomic constraints are identical if they are formed from the
2635 // same expression and the targets of the parameter mappings are
2636 // equivalent according to the rules for expressions [...]
2637
2638 // Because subsumption of atomic constraints is an identity
2639 // relationship that does not require further analysis
2640 // We cache the results such that if an atomic constraint literal
2641 // subsumes another, their literal will be the same
2642
2643 llvm::FoldingSetNodeID ID;
2644 ID.AddBoolean(Ori->hasParameterMapping());
2645 if (Ori->hasParameterMapping()) {
2646 const auto &Mapping = Ori->getParameterMapping();
2648 Ori->mappingOccurenceListForSubsumption();
2649 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2650 if (Indexes[Idx])
2651 SemaRef.getASTContext()
2652 .getCanonicalTemplateArgument(TAL.getArgument())
2653 .Profile(ID, SemaRef.getASTContext());
2654 }
2655 }
2656 auto It = Elems.find(ID);
2657 if (It == Elems.end()) {
2658 It = Elems
2659 .insert({ID,
2660 MappedAtomicConstraint{
2661 Ori, {getNewLiteralId(), Literal::Atomic}}})
2662 .first;
2663 ReverseMap[It->second.ID.Value] = Ori;
2664 }
2665 return It->getSecond().ID;
2666}
2667
2668auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2669 auto &Elems = FoldMap[Ori->getPattern()];
2670
2671 FoldExpendedConstraintKey K;
2672 K.Kind = Ori->getFoldOperator();
2673
2674 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2675 return K.Kind == Other.Kind;
2676 });
2677 if (It == Elems.end()) {
2678 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2679 It = Elems.insert(Elems.end(), std::move(K));
2680 ReverseMap[It->ID.Value] = Ori;
2681 }
2682 return It->ID;
2683}
2684
2685auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2686 return SubsumptionChecker::Normalize<CNFFormula>(C);
2687}
2688auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2689 return SubsumptionChecker::Normalize<DNFFormula>(C);
2690}
2691
2692///
2693/// \brief SubsumptionChecker::Normalize
2694///
2695/// Normalize a formula to Conjunctive Normal Form or
2696/// Disjunctive normal form.
2697///
2698/// Each Atomic (and Fold Expanded) constraint gets represented by
2699/// a single id to reduce space.
2700///
2701/// To minimize risks of exponential blow up, if two atomic
2702/// constraints subsumes each other (same constraint and mapping),
2703/// they are represented by the same literal.
2704///
2705template <typename FormulaType>
2706FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2707 FormulaType Res;
2708
2709 auto Add = [&, this](Clause C) {
2710 // Sort each clause and remove duplicates for faster comparisons.
2711 llvm::sort(C);
2712 C.erase(llvm::unique(C), C.end());
2713 AddUniqueClauseToFormula(Res, std::move(C));
2714 };
2715
2716 switch (NC.getKind()) {
2718 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2719
2721 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2722
2724 return Normalize<FormulaType>(
2725 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2726
2728 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2729 FormulaType Left, Right;
2730 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2731 Left = Normalize<FormulaType>(Compound.getLHS());
2732 Right = Normalize<FormulaType>(Compound.getRHS());
2733 });
2734
2735 if (Compound.getCompoundKind() == FormulaType::Kind) {
2736 unsigned SizeLeft = Left.size();
2737 Res = std::move(Left);
2738 Res.reserve(SizeLeft + Right.size());
2739 std::for_each(std::make_move_iterator(Right.begin()),
2740 std::make_move_iterator(Right.end()), Add);
2741 return Res;
2742 }
2743
2744 Res.reserve(Left.size() * Right.size());
2745 for (const auto &LTransform : Left) {
2746 for (const auto &RTransform : Right) {
2747 Clause Combined;
2748 Combined.reserve(LTransform.size() + RTransform.size());
2749 llvm::copy(LTransform, std::back_inserter(Combined));
2750 llvm::copy(RTransform, std::back_inserter(Combined));
2751 Add(std::move(Combined));
2752 }
2753 }
2754 return Res;
2755 }
2756 }
2757 llvm_unreachable("Unknown ConstraintKind enum");
2758}
2759
2760void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2761 for (auto &Other : F) {
2762 if (llvm::equal(C, Other))
2763 return;
2764 }
2765 F.push_back(C);
2766}
2767
2769 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2771 const NormalizedConstraint *PNormalized =
2772 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2773 if (!PNormalized)
2774 return std::nullopt;
2775
2776 const NormalizedConstraint *QNormalized =
2777 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2778 if (!QNormalized)
2779 return std::nullopt;
2780
2781 return Subsumes(PNormalized, QNormalized);
2782}
2783
2785 const NormalizedConstraint *Q) {
2786
2787 DNFFormula DNFP = DNF(*P);
2788 CNFFormula CNFQ = CNF(*Q);
2789 return Subsumes(DNFP, CNFQ);
2790}
2791
2792bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2793 const CNFFormula &QCNF) {
2794 for (const auto &Pi : PDNF) {
2795 for (const auto &Qj : QCNF) {
2796 // C++ [temp.constr.order] p2
2797 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2798 // and only if there exists an atomic constraint Pia in Pi for which
2799 // there exists an atomic constraint, Qjb, in Qj such that Pia
2800 // subsumes Qjb.
2801 if (!DNFSubsumes(Pi, Qj))
2802 return false;
2803 }
2804 }
2805 return true;
2806}
2807
2808bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2809
2810 return llvm::any_of(P, [&](Literal LP) {
2811 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2812 });
2813}
2814
2816 const FoldExpandedConstraint *B) {
2817 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2818 A, B};
2819
2820 auto It = FoldSubsumptionCache.find(Key);
2821 if (It == FoldSubsumptionCache.end()) {
2822 // C++ [temp.constr.order]
2823 // a fold expanded constraint A subsumes another fold expanded
2824 // constraint B if they are compatible for subsumption, have the same
2825 // fold-operator, and the constraint of A subsumes that of B.
2826 bool DoesSubsume =
2827 A->getFoldOperator() == B->getFoldOperator() &&
2830 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2831 }
2832 return It->second;
2833}
2834
2835bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2836 if (A.Kind != B.Kind)
2837 return false;
2838 switch (A.Kind) {
2839 case Literal::Atomic:
2840 if (!Callable)
2841 return A.Value == B.Value;
2842 return Callable(
2843 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2844 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2845 case Literal::FoldExpanded:
2846 return Subsumes(
2847 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2848 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2849 }
2850 llvm_unreachable("unknown literal kind");
2851}
This file provides AST data structures related to concepts.
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E)
FormatToken * Next
The next token in the unwrapped line.
Result
Implement __builtin_bit_cast and related operations.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Records Records
Definition MachO.h:40
llvm::MachO::Record Record
Definition MachO.h:31
Defines and computes precedence levels for binary/ternary operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc, bool First, concepts::NestedRequirement *Req=nullptr)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND)
static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)
static ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)
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 const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Decl *ND, const Expr *ConstrExpr)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)
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:884
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:6928
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:7059
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:2185
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:5102
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2147
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2952
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:76
void Adopt(NestedNameSpecifierLoc Other)
Adopt an existing nested-name-specifier (with source-range information).
Definition DeclSpec.cpp:103
Expr * getCallee()
Definition Expr.h: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.
Expr * getConstraintExpr() const
ConceptDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
const NormalizedConstraint & getNormalizedConstraint() const
const ConceptSpecializationExpr * getConceptSpecializationExpr() const
static ConceptIdConstraint * Create(ASTContext &Ctx, const ConceptReference *ConceptId, NormalizedConstraint *SubConstraint, const NamedDecl *ConstraintDecl, const ConceptSpecializationExpr *CSE, UnsignedOrNone PackIndex)
const ConceptReference * getConceptId() const
A reference to a concept and its template args, as it appears in the code.
Definition ASTConcept.h:130
const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const
Definition ASTConcept.h:170
NamedDecl * getFoundDecl() const
Definition ASTConcept.h:197
const DeclarationNameInfo & getConceptNameInfo() const
Definition ASTConcept.h:174
SourceLocation getBeginLoc() const LLVM_READONLY
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition ASTConcept.h:203
TemplateDecl * getNamedConcept() const
Definition ASTConcept.h:201
SourceLocation getTemplateKWLoc() const
Definition ASTConcept.h:180
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptReference * getConceptReference() const
const ImplicitConceptSpecializationDecl * getSpecializationDecl() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:47
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition ASTConcept.h:69
llvm::SmallVector< UnsatisfiedConstraintRecord, 4 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
Definition ASTConcept.h:67
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h: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
unsigned getTemplateDepth() const
Determine the number of levels of template parameter surrounding this declaration.
Definition DeclBase.cpp:320
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:3097
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:282
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:2018
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition Decl.cpp:4168
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4524
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2766
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition Decl.cpp:4289
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4305
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4233
TemplatedKind
The kind of templated function a FunctionDecl can be.
Definition Decl.h:2023
@ TK_FunctionTemplateSpecialization
Definition Decl.h:2034
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition Decl.cpp:4119
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4192
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4140
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:2078
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:8492
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:13685
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition Sema.h:8534
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:12505
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
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:15060
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:14921
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 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:7103
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
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:15067
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const Decl *D, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, UnsignedOrNone NumLevels=std::nullopt, bool SkipInnerNonInstantiated=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
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:13723
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13679
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14877
void PopSatisfactionStackEntry()
Definition Sema.h:14883
bool CheckFunctionSpecializationConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ConstraintSatisfaction &Satisfaction)
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:6813
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6792
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition Sema.h:14885
bool AreConstraintExpressionsEqual(const Decl *Old, const Expr *OldConstr, const Decl *New, const Expr *NewConstr)
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.
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...
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionTemplateDecl *FTD)
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
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
Location wrapper for a TemplateArgument.
Represents a template argument.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
bool containsUnexpandedParameterPack() const
Whether this template argument contains an unexpanded parameter pack.
@ Pack
The template argument is actually a parameter pack.
ArgKind getKind() const
Return the kind of stored template argument.
bool isPackExpansion() const
Determine whether this template argument is a pack expansion.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< AssociatedConstraint > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
bool isNull() const
Determine whether this template name is NULL.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
unsigned getMinRequiredArguments() const
Returns the minimum number of arguments needed to form a template specialization.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() const
Token - This structure provides full information about a lexed token.
Definition Token.h:36
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition Token.h:104
tok::TokenKind getKind() const
Definition Token.h:99
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition TypeLoc.h:133
SourceLocation getNameLoc() const
Definition TypeLoc.h:547
void setNameLoc(SourceLocation Loc)
Definition TypeLoc.h:551
The base class of the type hierarchy.
Definition TypeBase.h:1875
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2852
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:9012
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2844
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2465
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2862
bool isFunctionType() const
Definition TypeBase.h:8673
QualType desugar() const
Definition Type.cpp:4170
UnresolvedUsingTypenameDecl * getDecl() const
Definition TypeBase.h:6117
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
Definition DeclCXX.h:4079
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:417
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:388
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:1763
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:12088
A stack object to be created when performing template instantiation.
Definition Sema.h:13343