clang: lib/Sema/SemaConcept.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
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(E)) {
49 LHS = BO->getLHS();
50 RHS = BO->getRHS();
51 Loc = BO->getExprLoc();
52 } else if (auto *OO = dyn_cast(E)) {
53
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; }
70
72 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
73 }
74
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())
82
83
84
89 }
90};
91}
92
94 Token NextToken, bool *PossibleNonPrimary,
95 bool IsTrailingRequiresClause) {
96
97
98
100
101 if (LogicalBinOp BO = ConstraintExpression) {
103 PossibleNonPrimary) &&
105 PossibleNonPrimary);
106 } else if (auto *C = dyn_cast(ConstraintExpression))
108 PossibleNonPrimary);
109
111
112 auto CheckForNonPrimary = [&] {
113 if (!PossibleNonPrimary)
114 return;
115
116 *PossibleNonPrimary =
117
118
119
120
121
122
123
124
125
126
127 (NextToken.is(tok::l_paren) &&
128 (IsTrailingRequiresClause ||
131 !dyn_cast_if_present(getCurFunction())) ||
134
135
136
137
138
140 true,
142 };
143
144
146 CheckForNonPrimary();
147 return true;
148 }
149
152 diag::err_non_bool_atomic_constraint)
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) {
172 Inserted = true;
173 }
174 }
175 ~SatisfactionStackRAII() {
176 if (Inserted)
178 }
179};
180}
181
183 Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E,
186 if (MLTAL) {
187 for (const auto &List : *MLTAL)
188 for (const auto &TemplateArg : List.Args)
191 }
193 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
195 return true;
196 }
197 return false;
198}
199
200
201
202
203static unsigned
205 bool SkipForSpecialization = false) {
208 std::nullopt,
209 true,
210 nullptr,
211 true, SkipForSpecialization);
213}
214
215namespace {
216class AdjustConstraintDepth : public TreeTransform {
217 unsigned TemplateDepth = 0;
218
219public:
220 using inherited = TreeTransform;
221 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
222 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
223
224 using inherited::TransformTemplateTypeParmType;
225 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
226 TemplateTypeParmTypeLoc TL, bool) {
227 const TemplateTypeParmType *T = TL.getTypePtr();
228
229 TemplateTypeParmDecl *NewTTPDecl = nullptr;
230 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
231 NewTTPDecl = cast_or_null(
232 TransformDecl(TL.getNameLoc(), OldTTPDecl));
233
234 QualType Result = getSema().Context.getTemplateTypeParmType(
235 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
236 NewTTPDecl);
237 TemplateTypeParmTypeLoc NewTL = TLB.push(Result);
240 }
241
242 bool AlreadyTransformed(QualType T) {
243 if (T.isNull())
244 return true;
245
248 return false;
249 return true;
250 }
251};
252}
253
254namespace {
255
256
257class HashParameterMapping : public RecursiveASTVisitor {
258 using inherited = RecursiveASTVisitor;
259 friend inherited;
260
261 Sema &SemaRef;
262 const MultiLevelTemplateArgumentList &TemplateArgs;
263 llvm::FoldingSetNodeID &ID;
264 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
265
266 UnsignedOrNone OuterPackSubstIndex;
267
268 bool shouldVisitTemplateInstantiations() const { return true; }
269
270public:
271 HashParameterMapping(Sema &SemaRef,
272 const MultiLevelTemplateArgumentList &TemplateArgs,
273 llvm::FoldingSetNodeID &ID,
274 UnsignedOrNone OuterPackSubstIndex)
275 : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),
276 OuterPackSubstIndex(OuterPackSubstIndex) {}
277
278 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
279
280
281 if (T->getDepth() >= TemplateArgs.getNumLevels())
282 return true;
283
284
285
287 return true;
288
289 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
290
293 "Missing argument pack");
294
296 }
297
298 UsedTemplateArgs.push_back(
300 return true;
301 }
302
303 bool VisitDeclRefExpr(DeclRefExpr *E) {
304 NamedDecl *D = E->getDecl();
305 NonTypeTemplateParmDecl *NTTP = dyn_cast(D);
306 if (!NTTP)
307 return TraverseDecl(D);
308
310 return true;
311
313 return true;
314
315 TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
318 "Missing argument pack");
320 }
321
322 UsedTemplateArgs.push_back(
324 return true;
325 }
326
327 bool VisitTypedefType(TypedefType *TT) {
328 return inherited::TraverseType(TT->desugar());
329 }
330
331 bool TraverseDecl(Decl *D) {
332 if (auto *VD = dyn_cast(D)) {
333 if (auto *Var = dyn_cast(VD))
334 TraverseStmt(Var->getInit());
335 return TraverseType(VD->getType());
336 }
337
338 return inherited::TraverseDecl(D);
339 }
340
341 bool TraverseCallExpr(CallExpr *CE) {
342 inherited::TraverseStmt(CE->getCallee());
343
344 for (Expr *Arg : CE->arguments())
345 inherited::TraverseStmt(Arg);
346
347 return true;
348 }
349
350 bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
351
353 }
354
355 bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
356
357
358
359
360 return true;
361 }
362
363 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
364 bool TraverseQualifier) {
365 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));
366 }
367
368 bool TraverseTemplateArgument(const TemplateArgument &Arg) {
370
371 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
372 llvm::SaveAndRestore _2(OuterPackSubstIndex,
373 std::nullopt);
374 return inherited::TraverseTemplateArgument(Arg);
375 }
376
377 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
378 return inherited::TraverseTemplateArgument(Arg);
379 }
380
381 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
382 return TraverseDecl(SOPE->getPack());
383 }
384
385 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
387 }
388
390 if (auto *TTP = dyn_cast_if_present(
391 Template.getAsTemplateDecl());
392 TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
394 TTP->getPosition()))
395 return true;
396
397 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
400 "Missing argument pack");
402 }
404 "Null template template argument");
405 UsedTemplateArgs.push_back(
407 }
408 return inherited::TraverseTemplateName(Template);
409 }
410
411 void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
413 for (const auto &List : TemplateArgs)
414 for (const TemplateArgument &Arg : List.Args)
417 return;
418 }
419
420 llvm::ArrayRef Mapping =
422 for (auto &ArgLoc : Mapping) {
423 TemplateArgument Canonical =
425
426 UsedTemplateArgs.push_back(Canonical);
427 TraverseTemplateArgument(Canonical);
428 }
429
430 for (auto &Used : UsedTemplateArgs) {
431 llvm::FoldingSetNodeID R;
433 ID.AddNodeID(R);
434 }
435 }
436};
437
438class ConstraintSatisfactionChecker {
439 Sema &S;
441 SourceLocation TemplateNameLoc;
442 UnsignedOrNone PackSubstitutionIndex;
443 ConstraintSatisfaction &Satisfaction;
444 bool BuildExpression;
445
446private:
448 EvaluateAtomicConstraint(const Expr *AtomicExpr,
449 const MultiLevelTemplateArgumentList &MLTAL);
450
451 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
452 const FoldExpandedConstraint &FE,
453 const MultiLevelTemplateArgumentList &MLTAL);
454
455
456 std::optional SubstitutionInTemplateArguments(
457 const NormalizedConstraintWithParamMapping &Constraint,
458 const MultiLevelTemplateArgumentList &MLTAL,
459 llvm::SmallVector &SubstitutedOuterMost);
460
461 ExprResult EvaluateSlow(const AtomicConstraint &Constraint,
462 const MultiLevelTemplateArgumentList &MLTAL);
463
465 const MultiLevelTemplateArgumentList &MLTAL);
466
467 ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,
468 const MultiLevelTemplateArgumentList &MLTAL);
469
471 const MultiLevelTemplateArgumentList &MLTAL);
472
473 ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,
474 const MultiLevelTemplateArgumentList &MLTAL,
475 unsigned int Size);
476
478 const MultiLevelTemplateArgumentList &MLTAL);
479
481 const MultiLevelTemplateArgumentList &MLTAL);
482
483public:
484 ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,
485 SourceLocation TemplateNameLoc,
486 UnsignedOrNone PackSubstitutionIndex,
487 ConstraintSatisfaction &Satisfaction,
488 bool BuildExpression)
489 : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),
490 PackSubstitutionIndex(PackSubstitutionIndex),
491 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
492
494 const MultiLevelTemplateArgumentList &MLTAL);
495};
496
497StringRef allocateStringFromConceptDiagnostic(const Sema &S,
500 DiagString = ": ";
503}
504
505}
506
507ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
512
513 llvm::FoldingSetNodeID ID;
516 Satisfaction.IsSatisfied = false;
517 Satisfaction.ContainsErrors = true;
519 }
520 SatisfactionStackRAII StackRAII(S, Template, ID);
521
522
524 {
529
531 if (Inst.isInvalid())
533
534
536 SubstitutedExpression =
538
539 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
540
541
542
543 if (!Trap.hasErrorOccurred())
544
545
547
550 Info.takeSFINAEDiagnostic(SubstDiag);
551
552
553
554
555
556
557 Satisfaction.Details.emplace_back(
559 SubstDiag.first,
560 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
561 Satisfaction.IsSatisfied = false;
563 }
564 }
565
568
569
570
571
572
573
574
575
576
577
578
579 if (!SubstitutedExpression.get()->isPRValue())
581 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
582 SubstitutedExpression.get(),
584
585 return SubstitutedExpression;
586}
587
588std::optional
589ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
593
595 return std::move(MLTAL);
596
597
598
601
607
609 if (Inst.isInvalid())
610 return std::nullopt;
611
616 : PackSubstitutionIndex);
617
620 SubstArgs, true)) {
621 Satisfaction.IsSatisfied = false;
622 return std::nullopt;
623 }
624
629 TD->getLocation(), SubstArgs,
630 {},
631 false, CTAI))
632 return std::nullopt;
635
636
638 SubstitutedOutermost =
639 llvm::to_vector_of(MLTAL.getOutermost());
640 unsigned Offset = 0;
641 for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
646 if (I < SubstitutedOutermost.size()) {
647 SubstitutedOutermost[I] = Arg;
648 Offset = I + 1;
649 } else {
650 SubstitutedOutermost.push_back(Arg);
651 Offset = SubstitutedOutermost.size();
652 }
653 }
654 if (Offset < SubstitutedOutermost.size())
655 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
656
659 false);
660 return std::move(SubstitutedTemplateArgs);
661}
662
663ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
666
668 std::optional SubstitutedArgs =
669 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
670 if (!SubstitutedArgs) {
671 Satisfaction.IsSatisfied = false;
673 }
674
676 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
678
679 if (SubstitutedAtomicExpr.isInvalid())
681
682 if (SubstitutedAtomicExpr.isUnset())
683
685
686
687
688
689
690
692 Satisfaction.IsSatisfied = false;
693 Satisfaction.ContainsErrors = true;
694
696 Satisfaction.Details.emplace_back(
698 SubstitutedAtomicExpr.get()->getBeginLoc(),
699 allocateStringFromConceptDiagnostic(S, Msg)});
700 return SubstitutedAtomicExpr;
701 }
702
704 Satisfaction.IsSatisfied = true;
705 Satisfaction.ContainsErrors = false;
706 return SubstitutedAtomicExpr;
707 }
708
713 EvalResult.Diag = &EvaluationDiags;
716 !EvaluationDiags.empty()) {
717
718
720 diag::err_non_constant_constraint_expression)
723 S.Diag(PDiag.first, PDiag.second);
725 }
726
727 assert(EvalResult.Val.isInt() &&
728 "evaluating bool expression didn't produce int");
729 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
730 if (!Satisfaction.IsSatisfied)
731 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
732
733 return SubstitutedAtomicExpr;
734}
735
736ExprResult ConstraintSatisfactionChecker::Evaluate(
739
740 unsigned Size = Satisfaction.Details.size();
741 llvm::FoldingSetNodeID ID;
745 : PackSubstitutionIndex;
746
749 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
750 .VisitConstraint(Constraint);
751
754 auto &Cached = Iter->second.Satisfaction;
755 Satisfaction.ContainsErrors = Cached.ContainsErrors;
756 Satisfaction.IsSatisfied = Cached.IsSatisfied;
757 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
758 Cached.Details.begin(), Cached.Details.end());
759 return Iter->second.SubstExpr;
760 }
761
762 ExprResult E = EvaluateSlow(Constraint, MLTAL);
763
765 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
766 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
767 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
768 Satisfaction.Details.begin() + Size,
769 Satisfaction.Details.end());
770 Cache.SubstExpr = E;
772
773 return E;
774}
775
777ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
780
782
785 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
786 bool Expand = true;
787 bool RetainExpansion = false;
791 false, Expand, RetainExpansion,
792 NumExpansions, false) ||
793 !Expand || RetainExpansion)
794 return std::nullopt;
795
796 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)
797 return std::nullopt;
798 return NumExpansions;
799}
800
801ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
804
807 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
808
810
812 std::optional SubstitutedArgs =
813 SubstitutionInTemplateArguments(
815 MLTAL, SubstitutedOutermost);
816 if (!SubstitutedArgs) {
817 Satisfaction.IsSatisfied = false;
819 }
820
823 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
824 if (!NumExpansions)
826
827 if (*NumExpansions == 0) {
828 Satisfaction.IsSatisfied = Conjunction;
830 }
831
832 for (unsigned I = 0; I < *NumExpansions; I++) {
834 Satisfaction.IsSatisfied = false;
835 Satisfaction.ContainsErrors = false;
837 ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,
839 false)
841 if (BuildExpression && Expr.isUsable()) {
842 if (Out.isUnset())
844 else
846 Conjunction ? BinaryOperatorKind::BO_LAnd
847 : BinaryOperatorKind::BO_LOr,
851 } else {
852 assert(!BuildExpression || !Satisfaction.IsSatisfied);
853 }
854 if (!Conjunction && Satisfaction.IsSatisfied) {
855 Satisfaction.Details.erase(Satisfaction.Details.begin() +
856 EffectiveDetailEndIndex,
857 Satisfaction.Details.end());
858 break;
859 }
860 if (Satisfaction.IsSatisfied != Conjunction)
861 return Out;
862 }
863
864 return Out;
865}
866
867ExprResult ConstraintSatisfactionChecker::Evaluate(
870
871 llvm::FoldingSetNodeID ID;
873 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
874
877
878 auto &Cached = Iter->second.Satisfaction;
879 Satisfaction.ContainsErrors = Cached.ContainsErrors;
880 Satisfaction.IsSatisfied = Cached.IsSatisfied;
881 Satisfaction.Details.insert(Satisfaction.Details.end(),
882 Cached.Details.begin(), Cached.Details.end());
883 return Iter->second.SubstExpr;
884 }
885
886 unsigned Size = Satisfaction.Details.size();
887
888 ExprResult E = EvaluateSlow(Constraint, MLTAL);
890 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
891 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
892 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
893 Satisfaction.Details.begin() + Size,
894 Satisfaction.Details.end());
895 Cache.SubstExpr = E;
897 return E;
898}
899
900ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
904
906 std::optional SubstitutedArgs =
907 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
908
909 if (!SubstitutedArgs) {
910 Satisfaction.IsSatisfied = false;
911
913 }
914
918 : PackSubstitutionIndex);
919
927
930 Trap.hasErrorOccurred()) {
931 Satisfaction.IsSatisfied = false;
932 if (!Trap.hasErrorOccurred())
934
937 Info.takeSFINAEDiagnostic(SubstDiag);
938
939
940
941
942
943
944 Satisfaction.Details.insert(
945 Satisfaction.Details.begin() + Size,
947 SubstDiag.first,
948 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
950 }
951
954
958 false);
959
960 if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
962
963 if (Size != Satisfaction.Details.size()) {
964 Satisfaction.Details.insert(
965 Satisfaction.Details.begin() + Size,
969 }
970 return SubstitutedConceptId;
971}
972
973ExprResult ConstraintSatisfactionChecker::Evaluate(
976
978
982 : PackSubstitutionIndex;
983
988
989
990
991
992
996 if (InstTemplate.isInvalid())
998
999 unsigned Size = Satisfaction.Details.size();
1000
1002
1004 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1005 return E;
1006 }
1007
1008
1009
1010
1011 if (Satisfaction.IsSatisfied)
1012 return E;
1013
1014 llvm::FoldingSetNodeID ID;
1017 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1018 .VisitConstraint(Constraint);
1019
1022
1023 auto &Cached = Iter->second.Satisfaction;
1024 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1025 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1026 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1027 Cached.Details.begin(), Cached.Details.end());
1028 return Iter->second.SubstExpr;
1029 }
1030
1031 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1033 return E;
1035 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1036 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1037 Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),
1038 Satisfaction.Details.begin() + Size,
1039 Satisfaction.Details.end());
1040 Cache.SubstExpr = CE;
1042 return CE;
1043}
1044
1045ExprResult ConstraintSatisfactionChecker::Evaluate(
1048
1049 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1050
1051 bool Conjunction =
1053
1055
1056 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1057 return LHS;
1058
1059 if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&
1060 !Satisfaction.ContainsErrors)
1061 return LHS;
1062
1063 Satisfaction.ContainsErrors = false;
1064 Satisfaction.IsSatisfied = false;
1065
1067
1068 if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&
1069 !Satisfaction.ContainsErrors)
1070 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1071 EffectiveDetailEndIndex,
1072 Satisfaction.Details.end());
1073
1074 if (!BuildExpression)
1076
1078 return RHS;
1079
1081 return LHS;
1082
1084 Conjunction ? BinaryOperatorKind::BO_LAnd
1085 : BinaryOperatorKind::BO_LOr,
1088}
1089
1090ExprResult ConstraintSatisfactionChecker::Evaluate(
1093 switch (Constraint.getKind()) {
1096
1099 MLTAL);
1100
1103 MLTAL);
1104
1107 }
1108 llvm_unreachable("Unknown ConstraintKind enum");
1109}
1110
1116 Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
1117
1118 if (ConvertedExpr)
1119 *ConvertedExpr = nullptr;
1120
1121 if (AssociatedConstraints.empty()) {
1123 return false;
1124 }
1125
1127
1129 return false;
1130 }
1131
1135
1136 struct SynthesisContextPair {
1142 : Inst(S, InstantiationRange.getBegin(),
1144 TemplateArgs, InstantiationRange),
1145 NSC(S) {}
1146 };
1147 std::optional SynthesisContext;
1148 if (!TopLevelConceptId)
1149 SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,
1150 TemplateIDRange);
1151
1154 if () {
1156 return true;
1157 }
1158
1159 if (TopLevelConceptId)
1164
1165 ExprResult Res = ConstraintSatisfactionChecker(
1168 ConvertedExpr != nullptr)
1169 .Evaluate(*C, TemplateArgsLists);
1170
1172 return true;
1173
1174 if (Res.isUsable() && ConvertedExpr)
1175 *ConvertedExpr = Res.get();
1176
1177 return false;
1178}
1179
1186 llvm::TimeTraceScope TimeScope(
1187 "CheckConstraintSatisfaction", [TemplateIDRange, this] {
1189 });
1190 if (AssociatedConstraints.empty()) {
1192 return false;
1193 }
1196 return ::CheckConstraintSatisfaction(
1197 *this, nullptr, AssociatedConstraints, TemplateArgsLists,
1198 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1199 }
1200
1201
1202 if (Template->isInvalidDecl()) {
1204 return true;
1205 }
1206
1207
1208
1209
1210
1212 for (auto List : TemplateArgsLists)
1214 FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));
1215
1217 if (TopLevelConceptId)
1219
1220 llvm::FoldingSetNodeID ID;
1222 void *InsertPos;
1223 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1224 OutSatisfaction = *Cached;
1225 return false;
1226 }
1227
1228 auto Satisfaction =
1229 std::make_unique(Owner, FlattenedArgs);
1231 *this, Template, AssociatedConstraints, TemplateArgsLists,
1232 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1233 OutSatisfaction = std::move(*Satisfaction);
1234 return true;
1235 }
1236
1237 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1238
1239
1240
1241
1242
1243
1244
1245
1246 OutSatisfaction = *Cached;
1247 return false;
1248 }
1249
1250
1251 OutSatisfaction = *Satisfaction;
1252
1253
1254
1255 SatisfactionCache.InsertNode(Satisfaction.release());
1256 return false;
1257}
1258
1263
1264
1265
1266
1267
1268
1269
1272
1275 if (llvm::none_of(
1277 return !ArgLoc.getArgument().isDependent() &&
1278 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1279 })) {
1280 return Concept->getConstraintExpr();
1281 }
1282
1286 true,
1287 nullptr,
1288 true);
1290 MLTAL);
1291}
1292
1296
1300 return true;
1301
1303 Constraints.emplace_back(Res.get());
1304
1307 true);
1308
1313}
1314
1315bool Sema::SetupConstraintScope(
1320 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1321 "instantiations");
1324 InstantiatingTemplate Inst(
1329 if (Inst.isInvalid())
1330 return true;
1331
1332
1333
1334
1335
1336
1339 false);
1340 if (addInstantiatedParametersToScope(
1342 return true;
1343 }
1344
1345
1346
1349 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1351 return true;
1352 }
1353
1354 return false;
1355 }
1356
1359 FunctionDecl *InstantiatedFrom =
1363
1366 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1367 TemplateArgs ? *TemplateArgs : ArrayRef{},
1368 SourceRange());
1369 if (Inst.isInvalid())
1370 return true;
1371
1372
1373
1374 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1375 return true;
1376 }
1377
1378 return false;
1379}
1380
1381
1382
1383std::optional
1384Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1387 MultiLevelTemplateArgumentList MLTAL;
1388
1389
1390
1391
1392 MLTAL =
1394 false, std::nullopt,
1395 true,
1396 nullptr,
1397 true);
1398
1400 return MLTAL;
1401 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1402 return std::nullopt;
1403
1404 return MLTAL;
1405}
1406
1410 bool ForOverloadResolution) {
1411
1412
1413
1414
1419 return false;
1420 }
1421
1422
1423
1424
1425
1426
1427
1428
1429 if (const auto *MD = dyn_cast(FD);
1432 Satisfaction, UsageLoc,
1433 true);
1434
1436
1440 else
1442 }
1443
1444 ContextRAII SavedContext{*this, CtxToSave};
1446 std::optional MLTAL =
1447 SetupConstraintCheckingTemplateArgumentsAndScope(
1449
1450 if (!MLTAL)
1451 return true;
1452
1455 if (auto *Method = dyn_cast(FD)) {
1456 ThisQuals = Method->getMethodQualifiers();
1458 }
1460
1463 ForOverloadResolution);
1464
1468 Satisfaction);
1469}
1470
1473 const Expr *ConstrExpr) {
1476 std::nullopt,
1477 true,
1478 nullptr, true,
1479 false);
1480
1482 return ConstrExpr;
1483
1490 return nullptr;
1491
1492
1493
1494
1495
1496 std::optional ScopeForParameters;
1499 ScopeForParameters.emplace(S, true);
1503 FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1504 for (auto *PVD : FD->parameters()) {
1505 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1506 continue;
1507 if (!PVD->isParameterPack()) {
1508 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1509 continue;
1510 }
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1528 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1529 }
1530 }
1531
1532 std::optionalSema::CXXThisScopeRAII ThisScope;
1533
1534
1535
1536
1537
1538
1539
1540
1541 std::optionalSema::ContextRAII ContextScope;
1543 if (!DeclInfo.getDecl())
1548 }();
1549 if (auto *RD = dyn_cast(DC)) {
1552 false);
1553 }
1558 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1559 if (!SubstConstr.isUsable())
1560 return nullptr;
1561 return SubstConstr.get();
1562}
1563
1565 const Expr *OldConstr,
1567 const Expr *NewConstr) {
1568 if (OldConstr == NewConstr)
1569 return true;
1570
1571 if (Old && .isInvalid() &&
.ContainsDecl(Old) &&
1573 if (const Expr *SubstConstr =
1575 OldConstr))
1576 OldConstr = SubstConstr;
1577 else
1578 return false;
1579 if (const Expr *SubstConstr =
1581 NewConstr))
1582 NewConstr = SubstConstr;
1583 else
1584 return false;
1585 }
1586
1587 llvm::FoldingSetNodeID ID1, ID2;
1588 OldConstr->Profile(ID1, Context, true);
1589 NewConstr->Profile(ID2, Context, true);
1590 return ID1 == ID2;
1591}
1592
1595
1596
1597
1598
1600 "Non-function templates don't need to be checked");
1601
1604
1608 AC.ConstraintExpr))
1609 return true;
1610
1611 return false;
1612}
1613
1621 TemplateIDRange, Satisfaction))
1622 return true;
1623
1626 TemplateArgString = " ";
1630
1632 diag::err_template_arg_list_constraints_not_satisfied)
1634 << TemplateArgString << TemplateIDRange;
1636 return true;
1637 }
1638 return false;
1639}
1640
1646 Template->getAssociatedConstraints(TemplateAC);
1647 if (TemplateAC.empty()) {
1649 return false;
1650 }
1651
1653
1655
1656
1657
1658
1660 {
1661
1662
1663
1664
1666 SemaRef, PointOfInstantiation,
1668 PointOfInstantiation);
1669 if (Inst.isInvalid())
1670 return true;
1672 FD, FD,
1673 false, {}, true,
1674 nullptr, true);
1675 }
1676
1679 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1680}
1681
1686
1688
1690 return ::CheckFunctionConstraintsWithoutInstantiation(
1691 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1692 TemplateArgs, Satisfaction);
1693
1694
1695
1697 Template->getAssociatedConstraints(TemplateAC);
1698 if (TemplateAC.empty()) {
1700 return false;
1701 }
1702
1703
1704
1707
1708 std::optional MLTAL =
1709 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1711
1712 if (!MLTAL)
1713 return true;
1714
1717 if (auto *Method = dyn_cast(Decl)) {
1718 ThisQuals = Method->getMethodQualifiers();
1720 }
1721
1725
1727 PointOfInstantiation, Satisfaction);
1728}
1729
1734 "Diagnose() can only be used on an unsatisfied requirement");
1737 llvm_unreachable("Diagnosing a dependent requirement");
1738 break;
1741 if (!SubstDiag->DiagMessage.empty())
1742 S.Diag(SubstDiag->DiagLoc,
1743 diag::note_expr_requirement_expr_substitution_error)
1744 << (int)First << SubstDiag->SubstitutedEntity
1745 << SubstDiag->DiagMessage;
1746 else
1747 S.Diag(SubstDiag->DiagLoc,
1748 diag::note_expr_requirement_expr_unknown_substitution_error)
1749 << (int)First << SubstDiag->SubstitutedEntity;
1750 break;
1751 }
1753 S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
1755 break;
1757 auto *SubstDiag =
1759 if (!SubstDiag->DiagMessage.empty())
1760 S.Diag(SubstDiag->DiagLoc,
1761 diag::note_expr_requirement_type_requirement_substitution_error)
1762 << (int)First << SubstDiag->SubstitutedEntity
1763 << SubstDiag->DiagMessage;
1764 else
1766 SubstDiag->DiagLoc,
1768 note_expr_requirement_type_requirement_unknown_substitution_error)
1769 << (int)First << SubstDiag->SubstitutedEntity;
1770 break;
1771 }
1776 break;
1777 }
1779 llvm_unreachable("We checked this above");
1780 }
1781}
1782
1787 "Diagnose() can only be used on an unsatisfied requirement");
1790 llvm_unreachable("Diagnosing a dependent requirement");
1791 return;
1794 if (!SubstDiag->DiagMessage.empty())
1795 S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1796 << (int)First << SubstDiag->SubstitutedEntity
1797 << SubstDiag->DiagMessage;
1798 else
1799 S.Diag(SubstDiag->DiagLoc,
1800 diag::note_type_requirement_unknown_substitution_error)
1801 << (int)First << SubstDiag->SubstitutedEntity;
1802 return;
1803 }
1804 default:
1805 llvm_unreachable("Unknown satisfaction status");
1806 return;
1807 }
1808}
1809
1813 if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1815 Loc,
1817 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1819 << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1820 << Concept->getNamedConcept();
1821 } else {
1822 S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1824 }
1825}
1826
1830
1836 Loc = {};
1838 }
1839}
1840
1850
1852 const Expr *SubstExpr,
1855 if (const BinaryOperator *BO = dyn_cast(SubstExpr)) {
1856 switch (BO->getOpcode()) {
1857
1858
1859
1860 case BO_LOr:
1861
1864 false);
1865 return;
1866 case BO_LAnd: {
1867 bool LHSSatisfied =
1868 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1869 if (LHSSatisfied) {
1870
1872 return;
1873 }
1874
1876
1877
1878 bool RHSSatisfied =
1879 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1880 if (!RHSSatisfied)
1882 false);
1883 return;
1884 }
1885 case BO_GE:
1886 case BO_LE:
1887 case BO_GT:
1888 case BO_LT:
1889 case BO_EQ:
1890 case BO_NE:
1891 if (BO->getLHS()->getType()->isIntegerType() &&
1892 BO->getRHS()->getType()->isIntegerType()) {
1895 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1897 true);
1898 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1900 true);
1901 if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
1903 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1908 return;
1909 }
1910 }
1911 break;
1912
1913 default:
1914 break;
1915 }
1916 } else if (auto *RE = dyn_cast(SubstExpr)) {
1917
1919 if (!Req->isDependent() && !Req->isSatisfied()) {
1920 if (auto *E = dyn_castconcepts::ExprRequirement(Req))
1922 else if (auto *T = dyn_castconcepts::TypeRequirement(Req))
1924 else
1927 break;
1928 }
1929 return;
1930 } else if (auto *CSE = dyn_cast(SubstExpr)) {
1931
1933 return;
1934 } else if (auto *TTE = dyn_cast(SubstExpr);
1935 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1936 assert(TTE->getNumArgs() == 2);
1938 diag::note_is_deducible_constraint_evaluated_to_false)
1939 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1940 return;
1941 }
1942
1944 diag::note_atomic_constraint_evaluated_to_false)
1947}
1948
1952 if (auto *Diag =
1954 .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1955 if (Req)
1956 S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)
1958 else
1959 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1960 << Diag->second;
1961 return;
1962 }
1963 if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {
1965 Loc = Concept->getBeginLoc();
1967 return;
1968 }
1971}
1972
1976
1978 "Attempted to diagnose a satisfied constraint");
1980}
1981
1984
1987
1989 "Attempted to diagnose a satisfied constraint");
1990
1993}
1994
1995namespace {
1996
1997class SubstituteParameterMappings {
1998 Sema &SemaRef;
1999
2002
2003 bool InFoldExpr;
2004
2005 SubstituteParameterMappings(Sema &SemaRef,
2008 bool InFoldExpr)
2009 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2010 InFoldExpr(InFoldExpr) {}
2011
2013
2015
2017
2018public:
2019 SubstituteParameterMappings(Sema &SemaRef, bool InFoldExpr = false)
2020 : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),
2021 InFoldExpr(InFoldExpr) {}
2022
2023 bool substitute(NormalizedConstraint &N);
2024};
2025
2026void SubstituteParameterMappings::buildParameterMapping(
2030
2031 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
2032 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());
2033
2037 false,
2038 0, OccurringIndices);
2039
2042 0, OccurringIndicesForSubsumption);
2043
2044 } else if (N.getKind() ==
2048 false,
2049 0, OccurringIndices);
2052 .getConceptId()
2053 ->getTemplateArgsAsWritten();
2054 if (Args)
2056 0, OccurringIndices);
2057 }
2058 unsigned Size = OccurringIndices.count();
2059
2060
2061
2062
2066 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {
2067 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2068 ? ArgsAsWritten->arguments()[I].getLocation()
2070
2071
2072 if (OccurringIndices[I]) {
2076 UsedParams.push_back(Param);
2077 J++;
2078 }
2079 }
2084 nullptr);
2086 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2088}
2089
2090bool SubstituteParameterMappings::substitute(
2093 buildParameterMapping(N);
2094
2095
2097 return false;
2098
2102 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2103 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2104 } else {
2105 auto SR = Arguments[0].getSourceRange();
2106 InstLocBegin = SR.getBegin();
2107 InstLocEnd = SR.getEnd();
2108 }
2111 SemaRef, InstLocBegin,
2114 {InstLocBegin, InstLocEnd});
2115 if (Inst.isInvalid())
2116 return true;
2117
2118
2119
2120
2121
2125 !InFoldExpr))
2126 return true;
2128 auto *TD =
2131 TD->getLocation(), SubstArgs,
2132 {},
2133 false, CTAI))
2134 return true;
2135
2138
2139 for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {
2141
2142 if (I < SubstArgs.size())
2143 Loc = SubstArgs.arguments()[I].getLocation();
2144
2147 }
2148
2154 return false;
2155}
2156
2159
2161 return true;
2162
2164 assert(CSE);
2166
2168 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2170 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2171 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2172 } else {
2173 auto SR = Arguments[0].getSourceRange();
2174 InstLocBegin = SR.getBegin();
2175 InstLocEnd = SR.getEnd();
2176 }
2178
2180 SemaRef, InstLocBegin,
2183 {InstLocBegin, InstLocEnd});
2184 if (Inst.isInvalid())
2185 return true;
2186
2188
2189
2190
2191
2193 CSE->getTemplateArgsAsWritten();
2196 !InFoldExpr))
2197 return true;
2200 CSE->getConceptNameInfo().getLoc(), Out,
2201 {},
2202 false, CTAI,
2203 false))
2204 return true;
2205 auto TemplateArgs = *MLTAL;
2208 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2209 InFoldExpr)
2211}
2212
2216 if (!MLTAL) {
2217 assert(!ArgsAsWritten);
2218 return false;
2219 }
2221 }
2224 if (!MLTAL) {
2226 assert(!ArgsAsWritten);
2228 }
2231 return SubstituteParameterMappings(SemaRef, true)
2233 }
2236 if (MLTAL) {
2237 assert(ArgsAsWritten);
2238 return substitute(CC);
2239 }
2240 assert(!ArgsAsWritten);
2246 true,
2247 nullptr,
2248 true);
2249
2250 return SubstituteParameterMappings(
2253 }
2256 if (substitute(Compound.getLHS()))
2257 return true;
2258 return substitute(Compound.getRHS());
2259 }
2260 }
2261 llvm_unreachable("Unknown ConstraintKind enum");
2262}
2263
2264}
2265
2268 assert(ACs.size() != 0);
2269 auto *Conjunction =
2270 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2271 if (!Conjunction)
2272 return nullptr;
2273 for (unsigned I = 1; I < ACs.size(); ++I) {
2274 auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2275 ACs[I].ArgPackSubstIndex);
2277 return nullptr;
2279 Conjunction, Next);
2280 }
2281 return Conjunction;
2282}
2283
2286 assert(E != nullptr);
2287
2288
2289
2290
2291
2293
2294 llvm::FoldingSetNodeID ID;
2296 return nullptr;
2297 }
2298 SatisfactionStackRAII StackRAII(S, D, ID);
2299
2300
2301
2302
2303
2304
2305 if (LogicalBinOp BO = E) {
2306 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2307 if (!LHS)
2308 return nullptr;
2309 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2310 if (!RHS)
2311 return nullptr;
2312
2315 } else if (auto *CSE = dyn_cast(E)) {
2317 {
2318 Sema::NonSFINAEContext _(S);
2319 Sema::InstantiatingTemplate Inst(
2321 Sema::InstantiatingTemplate::ConstraintNormalization{},
2322
2324 if (Inst.isInvalid())
2325 return nullptr;
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2339
2343 return nullptr;
2344
2345 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2346 S, CD, AssociatedConstraint(Res.get(), SubstIndex));
2347
2348 if (!SubNF)
2349 return nullptr;
2350 }
2351
2354 CSE, SubstIndex);
2355
2356 } else if (auto *FE = dyn_cast(E);
2358 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2359 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2360
2361
2362
2364 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2367
2368 if (FE->getInit()) {
2369 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2370 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2371 if (!LHS || !RHS)
2372 return nullptr;
2373
2374 if (FE->isRightFold())
2377 else
2380
2383 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
2385 RHS);
2386 }
2387 auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2388 if (!Sub)
2389 return nullptr;
2391 D, Kind, Sub);
2392 }
2394}
2395
2399 if (!ConstrainedDeclOrNestedReq) {
2400 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2401 *this, nullptr, AssociatedConstraints);
2402 if (!Normalized ||
2403 SubstituteParameterMappings(*this).substitute(*Normalized))
2404 return nullptr;
2405
2406 return Normalized;
2407 }
2408
2409
2411 ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();
2412 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2413 if (CacheEntry == NormalizationCache.end()) {
2414 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2415 *this, ND, AssociatedConstraints);
2416 if (!Normalized) {
2417 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);
2418 return nullptr;
2419 }
2420
2421 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2422 CacheEntry =
2423 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2424 .first;
2425 if (Failed)
2426 return nullptr;
2427 }
2428 return CacheEntry->second;
2429}
2430
2433
2434
2435
2436
2437
2440 APacks);
2442 BPacks);
2443
2446 if (!ADI)
2447 continue;
2450 });
2451 if (It != BPacks.end())
2452 return true;
2453 }
2454 return false;
2455}
2456
2462#ifndef NDEBUG
2463 if (const auto *FD1 = dyn_cast(D1)) {
2464 auto IsExpectedEntity = [](const FunctionDecl *FD) {
2468 };
2469 const auto *FD2 = dyn_cast(D2);
2470 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2471 "use non-instantiated function declaration for constraints partial "
2472 "ordering");
2473 }
2474#endif
2475
2476 if (AC1.empty()) {
2477 Result = AC2.empty();
2478 return false;
2479 }
2480 if (AC2.empty()) {
2481
2483 return false;
2484 }
2485
2486 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2487 auto CacheEntry = SubsumptionCache.find(Key);
2488 if (CacheEntry != SubsumptionCache.end()) {
2489 Result = CacheEntry->second;
2490 return false;
2491 }
2492
2495
2496 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2497 if (Depth2 > Depth1) {
2498 AC1[I].ConstraintExpr =
2499 AdjustConstraintDepth(*this, Depth2 - Depth1)
2500 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
2501 .get();
2502 } else if (Depth1 > Depth2) {
2503 AC2[I].ConstraintExpr =
2504 AdjustConstraintDepth(*this, Depth1 - Depth2)
2505 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
2506 .get();
2507 }
2508 }
2509
2511 std::optional Subsumes = SC.Subsumes(D1, AC1, D2, AC2);
2512 if (!Subsumes) {
2513
2514 return true;
2515 }
2517 SubsumptionCache.try_emplace(Key, *Subsumes);
2518 return false;
2519}
2520
2525
2526 return false;
2527
2528 if (AC1.empty() || AC2.empty())
2529 return false;
2530
2531 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
2532 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
2535 return false;
2537 if (EA == EB)
2538 return true;
2539
2540
2541
2542 llvm::FoldingSetNodeID IDA, IDB;
2544 EB->Profile(IDB, Context, true);
2545 if (IDA != IDB)
2546 return false;
2547
2548 AmbiguousAtomic1 = EA;
2549 AmbiguousAtomic2 = EB;
2550 return true;
2551 };
2552
2553 {
2555 if (!Normalized1)
2556 return false;
2557
2559 if (!Normalized2)
2560 return false;
2561
2563
2564 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
2565 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
2566
2568 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
2569 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
2570
2571 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2572 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2573
2574 return false;
2575 }
2576
2577 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2578
2579 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2581 Diag(AmbiguousAtomic2->getBeginLoc(),
2582 diag::note_ambiguous_atomic_constraints_similar_expression)
2583 << AmbiguousAtomic2->getSourceRange();
2584 return true;
2585}
2586
2587
2588
2589
2590
2591
2594 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2595
2596uint16_t SubsumptionChecker::getNewLiteralId() {
2597 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2598 "too many constraints!");
2599 return NextID++;
2600}
2601
2602auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {
2603 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618 llvm::FoldingSetNodeID ID;
2619 ID.AddBoolean(Ori->hasParameterMapping());
2620 if (Ori->hasParameterMapping()) {
2621 const auto &Mapping = Ori->getParameterMapping();
2623 Ori->mappingOccurenceListForSubsumption();
2624 for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2625 if (Indexes[Idx])
2629 }
2630 }
2631 auto It = Elems.find(ID);
2632 if (It == Elems.end()) {
2633 It = Elems
2634 .insert({ID,
2635 MappedAtomicConstraint{
2636 Ori, {getNewLiteralId(), Literal::Atomic}}})
2637 .first;
2638 ReverseMap[It->second.ID.Value] = Ori;
2639 }
2640 return It->getSecond().ID;
2641}
2642
2644 auto &Elems = FoldMap[Ori->getPattern()];
2645
2646 FoldExpendedConstraintKey K;
2647 K.Kind = Ori->getFoldOperator();
2648
2649 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
2650 return K.Kind == Other.Kind;
2651 });
2652 if (It == Elems.end()) {
2653 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2654 It = Elems.insert(Elems.end(), std::move(K));
2655 ReverseMap[It->ID.Value] = Ori;
2656 }
2657 return It->ID;
2658}
2659
2661 return SubsumptionChecker::Normalize(C);
2662}
2664 return SubsumptionChecker::Normalize(C);
2665}
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680template
2682 FormulaType Res;
2683
2684 auto Add = [&, this](Clause C) {
2685
2686 llvm::sort(C);
2687 C.erase(llvm::unique(C), C.end());
2688 AddUniqueClauseToFormula(Res, std::move(C));
2689 };
2690
2693 return {{find(&static_cast<const AtomicConstraint &>(NC))}};
2694
2696 return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};
2697
2699 return Normalize(
2700 static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());
2701
2703 const auto &Compound = static_cast<const CompoundConstraint &>(NC);
2705 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2706 Left = Normalize(Compound.getLHS());
2707 Right = Normalize(Compound.getRHS());
2708 });
2709
2710 if (Compound.getCompoundKind() == FormulaType::Kind) {
2711 unsigned SizeLeft = Left.size();
2712 Res = std::move(Left);
2713 Res.reserve(SizeLeft + Right.size());
2714 std::for_each(std::make_move_iterator(Right.begin()),
2715 std::make_move_iterator(Right.end()), Add);
2716 return Res;
2717 }
2718
2719 Res.reserve(Left.size() * Right.size());
2720 for (const auto <ransform : Left) {
2721 for (const auto &RTransform : Right) {
2722 Clause Combined;
2723 Combined.reserve(LTransform.size() + RTransform.size());
2724 llvm::copy(LTransform, std::back_inserter(Combined));
2725 llvm::copy(RTransform, std::back_inserter(Combined));
2726 Add(std::move(Combined));
2727 }
2728 }
2729 return Res;
2730 }
2731 }
2732 llvm_unreachable("Unknown ConstraintKind enum");
2733}
2734
2735void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2736 for (auto &Other : F) {
2737 if (llvm::equal(C, Other))
2738 return;
2739 }
2740 F.push_back(C);
2741}
2742
2747 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2748 if (!PNormalized)
2749 return std::nullopt;
2750
2752 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2753 if (!QNormalized)
2754 return std::nullopt;
2755
2756 return Subsumes(PNormalized, QNormalized);
2757}
2758
2761
2762 DNFFormula DNFP = DNF(*P);
2763 CNFFormula CNFQ = CNF(*Q);
2764 return Subsumes(DNFP, CNFQ);
2765}
2766
2768 const CNFFormula &QCNF) {
2769 for (const auto &Pi : PDNF) {
2770 for (const auto &Qj : QCNF) {
2771
2772
2773
2774
2775
2776 if (!DNFSubsumes(Pi, Qj))
2777 return false;
2778 }
2779 }
2780 return true;
2781}
2782
2783bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2784
2785 return llvm::any_of(P, [&](Literal LP) {
2786 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2787 });
2788}
2789
2792 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2793 A, B};
2794
2795 auto It = FoldSubsumptionCache.find(Key);
2796 if (It == FoldSubsumptionCache.end()) {
2797
2798
2799
2800
2801 bool DoesSubsume =
2805 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2806 }
2807 return It->second;
2808}
2809
2811 if (A.Kind != B.Kind)
2812 return false;
2813 switch (A.Kind) {
2814 case Literal::Atomic:
2815 if (!Callable)
2816 return A.Value == B.Value;
2818 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2819 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2820 case Literal::FoldExpanded:
2822 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2823 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2824 }
2825 llvm_unreachable("unknown literal kind");
2826}
This file provides AST data structures related to concepts.
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E)
FormatToken * Next
The next token in the unwrapped line.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Records Records
llvm::MachO::Record Record
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)
Definition SemaConcept.cpp:1949
static ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)
Definition SemaConcept.cpp:1260
static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)
Definition SemaConcept.cpp:1831
static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
Definition SemaConcept.cpp:1471
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, const Expr *SubstExpr, bool First)
Definition SemaConcept.cpp:1851
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList *MLTAL=nullptr)
Definition SemaConcept.cpp:182
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId=nullptr)
Definition SemaConcept.cpp:1111
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
Definition SemaConcept.cpp:1730
static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)
Definition SemaConcept.cpp:1810
static bool CheckFunctionConstraintsWithoutInstantiation(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
Definition SemaConcept.cpp:1641
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
Definition SemaConcept.cpp:204
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
llvm::StringRef backupStr(llvm::StringRef S) const
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,...
SourceLocation getBeginLoc() const LLVM_READONLY
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
StringRef getOpcodeStr() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Represents a C++ conversion function within a class.
Represents a C++ struct/union/class.
Represents a C++ nested-name-specifier or a global scope specifier.
void Adopt(NestedNameSpecifierLoc Other)
Adopt an existing nested-name-specifier (with source-range information).
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.
const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const
NamedDecl * getFoundDecl() const
const DeclarationNameInfo & getConceptNameInfo() const
SourceLocation getBeginLoc() const LLVM_READONLY
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
TemplateDecl * getNamedConcept() const
SourceLocation getTemplateKWLoc() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getExprLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptReference * getConceptReference() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
llvm::SmallVector< UnsatisfiedConstraintRecord, 4 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
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()
Decl - This represents one declaration (or definition), e.g.
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
RAII object that enters a new expression evaluation context.
This represents one expression.
@ SE_NoSideEffects
Strictly evaluate the expression.
bool isValueDependent() const
Determines whether the value of this expression depends on.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
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...
Represents difference between two FPOptions values.
static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)
Definition SemaConcept.cpp:2431
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.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
ArrayRef< ParmVarDecl * > parameters() const
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
TemplatedKind
The kind of templated function a FunctionDecl can be.
@ TK_MemberSpecialization
@ TK_DependentNonTemplate
@ TK_FunctionTemplateSpecialization
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
FunctionDecl * getInstantiatedFromDecl() const
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
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)
const TypeClass * getTypePtr() const
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Data structure that captures multiple levels of template argument lists for use in template instantia...
bool hasTemplateArgument(unsigned Depth, unsigned Index) const
Determine whether there is a non-NULL template argument at the given depth and index.
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
bool isAnyArgInstantiationDependent() const
This represents a decl that may have a name.
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.
UnsignedOrNone getPackSubstitutionIndex() const
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
bool hasParameterMapping() const
void updateParameterMapping(OccurenceList Indexes, OccurenceList IndexesForSubsumption, llvm::MutableArrayRef< TemplateArgumentLoc > Args, TemplateParameterList *ParamList)
A (possibly-)qualified type.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
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.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
RAII object used to change the argument pack substitution index within a Sema object.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
SourceLocation getLocation() const
const DeclContext * getDeclContext() const
const NamedDecl * getDecl() const
const DeclContext * getLexicalDeclContext() const
Sema - This implements semantic analysis and AST building for C.
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, NamedDecl *TemplateParam=nullptr)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
ExprResult SubstConceptTemplateArguments(const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, const MultiLevelTemplateArgumentList &MLTAL)
Substitute concept template arguments in the constraint expression of a concept-id.
llvm::DenseMap< llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult > UnsubstitutedConstraintSatisfactionCache
Cache the satisfaction of an atomic constraint.
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
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.
Definition SemaConcept.cpp:93
ASTContext & getASTContext() const
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
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...
Definition SemaConcept.cpp:1180
const NormalizedConstraint * getNormalizedAssociatedConstraints(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints)
Definition SemaConcept.cpp:2396
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
Definition SemaConcept.cpp:1593
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
Definition SemaConcept.cpp:1614
const LangOptions & getLangOpts() const
void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)
Collect the set of unexpanded parameter packs within the given template argument.
TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
Definition SemaConcept.cpp:1564
sema::FunctionScopeInfo * getCurFunction() const
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.
Definition SemaConcept.cpp:1973
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.
Definition SemaConcept.cpp:1407
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
SourceManager & getSourceManager() const
bool isSFINAEContext() const
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
void PopSatisfactionStackEntry()
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...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
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...
Definition SemaConcept.cpp:2457
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)
Definition SemaConcept.cpp:1682
bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes)
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...
Definition SemaConcept.cpp:2521
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.
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...
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
Expr * getReplacement() const
SubsumptionChecker establishes subsumption between two set of constraints.
std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)
Definition SemaConcept.cpp:2743
SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})
Definition SemaConcept.cpp:2592
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.
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.
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)) {....
tok::TokenKind getKind() const
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.
SourceLocation getNameLoc() const
void setNameLoc(SourceLocation Loc)
The base class of the type hierarchy.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isFunctionType() const
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
A requires-expression requirement which queries the validity and properties of an expression ('simple...
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
@ SS_ConstraintsNotSatisfied
@ SS_TypeRequirementSubstitutionFailure
@ SS_ExprSubstitutionFailure
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
bool hasInvalidConstraint() const
Expr * getConstraintExpr() const
StringRef getInvalidConstraintEntity()
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.
bool Sub(InterpState &S, CodePtr OpPC)
bool Add(InterpState &S, CodePtr OpPC)
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)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
llvm::PointerUnion< const Expr *, const ConceptReference *, const ConstraintSubstitutionDiagnostic * > UnsatisfiedConstraintRecord
std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl *, const TemplateSpecializationType *, const SubstBuiltinTemplatePackType * >, SourceLocation > UnexpandedParameterPack
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
const FunctionProtoType * T
@ Template
We are parsing a template declaration.
@ Concept
The name was classified as a concept name.
std::pair< SourceLocation, StringRef > ConstraintSubstitutionDiagnostic
Unsatisfied constraint expressions if the template arguments could be substituted into them,...
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
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.
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
@ Other
Other implicit parameter.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
ArrayRef< UnsatisfiedConstraintRecord > records() const
Represents an explicit template argument list in C++, e.g., the "" in "sort".
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.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
NormalizedConstraint(const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)
SourceRange getSourceRange() const
ConstraintKind getKind() const
SourceLocation getBeginLoc() const
llvm::SmallBitVector OccurenceList
SmallVector< TemplateArgument, 4 > SugaredConverted
The checked, converted argument will be added to the end of these vectors.
A stack object to be created when performing template instantiation.
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
constexpr unsigned toInternalRepresentation() const