clang: lib/Sema/SemaConcept.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
27#include "llvm/ADT/DenseMap.h"
28#include "llvm/ADT/PointerUnion.h"
29#include "llvm/ADT/StringExtras.h"
30#include
31
32using namespace clang;
33using namespace sema;
34
35namespace {
36class LogicalBinOp {
39 const Expr *LHS = nullptr;
40 const Expr *RHS = nullptr;
41
42public:
43 LogicalBinOp(const Expr *E) {
44 if (auto *BO = dyn_cast(E)) {
46 LHS = BO->getLHS();
47 RHS = BO->getRHS();
48 Loc = BO->getExprLoc();
49 } else if (auto *OO = dyn_cast(E)) {
50
51 if (OO->getNumArgs() == 2) {
52 Op = OO->getOperator();
53 LHS = OO->getArg(0);
54 RHS = OO->getArg(1);
55 Loc = OO->getOperatorLoc();
56 }
57 }
58 }
59
60 bool isAnd() const { return Op == OO_AmpAmp; }
61 bool isOr() const { return Op == OO_PipePipe; }
62 explicit operator bool() const { return isAnd() || isOr(); }
63
64 const Expr *getLHS() const { return LHS; }
65 const Expr *getRHS() const { return RHS; }
67
69 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
70 }
71
74 assert((isAnd() || isOr()) && "Not the right kind of op?");
75 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
76
79
80
81
86 }
87};
88}
89
91 Token NextToken, bool *PossibleNonPrimary,
92 bool IsTrailingRequiresClause) {
93
94
95
97
98 if (LogicalBinOp BO = ConstraintExpression) {
100 PossibleNonPrimary) &&
102 PossibleNonPrimary);
103 } else if (auto *C = dyn_cast(ConstraintExpression))
105 PossibleNonPrimary);
106
108
109 auto CheckForNonPrimary = [&] {
110 if (!PossibleNonPrimary)
111 return;
112
113 *PossibleNonPrimary =
114
115
116
117
118
119
120
121
122
123
124 (NextToken.is(tok::l_paren) &&
125 (IsTrailingRequiresClause ||
127 isa(ConstraintExpression) &&
128 !dyn_cast_if_present(getCurFunction())) ||
131
132
133
134
135
137 true,
139 };
140
141
143 CheckForNonPrimary();
144 return true;
145 }
146
149 diag::err_non_bool_atomic_constraint) << Type
151 CheckForNonPrimary();
152 return false;
153 }
154
155 if (PossibleNonPrimary)
156 *PossibleNonPrimary = false;
157 return true;
158}
159
160namespace {
161struct SatisfactionStackRAII {
162 Sema &SemaRef;
163 bool Inserted = false;
164 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
165 const llvm::FoldingSetNodeID &FSNID)
166 : SemaRef(SemaRef) {
167 if (ND) {
169 Inserted = true;
170 }
171 }
172 ~SatisfactionStackRAII() {
173 if (Inserted)
175 }
176};
177}
178
179template
183 const ConstraintEvaluator &Evaluator);
184
185template
190 const ConstraintEvaluator &Evaluator) {
191 size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
192
195
198
199 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
200
201 if (Op == clang::OO_PipePipe && IsLHSSatisfied)
202
203
204
205
206
207
208
209 return LHSRes;
210
211 if (Op == clang::OO_AmpAmp && !IsLHSSatisfied)
212
213
214
215
216
217
218
219 return LHSRes;
220
225
226 bool IsRHSSatisfied = Satisfaction.IsSatisfied;
227
228
229
230
231
232
233
234
235 if (Op == clang::OO_PipePipe && IsRHSSatisfied) {
236 auto EffectiveDetailEnd = Satisfaction.Details.begin();
237 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
238 Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end());
239 }
240
243
248}
249
250template
254 const ConstraintEvaluator &Evaluator) {
255 bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd;
256 size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
257
261 Evaluator);
262 if (Out.isInvalid())
264
265
266
267
268
269 if (Conjunction != Satisfaction.IsSatisfied)
270 return Out;
271 }
272 std::optional NumExpansions =
273 Evaluator.EvaluateFoldExpandedConstraintSize(FE);
274 if (!NumExpansions)
276 for (unsigned I = 0; I < *NumExpansions; I++) {
279 Satisfaction, Evaluator);
282 bool IsRHSSatisfied = Satisfaction.IsSatisfied;
283 if (!Conjunction && IsRHSSatisfied) {
284 auto EffectiveDetailEnd = Satisfaction.Details.begin();
285 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
286 Satisfaction.Details.erase(EffectiveDetailEnd,
287 Satisfaction.Details.end());
288 }
289 if (Out.isUnset())
290 Out = Res;
291 else if (!Res.isUnset()) {
295 }
296 if (Conjunction != IsRHSSatisfied)
297 return Out;
298 }
299
302 Satisfaction, Evaluator);
303 if (Out.isInvalid())
305
306 if (Out.isUnset())
307 Out = Res;
308 else if (!Res.isUnset()) {
312 }
313 }
314
315 if (Out.isUnset()) {
318 }
319 return Out;
320}
321
322template
326 const ConstraintEvaluator &Evaluator) {
328
329 if (LogicalBinOp BO = ConstraintExpr)
331 S, BO.getLHS(), BO.getOp(), BO.getRHS(), Satisfaction, Evaluator);
332
333 if (auto *C = dyn_cast(ConstraintExpr)) {
334
335
337 Evaluator);
338 }
339
340 if (auto *FE = dyn_cast(ConstraintExpr);
342 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
343 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
345 }
346
347
349 Evaluator.EvaluateAtomicConstraint(ConstraintExpr);
350
351 if (SubstitutedAtomicExpr.isInvalid())
353
354 if (!SubstitutedAtomicExpr.isUsable())
355
357
358
359
360
361
362
366
369 DiagString = ": ";
371 unsigned MessageSize = DiagString.size();
372 char *Mem = new (S.Context) char[MessageSize];
373 memcpy(Mem, DiagString.c_str(), MessageSize);
374 Satisfaction.Details.emplace_back(
376 SubstitutedAtomicExpr.get()->getBeginLoc(),
377 StringRef(Mem, MessageSize)});
378 return SubstitutedAtomicExpr;
379 }
380
385 EvalResult.Diag = &EvaluationDiags;
388 !EvaluationDiags.empty()) {
389
390
392 diag::err_non_constant_constraint_expression)
395 S.Diag(PDiag.first, PDiag.second);
397 }
398
399 assert(EvalResult.Val.isInt() &&
400 "evaluating bool expression didn't produce int");
403 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
404
405 return SubstitutedAtomicExpr;
406}
407
408static bool
413 for (const auto &List : MLTAL)
414 for (const auto &TemplateArg : List.Args)
416
417
418
419
420
421
422
424 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
426 return true;
427 }
428
429 return false;
430}
431
436
437 struct ConstraintEvaluator {
443
446 S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
448
449
451 {
456 const_cast<NamedDecl *>(Template), Info,
460
461 llvm::FoldingSetNodeID ID;
462 if (Template &&
467 }
468
469 SatisfactionStackRAII StackRAII(S, Template, ID);
470
471
473 SubstitutedExpression =
475
477
478
479
481
482
484
488
489
490
491
492
493
495 DiagString = ": ";
496 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
497 unsigned MessageSize = DiagString.size();
498 char *Mem = new (S.Context) char[MessageSize];
499 memcpy(Mem, DiagString.c_str(), MessageSize);
500 Satisfaction.Details.emplace_back(
502 SubstDiag.first, StringRef(Mem, MessageSize)});
505 }
506 }
507
510
511
512
513
514
515
516
517
518
519
520
521 if (!SubstitutedExpression.get()->isPRValue())
524 CK_LValueToRValue, SubstitutedExpression.get(),
526
527 return SubstitutedExpression;
528 }
529
530 std::optional
531 EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {
532
533
535
537
540 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
541 bool Expand = true;
542 bool RetainExpansion = false;
543 std::optional OrigNumExpansions = FE->getNumExpansions(),
544 NumExpansions = OrigNumExpansions;
547 MLTAL, Expand, RetainExpansion, NumExpansions) ||
548 !Expand || RetainExpansion)
549 return std::nullopt;
550
551 if (NumExpansions && S.getLangOpts().BracketDepth < NumExpansions) {
553 clang::diag::err_fold_expression_limit_exceeded)
554 << *NumExpansions << S.getLangOpts().BracketDepth
557 return std::nullopt;
558 }
559 return NumExpansions;
560 }
561 };
562
564 S, ConstraintExpr, Satisfaction,
565 ConstraintEvaluator{S, Template, TemplateNameLoc, MLTAL, Satisfaction});
566}
567
573 if (ConstraintExprs.empty()) {
575 return false;
576 }
577
579
581 return false;
582 }
583
590 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
592 return true;
593
594 for (const Expr *ConstraintExpr : ConstraintExprs) {
596 S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
597 ConstraintExpr, Satisfaction);
599 return true;
600
601 Converted.push_back(Res.get());
603
604
605 Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
606
607
608
609
610 return false;
611 }
612 }
613 return false;
614}
615
621 if (ConstraintExprs.empty()) {
623 return false;
624 }
625 if (!Template) {
626 return ::CheckConstraintSatisfaction(
627 *this, nullptr, ConstraintExprs, ConvertedConstraints,
628 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
629 }
630
631
634 return true;
635 }
636
637
638
639
640
642 for (auto List : TemplateArgsLists)
643 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
644 List.Args.end());
645
646 llvm::FoldingSetNodeID ID;
648 void *InsertPos;
649 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
650 OutSatisfaction = *Cached;
651 return false;
652 }
653
654 auto Satisfaction =
655 std::make_unique(Template, FlattenedArgs);
657 ConvertedConstraints, TemplateArgsLists,
658 TemplateIDRange, *Satisfaction)) {
659 OutSatisfaction = *Satisfaction;
660 return true;
661 }
662
663 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
664
665
666
667
668
669
670
671
672 OutSatisfaction = *Cached;
673 return false;
674 }
675
676
677 OutSatisfaction = *Satisfaction;
678
679
680
681 SatisfactionCache.InsertNode(Satisfaction.release());
682 return false;
683}
684
687
688 struct ConstraintEvaluator {
692 }
693
694 std::optional
695 EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {
696 return 0;
697 }
698 };
699
701 ConstraintEvaluator{*this})
703}
704
705bool Sema::addInstantiatedCapturesToScope(
709 const auto *LambdaClass = cast(Function)->getParent();
710 const auto *LambdaPattern = cast(PatternDecl)->getParent();
711
712 unsigned Instantiated = 0;
713
714 auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
715 unsigned Index) {
716 ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
718 Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
719 };
720
721 for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
722 if (!CapturePattern.capturesVariable()) {
723 Instantiated++;
724 continue;
725 }
726 ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
727
729 Instantiated++;
730 continue;
731 }
732
734 AddSingleCapture(CapturedPattern, Instantiated++);
735 } else {
736 Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
739 dyn_cast(CapturedPattern)->getInit(), Unexpanded);
740 auto NumArgumentsInExpansion =
742 if (!NumArgumentsInExpansion)
743 continue;
744 for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
745 AddSingleCapture(CapturedPattern, Instantiated++);
746 }
747 }
748 return false;
749}
750
751bool Sema::SetupConstraintScope(
757 InstantiatingTemplate Inst(
762 if (Inst.isInvalid())
763 return true;
764
765
766
767
768
769
772 false);
773 if (addInstantiatedParametersToScope(
775 return true;
776 }
777
778
779
780
781
782
783
786 while (FromMemTempl->getInstantiatedFromMemberTemplate())
787 FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
788 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
790 return true;
791 }
792
793 return false;
794 }
795
802
803 InstantiatingTemplate Inst(
808 if (Inst.isInvalid())
809 return true;
810
811
812
813 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
814 return true;
815 }
816
817 return false;
818}
819
820
821
822std::optional
823Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
827
828
829
830
831 MLTAL =
833 false, std::nullopt,
834 true,
835 nullptr,
836 true);
837 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
838 return std::nullopt;
839
840 return MLTAL;
841}
842
846 bool ForOverloadResolution) {
847
848
849
850
855 return false;
856 }
857
858
859
860
861
862
863
864
865 if (const auto *MD = dyn_cast(FD);
868 Satisfaction, UsageLoc,
869 true);
870
872
876 else
878 }
879
880 ContextRAII SavedContext{*this, CtxToSave};
882 std::optional MLTAL =
883 SetupConstraintCheckingTemplateArgumentsAndScope(
885
886 if (!MLTAL)
887 return true;
888
891 if (auto *Method = dyn_cast(FD)) {
892 ThisQuals = Method->getMethodQualifiers();
894 }
896
899 ForOverloadResolution);
900
904 Satisfaction);
905}
906
907
908
909
910
911static unsigned
913 bool SkipForSpecialization = false) {
916 std::nullopt,
917 true,
918 nullptr,
919 true, SkipForSpecialization);
921}
922
923namespace {
924 class AdjustConstraintDepth : public TreeTransform {
925 unsigned TemplateDepth = 0;
926 public:
928 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
929 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
930
931 using inherited::TransformTemplateTypeParmType;
935
938 NewTTPDecl = cast_or_null(
939 TransformDecl(TL.getNameLoc(), OldTTPDecl));
940
941 QualType Result = getSema().Context.getTemplateTypeParmType(
942 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
943 NewTTPDecl);
946 return Result;
947 }
948 };
949}
950
953 const Expr *ConstrExpr) {
956 std::nullopt,
957 true,
958 nullptr, true,
959 false);
960
962 return ConstrExpr;
963
965
971 return nullptr;
972
973
974
975
976
977 std::optional ScopeForParameters;
980 ScopeForParameters.emplace(S, true);
983 if (!PVD->isParameterPack()) {
984 ScopeForParameters->InstantiatedLocal(PVD, PVD);
985 continue;
986 }
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1004 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1005 }
1006 }
1007
1008 std::optionalSema::CXXThisScopeRAII ThisScope;
1009
1010
1011
1012
1013
1014
1015
1016
1017 std::optionalSema::ContextRAII ContextScope;
1019 if (!DeclInfo.getDecl())
1024 }();
1025 if (auto *RD = dyn_cast(DC)) {
1027 ContextScope.emplace(S, const_cast<DeclContext *>(cast(RD)),
1028 false);
1029 }
1031 const_cast<clang::Expr *>(ConstrExpr), MLTAL);
1033 return nullptr;
1034 return SubstConstr.get();
1035}
1036
1038 const Expr *OldConstr,
1040 const Expr *NewConstr) {
1041 if (OldConstr == NewConstr)
1042 return true;
1043
1046 if (const Expr *SubstConstr =
1048 OldConstr))
1049 OldConstr = SubstConstr;
1050 else
1051 return false;
1052 if (const Expr *SubstConstr =
1054 NewConstr))
1055 NewConstr = SubstConstr;
1056 else
1057 return false;
1058 }
1059
1060 llvm::FoldingSetNodeID ID1, ID2;
1061 OldConstr->Profile(ID1, Context, true);
1062 NewConstr->Profile(ID2, Context, true);
1063 return ID1 == ID2;
1064}
1065
1068
1069
1070
1071
1073 "Non-function templates don't need to be checked");
1074
1077
1079 for (const Expr *Constraint : ACs)
1081 Constraint))
1082 return true;
1083
1084 return false;
1085}
1086
1094 TemplateIDRange, Satisfaction))
1095 return true;
1096
1099 TemplateArgString = " ";
1103
1105 diag::err_template_arg_list_constraints_not_satisfied)
1107 << TemplateArgString << TemplateIDRange;
1109 return true;
1110 }
1111 return false;
1112}
1113
1118
1120
1121
1124 if (TemplateAC.empty()) {
1126 return false;
1127 }
1128
1129
1130
1133
1134 std::optional MLTAL =
1135 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1137
1138 if (!MLTAL)
1139 return true;
1140
1143 if (auto *Method = dyn_cast(Decl)) {
1144 ThisQuals = Method->getMethodQualifiers();
1145 Record = Method->getParent();
1146 }
1147
1151
1154 PointOfInstantiation, Satisfaction);
1155}
1156
1161 && "Diagnose() can only be used on an unsatisfied requirement");
1164 llvm_unreachable("Diagnosing a dependent requirement");
1165 break;
1168 if (!SubstDiag->DiagMessage.empty())
1169 S.Diag(SubstDiag->DiagLoc,
1170 diag::note_expr_requirement_expr_substitution_error)
1171 << (int)First << SubstDiag->SubstitutedEntity
1172 << SubstDiag->DiagMessage;
1173 else
1174 S.Diag(SubstDiag->DiagLoc,
1175 diag::note_expr_requirement_expr_unknown_substitution_error)
1176 << (int)First << SubstDiag->SubstitutedEntity;
1177 break;
1178 }
1181 diag::note_expr_requirement_noexcept_not_met)
1183 break;
1185 auto *SubstDiag =
1187 if (!SubstDiag->DiagMessage.empty())
1188 S.Diag(SubstDiag->DiagLoc,
1189 diag::note_expr_requirement_type_requirement_substitution_error)
1190 << (int)First << SubstDiag->SubstitutedEntity
1191 << SubstDiag->DiagMessage;
1192 else
1193 S.Diag(SubstDiag->DiagLoc,
1194 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
1195 << (int)First << SubstDiag->SubstitutedEntity;
1196 break;
1197 }
1202
1203
1206 diag::note_expr_requirement_constraints_not_satisfied_simple)
1209 } else {
1211 diag::note_expr_requirement_constraints_not_satisfied)
1212 << (int)First << ConstraintExpr;
1213 }
1215 break;
1216 }
1218 llvm_unreachable("We checked this above");
1219 }
1220}
1221
1226 && "Diagnose() can only be used on an unsatisfied requirement");
1229 llvm_unreachable("Diagnosing a dependent requirement");
1230 return;
1233 if (!SubstDiag->DiagMessage.empty())
1234 S.Diag(SubstDiag->DiagLoc,
1235 diag::note_type_requirement_substitution_error) << (int)First
1236 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
1237 else
1238 S.Diag(SubstDiag->DiagLoc,
1239 diag::note_type_requirement_unknown_substitution_error)
1240 << (int)First << SubstDiag->SubstitutedEntity;
1241 return;
1242 }
1243 default:
1244 llvm_unreachable("Unknown satisfaction status");
1245 return;
1246 }
1247}
1249 Expr *SubstExpr,
1250 bool First = true);
1251
1255 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1257 if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>())
1258 S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1260 << SubstDiag->second;
1261 else
1265 }
1266}
1267
1269 Expr *SubstExpr,
1272 if (BinaryOperator *BO = dyn_cast(SubstExpr)) {
1273 switch (BO->getOpcode()) {
1274
1275
1276
1277 case BO_LOr:
1278
1281 false);
1282 return;
1283 case BO_LAnd: {
1284 bool LHSSatisfied =
1285 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1286 if (LHSSatisfied) {
1287
1289 return;
1290 }
1291
1293
1294
1295 bool RHSSatisfied =
1296 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1297 if (!RHSSatisfied)
1299 false);
1300 return;
1301 }
1302 case BO_GE:
1303 case BO_LE:
1304 case BO_GT:
1305 case BO_LT:
1306 case BO_EQ:
1307 case BO_NE:
1308 if (BO->getLHS()->getType()->isIntegerType() &&
1309 BO->getRHS()->getType()->isIntegerType()) {
1312 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1314 true);
1315 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1317 true);
1318 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1320 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1325 return;
1326 }
1327 }
1328 break;
1329
1330 default:
1331 break;
1332 }
1333 } else if (auto *CSE = dyn_cast(SubstExpr)) {
1334 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1336 CSE->getSourceRange().getBegin(),
1337 diag::
1338 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1340 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1341 << CSE->getNamedConcept();
1342 } else {
1344 diag::note_concept_specialization_constraint_evaluated_to_false)
1345 << (int)First << CSE;
1346 }
1348 return;
1349 } else if (auto *RE = dyn_cast(SubstExpr)) {
1350
1352 if (!Req->isDependent() && !Req->isSatisfied()) {
1353 if (auto *E = dyn_castconcepts::ExprRequirement(Req))
1355 else if (auto *T = dyn_castconcepts::TypeRequirement(Req))
1357 else
1359 S, castconcepts::NestedRequirement(Req), First);
1360 break;
1361 }
1362 return;
1363 } else if (auto *TTE = dyn_cast(SubstExpr);
1364 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1365 assert(TTE->getNumArgs() == 2);
1367 diag::note_is_deducible_constraint_evaluated_to_false)
1368 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1369 return;
1370 }
1371
1373 diag::note_atomic_constraint_evaluated_to_false)
1375}
1376
1377template
1379 Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1380 bool First = true) {
1381 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) {
1382 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1383 << Diag->second;
1384 return;
1385 }
1386
1388}
1389
1390void
1394 "Attempted to diagnose a satisfied constraint");
1398 }
1399}
1400
1405 "Attempted to diagnose a satisfied constraint");
1406 for (auto &Record : Satisfaction) {
1409 }
1410}
1411
1415
1416
1417
1418 ConstrainedDecl = cast(ConstrainedDecl->getCanonicalDecl());
1419
1420 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1421 if (CacheEntry == NormalizationCache.end()) {
1422 auto Normalized =
1423 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1424 AssociatedConstraints);
1425 CacheEntry =
1426 NormalizationCache
1427 .try_emplace(ConstrainedDecl,
1428 Normalized
1430 std::move(*Normalized))
1431 : nullptr)
1432 .first;
1433 }
1434 return CacheEntry->second;
1435}
1436
1441 AssociatedConstraints);
1442}
1443
1444static bool
1449
1452 ArgsAsWritten))
1453 return true;
1455 ArgsAsWritten);
1456 }
1457
1462 ArgsAsWritten);
1463 }
1464
1466
1469 if (.ParameterMapping) {
1470 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1472 0, OccurringIndices);
1475 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1476 if (OccurringIndices[I])
1477 new (&(TempArgs)[J++])
1479 TemplateParams->begin()[I],
1480
1481
1482
1483
1484
1485
1486
1487
1489 ? ArgsAsWritten->arguments()[I].getLocation()
1491 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
1492 }
1494 ArgsAsWritten->arguments().empty()
1496 : ArgsAsWritten->arguments().front().getSourceRange().getBegin();
1498 ArgsAsWritten->arguments().empty()
1500 : ArgsAsWritten->arguments().front().getSourceRange().getEnd();
1502 S, InstLocBegin,
1504 Atomic.ConstraintDecl, {InstLocBegin, InstLocEnd});
1505 if (Inst.isInvalid())
1506 return true;
1508 return true;
1509
1512 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1513 TempArgs);
1514 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1515 return false;
1516}
1517
1523 true,
1524 nullptr,
1525 true);
1526
1529}
1530
1537 Kind}} {}
1538
1541 if (Other.isAtomic()) {
1543 } else if (Other.isFoldExpanded()) {
1545 Other.getFoldExpandedConstraint()->Kind,
1547 Other.getFoldExpandedConstraint()->Pattern);
1548 } else {
1550 new (C)
1553 Other.getCompoundKind());
1554 }
1555}
1556
1558 assert(isCompound() && "getLHS called on a non-compound constraint.");
1559 return cast(Constraint).getPointer()->LHS;
1560}
1561
1563 assert(isCompound() && "getRHS called on a non-compound constraint.");
1564 return cast(Constraint).getPointer()->RHS;
1565}
1566
1567std::optional
1568NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1570 assert(E.size() != 0);
1571 auto Conjunction = fromConstraintExpr(S, D, E[0]);
1572 if (!Conjunction)
1573 return std::nullopt;
1574 for (unsigned I = 1; I < E.size(); ++I) {
1575 auto Next = fromConstraintExpr(S, D, E[I]);
1576 if (!Next)
1577 return std::nullopt;
1580 }
1581 return Conjunction;
1582}
1583
1584std::optional
1585NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1586 assert(E != nullptr);
1587
1588
1589
1590
1591
1593
1594
1595
1596
1597
1598
1599 if (LogicalBinOp BO = E) {
1600 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1601 if (!LHS)
1602 return std::nullopt;
1603 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1604 if (!RHS)
1605 return std::nullopt;
1606
1609 } else if (auto *CSE = dyn_cast(E)) {
1611 {
1613 S, CSE->getExprLoc(),
1616 if (Inst.isInvalid())
1617 return std::nullopt;
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627 ConceptDecl *CD = CSE->getNamedConcept();
1630 if (!SubNF)
1631 return std::nullopt;
1632 }
1633
1634 std::optional New;
1635 New.emplace(S.Context, *SubNF);
1636
1638 return std::nullopt;
1639
1640 return New;
1641 } else if (auto *FE = dyn_cast(E);
1643 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
1644 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
1645
1646
1647
1649 FE->getOperator() == BinaryOperatorKind::BO_LAnd
1652
1653 if (FE->getInit()) {
1654 auto LHS = fromConstraintExpr(S, D, FE->getLHS());
1655 auto RHS = fromConstraintExpr(S, D, FE->getRHS());
1656 if (!LHS || !RHS)
1657 return std::nullopt;
1658
1659 if (FE->isRightFold())
1661 Kind, std::move(*RHS), FE->getPattern()}};
1662 else
1664 Kind, std::move(*LHS), FE->getPattern()}};
1665
1667 S.Context, std::move(*LHS), std::move(*RHS),
1668 FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
1670 }
1671 auto Sub = fromConstraintExpr(S, D, FE->getPattern());
1672 if (!Sub)
1673 return std::nullopt;
1675 Kind, std::move(*Sub), FE->getPattern()}};
1676 }
1677
1679}
1680
1683
1684
1685
1686
1687
1691
1693 std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack);
1696 });
1697 if (it != BPacks.end())
1698 return true;
1699 }
1700 return false;
1701}
1702
1706
1709
1713 LCNF.reserve(LCNF.size() + RCNF.size());
1714 while (!RCNF.empty())
1715 LCNF.push_back(RCNF.pop_back_val());
1716 return LCNF;
1717 }
1718
1719
1721 Res.reserve(LCNF.size() * RCNF.size());
1722 for (auto &LDisjunction : LCNF)
1723 for (auto &RDisjunction : RCNF) {
1724 NormalForm::value_type Combined;
1725 Combined.reserve(LDisjunction.size() + RDisjunction.size());
1726 std::copy(LDisjunction.begin(), LDisjunction.end(),
1727 std::back_inserter(Combined));
1728 std::copy(RDisjunction.begin(), RDisjunction.end(),
1729 std::back_inserter(Combined));
1730 Res.emplace_back(Combined);
1731 }
1732 return Res;
1733}
1734
1738
1741
1745 LDNF.reserve(LDNF.size() + RDNF.size());
1746 while (!RDNF.empty())
1747 LDNF.push_back(RDNF.pop_back_val());
1748 return LDNF;
1749 }
1750
1751
1753 Res.reserve(LDNF.size() * RDNF.size());
1754 for (auto &LConjunction : LDNF) {
1755 for (auto &RConjunction : RDNF) {
1756 NormalForm::value_type Combined;
1757 Combined.reserve(LConjunction.size() + RConjunction.size());
1758 std::copy(LConjunction.begin(), LConjunction.end(),
1759 std::back_inserter(Combined));
1760 std::copy(RConjunction.begin(), RConjunction.end(),
1761 std::back_inserter(Combined));
1762 Res.emplace_back(Combined);
1763 }
1764 }
1765 return Res;
1766}
1767
1773 if (const auto *FD1 = dyn_cast(D1)) {
1774 auto IsExpectedEntity = [](const FunctionDecl *FD) {
1778 };
1779 const auto *FD2 = dyn_cast(D2);
1780 (void)IsExpectedEntity;
1781 (void)FD1;
1782 (void)FD2;
1783 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1784 "use non-instantiated function declaration for constraints partial "
1785 "ordering");
1786 }
1787
1788 if (AC1.empty()) {
1789 Result = AC2.empty();
1790 return false;
1791 }
1792 if (AC2.empty()) {
1793
1795 return false;
1796 }
1797
1798 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1799 auto CacheEntry = SubsumptionCache.find(Key);
1800 if (CacheEntry != SubsumptionCache.end()) {
1801 Result = CacheEntry->second;
1802 return false;
1803 }
1804
1807
1808 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1809 if (Depth2 > Depth1) {
1810 AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1811 .TransformExpr(const_cast<Expr *>(AC1[I]))
1812 .get();
1813 } else if (Depth1 > Depth2) {
1814 AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1815 .TransformExpr(const_cast<Expr *>(AC2[I]))
1816 .get();
1817 }
1818 }
1819
1821 *this, D1, AC1, D2, AC2, Result,
1824 }))
1825 return true;
1826 SubsumptionCache.try_emplace(Key, Result);
1827 return false;
1828}
1829
1833
1834 return false;
1835
1836 if (AC1.empty() || AC2.empty())
1837 return false;
1838
1839 auto NormalExprEvaluator =
1842 };
1843
1844 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1845 auto IdenticalExprEvaluator =
1848 return false;
1850 if (EA == EB)
1851 return true;
1852
1853
1854
1855 llvm::FoldingSetNodeID IDA, IDB;
1857 EB->Profile(IDB, Context, true);
1858 if (IDA != IDB)
1859 return false;
1860
1861 AmbiguousAtomic1 = EA;
1862 AmbiguousAtomic2 = EB;
1863 return true;
1864 };
1865
1866 {
1867
1870 if (!Normalized1)
1871 return false;
1874
1876 if (!Normalized2)
1877 return false;
1880
1881 bool Is1AtLeastAs2Normally =
1883 bool Is2AtLeastAs1Normally =
1885 bool Is1AtLeastAs2 = clang::subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1886 bool Is2AtLeastAs1 = clang::subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1887 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1888 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1889
1890 return false;
1891 }
1892
1893
1894 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1895
1896 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1898 Diag(AmbiguousAtomic2->getBeginLoc(),
1899 diag::note_ambiguous_atomic_constraints_similar_expression)
1900 << AmbiguousAtomic2->getSourceRange();
1901 return true;
1902}
1903
1908 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1909 Status == SS_Dependent &&
1910 (E->containsUnexpandedParameterPack() ||
1911 Req.containsUnexpandedParameterPack()),
1912 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1913 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1914 Status(Status) {
1915 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1916 "Simple requirement must not have a return type requirement or a "
1917 "noexcept specification");
1919 (SubstitutedConstraintExpr != nullptr));
1920}
1921
1925 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1926 Req.containsUnexpandedParameterPack(), false),
1927 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1928 Status(SS_ExprSubstitutionFailure) {
1929 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1930 "Simple requirement must not have a return type requirement or a "
1931 "noexcept specification");
1932}
1933
1936 TypeConstraintInfo(TPL, false) {
1937 assert(TPL->size() == 1);
1939 cast(TPL->getParam(0))->getTypeConstraint();
1940 assert(TC &&
1941 "TPL must have a template type parameter with a type constraint");
1942 auto *Constraint =
1945 Constraint->getTemplateArgsAsWritten() &&
1947 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1948 TypeConstraintInfo.setInt(Dependent ? true : false);
1949}
1950
1954
1955
1956
1957 true),
1959 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1961
1964 assert(isCompound() && "getCompoundKind on a non-compound constraint..");
1965 return cast(Constraint).getInt();
1966}
1967
1969 assert(isAtomic() && "getAtomicConstraint called on non-atomic constraint.");
1970 return cast<AtomicConstraint *>(Constraint);
1971}
1972
1975 assert(isFoldExpanded() &&
1976 "getFoldExpandedConstraint called on non-fold-expanded constraint.");
1977 return cast<FoldExpandedConstraint *>(Constraint);
1978}
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 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::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 bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, llvm::SmallVectorImpl< Expr * > &Converted, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
static ExprResult calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, const ConstraintEvaluator &Evaluator)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList &MLTAL)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, const MultiLevelTemplateArgumentList &MLTAL, const ASTTemplateArgumentListInfo *ArgsAsWritten)
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
static bool isInvalid(LocType Loc, bool *Invalid)
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getReferenceQualifiedType(const Expr *e) const
getReferenceQualifiedType - Given an expr, will return the type for that expression,...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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 folding of a pack over an operator.
SourceLocation getBeginLoc() const LLVM_READONLY
Expr * getInit() const
Get the operand that doesn't contain a pack, for a binary fold.
std::optional< unsigned > getNumExpansions() const
SourceLocation getEllipsisLoc() const
bool isLeftFold() const
Does this produce a left-associated sequence of operators?
bool isRightFold() const
Does this produce a right-associated sequence of operators?
Expr * getPattern() const
Get the pattern, that is, the operand that contains an unexpanded pack.
BinaryOperatorKind getOperator() const
Represents a C++ struct/union/class.
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
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
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...
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
llvm::SmallVector< Detail, 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.
bool isParameterPack() const
Whether this declaration is a parameter pack.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
bool isInvalidDecl() const
SourceLocation getLocation() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Expr * getTrailingRequiresClause()
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 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, e.g.
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.
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
Describes the capture of a variable or of this, or of a C++1y init-capture.
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...
const ArgList & getInnermost() const
Retrieve the innermost 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.
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
bool isAnyArgInstantiationDependent() const
This represents a decl that may have a name.
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
A (possibly-)qualified type.
The collection of all-type qualifiers we support.
Scope - A scope is a transient data structure that is used while parsing the program.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial 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...
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
SourceLocation getLocation() const
bool ContainsDecl(const NamedDecl *ND) const
const DeclContext * getDeclContext() const
const NamedDecl * getDecl() const
const DeclContext * getLexicalDeclContext() const
Sema - This implements semantic analysis and AST building for C.
bool CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, bool &RetainExpansion, std::optional< unsigned > &NumExpansions)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
DiagnosticsEngine & getDiagnostics() const
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.
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
std::optional< unsigned > getNumArgumentsInExpansionFromUnexpanded(llvm::ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs)
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
void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)
Collect the set of unexpanded parameter packs within the given template argument.
bool CheckConstraintSatisfaction(const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const
Determines whether we are currently in a context where template argument substitution failures are no...
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, ArrayRef< const Expr * > AC1, NamedDecl *D2, ArrayRef< const Expr * > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
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...
ExprResult PerformContextuallyConvertToBool(Expr *From)
PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...
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)
bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef< const Expr * > AC1, NamedDecl *D2, MutableArrayRef< const Expr * > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
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...
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, BinaryOperatorKind Operator)
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)
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
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
A convenient class for passing around template argument information.
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Location wrapper for a TemplateArgument.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< const Expr * > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Represents a C++ template name within the type system.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)
Declaration of a template type parameter.
Wrapper for template type parameters.
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.
Models the abbreviated syntax to constrain a template type parameter: template <convertible_to<string...
Expr * getImmediatelyDeclaredConstraint() const
Get the immediately-declared constraint expression introduced by this type-constraint,...
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
A container of type source information.
SourceLocation getNameLoc() const
void setNameLoc(SourceLocation Loc)
The base class of the type hierarchy.
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 isFunctionType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
ReturnTypeRequirement()
No return type requirement was specified.
bool isTypeConstraint() 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
ExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, ReturnTypeRequirement Req, SatisfactionStatus Status, ConceptSpecializationExpr *SubstitutedConstraintExpr=nullptr)
Construct a compound requirement.
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
StringRef getInvalidConstraintEntity()
A static requirement that can be used in a requires-expression to check properties of types and expre...
bool containsUnexpandedParameterPack() const
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
TypeRequirement(TypeSourceInfo *T)
Construct a type requirement from a type.
Provides information about an attempted template argument deduction, whose success or failure was des...
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
bool Sub(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.
NormalForm makeCNF(const NormalizedConstraint &Normalized)
NormalForm makeDNF(const NormalizedConstraint &Normalized)
@ OK_Ordinary
An ordinary object is located at an address in memory.
bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF, const AtomicSubsumptionEvaluator &E)
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 NormalizedConstraint * getNormalizedAssociatedConstraints(Sema &S, NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
const FunctionProtoType * T
std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl * >, SourceLocation > UnexpandedParameterPack
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ Other
Other implicit parameter.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Represents an explicit template argument list in C++, e.g., the "" in "sort".
SourceLocation getLAngleLoc() const
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
SourceLocation getRAngleLoc() const
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
const Expr * ConstraintExpr
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...
NormalizedConstraint Constraint
static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
llvm::PointerUnion< AtomicConstraint *, FoldExpandedConstraint *, CompoundConstraint > Constraint
bool isFoldExpanded() const
NormalizedConstraint & getRHS() const
llvm::PointerIntPair< NormalizedConstraintPair *, 1, CompoundConstraintKind > CompoundConstraint
CompoundConstraintKind getCompoundKind() const
NormalizedConstraint(AtomicConstraint *C)
AtomicConstraint * getAtomicConstraint() const
FoldExpandedConstraint * getFoldExpandedConstraint() const
NormalizedConstraint & getLHS() const
A stack object to be created when performing template instantiation.
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.