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 TraverseCXXThisExpr(CXXThisExpr *E) {
385 return inherited::TraverseType(E->getType());
386 }
387
388 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
389 // We don't care about TypeLocs. So traverse Types instead.
390 return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);
391 }
392
393 bool TraverseDependentNameType(const DependentNameType *T,
394 bool /*TraverseQualifier*/) {
395 return TraverseNestedNameSpecifier(T->getQualifier());
396 }
397
398 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
399 // T's parent can be dependent while T doesn't have any template arguments.
400 // We should have already traversed its qualifier.
401 // FIXME: Add an assert to catch cases where we failed to profile the
402 // concept.
403 return true;
404 }
405
406 bool TraverseUnresolvedUsingType(UnresolvedUsingType *T,
407 bool TraverseQualifier) {
408 // Sometimes the written type doesn't contain a qualifier which contains
409 // necessary template arguments, whereas the declaration does.
410 if (NestedNameSpecifier NNS = T->getDecl()->getQualifier();
411 TraverseQualifier && NNS)
412 return inherited::TraverseNestedNameSpecifier(NNS);
413 return inherited::TraverseUnresolvedUsingType(T, TraverseQualifier);
414 }
415
416 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
417 bool TraverseQualifier) {
418 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
419 }
420
421 bool TraverseTemplateArgument(const TemplateArgument &Arg) {
423 // Act as if we are fully expanding this pack, if it is a PackExpansion.
424 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
425 llvm::SaveAndRestore<UnsignedOrNone> _2(OuterPackSubstIndex,
426 std::nullopt);
427 return inherited::TraverseTemplateArgument(Arg);
428 }
429
430 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
431 return inherited::TraverseTemplateArgument(Arg);
432 }
433
434 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
435 return TraverseDecl(SOPE->getPack());
436 }
437
438 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
439 return inherited::TraverseStmt(E->getReplacement());
440 }
441
442 bool TraverseTemplateName(TemplateName Template) {
443 if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
444 Template.getAsTemplateDecl());
445 TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
446 if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
447 TTP->getPosition()))
448 return true;
449
450 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
451 if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
452 assert(Arg.getKind() == TemplateArgument::Pack &&
453 "Missing argument pack");
454 Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
455 }
456 assert(!Arg.getAsTemplate().isNull() &&
457 "Null template template argument");
458 UsedTemplateArgs.push_back(
460 }
461 return inherited::TraverseTemplateName(Template);
462 }
463
464 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
465 if (!Constraint.hasParameterMapping()) {
466 for (const auto &List : TemplateArgs)
467 for (const TemplateArgument &Arg : List.Args)
469 ID, SemaRef.Context);
470 return;
471 }
472
473 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
474 Constraint.getParameterMapping();
475 for (auto &ArgLoc : Mapping) {
476 TemplateArgument Canonical =
477 SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());
478 // We don't want sugars to impede the profile of cache.
479 UsedTemplateArgs.push_back(Canonical);
480 TraverseTemplateArgument(Canonical);
481 }
482
483 for (auto &Used : UsedTemplateArgs) {
484 llvm::FoldingSetNodeID R;
485 Used.Profile(R, SemaRef.Context);
486 ID.AddNodeID(R);
487 }
488 }
489};
490
491class ConstraintSatisfactionChecker {
492 Sema &S;
493 const NamedDecl *Template;
494 SourceLocation TemplateNameLoc;
495 UnsignedOrNone PackSubstitutionIndex;
496 ConstraintSatisfaction &Satisfaction;
497 bool BuildExpression;
498
499 // The closest concept declaration when evaluating atomic constraints.
500 ConceptDecl *ParentConcept = nullptr;
501
502 // This is for TemplateInstantiator to not instantiate the same template
503 // parameter mapping many times, in order to improve substitution performance.
504 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
505 CachedTemplateArgs;
506
507private:
508 template <class Constraint>
509 UnsignedOrNone getOuterPackIndex(const Constraint &C) const {
510 return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex()
511 : PackSubstitutionIndex;
512 }
513
515 EvaluateAtomicConstraint(const Expr *AtomicExpr,
516 const MultiLevelTemplateArgumentList &MLTAL);
517
518 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
519 const FoldExpandedConstraint &FE,
520 const MultiLevelTemplateArgumentList &MLTAL);
521
522 // XXX: It is SLOW! Use it very carefully.
523 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
524 const NormalizedConstraintWithParamMapping &Constraint,
525 const MultiLevelTemplateArgumentList &MLTAL,
526 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
527
528 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
529 const MultiLevelTemplateArgumentList &MLTAL);
530
531 ExprResult Evaluate(const AtomicConstraint &Constraint,
532 const MultiLevelTemplateArgumentList &MLTAL);
533
534 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
535 const MultiLevelTemplateArgumentList &MLTAL);
536
537 ExprResult Evaluate(const FoldExpandedConstraint &Constraint,
538 const MultiLevelTemplateArgumentList &MLTAL);
539
540 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
541 const MultiLevelTemplateArgumentList &MLTAL,
542 unsigned int Size);
543
544 ExprResult Evaluate(const ConceptIdConstraint &Constraint,
545 const MultiLevelTemplateArgumentList &MLTAL);
546
547 ExprResult Evaluate(const CompoundConstraint &Constraint,
548 const MultiLevelTemplateArgumentList &MLTAL);
549
550public:
551 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
552 SourceLocation TemplateNameLoc,
553 UnsignedOrNone PackSubstitutionIndex,
554 ConstraintSatisfaction &Satisfaction,
555 bool BuildExpression)
556 : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),
557 PackSubstitutionIndex(PackSubstitutionIndex),
558 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
559
560 ExprResult Evaluate(const NormalizedConstraint &Constraint,
561 const MultiLevelTemplateArgumentList &MLTAL);
562};
563
564StringRef allocateStringFromConceptDiagnostic(const Sema &S,
565 const PartialDiagnostic Diag) {
566 SmallString<128> DiagString;
567 DiagString = ": ";
568 Diag.EmitToString(S.getDiagnostics(), DiagString);
569 return S.getASTContext().backupStr(DiagString);
570}
571
572} // namespace
573
574ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
575 const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {
576 llvm::FoldingSetNodeID ID;
577 if (Template &&
579 Satisfaction.IsSatisfied = false;
580 Satisfaction.ContainsErrors = true;
581 return ExprEmpty();
582 }
583 SatisfactionStackRAII StackRAII(S, Template, ID);
584
585 // Atomic constraint - substitute arguments and check satisfaction.
586 ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);
587 {
588 TemplateDeductionInfo Info(TemplateNameLoc);
592 // FIXME: improve const-correctness of InstantiatingTemplate
593 const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());
594 if (Inst.isInvalid())
595 return ExprError();
596
597 // We do not want error diagnostics escaping here.
598 Sema::SFINAETrap Trap(S, Info);
599 SubstitutedExpression =
600 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
601
602 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
603 // C++2a [temp.constr.atomic]p1
604 // ...If substitution results in an invalid type or expression, the
605 // constraint is not satisfied.
606 if (!Trap.hasErrorOccurred())
607 // A non-SFINAE error has occurred as a result of this
608 // substitution.
609 return ExprError();
610
613 Info.takeSFINAEDiagnostic(SubstDiag);
614 // FIXME: This is an unfortunate consequence of there
615 // being no serialization code for PartialDiagnostics and the fact
616 // that serializing them would likely take a lot more storage than
617 // just storing them as strings. We would still like, in the
618 // future, to serialize the proper PartialDiagnostic as serializing
619 // it as a string defeats the purpose of the diagnostic mechanism.
620 Satisfaction.Details.emplace_back(
622 SubstDiag.first,
623 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
624 Satisfaction.IsSatisfied = false;
625 return ExprEmpty();
626 }
627 }
628
629 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
630 return ExprError();
631
632 // [temp.constr.atomic]p3: To determine if an atomic constraint is
633 // satisfied, the parameter mapping and template arguments are first
634 // substituted into its expression. If substitution results in an
635 // invalid type or expression, the constraint is not satisfied.
636 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
637 // and E shall be a constant expression of type bool.
638 //
639 // Perform the L to R Value conversion if necessary. We do so for all
640 // non-PRValue categories, else we fail to extend the lifetime of
641 // temporaries, and that fails the constant expression check.
642 if (!SubstitutedExpression.get()->isPRValue())
643 SubstitutedExpression = ImplicitCastExpr::Create(
644 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
645 SubstitutedExpression.get(),
646 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
647
648 return SubstitutedExpression;
649}
650
651std::optional<MultiLevelTemplateArgumentList>
652ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
653 const NormalizedConstraintWithParamMapping &Constraint,
655 llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {
656
657 if (!Constraint.hasParameterMapping()) {
658 if (MLTAL.getNumSubstitutedLevels())
659 SubstitutedOutermost.assign(MLTAL.getOutermost());
660 return MLTAL;
661 }
662
663 // The mapping is empty, meaning no template arguments are needed for
664 // evaluation.
665 if (Constraint.getParameterMapping().empty())
667
668 TemplateDeductionInfo Info(Constraint.getBeginLoc());
669 Sema::SFINAETrap Trap(S, Info);
671 S, Constraint.getBeginLoc(),
673 // FIXME: improve const-correctness of InstantiatingTemplate
674 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
675 if (Inst.isInvalid())
676 return std::nullopt;
677
678 TemplateArgumentListInfo SubstArgs;
679 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
680
681 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
682 &CachedTemplateArgs);
683
685 Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,
686 SubstArgs)) {
687 Satisfaction.IsSatisfied = false;
688 return std::nullopt;
689 }
690
692 auto *TD = const_cast<TemplateDecl *>(
695 TD->getLocation(), SubstArgs,
696 /*DefaultArguments=*/{},
697 /*PartialTemplateArgs=*/false, CTAI))
698 return std::nullopt;
700 Constraint.mappingOccurenceList();
701 // The empty MLTAL situation should only occur when evaluating non-dependent
702 // constraints.
703 if (MLTAL.getNumSubstitutedLevels())
704 SubstitutedOutermost =
705 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
706 unsigned Offset = 0;
707 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
709 if (Used[I])
711 CTAI.SugaredConverted[MappedIndex++]);
712 if (I < SubstitutedOutermost.size()) {
713 SubstitutedOutermost[I] = Arg;
714 Offset = I + 1;
715 } else {
716 SubstitutedOutermost.push_back(Arg);
717 Offset = SubstitutedOutermost.size();
718 }
719 }
720 if (Offset < SubstitutedOutermost.size())
721 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
722
723 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
724 SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,
725 /*Final=*/false);
726 return std::move(SubstitutedTemplateArgs);
727}
728
729ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
730 const AtomicConstraint &Constraint,
731 const MultiLevelTemplateArgumentList &MLTAL) {
732 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
733 EvaluationContext.emplace(
736
737 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
738 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
739 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
740 if (!SubstitutedArgs) {
741 Satisfaction.IsSatisfied = false;
742 return ExprEmpty();
743 }
744
745 // Make sure that concepts are not evaluated in the context they are used,
746 // i.e they should not have access to the current class object or its
747 // non-public members.
748 std::optional<Sema::ContextRAII> ConceptContext;
749 if (ParentConcept) {
750 ConceptContext.emplace(S, ParentConcept->getDeclContext());
751 // FIXME: the evaluation context should learn to track template arguments
752 // separately from a Decl.
753 EvaluationContext.emplace(
755 /*LambdaContextDecl=*/
757 S.Context, ParentConcept->getDeclContext(),
758 ParentConcept->getBeginLoc(), SubstitutedOutermost));
759 }
760
761 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
762 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
763 Constraint.getConstraintExpr(), *SubstitutedArgs);
764
765 if (SubstitutedAtomicExpr.isInvalid())
766 return ExprError();
767
768 if (SubstitutedAtomicExpr.isUnset())
769 // Evaluator has decided satisfaction without yielding an expression.
770 return ExprEmpty();
771
772 // We don't have the ability to evaluate this, since it contains a
773 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
774 // we'd potentially pick up a different overload, and cause confusing
775 // diagnostics. SO, add a failure detail that will cause us to make this
776 // overload set not viable.
777 if (SubstitutedAtomicExpr.get()->containsErrors()) {
778 Satisfaction.IsSatisfied = false;
779 Satisfaction.ContainsErrors = true;
780
781 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
782 Satisfaction.Details.emplace_back(
784 SubstitutedAtomicExpr.get()->getBeginLoc(),
785 allocateStringFromConceptDiagnostic(S, Msg)});
786 return SubstitutedAtomicExpr;
787 }
788
789 if (SubstitutedAtomicExpr.get()->isValueDependent()) {
790 Satisfaction.IsSatisfied = true;
791 Satisfaction.ContainsErrors = false;
792 return SubstitutedAtomicExpr;
793 }
794
796 Expr::EvalResult EvalResult;
797 EvalResult.Diag = &EvaluationDiags;
798 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
799 S.Context) ||
800 !EvaluationDiags.empty()) {
801 // C++2a [temp.constr.atomic]p1
802 // ...E shall be a constant expression of type bool.
803 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
804 diag::err_non_constant_constraint_expression)
805 << SubstitutedAtomicExpr.get()->getSourceRange();
806 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
807 S.Diag(PDiag.first, PDiag.second);
808 return ExprError();
809 }
810
811 assert(EvalResult.Val.isInt() &&
812 "evaluating bool expression didn't produce int");
813 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
814 if (!Satisfaction.IsSatisfied)
815 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
816
817 return SubstitutedAtomicExpr;
818}
819
820ExprResult ConstraintSatisfactionChecker::Evaluate(
821 const AtomicConstraint &Constraint,
822 const MultiLevelTemplateArgumentList &MLTAL) {
823
824 unsigned Size = Satisfaction.Details.size();
825 llvm::FoldingSetNodeID ID;
826 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
827
828 ID.AddPointer(Constraint.getConstraintExpr());
829 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
830 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
831 .VisitConstraint(Constraint);
832
833 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
835 auto &Cached = Iter->second.Satisfaction;
836 Satisfaction.ContainsErrors = Cached.ContainsErrors;
837 Satisfaction.IsSatisfied = Cached.IsSatisfied;
838 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
839 Cached.Details.begin(), Cached.Details.end());
840 return Iter->second.SubstExpr;
841 }
842
843 ExprResult E = EvaluateSlow(Constraint, MLTAL);
844
846 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
847 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
848 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
849 Satisfaction.Details.begin() + Size,
850 Satisfaction.Details.end());
851 Cache.SubstExpr = E;
852 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
853
854 return E;
855}
856
858ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
859 const FoldExpandedConstraint &FE,
860 const MultiLevelTemplateArgumentList &MLTAL) {
861
862 Expr *Pattern = const_cast<Expr *>(FE.getPattern());
863
865 S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
866 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
867 bool Expand = true;
868 bool RetainExpansion = false;
869 UnsignedOrNone NumExpansions(std::nullopt);
871 Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
872 /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,
873 NumExpansions, /*Diagnose=*/false) ||
874 !Expand || RetainExpansion)
875 return std::nullopt;
876
877 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)
878 return std::nullopt;
879 return NumExpansions;
880}
881
882ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
883 const FoldExpandedConstraint &Constraint,
884 const MultiLevelTemplateArgumentList &MLTAL) {
885
886 bool Conjunction = Constraint.getFoldOperator() ==
888 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
889
890 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
891 // FIXME: Is PackSubstitutionIndex correct?
892 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
893 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
894 SubstitutionInTemplateArguments(
895 static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),
896 MLTAL, SubstitutedOutermost);
897 if (!SubstitutedArgs) {
898 Satisfaction.IsSatisfied = false;
899 return ExprError();
900 }
901
903 UnsignedOrNone NumExpansions =
904 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
905 if (!NumExpansions)
906 return ExprEmpty();
907
908 if (*NumExpansions == 0) {
909 Satisfaction.IsSatisfied = Conjunction;
910 return ExprEmpty();
911 }
912
913 for (unsigned I = 0; I < *NumExpansions; I++) {
914 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
915 Satisfaction.IsSatisfied = false;
916 Satisfaction.ContainsErrors = false;
918 ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,
919 UnsignedOrNone(I), Satisfaction,
920 /*BuildExpression=*/false)
921 .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);
922 if (BuildExpression) {
923 if (Out.isUnset() || !Expr.isUsable())
924 Out = Expr;
925 else
926 Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),
927 Conjunction ? BinaryOperatorKind::BO_LAnd
928 : BinaryOperatorKind::BO_LOr,
930 Constraint.getBeginLoc(),
932 }
933 if (!Conjunction && Satisfaction.IsSatisfied) {
934 Satisfaction.Details.erase(Satisfaction.Details.begin() +
935 EffectiveDetailEndIndex,
936 Satisfaction.Details.end());
937 break;
938 }
939 if (Satisfaction.IsSatisfied != Conjunction)
940 return Out;
941 }
942
943 return Out;
944}
945
946ExprResult ConstraintSatisfactionChecker::Evaluate(
947 const FoldExpandedConstraint &Constraint,
948 const MultiLevelTemplateArgumentList &MLTAL) {
949
950 llvm::FoldingSetNodeID ID;
951 ID.AddPointer(Constraint.getPattern());
952 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
953
954 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
956
957 auto &Cached = Iter->second.Satisfaction;
958 Satisfaction.ContainsErrors = Cached.ContainsErrors;
959 Satisfaction.IsSatisfied = Cached.IsSatisfied;
960 Satisfaction.Details.insert(Satisfaction.Details.end(),
961 Cached.Details.begin(), Cached.Details.end());
962 return Iter->second.SubstExpr;
963 }
964
965 unsigned Size = Satisfaction.Details.size();
966
967 ExprResult E = EvaluateSlow(Constraint, MLTAL);
969 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
970 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
971 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
972 Satisfaction.Details.begin() + Size,
973 Satisfaction.Details.end());
974 Cache.SubstExpr = E;
975 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
976 return E;
977}
978
979ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
980 const ConceptIdConstraint &Constraint,
981 const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
982 const ConceptReference *ConceptId = Constraint.getConceptId();
983
984 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
985 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
986 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
987
988 if (!SubstitutedArgs) {
989 Satisfaction.IsSatisfied = false;
990 // FIXME: diagnostics?
991 return ExprError();
992 }
993
994 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
995
996 const ASTTemplateArgumentListInfo *Ori =
997 ConceptId->getTemplateArgsAsWritten();
998 TemplateDeductionInfo Info(TemplateNameLoc);
999 Sema::SFINAETrap Trap(S, Info);
1002 const_cast<NamedDecl *>(Template), Constraint.getSourceRange());
1003
1004 TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);
1005 if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, OutArgs) ||
1006 Trap.hasErrorOccurred()) {
1007 Satisfaction.IsSatisfied = false;
1008 if (!Trap.hasErrorOccurred())
1009 return ExprError();
1010
1013 Info.takeSFINAEDiagnostic(SubstDiag);
1014 // FIXME: This is an unfortunate consequence of there
1015 // being no serialization code for PartialDiagnostics and the fact
1016 // that serializing them would likely take a lot more storage than
1017 // just storing them as strings. We would still like, in the
1018 // future, to serialize the proper PartialDiagnostic as serializing
1019 // it as a string defeats the purpose of the diagnostic mechanism.
1020 Satisfaction.Details.insert(
1021 Satisfaction.Details.begin() + Size,
1023 SubstDiag.first,
1024 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
1025 return ExprError();
1026 }
1027
1028 CXXScopeSpec SS;
1029 SS.Adopt(ConceptId->getNestedNameSpecifierLoc());
1030
1031 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1032 SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),
1033 ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs,
1034 /*DoCheckConstraintSatisfaction=*/false);
1035
1036 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
1037 return ExprError();
1038
1039 if (Size != Satisfaction.Details.size()) {
1040 Satisfaction.Details.insert(
1041 Satisfaction.Details.begin() + Size,
1043 SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
1044 ->getConceptReference()));
1045 }
1046 return SubstitutedConceptId;
1047}
1048
1049ExprResult ConstraintSatisfactionChecker::Evaluate(
1050 const ConceptIdConstraint &Constraint,
1051 const MultiLevelTemplateArgumentList &MLTAL) {
1052
1053 const ConceptReference *ConceptId = Constraint.getConceptId();
1054 Sema::InstantiatingTemplate InstTemplate(
1055 S, ConceptId->getBeginLoc(),
1057 ConceptId->getNamedConcept(),
1058 // We may have empty template arguments when checking non-dependent
1059 // nested constraint expressions.
1060 // In such cases, non-SFINAE errors would have already been diagnosed
1061 // during parameter mapping substitution, so the instantiating template
1062 // arguments are less useful here.
1063 MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()
1065 Constraint.getSourceRange());
1066 if (InstTemplate.isInvalid())
1067 return ExprError();
1068
1069 unsigned Size = Satisfaction.Details.size();
1070
1071 llvm::SaveAndRestore PushConceptDecl(
1072 ParentConcept, cast<ConceptDecl>(ConceptId->getNamedConcept()));
1073
1074 ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);
1075
1076 if (E.isInvalid()) {
1077 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1078 return E;
1079 }
1080
1081 // ConceptIdConstraint is only relevant for diagnostics,
1082 // so if the normalized constraint is satisfied, we should not
1083 // substitute into the constraint.
1084 if (Satisfaction.IsSatisfied)
1085 return E;
1086
1087 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
1088 llvm::FoldingSetNodeID ID;
1089 ID.AddPointer(Constraint.getConceptId());
1090 ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
1091 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1092 .VisitConstraint(Constraint);
1093
1094 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
1096
1097 auto &Cached = Iter->second.Satisfaction;
1098 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1099 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1100 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1101 Cached.Details.begin(), Cached.Details.end());
1102 return Iter->second.SubstExpr;
1103 }
1104
1105 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1106 if (CE.isInvalid())
1107 return E;
1109 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1110 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1111 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1112 Satisfaction.Details.begin() + Size,
1113 Satisfaction.Details.end());
1114 Cache.SubstExpr = CE;
1115 S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});
1116 return CE;
1117}
1118
1119ExprResult ConstraintSatisfactionChecker::Evaluate(
1120 const CompoundConstraint &Constraint,
1121 const MultiLevelTemplateArgumentList &MLTAL) {
1122
1123 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1124
1125 bool Conjunction =
1127
1128 ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);
1129
1130 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1131 return LHS;
1132
1133 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
1134 !Satisfaction.ContainsErrors)
1135 return LHS;
1136
1137 Satisfaction.ContainsErrors = false;
1138 Satisfaction.IsSatisfied = false;
1139
1140 ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);
1141
1142 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
1143 !Satisfaction.ContainsErrors)
1144 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1145 EffectiveDetailEndIndex,
1146 Satisfaction.Details.end());
1147
1148 if (!BuildExpression)
1149 return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();
1150
1151 if (!LHS.isUsable())
1152 return RHS;
1153
1154 if (!RHS.isUsable())
1155 return LHS;
1156
1157 return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),
1158 Conjunction ? BinaryOperatorKind::BO_LAnd
1159 : BinaryOperatorKind::BO_LOr,
1161 Constraint.getBeginLoc(), FPOptionsOverride{});
1162}
1163
1164ExprResult ConstraintSatisfactionChecker::Evaluate(
1165 const NormalizedConstraint &Constraint,
1166 const MultiLevelTemplateArgumentList &MLTAL) {
1167 switch (Constraint.getKind()) {
1169 return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);
1170
1172 return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),
1173 MLTAL);
1174
1176 return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),
1177 MLTAL);
1178
1180 return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);
1181 }
1182 llvm_unreachable("Unknown ConstraintKind enum");
1183}
1184
1186 Sema &S, const NamedDecl *Template,
1187 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1188 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1189 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
1190 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1191
1192 if (ConvertedExpr)
1193 *ConvertedExpr = nullptr;
1194
1195 if (AssociatedConstraints.empty()) {
1196 Satisfaction.IsSatisfied = true;
1197 return false;
1198 }
1199
1200 // In the general case, we can't check satisfaction if the arguments contain
1201 // unsubstituted template parameters, even if they are purely syntactic,
1202 // because they may still turn out to be invalid after substitution.
1203 // This could be permitted in cases where this substitution will still be
1204 // attempted later and diagnosed, such as function template specializations,
1205 // but that's not the case for concept specializations.
1206 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
1207 Satisfaction.IsSatisfied = true;
1208 return false;
1209 }
1210
1212 if (TemplateArgsLists.getNumLevels() != 0)
1213 Args = TemplateArgsLists.getInnermost();
1214
1215 struct SynthesisContextPair {
1218 SynthesisContextPair(Sema &S, NamedDecl *Template,
1219 ArrayRef<TemplateArgument> TemplateArgs,
1220 SourceRange InstantiationRange)
1221 : Inst(S, InstantiationRange.getBegin(),
1223 TemplateArgs, InstantiationRange),
1224 NSC(S) {}
1225 };
1226 std::optional<SynthesisContextPair> SynthesisContext;
1227 if (!TopLevelConceptId)
1228 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
1229 TemplateIDRange);
1230
1231 const NormalizedConstraint *C =
1232 S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);
1233 if (!C) {
1234 Satisfaction.IsSatisfied = false;
1235 return true;
1236 }
1237
1238 if (TopLevelConceptId)
1239 C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
1240 const_cast<NormalizedConstraint *>(C),
1241 Template, /*CSE=*/nullptr,
1243
1244 ExprResult Res = ConstraintSatisfactionChecker(
1245 S, Template, TemplateIDRange.getBegin(),
1246 S.ArgPackSubstIndex, Satisfaction,
1247 /*BuildExpression=*/ConvertedExpr != nullptr)
1248 .Evaluate(*C, TemplateArgsLists);
1249
1250 if (Res.isInvalid())
1251 return true;
1252
1253 if (Res.isUsable() && ConvertedExpr)
1254 *ConvertedExpr = Res.get();
1255
1256 return false;
1257}
1258
1261 ArrayRef<AssociatedConstraint> AssociatedConstraints,
1262 const MultiLevelTemplateArgumentList &TemplateArgsLists,
1263 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
1264 const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
1265 llvm::TimeTraceScope TimeScope(
1266 "CheckConstraintSatisfaction", [TemplateIDRange, this] {
1267 return TemplateIDRange.printToString(getSourceManager());
1268 });
1269 if (AssociatedConstraints.empty()) {
1270 OutSatisfaction.IsSatisfied = true;
1271 return false;
1272 }
1273 const auto *Template = Entity.dyn_cast<const NamedDecl *>();
1274 if (!Template) {
1275 return ::CheckConstraintSatisfaction(
1276 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1277 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1278 }
1279 // Invalid templates could make their way here. Substituting them could result
1280 // in dependent expressions.
1281 if (Template->isInvalidDecl()) {
1282 OutSatisfaction.IsSatisfied = false;
1283 return true;
1284 }
1285
1286 // A list of the template argument list flattened in a predictible manner for
1287 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
1288 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
1289 // here.
1291 for (auto List : TemplateArgsLists)
1292 for (const TemplateArgument &Arg : List.Args)
1293 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1294
1295 const NamedDecl *Owner = Template;
1296 if (TopLevelConceptId)
1297 Owner = TopLevelConceptId->getNamedConcept();
1298
1299 llvm::FoldingSetNodeID ID;
1300 ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);
1301 void *InsertPos;
1302 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1303 OutSatisfaction = *Cached;
1304 return false;
1305 }
1306
1307 auto Satisfaction =
1308 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1310 *this, Template, AssociatedConstraints, TemplateArgsLists,
1311 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1312 OutSatisfaction = std::move(*Satisfaction);
1313 return true;
1314 }
1315
1316 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1317 // The evaluation of this constraint resulted in us trying to re-evaluate it
1318 // recursively. This isn't really possible, except we try to form a
1319 // RecoveryExpr as a part of the evaluation. If this is the case, just
1320 // return the 'cached' version (which will have the same result), and save
1321 // ourselves the extra-insert. If it ever becomes possible to legitimately
1322 // recursively check a constraint, we should skip checking the 'inner' one
1323 // above, and replace the cached version with this one, as it would be more
1324 // specific.
1325 OutSatisfaction = *Cached;
1326 return false;
1327 }
1328
1329 // Else we can simply add this satisfaction to the list.
1330 OutSatisfaction = *Satisfaction;
1331 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
1332 // invalidated it.
1333 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
1334 SatisfactionCache.InsertNode(Satisfaction.release());
1335 return false;
1336}
1337
1338static ExprResult
1340 const ConceptSpecializationExpr *CSE,
1341 UnsignedOrNone SubstIndex) {
1342 Sema::SFINAETrap Trap(S);
1343 // [C++2c] [temp.constr.normal]
1344 // Otherwise, to form CE, any non-dependent concept template argument Ai
1345 // is substituted into the constraint-expression of C.
1346 // If any such substitution results in an invalid concept-id,
1347 // the program is ill-formed; no diagnostic is required.
1348
1350 Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
1351
1352 const ASTTemplateArgumentListInfo *ArgsAsWritten =
1354 if (llvm::none_of(
1355 ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {
1356 return !ArgLoc.getArgument().isDependent() &&
1357 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1358 })) {
1359 return Concept->getConstraintExpr();
1360 }
1361
1363 Concept, Concept->getLexicalDeclContext(),
1364 /*Final=*/false, CSE->getTemplateArguments(),
1365 /*RelativeToPrimary=*/true,
1366 /*Pattern=*/nullptr,
1367 /*ForConstraintInstantiation=*/true);
1368 return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),
1369 MLTAL);
1370}
1371
1372bool Sema::SetupConstraintScope(
1373 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1374 const MultiLevelTemplateArgumentList &MLTAL,
1376 assert(!isLambdaCallOperator(FD) &&
1377 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1378 "instantiations");
1379 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
1380 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
1382 *this, FD->getPointOfInstantiation(),
1383 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1384 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1385 SourceRange());
1386 if (Inst.isInvalid())
1387 return true;
1388
1389 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
1390 // 'instantiated' parameters and adds it to the context. For the case where
1391 // this function is a template being instantiated NOW, we also need to add
1392 // the list of current template arguments to the list so that they also can
1393 // be picked out of the map.
1394 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
1395 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1396 /*Final=*/false);
1397 if (addInstantiatedParametersToScope(
1398 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
1399 return true;
1400 }
1401
1402 // If this is a member function, make sure we get the parameters that
1403 // reference the original primary template.
1404 if (FunctionTemplateDecl *FromMemTempl =
1405 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
1406 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1407 Scope, MLTAL))
1408 return true;
1409 }
1410
1411 return false;
1412 }
1413
1416 FunctionDecl *InstantiatedFrom =
1420
1422 *this, FD->getPointOfInstantiation(),
1423 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1424 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1425 SourceRange());
1426 if (Inst.isInvalid())
1427 return true;
1428
1429 // Case where this was not a template, but instantiated as a
1430 // child-function.
1431 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1432 return true;
1433 }
1434
1435 return false;
1436}
1437
1438// This function collects all of the template arguments for the purposes of
1439// constraint-instantiation and checking.
1440std::optional<MultiLevelTemplateArgumentList>
1441Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1442 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
1444 MultiLevelTemplateArgumentList MLTAL;
1445
1446 // Collect the list of template arguments relative to the 'primary' template.
1447 // We need the entire list, since the constraint is completely uninstantiated
1448 // at this point.
1449 MLTAL =
1451 /*Final=*/false, /*Innermost=*/std::nullopt,
1452 /*RelativeToPrimary=*/true,
1453 /*Pattern=*/nullptr,
1454 /*ForConstraintInstantiation=*/true);
1455 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
1456 if (isLambdaCallOperator(FD))
1457 return MLTAL;
1458 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1459 return std::nullopt;
1460
1461 return MLTAL;
1462}
1463
1465 ConstraintSatisfaction &Satisfaction,
1466 SourceLocation UsageLoc,
1467 bool ForOverloadResolution) {
1468 // Don't check constraints if the function is dependent. Also don't check if
1469 // this is a function template specialization, as the call to
1470 // CheckFunctionTemplateConstraints after this will check it
1471 // better.
1472 if (FD->isDependentContext() ||
1473 FD->getTemplatedKind() ==
1475 Satisfaction.IsSatisfied = true;
1476 return false;
1477 }
1478
1479 // A lambda conversion operator has the same constraints as the call operator
1480 // and constraints checking relies on whether we are in a lambda call operator
1481 // (and may refer to its parameters), so check the call operator instead.
1482 // Note that the declarations outside of the lambda should also be
1483 // considered. Turning on the 'ForOverloadResolution' flag results in the
1484 // LocalInstantiationScope not looking into its parents, but we can still
1485 // access Decls from the parents while building a lambda RAII scope later.
1486 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1487 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
1488 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
1489 Satisfaction, UsageLoc,
1490 /*ShouldAddDeclsFromParentScope=*/true);
1491
1492 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
1493
1494 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
1495 if (isLambdaCallOperator(CtxToSave))
1496 CtxToSave = CtxToSave->getParent()->getParent();
1497 else
1498 CtxToSave = CtxToSave->getNonTransparentContext();
1499 }
1500
1501 ContextRAII SavedContext{*this, CtxToSave};
1502 LocalInstantiationScope Scope(*this, !ForOverloadResolution);
1503 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1504 SetupConstraintCheckingTemplateArgumentsAndScope(
1505 const_cast<FunctionDecl *>(FD), {}, Scope);
1506
1507 if (!MLTAL)
1508 return true;
1509
1510 Qualifiers ThisQuals;
1511 CXXRecordDecl *Record = nullptr;
1512 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1513 ThisQuals = Method->getMethodQualifiers();
1514 Record = const_cast<CXXRecordDecl *>(Method->getParent());
1515 }
1516 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1517
1519 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
1520 ForOverloadResolution);
1521
1523 FD, FD->getTrailingRequiresClause(), *MLTAL,
1524 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
1525 Satisfaction);
1526}
1527
1529 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
1530 const Expr *ConstrExpr) {
1532 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
1533 /*Innermost=*/std::nullopt,
1534 /*RelativeToPrimary=*/true,
1535 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
1536 /*SkipForSpecialization*/ false);
1537
1538 if (MLTAL.getNumSubstitutedLevels() == 0)
1539 return ConstrExpr;
1540
1541 // Set up a dummy 'instantiation' scope in the case of reference to function
1542 // parameters that the surrounding function hasn't been instantiated yet. Note
1543 // this may happen while we're comparing two templates' constraint
1544 // equivalence.
1545 std::optional<LocalInstantiationScope> ScopeForParameters;
1546 if (const NamedDecl *ND = DeclInfo.getDecl();
1547 ND && ND->isFunctionOrFunctionTemplate()) {
1548 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
1549 const FunctionDecl *FD = ND->getAsFunction();
1551 Template && Template->getInstantiatedFromMemberTemplate())
1552 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1553 for (auto *PVD : FD->parameters()) {
1554 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1555 continue;
1556 if (!PVD->isParameterPack()) {
1557 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1558 continue;
1559 }
1560 // This is hacky: we're mapping the parameter pack to a size-of-1 argument
1561 // to avoid building SubstTemplateTypeParmPackTypes for
1562 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
1563 // otherwise reference the AssociatedDecl of the template arguments, which
1564 // is, in this case, the template declaration.
1565 //
1566 // However, as we are in the process of comparing potential
1567 // re-declarations, the canonical declaration is the declaration itself at
1568 // this point. So if we didn't expand these packs, we would end up with an
1569 // incorrect profile difference because we will be profiling the
1570 // canonical types!
1571 //
1572 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1573 // that we can eliminate the Scope in the cases where the declarations are
1574 // not necessarily instantiated. It would also benefit the noexcept
1575 // specifier comparison.
1576 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1577 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1578 }
1579 }
1580
1581 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1582
1583 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1584 // essential for having an injected class as the canonical type for a template
1585 // specialization type at the rebuilding stage. This guarantees that, for
1586 // out-of-line definitions, injected class name types and their equivalent
1587 // template specializations can be profiled to the same value, which makes it
1588 // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1589 // perceived identical.
1590 std::optional<Sema::ContextRAII> ContextScope;
1591 const DeclContext *DC = [&] {
1592 if (!DeclInfo.getDecl())
1593 return DeclInfo.getDeclContext();
1594 return DeclInfo.getDecl()->getFriendObjectKind()
1595 ? DeclInfo.getLexicalDeclContext()
1596 : DeclInfo.getDeclContext();
1597 }();
1598 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1599 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1600 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1601 /*NewThisContext=*/false);
1602 }
1603 EnterExpressionEvaluationContext UnevaluatedContext(
1607 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1608 if (!SubstConstr.isUsable())
1609 return nullptr;
1610 return SubstConstr.get();
1611}
1612
1614 const Expr *OldConstr,
1616 const Expr *NewConstr) {
1617 if (OldConstr == NewConstr)
1618 return true;
1619 // C++ [temp.constr.decl]p4
1620 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
1621 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
1622 Sema::SFINAETrap _(*this);
1623 if (const Expr *SubstConstr =
1625 OldConstr))
1626 OldConstr = SubstConstr;
1627 else
1628 return false;
1629 if (const Expr *SubstConstr =
1631 NewConstr))
1632 NewConstr = SubstConstr;
1633 else
1634 return false;
1635 }
1636
1637 llvm::FoldingSetNodeID ID1, ID2;
1638 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1639 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1640 return ID1 == ID2;
1641}
1642
1644 assert(FD->getFriendObjectKind() && "Must be a friend!");
1645
1646 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1647 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1648 // non-function-template.
1649 assert(FD->getDescribedFunctionTemplate() &&
1650 "Non-function templates don't need to be checked");
1651
1654
1655 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1656 for (const AssociatedConstraint &AC : ACs)
1657 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1658 AC.ConstraintExpr))
1659 return true;
1660
1661 return false;
1662}
1663
1665 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1666 SourceRange TemplateIDRange) {
1667 ConstraintSatisfaction Satisfaction;
1668 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1669 TD->getAssociatedConstraints(AssociatedConstraints);
1670 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1671 TemplateIDRange, Satisfaction))
1672 return true;
1673
1674 if (!Satisfaction.IsSatisfied) {
1675 SmallString<128> TemplateArgString;
1676 TemplateArgString = " ";
1677 TemplateArgString += getTemplateArgumentBindingsText(
1678 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1679 TemplateArgsLists.getInnermost().size());
1680
1681 Diag(TemplateIDRange.getBegin(),
1682 diag::err_template_arg_list_constraints_not_satisfied)
1684 << TemplateArgString << TemplateIDRange;
1685 DiagnoseUnsatisfiedConstraint(Satisfaction);
1686 return true;
1687 }
1688 return false;
1689}
1690
1692 Sema &SemaRef, SourceLocation PointOfInstantiation,
1694 ConstraintSatisfaction &Satisfaction) {
1696 Template->getAssociatedConstraints(TemplateAC);
1697 if (TemplateAC.empty()) {
1698 Satisfaction.IsSatisfied = true;
1699 return false;
1700 }
1701
1703
1704 FunctionDecl *FD = Template->getTemplatedDecl();
1705 // Collect the list of template arguments relative to the 'primary'
1706 // template. We need the entire list, since the constraint is completely
1707 // uninstantiated at this point.
1708
1710 {
1711 // getTemplateInstantiationArgs uses this instantiation context to find out
1712 // template arguments for uninstantiated functions.
1713 // We don't want this RAII object to persist, because there would be
1714 // otherwise duplicate diagnostic notes.
1716 SemaRef, PointOfInstantiation,
1718 PointOfInstantiation);
1719 if (Inst.isInvalid())
1720 return true;
1721 MLTAL = SemaRef.getTemplateInstantiationArgs(
1722 /*D=*/FD, FD,
1723 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1724 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1725 }
1726
1727 Sema::ContextRAII SavedContext(SemaRef, FD);
1728 return SemaRef.CheckConstraintSatisfaction(
1729 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1730}
1731
1733 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1734 ArrayRef<TemplateArgument> TemplateArgs,
1735 ConstraintSatisfaction &Satisfaction) {
1736 // In most cases we're not going to have constraints, so check for that first.
1737 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1738
1739 if (!Template)
1740 return ::CheckFunctionConstraintsWithoutInstantiation(
1741 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1742 TemplateArgs, Satisfaction);
1743
1744 // Note - code synthesis context for the constraints check is created
1745 // inside CheckConstraintsSatisfaction.
1747 Template->getAssociatedConstraints(TemplateAC);
1748 if (TemplateAC.empty()) {
1749 Satisfaction.IsSatisfied = true;
1750 return false;
1751 }
1752
1753 // Enter the scope of this instantiation. We don't use
1754 // PushDeclContext because we don't have a scope.
1755 Sema::ContextRAII savedContext(*this, Decl);
1757
1758 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1759 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1760 Scope);
1761
1762 if (!MLTAL)
1763 return true;
1764
1765 Qualifiers ThisQuals;
1766 CXXRecordDecl *Record = nullptr;
1767 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1768 ThisQuals = Method->getMethodQualifiers();
1769 Record = Method->getParent();
1770 }
1771
1772 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1773 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1774 Scope);
1775
1776 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1777 PointOfInstantiation, Satisfaction);
1778}
1779
1782 bool First) {
1783 assert(!Req->isSatisfied() &&
1784 "Diagnose() can only be used on an unsatisfied requirement");
1785 switch (Req->getSatisfactionStatus()) {
1787 llvm_unreachable("Diagnosing a dependent requirement");
1788 break;
1790 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1791 if (!SubstDiag->DiagMessage.empty())
1792 S.Diag(SubstDiag->DiagLoc,
1793 diag::note_expr_requirement_expr_substitution_error)
1794 << (int)First << SubstDiag->SubstitutedEntity
1795 << SubstDiag->DiagMessage;
1796 else
1797 S.Diag(SubstDiag->DiagLoc,
1798 diag::note_expr_requirement_expr_unknown_substitution_error)
1799 << (int)First << SubstDiag->SubstitutedEntity;
1800 break;
1801 }
1803 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1804 << (int)First << Req->getExpr();
1805 break;
1807 auto *SubstDiag =
1809 if (!SubstDiag->DiagMessage.empty())
1810 S.Diag(SubstDiag->DiagLoc,
1811 diag::note_expr_requirement_type_requirement_substitution_error)
1812 << (int)First << SubstDiag->SubstitutedEntity
1813 << SubstDiag->DiagMessage;
1814 else
1815 S.Diag(
1816 SubstDiag->DiagLoc,
1817 diag::
1818 note_expr_requirement_type_requirement_unknown_substitution_error)
1819 << (int)First << SubstDiag->SubstitutedEntity;
1820 break;
1821 }
1823 ConceptSpecializationExpr *ConstraintExpr =
1825 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);
1826 break;
1827 }
1829 llvm_unreachable("We checked this above");
1830 }
1831}
1832
1835 bool First) {
1836 assert(!Req->isSatisfied() &&
1837 "Diagnose() can only be used on an unsatisfied requirement");
1838 switch (Req->getSatisfactionStatus()) {
1840 llvm_unreachable("Diagnosing a dependent requirement");
1841 return;
1843 auto *SubstDiag = Req->getSubstitutionDiagnostic();
1844 if (!SubstDiag->DiagMessage.empty())
1845 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1846 << (int)First << SubstDiag->SubstitutedEntity
1847 << SubstDiag->DiagMessage;
1848 else
1849 S.Diag(SubstDiag->DiagLoc,
1850 diag::note_type_requirement_unknown_substitution_error)
1851 << (int)First << SubstDiag->SubstitutedEntity;
1852 return;
1853 }
1854 default:
1855 llvm_unreachable("Unknown satisfaction status");
1856 return;
1857 }
1858}
1859
1862 SourceLocation Loc, bool First) {
1863 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1864 S.Diag(
1865 Loc,
1866 diag::
1867 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1868 << (int)First
1869 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1870 << Concept->getNamedConcept();
1871 } else {
1872 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1873 << (int)First << Concept;
1874 }
1875}
1876
1879 bool First, concepts::NestedRequirement *Req = nullptr);
1880
1883 bool First = true, concepts::NestedRequirement *Req = nullptr) {
1884 for (auto &Record : Records) {
1886 Loc = {};
1888 }
1889}
1890
1900
1902 const Expr *SubstExpr,
1903 bool First) {
1904 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1905 if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1906 switch (BO->getOpcode()) {
1907 // These two cases will in practice only be reached when using fold
1908 // expressions with || and &&, since otherwise the || and && will have been
1909 // broken down into atomic constraints during satisfaction checking.
1910 case BO_LOr:
1911 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1914 /*First=*/false);
1915 return;
1916 case BO_LAnd: {
1917 bool LHSSatisfied =
1918 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1919 if (LHSSatisfied) {
1920 // LHS is true, so RHS must be false.
1922 return;
1923 }
1924 // LHS is false
1926
1927 // RHS might also be false
1928 bool RHSSatisfied =
1929 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1930 if (!RHSSatisfied)
1932 /*First=*/false);
1933 return;
1934 }
1935 case BO_GE:
1936 case BO_LE:
1937 case BO_GT:
1938 case BO_LT:
1939 case BO_EQ:
1940 case BO_NE:
1941 if (BO->getLHS()->getType()->isIntegerType() &&
1942 BO->getRHS()->getType()->isIntegerType()) {
1943 Expr::EvalResult SimplifiedLHS;
1944 Expr::EvalResult SimplifiedRHS;
1945 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1947 /*InConstantContext=*/true);
1948 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1950 /*InConstantContext=*/true);
1951 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1952 S.Diag(SubstExpr->getBeginLoc(),
1953 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1954 << (int)First << SubstExpr
1955 << toString(SimplifiedLHS.Val.getInt(), 10)
1956 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1957 << toString(SimplifiedRHS.Val.getInt(), 10);
1958 return;
1959 }
1960 }
1961 break;
1962
1963 default:
1964 break;
1965 }
1966 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1967 // FIXME: RequiresExpr should store dependent diagnostics.
1968 for (concepts::Requirement *Req : RE->getRequirements())
1969 if (!Req->isDependent() && !Req->isSatisfied()) {
1970 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1972 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1974 else
1977 break;
1978 }
1979 return;
1980 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1981 // Drill down concept ids treated as atomic constraints
1983 return;
1984 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1985 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1986 assert(TTE->getNumArgs() == 2);
1987 S.Diag(SubstExpr->getSourceRange().getBegin(),
1988 diag::note_is_deducible_constraint_evaluated_to_false)
1989 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1990 return;
1991 }
1992
1993 S.Diag(SubstExpr->getSourceRange().getBegin(),
1994 diag::note_atomic_constraint_evaluated_to_false)
1995 << (int)First << SubstExpr;
1996 S.DiagnoseTypeTraitDetails(SubstExpr);
1997}
1998
2002 if (auto *Diag =
2003 Record
2004 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
2005 if (Req)
2006 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
2007 << (int)First << Req->getInvalidConstraintEntity() << Diag->second;
2008 else
2009 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2010 << Diag->second;
2011 return;
2012 }
2013 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
2014 if (Loc.isInvalid())
2015 Loc = Concept->getBeginLoc();
2017 return;
2018 }
2021}
2022
2024 const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,
2025 bool First) {
2026
2027 assert(!Satisfaction.IsSatisfied &&
2028 "Attempted to diagnose a satisfied constraint");
2029 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);
2030}
2031
2033 const ConceptSpecializationExpr *ConstraintExpr, bool First) {
2034
2035 const ASTConstraintSatisfaction &Satisfaction =
2036 ConstraintExpr->getSatisfaction();
2037
2038 assert(!Satisfaction.IsSatisfied &&
2039 "Attempted to diagnose a satisfied constraint");
2040
2041 ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),
2042 ConstraintExpr->getBeginLoc(), First);
2043}
2044
2045namespace {
2046
2047class SubstituteParameterMappings {
2048 Sema &SemaRef;
2049
2050 const MultiLevelTemplateArgumentList *MLTAL;
2051 const ASTTemplateArgumentListInfo *ArgsAsWritten;
2052
2053 // When normalizing a fold constraint, e.g.
2054 // C<Pack1, Pack2...> && ...
2055 // we want the TreeTransform to expand only Pack2 but not Pack1,
2056 // since Pack1 will be expanded during the evaluation of the fold expression.
2057 // This flag helps rewrite any non-PackExpansion packs into "expanded"
2058 // parameters.
2059 bool RemovePacksForFoldExpr;
2060
2061 SubstituteParameterMappings(Sema &SemaRef,
2062 const MultiLevelTemplateArgumentList *MLTAL,
2063 const ASTTemplateArgumentListInfo *ArgsAsWritten,
2064 bool RemovePacksForFoldExpr)
2065 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2066 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2067
2068 void buildParameterMapping(NormalizedConstraintWithParamMapping &N);
2069
2070 bool substitute(NormalizedConstraintWithParamMapping &N);
2071
2072 bool substitute(ConceptIdConstraint &CC);
2073
2074public:
2075 SubstituteParameterMappings(Sema &SemaRef,
2076 bool RemovePacksForFoldExpr = false)
2077 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
2078 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2079
2080 bool substitute(NormalizedConstraint &N);
2081};
2082
2083void SubstituteParameterMappings::buildParameterMapping(
2085 TemplateParameterList *TemplateParams =
2086 cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();
2087
2088 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2089 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2090
2093 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2094 /*OnlyDeduced=*/false,
2095 /*Depth=*/0, OccurringIndices);
2096
2098 static_cast<AtomicConstraint &>(N).getConstraintExpr(),
2099 /*Depth=*/0, OccurringIndicesForSubsumption);
2100
2101 } else if (N.getKind() ==
2104 static_cast<FoldExpandedConstraint &>(N).getPattern(),
2105 /*OnlyDeduced=*/false,
2106 /*Depth=*/0, OccurringIndices);
2108 auto *Args = static_cast<ConceptIdConstraint &>(N)
2109 .getConceptId()
2110 ->getTemplateArgsAsWritten();
2111 if (Args)
2112 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2113 /*Depth=*/0, OccurringIndices);
2114 }
2115
2116 // If a parameter is only referenced in a default template argument,
2117 // we need to add it to the mapping explicitly.
2118 {
2120 for (unsigned I = TemplateParams->getMinRequiredArguments();
2121 I < TemplateParams->size(); ++I) {
2122 const NamedDecl *Param = TemplateParams->getParam(I);
2123 if (Param->isParameterPack())
2124 break;
2125 const TemplateArgument *Arg =
2127 assert(Arg && "expected a default argument");
2128 DefaultArgs.emplace_back(std::move(*Arg));
2129 }
2130 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0,
2131 OccurringIndices);
2132 SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0,
2133 OccurringIndicesForSubsumption);
2134 }
2135
2136 unsigned Size = OccurringIndices.count();
2137 // When the constraint is independent of any template parameters,
2138 // we build an empty mapping so that we can distinguish these cases
2139 // from cases where no mapping exists at all, e.g. when there are only atomic
2140 // constraints.
2141 TemplateArgumentLoc *TempArgs =
2142 new (SemaRef.Context) TemplateArgumentLoc[Size];
2144 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2145 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2146 ? ArgsAsWritten->arguments()[I].getLocation()
2147 : SourceLocation();
2148 // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
2149 // can't assert Loc.isValid() now.
2150 if (OccurringIndices[I]) {
2151 NamedDecl *Param = TemplateParams->begin()[I];
2152 new (&(TempArgs)[J]) TemplateArgumentLoc(
2153 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2154 UsedParams.push_back(Param);
2155 J++;
2156 }
2157 }
2158 auto *UsedList = TemplateParameterList::Create(
2159 SemaRef.Context, TemplateParams->getTemplateLoc(),
2160 TemplateParams->getLAngleLoc(), UsedParams,
2161 /*RAngleLoc=*/SourceLocation(),
2162 /*RequiresClause=*/nullptr);
2164 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2165 MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);
2166}
2167
2168bool SubstituteParameterMappings::substitute(
2170 if (!N.hasParameterMapping())
2171 buildParameterMapping(N);
2172
2173 // If the parameter mapping is empty, there is nothing to substitute.
2174 if (N.getParameterMapping().empty())
2175 return false;
2176
2177 SourceLocation InstLocBegin, InstLocEnd;
2178 llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2179 if (Arguments.empty()) {
2180 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2181 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2182 } else {
2183 auto SR = Arguments[0].getSourceRange();
2184 InstLocBegin = SR.getBegin();
2185 InstLocEnd = SR.getEnd();
2186 }
2187 Sema::NonSFINAEContext _(SemaRef);
2189 SemaRef, InstLocBegin,
2191 const_cast<NamedDecl *>(N.getConstraintDecl()),
2192 {InstLocBegin, InstLocEnd});
2193 if (Inst.isInvalid())
2194 return true;
2195
2196 // TransformTemplateArguments is unable to preserve the source location of a
2197 // pack. The SourceLocation is necessary for the instantiation location.
2198 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2199 // which is wrong.
2200 TemplateArgumentListInfo SubstArgs;
2202 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2204 N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs))
2205 return true;
2207 auto *TD =
2210 TD->getLocation(), SubstArgs,
2211 /*DefaultArguments=*/{},
2212 /*PartialTemplateArgs=*/false, CTAI))
2213 return true;
2214
2215 TemplateArgumentLoc *TempArgs =
2216 new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];
2217
2218 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2219 SourceLocation Loc;
2220 // If this is an empty pack, we have no corresponding SubstArgs.
2221 if (I < SubstArgs.size())
2222 Loc = SubstArgs.arguments()[I].getLocation();
2223
2224 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2225 CTAI.SugaredConverted[I], QualType(), Loc);
2226 }
2227
2228 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2229 CTAI.SugaredConverted.size());
2233 return false;
2234}
2235
2236bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {
2237 assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);
2238
2239 if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))
2240 return true;
2241
2242 auto *CSE = CC.getConceptSpecializationExpr();
2243 assert(CSE);
2244 assert(!CC.getBeginLoc().isInvalid());
2245
2246 SourceLocation InstLocBegin, InstLocEnd;
2247 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2248 Arguments.empty()) {
2249 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2250 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2251 } else {
2252 auto SR = Arguments[0].getSourceRange();
2253 InstLocBegin = SR.getBegin();
2254 InstLocEnd = SR.getEnd();
2255 }
2256 Sema::NonSFINAEContext _(SemaRef);
2257 // This is useful for name lookup across modules; see Sema::getLookupModules.
2259 SemaRef, InstLocBegin,
2261 const_cast<NamedDecl *>(CC.getConstraintDecl()),
2262 {InstLocBegin, InstLocEnd});
2263 if (Inst.isInvalid())
2264 return true;
2265
2267 // TransformTemplateArguments is unable to preserve the source location of a
2268 // pack. The SourceLocation is necessary for the instantiation location.
2269 // FIXME: The BaseLoc will be used as the location of the pack expansion,
2270 // which is wrong.
2272 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs, nullptr);
2273 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2274 CSE->getTemplateArgsAsWritten();
2276 ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out))
2277 return true;
2279 if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(),
2280 CSE->getConceptNameInfo().getLoc(), Out,
2281 /*DefaultArgs=*/{},
2282 /*PartialTemplateArgs=*/false, CTAI,
2283 /*UpdateArgsWithConversions=*/false))
2284 return true;
2285 auto TemplateArgs = *MLTAL;
2286 TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(),
2287 CTAI.SugaredConverted);
2288 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2289 RemovePacksForFoldExpr)
2290 .substitute(CC.getNormalizedConstraint());
2291}
2292
2293bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
2294 switch (N.getKind()) {
2296 if (!MLTAL) {
2297 assert(!ArgsAsWritten);
2298 return false;
2299 }
2300 return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));
2301 }
2303 auto &FE = static_cast<FoldExpandedConstraint &>(N);
2304 if (!MLTAL) {
2305 llvm::SaveAndRestore _1(RemovePacksForFoldExpr, true);
2306 assert(!ArgsAsWritten);
2307 return substitute(FE.getNormalizedPattern());
2308 }
2309 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
2310 substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));
2311 return SubstituteParameterMappings(SemaRef, /*RemovePacksForFoldExpr=*/true)
2312 .substitute(FE.getNormalizedPattern());
2313 }
2315 auto &CC = static_cast<ConceptIdConstraint &>(N);
2316 if (MLTAL) {
2317 assert(ArgsAsWritten);
2318 return substitute(CC);
2319 }
2320 assert(!ArgsAsWritten);
2324 if (RemovePacksForFoldExpr) {
2326 ArrayRef<TemplateArgumentLoc> InputArgLoc =
2328 if (AdjustConstraints(SemaRef, /*TemplateDepth=*/0,
2329 /*RemoveNonPackExpansionPacks=*/true)
2330 .TransformTemplateArguments(InputArgLoc.begin(),
2331 InputArgLoc.end(), OutArgs))
2332 return true;
2334 // Repack the packs.
2335 if (SemaRef.CheckTemplateArgumentList(
2336 Concept, Concept->getTemplateParameters(), Concept->getBeginLoc(),
2337 OutArgs,
2338 /*DefaultArguments=*/{},
2339 /*PartialTemplateArgs=*/false, CTAI))
2340 return true;
2341 InnerArgs = std::move(CTAI.SugaredConverted);
2342 }
2343
2345 Concept, Concept->getLexicalDeclContext(),
2346 /*Final=*/true, InnerArgs,
2347 /*RelativeToPrimary=*/true,
2348 /*Pattern=*/nullptr,
2349 /*ForConstraintInstantiation=*/true);
2350
2351 return SubstituteParameterMappings(SemaRef, &MLTAL,
2353 RemovePacksForFoldExpr)
2354 .substitute(CC.getNormalizedConstraint());
2355 }
2357 auto &Compound = static_cast<CompoundConstraint &>(N);
2358 if (substitute(Compound.getLHS()))
2359 return true;
2360 return substitute(Compound.getRHS());
2361 }
2362 }
2363 llvm_unreachable("Unknown ConstraintKind enum");
2364}
2365
2366} // namespace
2367
2368NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
2369 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
2370 assert(ACs.size() != 0);
2371 auto *Conjunction =
2372 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2373 if (!Conjunction)
2374 return nullptr;
2375 for (unsigned I = 1; I < ACs.size(); ++I) {
2376 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2377 ACs[I].ArgPackSubstIndex);
2378 if (!Next)
2379 return nullptr;
2381 Conjunction, Next);
2382 }
2383 return Conjunction;
2384}
2385
2386NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
2387 Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {
2388 assert(E != nullptr);
2389
2390 // C++ [temp.constr.normal]p1.1
2391 // [...]
2392 // - The normal form of an expression (E) is the normal form of E.
2393 // [...]
2394 E = E->IgnoreParenImpCasts();
2395
2396 llvm::FoldingSetNodeID ID;
2397 if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {
2398 return nullptr;
2399 }
2400 SatisfactionStackRAII StackRAII(S, D, ID);
2401
2402 // C++2a [temp.param]p4:
2403 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
2404 // Fold expression is considered atomic constraints per current wording.
2405 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
2406
2407 if (LogicalBinOp BO = E) {
2408 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2409 if (!LHS)
2410 return nullptr;
2411 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2412 if (!RHS)
2413 return nullptr;
2414
2416 S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);
2417 }
2418 if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2419 // C++ [temp.constr.normal]p1.1
2420 // [...]
2421 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
2422 // where C names a concept, is the normal form of the
2423 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
2424 // respective template parameters in the parameter mappings in each atomic
2425 // constraint. If any such substitution results in an invalid type or
2426 // expression, the program is ill-formed; no diagnostic is required.
2427 // [...]
2428 NormalizedConstraint *SubNF;
2429 if (ExprResult Res =
2430 SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);
2431 Res.isUsable())
2432 // Use canonical declarations to merge ConceptDecls across different
2433 // modules.
2434 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2435 S, CSE->getNamedConcept()->getCanonicalDecl(),
2436 AssociatedConstraint(Res.get(), SubstIndex));
2437 else
2438 return nullptr;
2440 CSE->getConceptReference(), SubNF, D,
2441 CSE, SubstIndex);
2442 }
2443 if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
2444 FE && S.getLangOpts().CPlusPlus26 &&
2445 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2446 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2447
2448 // Normalize fold expressions in C++26.
2449
2451 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2454
2455 if (FE->getInit()) {
2456 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2457 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2458 if (!LHS || !RHS)
2459 return nullptr;
2460
2461 if (FE->isRightFold())
2463 FE->getPattern(), D, Kind, LHS);
2464 else
2466 FE->getPattern(), D, Kind, RHS);
2467
2469 S.getASTContext(), LHS,
2470 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2471 : CCK_Disjunction),
2472 RHS);
2473 }
2474 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2475 if (!Sub)
2476 return nullptr;
2478 D, Kind, Sub);
2479 }
2480 return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
2481}
2482
2484 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
2485 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
2486 if (!ConstrainedDeclOrNestedReq) {
2487 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2488 *this, nullptr, AssociatedConstraints);
2489 if (!Normalized ||
2490 SubstituteParameterMappings(*this).substitute(*Normalized))
2491 return nullptr;
2492
2493 return Normalized;
2494 }
2495
2496 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
2497 const NamedDecl *ND =
2498 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2499 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2500 if (CacheEntry == NormalizationCache.end()) {
2501 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2502 *this, ND, AssociatedConstraints);
2503 if (!Normalized) {
2504 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);
2505 return nullptr;
2506 }
2507 // substitute() can invalidate iterators of NormalizationCache.
2508 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2509 CacheEntry =
2510 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2511 .first;
2512 if (Failed)
2513 return nullptr;
2514 }
2515 return CacheEntry->second;
2516}
2517
2520
2521 // [C++26] [temp.constr.fold]
2522 // Two fold expanded constraints are compatible for subsumption
2523 // if their respective constraints both contain an equivalent unexpanded pack.
2524
2527 APacks);
2529 BPacks);
2530
2531 for (const UnexpandedParameterPack &APack : APacks) {
2532 auto ADI = getDepthAndIndex(APack);
2533 if (!ADI)
2534 continue;
2535 auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
2536 return getDepthAndIndex(BPack) == ADI;
2537 });
2538 if (It != BPacks.end())
2539 return true;
2540 }
2541 return false;
2542}
2543
2546 const NamedDecl *D2,
2548 bool &Result) {
2549#ifndef NDEBUG
2550 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2551 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2553 return Kind == FunctionDecl::TK_NonTemplate ||
2555 };
2556 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2557 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2558 "use non-instantiated function declaration for constraints partial "
2559 "ordering");
2560 }
2561#endif
2562
2563 if (AC1.empty()) {
2564 Result = AC2.empty();
2565 return false;
2566 }
2567 if (AC2.empty()) {
2568 // TD1 has associated constraints and TD2 does not.
2569 Result = true;
2570 return false;
2571 }
2572
2573 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2574 auto CacheEntry = SubsumptionCache.find(Key);
2575 if (CacheEntry != SubsumptionCache.end()) {
2576 Result = CacheEntry->second;
2577 return false;
2578 }
2579
2580 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
2581 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
2582
2583 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2584 if (Depth2 > Depth1) {
2585 AC1[I].ConstraintExpr =
2586 AdjustConstraints(*this, Depth2 - Depth1)
2587 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2588 .get();
2589 } else if (Depth1 > Depth2) {
2590 AC2[I].ConstraintExpr =
2591 AdjustConstraints(*this, Depth1 - Depth2)
2592 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2593 .get();
2594 }
2595 }
2596
2597 SubsumptionChecker SC(*this);
2598 // Associated declarations are used as a cache key in the event they were
2599 // normalized earlier during concept checking. However we cannot reuse these
2600 // cached results if any of the template depths have been adjusted.
2601 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2602 if (Depth2 > Depth1)
2603 DeclAC1 = nullptr;
2604 else if (Depth1 > Depth2)
2605 DeclAC2 = nullptr;
2606 std::optional<bool> Subsumes = SC.Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2607 if (!Subsumes) {
2608 // Normalization failed
2609 return true;
2610 }
2611 Result = *Subsumes;
2612 SubsumptionCache.try_emplace(Key, *Subsumes);
2613 return false;
2614}
2615
2619 if (isSFINAEContext())
2620 // No need to work here because our notes would be discarded.
2621 return false;
2622
2623 if (AC1.empty() || AC2.empty())
2624 return false;
2625
2626 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2627 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2628 const AtomicConstraint &B) {
2630 return false;
2631 const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();
2632 if (EA == EB)
2633 return true;
2634
2635 // Not the same source level expression - are the expressions
2636 // identical?
2637 llvm::FoldingSetNodeID IDA, IDB;
2638 EA->Profile(IDA, Context, /*Canonical=*/true);
2639 EB->Profile(IDB, Context, /*Canonical=*/true);
2640 if (IDA != IDB)
2641 return false;
2642
2643 AmbiguousAtomic1 = EA;
2644 AmbiguousAtomic2 = EB;
2645 return true;
2646 };
2647
2648 {
2649 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
2650 if (!Normalized1)
2651 return false;
2652
2653 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
2654 if (!Normalized2)
2655 return false;
2656
2657 SubsumptionChecker SC(*this);
2658
2659 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2660 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2661
2662 SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
2663 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2664 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2665
2666 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2667 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2668 // Same result - no ambiguity was caused by identical atomic expressions.
2669 return false;
2670 }
2671 // A different result! Some ambiguous atomic constraint(s) caused a difference
2672 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2673
2674 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2675 << AmbiguousAtomic1->getSourceRange();
2676 Diag(AmbiguousAtomic2->getBeginLoc(),
2677 diag::note_ambiguous_atomic_constraints_similar_expression)
2678 << AmbiguousAtomic2->getSourceRange();
2679 return true;
2680}
2681
2682//
2683//
2684// ------------------------ Subsumption -----------------------------------
2685//
2686//
2688 SubsumptionCallable Callable)
2689 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2690
2691uint16_t SubsumptionChecker::getNewLiteralId() {
2692 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2693 "too many constraints!");
2694 return NextID++;
2695}
2696
2697auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2698 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2699 // C++ [temp.constr.order] p2
2700 // - an atomic constraint A subsumes another atomic constraint B
2701 // if and only if the A and B are identical [...]
2702 //
2703 // C++ [temp.constr.atomic] p2
2704 // Two atomic constraints are identical if they are formed from the
2705 // same expression and the targets of the parameter mappings are
2706 // equivalent according to the rules for expressions [...]
2707
2708 // Because subsumption of atomic constraints is an identity
2709 // relationship that does not require further analysis
2710 // We cache the results such that if an atomic constraint literal
2711 // subsumes another, their literal will be the same
2712
2713 llvm::FoldingSetNodeID ID;
2714 ID.AddBoolean(Ori->hasParameterMapping());
2715 if (Ori->hasParameterMapping()) {
2716 const auto &Mapping = Ori->getParameterMapping();
2718 Ori->mappingOccurenceListForSubsumption();
2719 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2720 if (Indexes[Idx])
2721 SemaRef.getASTContext()
2722 .getCanonicalTemplateArgument(TAL.getArgument())
2723 .Profile(ID, SemaRef.getASTContext());
2724 }
2725 }
2726 auto It = Elems.find(ID);
2727 if (It == Elems.end()) {
2728 It = Elems
2729 .insert({ID,
2730 MappedAtomicConstraint{
2731 Ori, {getNewLiteralId(), Literal::Atomic}}})
2732 .first;
2733 ReverseMap[It->second.ID.Value] = Ori;
2734 }
2735 return It->getSecond().ID;
2736}
2737
2738auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {
2739 auto &Elems = FoldMap[Ori->getPattern()];
2740
2741 FoldExpendedConstraintKey K;
2742 K.Kind = Ori->getFoldOperator();
2743
2744 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2745 return K.Kind == Other.Kind;
2746 });
2747 if (It == Elems.end()) {
2748 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2749 It = Elems.insert(Elems.end(), std::move(K));
2750 ReverseMap[It->ID.Value] = Ori;
2751 }
2752 return It->ID;
2753}
2754
2755auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
2756 return SubsumptionChecker::Normalize<CNFFormula>(C);
2757}
2758auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
2759 return SubsumptionChecker::Normalize<DNFFormula>(C);
2760}
2761
2762///
2763/// \brief SubsumptionChecker::Normalize
2764///
2765/// Normalize a formula to Conjunctive Normal Form or
2766/// Disjunctive normal form.
2767///
2768/// Each Atomic (and Fold Expanded) constraint gets represented by
2769/// a single id to reduce space.
2770///
2771/// To minimize risks of exponential blow up, if two atomic
2772/// constraints subsumes each other (same constraint and mapping),
2773/// they are represented by the same literal.
2774///
2775template <typename FormulaType>
2776FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
2777 FormulaType Res;
2778
2779 auto Add = [&, this](Clause C) {
2780 // Sort each clause and remove duplicates for faster comparisons.
2781 llvm::sort(C);
2782 C.erase(llvm::unique(C), C.end());
2783 AddUniqueClauseToFormula(Res, std::move(C));
2784 };
2785
2786 switch (NC.getKind()) {
2788 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2789
2791 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2792
2794 return Normalize<FormulaType>(
2795 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2796
2798 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2799 FormulaType Left, Right;
2800 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2801 Left = Normalize<FormulaType>(Compound.getLHS());
2802 Right = Normalize<FormulaType>(Compound.getRHS());
2803 });
2804
2805 if (Compound.getCompoundKind() == FormulaType::Kind) {
2806 unsigned SizeLeft = Left.size();
2807 Res = std::move(Left);
2808 Res.reserve(SizeLeft + Right.size());
2809 std::for_each(std::make_move_iterator(Right.begin()),
2810 std::make_move_iterator(Right.end()), Add);
2811 return Res;
2812 }
2813
2814 Res.reserve(Left.size() * Right.size());
2815 for (const auto &LTransform : Left) {
2816 for (const auto &RTransform : Right) {
2817 Clause Combined;
2818 Combined.reserve(LTransform.size() + RTransform.size());
2819 llvm::copy(LTransform, std::back_inserter(Combined));
2820 llvm::copy(RTransform, std::back_inserter(Combined));
2821 Add(std::move(Combined));
2822 }
2823 }
2824 return Res;
2825 }
2826 }
2827 llvm_unreachable("Unknown ConstraintKind enum");
2828}
2829
2830void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2831 for (auto &Other : F) {
2832 if (llvm::equal(C, Other))
2833 return;
2834 }
2835 F.push_back(C);
2836}
2837
2839 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2841 const NormalizedConstraint *PNormalized =
2842 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2843 if (!PNormalized)
2844 return std::nullopt;
2845
2846 const NormalizedConstraint *QNormalized =
2847 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2848 if (!QNormalized)
2849 return std::nullopt;
2850
2851 return Subsumes(PNormalized, QNormalized);
2852}
2853
2855 const NormalizedConstraint *Q) {
2856
2857 DNFFormula DNFP = DNF(*P);
2858 CNFFormula CNFQ = CNF(*Q);
2859 return Subsumes(DNFP, CNFQ);
2860}
2861
2862bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2863 const CNFFormula &QCNF) {
2864 for (const auto &Pi : PDNF) {
2865 for (const auto &Qj : QCNF) {
2866 // C++ [temp.constr.order] p2
2867 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2868 // and only if there exists an atomic constraint Pia in Pi for which
2869 // there exists an atomic constraint, Qjb, in Qj such that Pia
2870 // subsumes Qjb.
2871 if (!DNFSubsumes(Pi, Qj))
2872 return false;
2873 }
2874 }
2875 return true;
2876}
2877
2878bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2879
2880 return llvm::any_of(P, [&](Literal LP) {
2881 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2882 });
2883}
2884
2886 const FoldExpandedConstraint *B) {
2887 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2888 A, B};
2889
2890 auto It = FoldSubsumptionCache.find(Key);
2891 if (It == FoldSubsumptionCache.end()) {
2892 // C++ [temp.constr.order]
2893 // a fold expanded constraint A subsumes another fold expanded
2894 // constraint B if they are compatible for subsumption, have the same
2895 // fold-operator, and the constraint of A subsumes that of B.
2896 bool DoesSubsume =
2897 A->getFoldOperator() == B->getFoldOperator() &&
2900 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2901 }
2902 return It->second;
2903}
2904
2905bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2906 if (A.Kind != B.Kind)
2907 return false;
2908 switch (A.Kind) {
2909 case Literal::Atomic:
2910 if (!Callable)
2911 return A.Value == B.Value;
2912 return Callable(
2913 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2914 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2915 case Literal::FoldExpanded:
2916 return Subsumes(
2917 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2918 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2919 }
2920 llvm_unreachable("unknown literal kind");
2921}
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:886
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 ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:47
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition ASTConcept.h:69
llvm::SmallVector< UnsatisfiedConstraintRecord, 4 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
Definition ASTConcept.h:67
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1462
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2122
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getNonTransparentContext()
ValueDecl * getDecl()
Definition Expr.h:1341
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
Definition DeclBase.h:1239
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition DeclBase.h:1132
bool isParameterPack() const
Whether this declaration is a parameter pack.
Definition DeclBase.cpp:266
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:931
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition Decl.h:855
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition Expr.h:112
@ SE_NoSideEffects
Strictly evaluate the expression.
Definition Expr.h:674
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:177
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp: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:4167
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition Decl.cpp:4508
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:4287
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition Decl.cpp:4303
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition Decl.cpp:4231
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:4118
FunctionDecl * getInstantiatedFromDecl() const
Definition Decl.cpp:4191
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition Decl.cpp:4139
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
FunctionTemplateDecl * getInstantiatedFromMemberTemplate() const
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2078
static ImplicitConceptSpecializationDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, ArrayRef< TemplateArgument > ConvertedArgs)
const TypeClass * getTypePtr() const
Definition TypeLoc.h:526
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Definition Template.h:371
Data structure that captures multiple levels of template argument lists for use in template instantia...
Definition Template.h:76
bool hasTemplateArgument(unsigned Depth, unsigned Index) const
Determine whether there is a non-NULL template argument at the given depth and index.
Definition Template.h:175
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
Definition Template.h:271
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
Definition Template.h:212
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
Definition Template.h:123
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
Definition Template.h:129
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
Definition Template.h:253
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
Definition Template.h:275
This represents a decl that may have a name.
Definition Decl.h:274
unsigned getPosition() const
Get the position of the template parameter within its parameter list.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getIndex() const
Get the index of the template parameter within its parameter list.
unsigned getDepth() const
Get the nesting depth of the template parameter.
const NamedDecl * getConstraintDecl() const
bool hasMatchingParameterMapping(ASTContext &C, const NormalizedConstraint &Other) const
const OccurenceList & mappingOccurenceList() const
const OccurenceList & mappingOccurenceListForSubsumption() const
TemplateParameterList * getUsedTemplateParamList() const
llvm::MutableArrayRef< TemplateArgumentLoc > getParameterMapping() const
void updateParameterMapping(OccurenceList Indexes, OccurenceList IndexesForSubsumption, llvm::MutableArrayRef< TemplateArgumentLoc > Args, TemplateParameterList *ParamList)
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
QualType getCanonicalType() const
Definition TypeBase.h: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:13749
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:12552
const DeclContext * getDeclContext() const
Definition Sema.h:12306
const NamedDecl * getDecl() const
Definition Sema.h:12298
const DeclContext * getLexicalDeclContext() const
Definition Sema.h:12302
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
ExprResult SubstConceptTemplateArguments(const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, const MultiLevelTemplateArgumentList &MLTAL)
Substitute concept template arguments in the constraint expression of a concept-id.
llvm::DenseMap< llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult > UnsubstitutedConstraintSatisfactionCache
Cache the satisfaction of an atomic constraint.
Definition Sema.h:15116
ASTContext & Context
Definition Sema.h:1308
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
void MarkUsedTemplateParametersForSubsumptionParameterMapping(const Expr *E, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are named in a given expression.
DiagnosticsEngine & getDiagnostics() const
Definition Sema.h:936
void DiagnoseTypeTraitDetails(const Expr *E)
If E represents a built-in type trait, or a known standard type trait, try to print more information ...
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions, bool Diagnose=true)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
ASTContext & getASTContext() const
Definition Sema.h:939
ExprResult CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs, bool DoCheckConstraintSatisfaction=true)
llvm::PointerUnion< const NamedDecl *, const concepts::NestedRequirement * > ConstrainedDeclOrNestedRequirement
Definition Sema.h:14985
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool CheckConstraintSatisfaction(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, const ConceptReference *TopLevelConceptId=nullptr, Expr **ConvertedExpr=nullptr)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
const NormalizedConstraint * getNormalizedAssociatedConstraints(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints)
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
const LangOptions & getLangOpts() const
Definition Sema.h:932
@ ReuseLambdaContextDecl
Definition Sema.h: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:11868
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
Definition Sema.h:1341
llvm::DenseMap< llvm::FoldingSetNodeID, TemplateArgumentLoc > * CurrentCachedTemplateArgs
Cache the instantiation results of template parameter mappings within concepts.
Definition Sema.h:15123
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, const DeclContext *DC=nullptr, bool Final=false, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false, bool ForDefaultArgumentSubstitution=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)
Check whether the given function decl's trailing requires clause is satisfied, if any.
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
SourceManager & getSourceManager() const
Definition Sema.h:937
bool isSFINAEContext() const
Definition Sema.h:13787
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
Definition Sema.h:13743
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
Definition Sema.h:14941
void PopSatisfactionStackEntry()
Definition Sema.h:14947
ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
Definition Sema.h: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:14949
bool IsAtLeastAsConstrained(const NamedDecl *D1, MutableArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, MutableArrayRef< AssociatedConstraint > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(const NamedDecl *D1, ArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, ArrayRef< AssociatedConstraint > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions=true, bool *ConstraintsNotSatisfied=nullptr)
Check that the given template arguments can be provided to the given template, converting the argumen...
NamedDecl * getPack() const
Retrieve the parameter pack.
Definition ExprCXX.h:4509
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
std::string printToString(const SourceManager &SM) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
SubsumptionChecker establishes subsumption between two set of constraints.
std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)
SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})
llvm::function_ref< bool( const AtomicConstraint &, const AtomicConstraint &)> SubsumptionCallable
A convenient class for passing around template argument information.
ArrayRef< TemplateArgumentLoc > arguments() const
Location wrapper for a TemplateArgument.
Represents a template argument.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
bool containsUnexpandedParameterPack() const
Whether this template argument contains an unexpanded parameter pack.
@ Pack
The template argument is actually a parameter pack.
ArgKind getKind() const
Return the kind of stored template argument.
bool isPackExpansion() const
Determine whether this template argument is a pack expansion.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< AssociatedConstraint > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
bool isNull() const
Determine whether this template name is NULL.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
unsigned getMinRequiredArguments() const
Returns the minimum number of arguments needed to form a template specialization.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() const
Token - This structure provides full information about a lexed token.
Definition Token.h:36
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition Token.h:104
tok::TokenKind getKind() const
Definition Token.h:99
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition TypeLoc.h:133
SourceLocation getNameLoc() const
Definition TypeLoc.h:547
void setNameLoc(SourceLocation Loc)
Definition TypeLoc.h:551
The base class of the type hierarchy.
Definition TypeBase.h: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
UnresolvedUsingTypenameDecl * getDecl() const
Definition TypeBase.h:6117
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
Definition DeclCXX.h:4079
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
A requires-expression requirement which queries the validity and properties of an expression ('simple...
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
const ReturnTypeRequirement & getReturnTypeRequirement() const
SatisfactionStatus getSatisfactionStatus() const
SourceLocation getNoexceptLoc() const
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
A static requirement that can be used in a requires-expression to check properties of types and expre...
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
Provides information about an attempted template argument deduction, whose success or failure was des...
__inline void unsigned int _2
uint32_t Literal
Literals are represented as positive integers.
Definition CNFFormula.h:35
bool Sub(InterpState &S, CodePtr OpPC)
Definition Interp.h:417
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:388
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus11
@ CPlusPlus26
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:152
llvm::PointerUnion< const Expr *, const ConceptReference *, const ConstraintSubstitutionDiagnostic * > UnsatisfiedConstraintRecord
Definition ASTConcept.h:41
std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl *, const TemplateSpecializationType *, const SubstBuiltinTemplatePackType * >, SourceLocation > UnexpandedParameterPack
Definition Sema.h:238
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
ExprResult ExprEmpty()
Definition Ownership.h:272
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Result
The result type of a method or function.
Definition TypeBase.h:905
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
OptionalUnsigned< unsigned > UnsignedOrNone
@ Template
We are parsing a template declaration.
Definition Parser.h:81
ExprResult ExprError()
Definition Ownership.h:265
@ Concept
The name was classified as a concept name.
Definition Sema.h:591
std::pair< SourceLocation, StringRef > ConstraintSubstitutionDiagnostic
Unsatisfied constraint expressions if the template arguments could be substituted into them,...
Definition ASTConcept.h:40
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
Definition ASTLambda.h:69
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:136
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1763
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:91
ArrayRef< UnsatisfiedConstraintRecord > records() const
Definition ASTConcept.h:104
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
SourceLocation RAngleLoc
The source location of the right angle bracket ('>').
SourceLocation LAngleLoc
The source location of the left angle bracket ('<').
ArrayRef< TemplateArgumentLoc > arguments() const
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:648
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:650
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition Expr.h:636
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
Definition SemaConcept.h:36
NormalizedConstraint(const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)
SourceRange getSourceRange() const
ConstraintKind getKind() const
SourceLocation getBeginLoc() const
llvm::SmallBitVector OccurenceList
Definition SemaConcept.h:51
constexpr underlying_type toInternalRepresentation() const
SmallVector< TemplateArgument, 4 > SugaredConverted
The checked, converted argument will be added to the end of these vectors.
Definition Sema.h:12087
A stack object to be created when performing template instantiation.
Definition Sema.h:13390