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