clang: lib/AST/ByteCode/Interp.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef LLVM_CLANG_AST_INTERP_INTERP_H
14#define LLVM_CLANG_AST_INTERP_INTERP_H
15
34#include "llvm/ADT/APFloat.h"
35#include "llvm/ADT/APSInt.h"
36#include <type_traits>
37
40
41using APSInt = llvm::APSInt;
43
44
46
47
50
51
54
55
56
58 uint32_t Offset);
59
60
62
63
65
67
72
73
76
77
79 bool WillBeActivated = false);
80
81
83
84
86
87
88
90
91
92
95
98
99
100
103
105 uint32_t VarArgSize);
107 uint32_t VarArgSize);
109 uint32_t VarArgSize);
111 uint32_t BuiltinID);
117 bool TargetIsUCharOrByte);
121
124
126
128
129
130template <ShiftDir Dir, typename LT, typename RT>
132 unsigned Bits) {
133 if (RHS.isNegative()) {
135 S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
137 return false;
138 }
139
140
141
142 if (Bits > 1 && RHS >= Bits) {
144 const APSInt Val = RHS.toAPSInt();
146 S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
148 return false;
149 }
150
152 if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
153
154
155 if (LHS.isNegative()) {
157 S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
159 return false;
160 } else if (LHS.toUnsigned().countLeadingZeros() <
161 static_cast<unsigned>(RHS)) {
163 S.CCEDiag(E, diag::note_constexpr_lshift_discards);
165 return false;
166 }
167 }
168 }
169
170
171
172
173 return true;
174}
175
176
177template
179 if (RHS.isZero()) {
181 if constexpr (std::is_same_v<T, Floating>) {
182 S.CCEDiag(Op, diag::note_expr_divide_by_zero)
183 << Op->getRHS()->getSourceRange();
184 return true;
185 }
186
187 S.FFDiag(Op, diag::note_expr_divide_by_zero)
188 << Op->getRHS()->getSourceRange();
189 return false;
190 }
191
192 if constexpr (!std::is_same_v<T, FixedPoint>) {
193 if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
194 APSInt LHSInt = LHS.toAPSInt();
196 (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
199 S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType();
200 return false;
201 }
202 }
203 return true;
204}
205
206
207
209 APFloat::opStatus Status, FPOptions FPO);
210
211
213
215
216
217
218
219
222
223template <PrimType Name, class T = typename PrimConv::T>
226
231
237 } else {
240
241
242 }
243 return true;
244}
245
248
251
256 } else {
259 }
260 return true;
261}
262
263
264
265
266
268 template class OpAP>
270 const T &RHS) {
271
275
276 if (!OpFW(LHS, RHS, Bits, &Result)) {
278 return true;
279 }
280
282
283
284 if constexpr (std::is_same_v<T, FixedPoint>)
286
287
289
290
296 .toString(Trunc, 10, Result.isSigned(), false,
297 true, true);
298 S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
300 }
301
304 return false;
305 }
306 return true;
307}
308
309template <PrimType Name, class T = typename PrimConv::T>
311 const T &RHS = S.Stk.pop<T>();
312 const T &LHS = S.Stk.pop<T>();
313 const unsigned Bits = RHS.bitWidth() + 1;
314
316}
317
328
329template <PrimType Name, class T = typename PrimConv::T>
331 const T &RHS = S.Stk.pop<T>();
332 const T &LHS = S.Stk.pop<T>();
333 const unsigned Bits = RHS.bitWidth() + 1;
334
336}
337
348
349template <PrimType Name, class T = typename PrimConv::T>
351 const T &RHS = S.Stk.pop<T>();
352 const T &LHS = S.Stk.pop<T>();
353 const unsigned Bits = RHS.bitWidth() * 2;
354
356}
357
370
371template <PrimType Name, class T = typename PrimConv::T>
376
377 if constexpr (std::is_same_v<T, Floating>) {
382
383 APFloat ResR(A.getSemantics());
384 APFloat ResI(A.getSemantics());
386
387
389 RA.copy(ResR);
391
393 RI.copy(ResI);
395 Result.initializeAllElements();
396 } else {
397
398 const T &LHSR = LHS.elem<T>(0);
399 const T &LHSI = LHS.elem<T>(1);
400 const T &RHSR = RHS.elem<T>(0);
401 const T &RHSI = RHS.elem<T>(1);
402 unsigned Bits = LHSR.bitWidth();
403
404
405 T A;
406 if (T::mul(LHSR, RHSR, Bits, &A))
407 return false;
408 T B;
409 if (T::mul(LHSI, RHSI, Bits, &B))
410 return false;
411 if (T::sub(A, B, Bits, &Result.elem<T>(0)))
412 return false;
413
414
415 if (T::mul(LHSR, RHSI, Bits, &A))
416 return false;
417 if (T::mul(LHSI, RHSR, Bits, &B))
418 return false;
419 if (T::add(A, B, Bits, &Result.elem<T>(1)))
420 return false;
422 Result.initializeAllElements();
423 }
424
425 return true;
426}
427
428template <PrimType Name, class T = typename PrimConv::T>
433
434 if constexpr (std::is_same_v<T, Floating>) {
439
440 APFloat ResR(A.getSemantics());
441 APFloat ResI(A.getSemantics());
443
444
446 RA.copy(ResR);
448
450 RI.copy(ResI);
452
453 Result.initializeAllElements();
454 } else {
455
456 const T &LHSR = LHS.elem<T>(0);
457 const T &LHSI = LHS.elem<T>(1);
458 const T &RHSR = RHS.elem<T>(0);
459 const T &RHSI = RHS.elem<T>(1);
460 unsigned Bits = LHSR.bitWidth();
462
466 S.FFDiag(E, diag::note_expr_divide_by_zero);
467 return false;
468 }
469
470
471 T A, B;
472 if (T::mul(RHSR, RHSR, Bits, &A) || T::mul(RHSI, RHSI, Bits, &B)) {
473
474 }
475 T Den;
476 if (T::add(A, B, Bits, &Den))
477 return false;
478
481 S.FFDiag(E, diag::note_expr_divide_by_zero);
482 return false;
483 }
484
485
486 T &ResultR = Result.elem<T>(0);
487 T &ResultI = Result.elem<T>(1);
488
489 if (T::mul(LHSR, RHSR, Bits, &A) || T::mul(LHSI, RHSI, Bits, &B))
490 return false;
491 if (T::add(A, B, Bits, &ResultR))
492 return false;
493 if (T::div(ResultR, Den, Bits, &ResultR))
494 return false;
495
496
497 if (T::mul(LHSI, RHSR, Bits, &A) || T::mul(LHSR, RHSI, Bits, &B))
498 return false;
499 if (T::sub(A, B, Bits, &ResultI))
500 return false;
501 if (T::div(ResultI, Den, Bits, &ResultI))
502 return false;
503 Result.initializeAllElements();
504 }
505
506 return true;
507}
508
509
510
511
512template <PrimType Name, class T = typename PrimConv::T>
514 const T &RHS = S.Stk.pop<T>();
515 const T &LHS = S.Stk.pop<T>();
516 unsigned Bits = RHS.bitWidth();
517
521
522 if (!T::bitAnd(LHS, RHS, Bits, &Result)) {
524 return true;
525 }
526 return false;
527}
528
529
530
531
532template <PrimType Name, class T = typename PrimConv::T>
534 const T &RHS = S.Stk.pop<T>();
535 const T &LHS = S.Stk.pop<T>();
536 unsigned Bits = RHS.bitWidth();
537
541
542 if (!T::bitOr(LHS, RHS, Bits, &Result)) {
544 return true;
545 }
546 return false;
547}
548
549
550
551
552template <PrimType Name, class T = typename PrimConv::T>
554 const T &RHS = S.Stk.pop<T>();
555 const T &LHS = S.Stk.pop<T>();
556
557 unsigned Bits = RHS.bitWidth();
558
562
563 if (!T::bitXor(LHS, RHS, Bits, &Result)) {
565 return true;
566 }
567 return false;
568}
569
570
571
572
573template <PrimType Name, class T = typename PrimConv::T>
575 const T &RHS = S.Stk.pop<T>();
576 const T &LHS = S.Stk.pop<T>();
577 const unsigned Bits = RHS.bitWidth() * 2;
578
580 return false;
581
585
586 if (!T::rem(LHS, RHS, Bits, &Result)) {
588 return true;
589 }
590 return false;
591}
592
593
594
595
596template <PrimType Name, class T = typename PrimConv::T>
598 const T &RHS = S.Stk.pop<T>();
599 const T &LHS = S.Stk.pop<T>();
600 const unsigned Bits = RHS.bitWidth() * 2;
601
603 return false;
604
608
609 if (!T::div(LHS, RHS, Bits, &Result)) {
611 return true;
612 }
613
614 if constexpr (std::is_same_v<T, FixedPoint>) {
617 return true;
618 }
619 }
620 return false;
621}
622
626
628 return false;
629
631
634
637}
638
639
640
641
642
648
649
650
651
652
653template <PrimType Name, class T = typename PrimConv::T>
656
657 if constexpr (std::is_same_v<T, Floating>) {
659
662 return true;
663 }
664 return false;
665 } else {
669
672 return true;
673 }
674
676 "don't expect other types to fail at constexpr negation");
678
684 NegatedValue.trunc(Result.bitWidth())
685 .toString(Trunc, 10, Result.isSigned(), false,
686 true, true);
687 S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
689 return true;
690 }
691
693 }
694}
695
704
705template <typename T, IncDecOp Op, PushVal DoPush>
707 bool CanOverflow, UnsignedOrNone BitWidth = std::nullopt) {
709
712 return false;
713 }
714
715 if constexpr (std::is_same_v<T, Boolean>) {
718 }
719
724
727
729 if (!T::increment(Value, &Result) || !CanOverflow) {
730 if (BitWidth)
732 else
734 return true;
735 }
736 } else {
737 if (!T::decrement(Value, &Result) || !CanOverflow) {
738 if (BitWidth)
740 else
742 return true;
743 }
744 }
745 assert(CanOverflow);
746
747
748
749 unsigned Bits = Value.bitWidth() + 1;
752 APResult = ++Value.toAPSInt(Bits);
753 else
754 APResult = --Value.toAPSInt(Bits);
755
756
761 APResult.trunc(Result.bitWidth())
762 .toString(Trunc, 10, Result.isSigned(), false,
763 true, true);
764 S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
766 return true;
767 }
769}
770
771
772
773
774
775template <PrimType Name, class T = typename PrimConv::T>
779 return false;
780
782 CanOverflow);
783}
784
785template <PrimType Name, class T = typename PrimConv::T>
787 unsigned BitWidth) {
790 return false;
791
793 BitWidth);
794}
795
796
797
798
799template <PrimType Name, class T = typename PrimConv::T>
803 return false;
804
806}
807
808template <PrimType Name, class T = typename PrimConv::T>
810 uint32_t BitWidth) {
813 return false;
814
816 BitWidth);
817}
818
819template <PrimType Name, class T = typename PrimConv::T>
823 return false;
824
826}
827
828template <PrimType Name, class T = typename PrimConv::T>
830 uint32_t BitWidth) {
833 return false;
834
836 BitWidth);
837}
838
839
840
841
842
843template <PrimType Name, class T = typename PrimConv::T>
847 return false;
848
850 CanOverflow);
851}
852template <PrimType Name, class T = typename PrimConv::T>
854 uint32_t BitWidth) {
857 return false;
858
860 BitWidth);
861}
862
863
864
865
866template <PrimType Name, class T = typename PrimConv::T>
870 return false;
871
873}
874
875template <PrimType Name, class T = typename PrimConv::T>
877 uint32_t BitWidth) {
880 return false;
881
883 BitWidth);
884}
885
886template <PrimType Name, class T = typename PrimConv::T>
893
894template <PrimType Name, class T = typename PrimConv::T>
896 uint32_t BitWidth) {
899 return false;
901 BitWidth);
902}
903
904template <IncDecOp Op, PushVal DoPush>
906 uint32_t FPOI) {
909
912
914 llvm::APFloat::opStatus Status;
917 else
919
921
923}
924
928 return false;
929
931}
932
936 return false;
937
939}
940
944 return false;
945
947}
948
952 return false;
953
955}
956
957
958
959template <PrimType Name, class T = typename PrimConv::T>
961 const T &Val = S.Stk.pop<T>();
962
966
967 if (!T::comp(Val, &Result)) {
969 return true;
970 }
971 return false;
972}
973
974
975
976
977
979
980template
982 assert((!std::is_same_v<T, MemberPointer>) &&
983 "Non-equality comparisons on member pointer types should already be "
984 "rejected in Sema.");
986 const T &RHS = S.Stk.pop<T>();
987 const T &LHS = S.Stk.pop<T>();
988 S.Stk.push(BoolT::from(Fn(LHS.compare(RHS))));
989 return true;
990}
991
992template
996
997template <>
1002
1003
1007 S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1010 return false;
1011 }
1012
1015 S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1018 return false;
1019 }
1020
1021
1022 if (std::optional<std::pair<Pointer, Pointer>> Split =
1024 const FieldDecl *LF = Split->first.getField();
1025 const FieldDecl *RF = Split->second.getField();
1029 diag::note_constexpr_pointer_comparison_differing_access)
1031 }
1032 }
1033
1037 return true;
1038}
1039
1042 return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
1043 Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
1044 Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
1045 Builtin == Builtin::BI__builtin_function_start);
1046}
1047
1050
1051template <>
1056
1057 if (LHS.isZero() && RHS.isZero()) {
1059 return true;
1060 }
1061
1062
1063 for (const auto &P : {LHS, RHS}) {
1064 if (P.isZero())
1065 continue;
1066 if (P.isWeak()) {
1068 S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
1070 return false;
1071 }
1072 }
1073
1076 return false;
1077 }
1078
1080 S.Stk.push(BoolT::from(Fn(Compare(LHS.getIntegerRepresentation(),
1082 return true;
1083 }
1084
1085
1090 S.FFDiag(Loc, diag::note_constexpr_literal_comparison)
1093 return false;
1094 }
1095 }
1096
1098 size_t A = LHS.computeOffsetForComparison();
1101 return true;
1102 }
1103
1104
1108 S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1110 return false;
1111 }
1112 if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
1113 LHS.getOffset() == 0) {
1115 S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
1117 return false;
1118 }
1119
1120 bool BothNonNull = !LHS.isZero() && !RHS.isZero();
1121
1122 for (const auto &P : {LHS, RHS}) {
1123 if (P.isZero())
1124 continue;
1125 if (BothNonNull && P.pointsToLiteral()) {
1126 const Expr *E = P.getDeclDesc()->asExpr();
1129 S.FFDiag(Loc, diag::note_constexpr_literal_comparison);
1130 return false;
1131 }
1132 if (const auto *CE = dyn_cast(E);
1135 S.FFDiag(Loc, diag::note_constexpr_opaque_call_comparison)
1137 return false;
1138 }
1139 } else if (BothNonNull && P.isIntegralPointer()) {
1141 S.FFDiag(Loc, diag::note_constexpr_pointer_constant_comparison)
1144 return false;
1145 }
1146 }
1147
1150 S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_zero_sized)
1153 return false;
1154 }
1155
1157 return true;
1158}
1159
1160template <>
1165
1166
1167
1168 for (const auto &MP : {LHS, RHS}) {
1169 if (MP.isWeak()) {
1171 S.FFDiag(Loc, diag::note_constexpr_mem_pointer_weak_comparison)
1172 << MP.getMemberFunction();
1173 return false;
1174 }
1175 }
1176
1177
1178
1179
1180 if (LHS.isZero() && RHS.isZero()) {
1182 return true;
1183 }
1184 if (LHS.isZero() || RHS.isZero()) {
1186 return true;
1187 }
1188
1189
1190 for (const auto &MP : {LHS, RHS}) {
1191 if (const CXXMethodDecl *MD = MP.getMemberFunction();
1194 S.CCEDiag(Loc, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
1195 }
1196 }
1197
1199 return true;
1200}
1201
1202template <PrimType Name, class T = typename PrimConv::T>
1208
1209template <PrimType Name, class T = typename PrimConv::T>
1211 const T &RHS = S.Stk.pop<T>();
1212 const T &LHS = S.Stk.pop<T>();
1214
1216 if constexpr (std::is_same_v<T, Pointer>) {
1219 S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
1222 return false;
1223 }
1224 }
1225
1226 assert(CmpInfo);
1227 const auto *CmpValueInfo =
1229 assert(CmpValueInfo);
1230 assert(CmpValueInfo->hasValidIntValue());
1232}
1233
1234template <PrimType Name, class T = typename PrimConv::T>
1240
1241template <PrimType Name, class T = typename PrimConv::T>
1247
1248template <PrimType Name, class T = typename PrimConv::T>
1255
1256template <PrimType Name, class T = typename PrimConv::T>
1262
1263template <PrimType Name, class T = typename PrimConv::T>
1270
1271
1272
1273
1274
1275template <PrimType Name, class T = typename PrimConv::T>
1280
1281template <PrimType Name, class T = typename PrimConv::T>
1286
1287
1288template <PrimType TopName, PrimType BottomName>
1292
1293 const auto &Top = S.Stk.pop();
1294 const auto &Bottom = S.Stk.pop();
1295
1298
1299 return true;
1300}
1301
1302
1303
1304
1305
1306template <PrimType Name, class T = typename PrimConv::T>
1310 Result.copy(Arg.toAPSInt());
1312 return true;
1313 }
1315 return true;
1316}
1317
1324
1325
1326
1327
1328
1329template <PrimType Name, class T = typename PrimConv::T>
1333 return false;
1335 return true;
1336}
1337
1338bool EndLifetime(InterpState &S, CodePtr OpPC);
1340bool StartLifetime(InterpState &S, CodePtr OpPC);
1341
1342
1343
1344
1345template <PrimType Name, class T = typename PrimConv::T>
1350
1351template <PrimType Name, class T = typename PrimConv::T>
1354 return false;
1355 }
1357 return true;
1358}
1359
1360template <PrimType Name, class T = typename PrimConv::T>
1365
1366
1367
1368template <PrimType Name, class T = typename PrimConv::T>
1372 return false;
1374 return false;
1377 return false;
1378 S.Stk.push<T>(Field.deref<T>());
1379 return true;
1380}
1381
1382template <PrimType Name, class T = typename PrimConv::T>
1387 return false;
1389 return false;
1392 return false;
1394 Field.deref<T>() = Value;
1395 return true;
1396}
1397
1398
1399
1400template <PrimType Name, class T = typename PrimConv::T>
1404 return false;
1406 return false;
1409 return false;
1410 S.Stk.push<T>(Field.deref<T>());
1411 return true;
1412}
1413
1414template <PrimType Name, class T = typename PrimConv::T>
1417 return false;
1419 return false;
1423 return false;
1424 S.Stk.push<T>(Field.deref<T>());
1425 return true;
1426}
1427
1428template <PrimType Name, class T = typename PrimConv::T>
1431 return false;
1433 return false;
1438 return false;
1439 Field.deref<T>() = Value;
1440 return true;
1441}
1442
1443template <PrimType Name, class T = typename PrimConv::T>
1446
1448 return false;
1449
1451 return true;
1452}
1453
1454
1455template <PrimType Name, class T = typename PrimConv::T>
1458 const auto &Desc =
1463
1465 return true;
1466}
1467
1468template <PrimType Name, class T = typename PrimConv::T>
1470
1471 return false;
1472}
1473
1474template <PrimType Name, class T = typename PrimConv::T>
1477
1479
1480 if constexpr (std::is_same_v<T, Floating>) {
1482 if (!Val.singleWord()) {
1483 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
1484 Val.take(NewMemory);
1485 }
1486
1488 auto &Val = P.deref<T>();
1489 if (!Val.singleWord()) {
1490 uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
1491 Val.take(NewMemory);
1492 }
1493 }
1494
1496 return true;
1497}
1498
1499
1500
1501
1502template <PrimType Name, class T = typename PrimConv::T>
1506 return false;
1507 assert(Temp);
1508
1513
1516 return true;
1517}
1518
1519
1520
1521
1525 return false;
1526 assert(Temp);
1527
1531 return true;
1532}
1533
1534template <PrimType Name, class T = typename PrimConv::T>
1537 return false;
1539 return false;
1542 assert(Field.canBeInitialized());
1543 Field.deref<T>() = S.Stk.pop<T>();
1544 Field.initialize();
1545 return true;
1546}
1547
1548template <PrimType Name, class T = typename PrimConv::T>
1551 return false;
1553 return false;
1556 assert(Field.canBeInitialized());
1557 Field.deref<T>() = S.Stk.pop<T>();
1558 Field.activate();
1559 Field.initialize();
1560 return true;
1561}
1562
1563
1564
1565template <PrimType Name, class T = typename PrimConv::T>
1567 uint32_t FieldOffset) {
1568 assert(F->isBitField());
1570 return false;
1572 return false;
1574 const Pointer &Field = This.atField(FieldOffset);
1575 assert(Field.canBeInitialized());
1577 Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
1578 Field.initialize();
1579 return true;
1580}
1581
1582template <PrimType Name, class T = typename PrimConv::T>
1584 const Record::Field *F, uint32_t FieldOffset) {
1585 assert(F->isBitField());
1587 return false;
1589 return false;
1591 const Pointer &Field = This.atField(FieldOffset);
1592 assert(Field.canBeInitialized());
1594 Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
1595 Field.initialize();
1596 Field.activate();
1597 return true;
1598}
1599
1600
1601
1602
1603template <PrimType Name, class T = typename PrimConv::T>
1608 return false;
1610 return false;
1611
1614 Field.initialize();
1615 return true;
1616}
1617
1618template <PrimType Name, class T = typename PrimConv::T>
1623 return false;
1625 return false;
1626
1629 Field.activate();
1630 Field.initialize();
1631 return true;
1632}
1633
1634template <PrimType Name, class T = typename PrimConv::T>
1636 assert(F->isBitField());
1640 return false;
1642 return false;
1643
1645
1648 if (T::isSigned())
1650 .trunc(F->Decl->getBitWidthValue())
1651 .sextOrTrunc(Value.bitWidth()));
1652 else
1654 .trunc(F->Decl->getBitWidthValue())
1655 .zextOrTrunc(Value.bitWidth()));
1656
1657 Field.deref<T>() = Result;
1658 } else {
1659 Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
1660 }
1662 return true;
1663}
1664
1665template <PrimType Name, class T = typename PrimConv::T>
1667 const Record::Field *F) {
1668 assert(F->isBitField());
1672 return false;
1674 return false;
1675
1677
1680 if (T::isSigned())
1682 .trunc(F->Decl->getBitWidthValue())
1683 .sextOrTrunc(Value.bitWidth()));
1684 else
1686 .trunc(F->Decl->getBitWidthValue())
1687 .zextOrTrunc(Value.bitWidth()));
1688
1689 Field.deref<T>() = Result;
1690 } else {
1691 Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
1692 }
1694 Field.initialize();
1695 return true;
1696}
1697
1698
1699
1700
1701
1706
1709 return false;
1711 return true;
1712}
1713
1718
1719
1720
1721bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off);
1722bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off);
1723
1726 return false;
1728 return false;
1731 return true;
1732}
1733
1735 bool NullOK, const Type *TargetType) {
1738 return false;
1739
1741
1742
1743
1745 return true;
1746 }
1747
1749 return false;
1751 return false;
1752
1754 assert(TargetRecord);
1755
1760 << MostDerivedType << QualType(TargetType, 0);
1761 return false;
1762 }
1763
1765 return true;
1766}
1767
1771 return false;
1772
1775 return false;
1777 return true;
1778 }
1779
1781 return false;
1783 if (Result.isPastEnd() || .isBaseClass())
1784 return false;
1786 return true;
1787}
1788
1790 bool NullOK) {
1792
1794 return false;
1795
1798 return false;
1800 return true;
1801 }
1802
1804 return false;
1806 if (Result.isPastEnd() || .isBaseClass())
1807 return false;
1809 return true;
1810}
1811
1817
1820 return false;
1822 return false;
1825 return true;
1826}
1827
1834
1841
1847 }
1848 return true;
1849}
1850
1856 }
1857 return true;
1858}
1859
1861
1866
1869 if (Ptr.isZero()) {
1871 diag::note_constexpr_dereferencing_null);
1873 }
1874 return true;
1875}
1876
1880 while (Base.isBaseClass())
1882
1883 const Record::Base *VirtBase = Base.getRecord()->getVirtualBase(Decl);
1885 return true;
1886}
1887
1890 assert(D);
1893 return false;
1895}
1896
1899 assert(D);
1901 return false;
1903 return false;
1906}
1907
1908
1909
1910
1911
1912template <PrimType Name, class T = typename PrimConv::T>
1916 return false;
1918 return false;
1920 !(D->isPrimitive() || D->isPrimitiveArray()) || D->getPrimType() != Name)
1921 return false;
1923 return true;
1924}
1925
1926template <PrimType Name, class T = typename PrimConv::T>
1930 return false;
1932 return false;
1934 !(D->isPrimitive() || D->isPrimitiveArray()) || D->getPrimType() != Name)
1935 return false;
1937 return true;
1938}
1939
1940template <PrimType Name, class T = typename PrimConv::T>
1945 return false;
1946 if (Ptr.canBeInitialized())
1949 return true;
1950}
1951
1952template <PrimType Name, class T = typename PrimConv::T>
1957 return false;
1958 if (Ptr.canBeInitialized())
1961 return true;
1962}
1963
1970
1973 return false;
1975 return false;
1976
1980 return true;
1981}
1982
1983template <PrimType Name, class T = typename PrimConv::T>
1987
1988 if ((S, OpPC, Ptr, true))
1989 return false;
1990 if (Ptr.canBeInitialized()) {
1991 Ptr.initialize();
1992 Ptr.activate();
1993 }
1995 return true;
1996}
1997
1998template <PrimType Name, class T = typename PrimConv::T>
2002
2003 if ((S, OpPC, Ptr, true))
2004 return false;
2005 if (Ptr.canBeInitialized()) {
2006 Ptr.initialize();
2007 Ptr.activate();
2008 }
2010 return true;
2011}
2012
2013template <PrimType Name, class T = typename PrimConv::T>
2017
2018 if ((S, OpPC, Ptr, true))
2019 return false;
2020 if (Ptr.canBeInitialized())
2022 if (const auto *FD = Ptr.getField())
2023 Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
2024 else
2026 return true;
2027}
2028
2029template <PrimType Name, class T = typename PrimConv::T>
2034 return false;
2035 if (Ptr.canBeInitialized())
2037 if (const auto *FD = Ptr.getField())
2038 Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
2039 else
2041 return true;
2042}
2043
2044template <PrimType Name, class T = typename PrimConv::T>
2048
2049 if ((S, OpPC, Ptr, true))
2050 return false;
2051 if (Ptr.canBeInitialized()) {
2052 Ptr.initialize();
2053 Ptr.activate();
2054 }
2055 if (const auto *FD = Ptr.getField())
2056 Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
2057 else
2059 return true;
2060}
2061
2062template <PrimType Name, class T = typename PrimConv::T>
2066
2067 if ((S, OpPC, Ptr, true))
2068 return false;
2069 if (Ptr.canBeInitialized()) {
2070 Ptr.initialize();
2071 Ptr.activate();
2072 }
2073 if (const auto *FD = Ptr.getField())
2074 Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
2075 else
2077 return true;
2078}
2079
2080template <PrimType Name, class T = typename PrimConv::T>
2085 return false;
2087 new (&Ptr.deref<T>()) T(Value);
2088 return true;
2089}
2090
2091template <PrimType Name, class T = typename PrimConv::T>
2096 return false;
2098 new (&Ptr.deref<T>()) T(Value);
2099 return true;
2100}
2101
2102
2103
2104
2105template <PrimType Name, class T = typename PrimConv::T>
2109
2110 const Descriptor *Desc = Ptr.getFieldDesc();
2111 if (Desc->isUnknownSizeArray())
2112 return false;
2113
2114
2115
2116 if (Idx == 0 && !Desc->isArray()) {
2117 Ptr.initialize();
2118 new (&Ptr.deref<T>()) T(Value);
2119 return true;
2120 }
2121
2123 return false;
2124 if (Idx >= Desc->getNumElems()) {
2125
2128 S.FFDiag(Loc, diag::note_constexpr_access_past_end)
2130 }
2131 return false;
2132 }
2133 Ptr.initializeElement(Idx);
2134 new (&Ptr.elem<T>(Idx)) T(Value);
2135 return true;
2136}
2137
2138
2139template <PrimType Name, class T = typename PrimConv::T>
2143
2144 const Descriptor *Desc = Ptr.getFieldDesc();
2145 if (Desc->isUnknownSizeArray())
2146 return false;
2147
2148
2149
2150 if (Idx == 0 && !Desc->isArray()) {
2151 Ptr.initialize();
2152 new (&Ptr.deref<T>()) T(Value);
2153 return true;
2154 }
2155
2157 return false;
2158 if (Idx >= Desc->getNumElems()) {
2159
2162 S.FFDiag(Loc, diag::note_constexpr_access_past_end)
2164 }
2165 return false;
2166 }
2167 Ptr.initializeElement(Idx);
2168 new (&Ptr.elem<T>(Idx)) T(Value);
2169 return true;
2170}
2171
2175
2177 return false;
2178
2179 return DoMemcpy(S, OpPC, Src, Dest);
2180}
2181
2185
2187 return true;
2188}
2189
2192
2193 if (std::optional Ptr = MP.toPointer(S.Ctx)) {
2195 return true;
2196 }
2197 return Invalid(S, OpPC);
2198}
2199
2200
2201
2202
2203
2204template <class T, ArithOp Op>
2206 const T &Offset, const Pointer &Ptr,
2207 bool IsPointerArith = false) {
2208
2209 if (Offset.isZero())
2210 return Ptr;
2211
2213
2214
2216 return std::nullopt;
2217 }
2218
2219
2221 return std::nullopt;
2222
2223
2226 uint64_t O = static_cast<uint64_t>(Offset) * Ptr.elemSize();
2229 else
2232 uint64_t O = static_cast<uint64_t>(Offset);
2233 uint64_t N;
2236 else
2238
2239 if (N > 1)
2241 << N << true << 0;
2244 return std::nullopt;
2245 }
2246
2248
2249 uint64_t MaxIndex = static_cast<uint64_t>(Ptr.getNumElems());
2250 uint64_t Index;
2252 Index = MaxIndex;
2253 else
2255
2257
2258 auto DiagInvalidOffset = [&]() -> void {
2259 const unsigned Bits = Offset.bitWidth();
2260 APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), false);
2261 APSInt APIndex(APInt(Bits + 2, Index, true),
2262 false);
2264 (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
2266 << NewIndex << static_cast<int>(!Ptr.inArray()) << MaxIndex;
2268 };
2269
2271 uint64_t IOffset = static_cast<uint64_t>(Offset);
2272 uint64_t MaxOffset = MaxIndex - Index;
2273
2275
2276 if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
2277 DiagInvalidOffset();
2278
2279
2280 if (Offset.isPositive() && IOffset > MaxOffset)
2281 DiagInvalidOffset();
2282 } else {
2283
2284 if (Offset.isPositive() && Index < IOffset)
2285 DiagInvalidOffset();
2286
2287
2288 if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
2289 DiagInvalidOffset();
2290 }
2291 }
2292
2294 return std::nullopt;
2295
2296
2297 int64_t WideIndex = static_cast<int64_t>(Index);
2298 int64_t WideOffset = static_cast<int64_t>(Offset);
2301 Result = WideIndex + WideOffset;
2302 else
2303 Result = WideIndex - WideOffset;
2304
2305
2306
2307
2312 }
2313
2314 return Ptr.atIndex(static_cast<uint64_t>(Result));
2315}
2316
2317template <PrimType Name, class T = typename PrimConv::T>
2319 const T &Offset = S.Stk.pop<T>();
2321
2323 S, OpPC, Offset, Ptr, true)) {
2325 return true;
2326 }
2327 return false;
2328}
2329
2330template <PrimType Name, class T = typename PrimConv::T>
2332 const T &Offset = S.Stk.pop<T>();
2334
2336 S, OpPC, Offset, Ptr, true)) {
2338 return true;
2339 }
2340 return false;
2341}
2342
2343template
2347 return false;
2348
2350
2353 return false;
2354
2355
2357
2358
2359 OneT One = OneT::from(1);
2360 if (std::optional Result =
2362
2364 return true;
2365 }
2366 return false;
2367}
2368
2377
2386
2387
2388
2389
2390template <PrimType Name, class T = typename PrimConv::T>
2394
2397 diag::note_constexpr_pointer_arith_unspecified)
2400 return false;
2401 }
2402
2403 if (ElemSizeIsZero) {
2405 while (auto *AT = dyn_cast(PtrT))
2406 PtrT = AT->getElementType();
2407
2411 diag::note_constexpr_pointer_subtraction_zero_size)
2412 << ArrayTy;
2413
2414 return false;
2415 }
2416
2417 if (LHS == RHS) {
2419 return true;
2420 }
2421
2422 int64_t A64 =
2426
2427 int64_t B64 =
2431
2432 int64_t R64 = A64 - B64;
2433 if (static_cast<int64_t>(T::from(R64)) != R64)
2435
2436 S.Stk.push<T>(T::from(R64));
2437 return true;
2438}
2439
2440
2441
2442
2443
2446
2447
2448
2451
2453
2456 S.FFDiag(ND->getLocation(),
2457 diag::note_constexpr_destroy_out_of_lifetime)
2458 << ND->getNameAsString();
2459 } else {
2461 diag::note_constexpr_destroy_out_of_lifetime)
2463 }
2464 return false;
2465 }
2466 }
2467
2469 return true;
2470}
2471
2476
2482
2488
2489
2490
2491
2492
2499
2500
2501
2503 llvm::RoundingMode RM) {
2508 return true;
2509}
2510
2513 FixedPointSemantics::getFromOpaqueInt(FPS);
2515
2516 bool Overflow;
2517 FixedPoint Result = Source.toSemantics(TargetSemantics, &Overflow);
2518
2520 return false;
2521
2523 return true;
2524}
2525
2526
2527
2528template <PrimType Name, class T = typename PrimConv::T>
2531
2532 {
2533 APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
2534 Result.copy(Source);
2535 }
2537 return true;
2538}
2539
2540template <PrimType Name, class T = typename PrimConv::T>
2543
2544 {
2545 APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
2546 Result.copy(Source);
2547 }
2549 return true;
2550}
2551
2552template <PrimType Name, class T = typename PrimConv::T>
2554 const llvm::fltSemantics *Sem, uint32_t FPOI) {
2555 const T &From = S.Stk.pop<T>();
2556 APSInt FromAP = From.toAPSInt();
2557
2560 auto Status =
2563
2565}
2566
2567template <PrimType Name, class T = typename PrimConv::T>
2570
2571 if constexpr (std::is_same_v<T, Boolean>) {
2573 return true;
2574 } else {
2576 !T::isSigned());
2578
2579
2580 if ((Status & APFloat::opStatus::opInvalidOp)) {
2583
2587 return true;
2588 }
2589 return false;
2590 }
2591
2595 }
2596}
2597
2599 uint32_t BitWidth, uint32_t FPOI) {
2601
2602 APSInt Result(BitWidth, true);
2604
2605
2606 if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite())
2608
2610
2613
2615
2617}
2618
2620 uint32_t BitWidth, uint32_t FPOI) {
2622
2623 APSInt Result(BitWidth, false);
2625
2626
2627 if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite())
2629
2631
2634
2636
2638}
2639
2641 const Pointer &Ptr, unsigned BitWidth);
2644
2645template <PrimType Name, class T = typename PrimConv::T>
2648
2650 return Invalid(S, OpPC);
2651
2653 return true;
2654}
2655
2656template <PrimType Name, class T = typename PrimConv::T>
2658 uint32_t FPS) {
2660
2662
2663 bool Overflow;
2665
2667 return false;
2668
2670 return true;
2671}
2672
2674 uint32_t FPS) {
2676
2678
2679 bool Overflow;
2681
2683 return false;
2684
2686 return true;
2687}
2688
2690 const llvm::fltSemantics *Sem) {
2693 Result.copy(Fixed.toFloat(Sem));
2695 return true;
2696}
2697
2698template <PrimType Name, class T = typename PrimConv::T>
2701
2702 bool Overflow;
2703 APSInt Int = Fixed.toInt(T::bitWidth(), T::isSigned(), &Overflow);
2704
2706 return false;
2707
2709 return true;
2710}
2711
2714 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
2715 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2717 return true;
2718}
2719
2722
2723 if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
2724 bool HasValidResult = !Ptr.isZero();
2725
2726 if (HasValidResult) {
2728 return true;
2729
2733 E->getType()->getPointeeType()))
2734 return true;
2735
2736 S.CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
2737 << E->getSubExpr()->getType() << S.getLangOpts().CPlusPlus26
2738 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
2739 } else if (!S.getLangOpts().CPlusPlus26) {
2741 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
2742 << diag::ConstexprInvalidCastKind::CastFrom << "'void *'"
2744 }
2745 } else {
2747 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
2748 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
2750 }
2751
2752 return true;
2753}
2754
2755
2756
2757
2758
2759template <PrimType Name, class T = typename PrimConv::T>
2764
2767 if (.singleWord())
2768 std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
2770 return true;
2771}
2772
2775 if (.singleWord())
2776 std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
2778 return true;
2779}
2780
2781template <PrimType Name, class T = typename PrimConv::T>
2784
2785
2787 return true;
2788}
2789
2790template <PrimType Name, class T = typename PrimConv::T>
2792 const auto &P = S.Stk.pop<T>();
2793 if (P.isWeak())
2794 return false;
2796 return true;
2797}
2798
2799
2800
2801
2802
2804
2806 return false;
2808 return false;
2810
2811
2812 if (.isDummy()) {
2814 if (.isTypeidPointer()) {
2815 [[maybe_unused]] const Record *R = This.getRecord();
2816 if (!R)
2817 R = This.narrow().getRecord();
2818 assert(R);
2821 ->getParent());
2822 }
2823 }
2824
2826 return true;
2827}
2828
2832 return false;
2834 return true;
2835}
2836
2837
2838
2839
2840
2841template <class LT, class RT, ShiftDir Dir>
2845 const unsigned Bits = LHS.bitWidth();
2846
2847
2849 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
2850 RHS.bitWidth(), &RHS);
2851
2852 if (RHS.isNegative()) {
2853
2854
2856 S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
2858 return false;
2859 RHS = -RHS;
2862 S, OpPC, LHS, RHS, Result);
2863 }
2864
2866 return false;
2867
2868
2869
2870
2871
2872
2873
2874 typename LT::AsUnsigned R;
2875 unsigned MaxShiftAmount = LHS.bitWidth() - 1;
2877 if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
2879 if (LHS.isNegative())
2880 R = LT::AsUnsigned::zero(LHS.bitWidth());
2881 else {
2882 RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
2883 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2884 LT::AsUnsigned::from(RHS, Bits), Bits, &R);
2885 }
2886 } else if (LHS.isNegative()) {
2887 if (LHS.isMin()) {
2888 R = LT::AsUnsigned::zero(LHS.bitWidth());
2889 } else {
2890
2891 typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
2892 LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS, Bits), Bits,
2893 &R);
2894 R = -R;
2895 }
2896 } else {
2897
2898 LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
2899 LT::AsUnsigned::from(RHS, Bits), Bits, &R);
2900 }
2902 return true;
2903 }
2904
2905
2906 if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
2908 R = LT::AsUnsigned::from(-1);
2909 } else {
2910
2911 LT A;
2912 LT::shiftRight(LHS, LT::from(RHS, Bits), Bits, &A);
2913 R = LT::AsUnsigned::from(A);
2914 }
2915
2917 return true;
2918}
2919
2920
2921template <class LT, class RT, ShiftDir Dir>
2924 const unsigned Bits = LHS.getBitWidth();
2925
2926
2928 RHS &=
2929 APSInt(llvm::APInt(RHS.getBitWidth(), static_cast<uint64_t>(Bits - 1)),
2930 RHS.isUnsigned());
2931
2932 if (RHS.isNegative()) {
2933
2934
2936 S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS;
2938 return false;
2941 S, OpPC, LHS, -RHS, Result);
2942 }
2943
2944 if ((S, OpPC, static_cast<LT>(LHS), static_cast<RT>(RHS),
2946 return false;
2947
2948 unsigned SA = (unsigned)RHS.getLimitedValue(Bits - 1);
2951 Result->copy(LHS << SA);
2952 else
2954 } else {
2956 Result->copy(LHS >> SA);
2957 else
2959 }
2960
2962 return true;
2963}
2964
2965template <PrimType NameL, PrimType NameR>
2971
2977 RHS.toAPSInt(), &Result);
2978 } else {
2981 }
2982}
2983
2984template <PrimType NameL, PrimType NameR>
2990
2996 RHS.toAPSInt(), &Result);
2997 } else {
3000 }
3001}
3002
3006 llvm::FixedPointSemantics LHSSema = LHS.getSemantics();
3007
3008 unsigned ShiftBitWidth =
3009 LHSSema.getWidth() - (unsigned)LHSSema.hasUnsignedPadding() - 1;
3010
3011
3012
3013
3014 if (RHS.isNegative()) {
3016 << RHS.toAPSInt();
3017 } else if (static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
3018 ShiftBitWidth)) != RHS.toAPSInt()) {
3020 S.CCEDiag(E, diag::note_constexpr_large_shift)
3021 << RHS.toAPSInt() << E->getType() << ShiftBitWidth;
3022 }
3023
3028 return false;
3029 } else {
3032 return false;
3033 }
3034
3036 return true;
3037}
3038
3039
3040
3041
3042
3045 S.FFDiag(EndLoc, diag::note_constexpr_no_return);
3046 return false;
3047}
3048
3049
3050
3051
3052
3058
3063 else
3065 return true;
3066}
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076template <PrimType Name, class T = typename PrimConv::T>
3078 const T &Offset = S.Stk.pop<T>();
3080
3081 if (!Ptr.isZero() && !Offset.isZero()) {
3083 return false;
3084 }
3085
3086 if (Offset.isZero()) {
3087 if (const Descriptor *Desc = Ptr.getFieldDesc();
3088 Desc && Desc->isArray() && Ptr.getIndex() == 0) {
3090 return true;
3091 }
3093 return true;
3094 }
3095
3096 assert(!Offset.isZero());
3097
3098 if (std::optional Result =
3101 return true;
3102 }
3103
3104 return false;
3105}
3106
3107template <PrimType Name, class T = typename PrimConv::T>
3109 const T &Offset = S.Stk.pop<T>();
3111
3112 if (!Ptr.isZero() && !Offset.isZero()) {
3114 return false;
3115 }
3116
3117 if (Offset.isZero()) {
3118 if (const Descriptor *Desc = Ptr.getFieldDesc();
3119 Desc && Desc->isArray() && Ptr.getIndex() == 0) {
3121 return true;
3122 }
3124 return true;
3125 }
3126
3127 assert(!Offset.isZero());
3128
3129 if (std::optional Result =
3132 return true;
3133 }
3134 return false;
3135}
3136
3137template <PrimType Name, class T = typename PrimConv::T>
3140
3142 return false;
3143
3146 return true;
3147}
3148
3149template <PrimType Name, class T = typename PrimConv::T>
3152
3154 return false;
3155
3158 return true;
3159}
3160
3161template <PrimType Name, class T = typename PrimConv::T>
3163 uint32_t DestIndex, uint32_t Size) {
3166
3167 if (SrcPtr.isDummy() || DestPtr.isDummy())
3168 return false;
3169
3170 for (uint32_t I = 0; I != Size; ++I) {
3172
3174 return false;
3175
3176 DestPtr.elem<T>(DestIndex + I) = SrcPtr.elem<T>(SrcIndex + I);
3178 }
3179 return true;
3180}
3181
3182
3183
3186
3189 return true;
3190 }
3191
3194 return false;
3195 }
3196
3199 return true;
3200 }
3201
3203 S.FFDiag(E, diag::note_constexpr_unsupported_unsized_array);
3204
3205 return false;
3206}
3207
3209 assert(Func);
3211 return true;
3212}
3213
3214template <PrimType Name, class T = typename PrimConv::T>
3216 const T &IntVal = S.Stk.pop<T>();
3217
3219 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3221
3222 S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc);
3223 return true;
3224}
3225
3230
3233
3234 if (!MP.isBaseCastPossible())
3235 return false;
3236
3238 return true;
3239}
3240
3243
3246
3248 return true;
3249}
3250
3251
3252
3253
3256 S.FFDiag(Loc, diag::note_constexpr_stmt_expr_unsupported)
3258 return false;
3259}
3260
3264 return true;
3265
3269 return true;
3270}
3277 }
3278 return true;
3279}
3280
3289
3290
3292
3296
3298 bool SrcIsVoidPtr) {
3300 if (Ptr.isZero())
3301 return true;
3302 if (!Ptr.isBlockPointer())
3303 return true;
3304
3306 return true;
3307
3308 if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
3309 bool HasValidResult = !Ptr.isZero();
3310
3311 if (HasValidResult) {
3313 return true;
3314
3319 return true;
3320
3321 S.CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
3322 << E->getSubExpr()->getType() << S.getLangOpts().CPlusPlus26
3323 << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
3324 } else if (!S.getLangOpts().CPlusPlus26) {
3326 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
3327 << diag::ConstexprInvalidCastKind::CastFrom << "'void *'"
3329 }
3330 }
3331
3332 QualType PtrType = Ptr.getType();
3336 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3338 return false;
3339 }
3340 return true;
3341}
3342
3343
3345 bool Fatal) {
3347
3348 switch (Kind) {
3350 S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3351 << diag::ConstexprInvalidCastKind::Reinterpret
3353 return !Fatal;
3355 S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3356 << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3358 return !Fatal;
3363 S.FFDiag(E, diag::note_constexpr_access_volatile_type)
3364 << AK_Read << E->getSubExpr()->getType();
3365 else
3367 }
3368
3369 return false;
3372 S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
3373 << diag::ConstexprInvalidCastKind::Dynamic;
3374 return true;
3375 }
3376 llvm_unreachable("Unhandled CastKind");
3377 return false;
3378}
3379
3384 diag::note_constexpr_access_volatile_type)
3386 } else {
3388 }
3389 return false;
3390}
3391
3394 assert(DR);
3395
3399 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
3400 S.Note(VD->getLocation(), diag::note_declared_at);
3401 return false;
3402 }
3403
3405}
3406
3411 S.CCEDiag(E, diag::note_constexpr_non_const_vectorelements) << ArgRange;
3412 }
3413 return false;
3414}
3415
3419 diag::note_constexpr_pseudo_destructor);
3420 return true;
3421}
3422
3425
3426 if (Val)
3427 return true;
3428
3429
3431 S.CCEDiag(Loc, diag::note_constexpr_assumption_failed);
3432 return false;
3433}
3434
3435template <PrimType Name, class T = typename PrimConv::T>
3439 ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
3440
3443 return false;
3444
3446
3447 return true;
3448}
3449
3450template <PrimType Name, class T = typename PrimConv::T>
3453 if (!Arg.isZero())
3454 return true;
3455
3457 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
3458
3459 return false;
3460}
3461
3463 const APSInt &Value);
3464
3465template <PrimType Name, class T = typename PrimConv::T>
3467 assert(ED);
3469
3473 }
3474 return true;
3475}
3476
3477
3478template <PrimType TIn, PrimType TOut>
3483
3484 const FromT &OldPtr = S.Stk.pop();
3485
3486 if constexpr (std::is_same_v<FromT, FunctionPointer> &&
3487 std::is_same_v<ToT, Pointer>) {
3488 S.Stk.push<Pointer>(OldPtr.getFunction(), OldPtr.getOffset());
3489 return true;
3490 } else if constexpr (std::is_same_v<FromT, Pointer> &&
3491 std::is_same_v<ToT, FunctionPointer>) {
3492 if (OldPtr.isFunctionPointer()) {
3494 OldPtr.getByteOffset());
3495 return true;
3496 }
3497 }
3498
3499 S.Stk.push(ToT(OldPtr.getIntegerRepresentation(), nullptr));
3500 return true;
3501}
3502
3504
3505
3506
3507
3509 VD->isStaticLocal());
3510
3512 return true;
3513
3517 return false;
3518 }
3519 return true;
3520}
3521
3523 assert(Desc);
3524
3526 return false;
3527
3531 assert(B);
3533 return true;
3534}
3535
3536template <PrimType Name, class SizeT = typename PrimConv::T>
3538 bool IsNoThrow) {
3540 return false;
3541
3544 if (!IsNoThrow)
3545 return false;
3546
3547
3549 return true;
3550 }
3551 if (NumElements.isNegative()) {
3552 if (!IsNoThrow) {
3554 << NumElements.toDiagnosticString(S.getASTContext());
3555 return false;
3556 }
3558 return true;
3559 }
3560
3561 if ((S, OpPC, static_cast<uint64_t>(NumElements)))
3562 return false;
3563
3566 Allocator.allocate(Source, T, static_cast<size_t>(NumElements),
3568 assert(B);
3569 if (NumElements.isZero())
3571 else
3573 return true;
3574}
3575
3576template <PrimType Name, class SizeT = typename PrimConv::T>
3578 bool IsNoThrow) {
3580 return false;
3581
3582 if (!ElementDesc)
3583 return false;
3584
3587 IsNoThrow)) {
3588 if (!IsNoThrow)
3589 return false;
3590
3591
3593 return true;
3594 }
3595 assert(NumElements.isPositive());
3596
3597 if ((S, OpPC, static_cast<uint64_t>(NumElements)))
3598 return false;
3599
3602 Allocator.allocate(ElementDesc, static_cast<size_t>(NumElements),
3604 assert(B);
3605 if (NumElements.isZero())
3607 else
3609
3610 return true;
3611}
3612
3613bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
3614 bool IsGlobalDelete);
3615
3620
3624
3625
3626
3628 std::optional<uint64_t> ArraySize = std::nullopt);
3629
3630template <PrimType Name, class T = typename PrimConv::T>
3632 const auto &Size = S.Stk.pop<T>();
3634}
3636
3637template <PrimType Name, class T = typename PrimConv::T>
3639 uint32_t ResultBitWidth, const llvm::fltSemantics *Sem,
3640 const Type *TargetType) {
3642
3643 if ((S, OpPC, FromPtr))
3644 return false;
3645
3646 if constexpr (std::is_same_v<T, Pointer>) {
3649 diag::note_constexpr_bit_cast_invalid_type)
3650 << true << false << 1 ;
3651 return false;
3652 }
3653
3655 return true;
3656 } else if constexpr (std::is_same_v<T, MemberPointer>) {
3658 diag::note_constexpr_bit_cast_invalid_type)
3659 << true << false << 2 ;
3660 return false;
3661 } else {
3662
3663 size_t BuffSize = ResultBitWidth / 8;
3665 bool HasIndeterminateBits = false;
3666
3667 Bits FullBitWidth(ResultBitWidth);
3668 Bits BitWidth = FullBitWidth;
3669
3670 if constexpr (std::is_same_v<T, Floating>) {
3671 assert(Sem);
3672 BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
3673 }
3674
3675 if ((S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
3676 HasIndeterminateBits))
3677 return false;
3678
3679 if ((S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
3680 return false;
3681
3682 if constexpr (std::is_same_v<T, Floating>) {
3683 assert(Sem);
3689 T::bitcastFromMemory(Buff.data(), ResultBitWidth, &Result);
3691 } else if constexpr (std::is_same_v<T, Boolean>) {
3692
3693
3694 assert(FullBitWidth.getQuantity() == 8);
3695 auto Val = static_cast<unsigned int>(Buff[0]);
3696 if (Val > 1) {
3698 diag::note_constexpr_bit_cast_unrepresentable_value)
3700 return false;
3701 }
3702 S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
3703 } else {
3704 assert(!Sem);
3705 S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
3706 }
3707 return true;
3708 }
3709}
3710
3714
3715 if ((S, OpPC, FromPtr))
3716 return false;
3717
3719 return false;
3720
3721 return true;
3722}
3723
3724
3725bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr,
3726 const Type *TypeInfoType);
3727bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType);
3728bool DiagTypeid(InterpState &S, CodePtr OpPC);
3729
3734
3735
3736
3737
3738
3740 if constexpr (std::is_pointer::value) {
3741 uint32_t ID = OpPC.read<uint32_t>();
3743 } else {
3745 }
3746}
3747
3749 auto &Semantics =
3751
3754 OpPC += align(F.bytesToSerialize());
3755 return F;
3756}
3757
3758template <>
3760 CodePtr &OpPC) {
3762 auto Result = S.allocAP<IntegralAP>(BitWidth);
3763 assert(Result.bitWidth() == BitWidth);
3764
3766 OpPC += align(Result.bytesToSerialize());
3768}
3769
3770template <>
3772 CodePtr &OpPC) {
3774 auto Result = S.allocAP<IntegralAP>(BitWidth);
3775 assert(Result.bitWidth() == BitWidth);
3776
3778 OpPC += align(Result.bytesToSerialize());
3779 return Result;
3780}
3781
3782template <>
3788
3789}
3790}
3791
3792#endif
Defines the clang::ASTContext interface.
void HandleComplexComplexDiv(APFloat A, APFloat B, APFloat C, APFloat D, APFloat &ResR, APFloat &ResI)
void HandleComplexComplexMul(APFloat A, APFloat B, APFloat C, APFloat D, APFloat &ResR, APFloat &ResI)
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
Represents a static or instance method of a struct/union/class.
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const
Converts the specified result kind into the correct result kind for this category.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getLocation() const
AccessSpecifier getAccess() const
bool isFixed() const
Returns true if this is an Objective-C, C++11, or Microsoft-style enumeration with a fixed underlying...
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static FPOptions getFromOpaqueInt(storage_type Value)
Represents a member of a struct/union/class.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Represents a function declaration or definition.
Implicit declaration of a temporary that was materialized by a MaterializeTemporaryExpr and lifetime-...
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
unsigned getNumExpressions() const
A (possibly-)qualified type.
QualType withVolatile() const
Represents a struct/union/class.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
TagDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isNullPtrType() const
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
ThreadStorageClassSpecifier getTSCSpec() const
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
A memory block, either on the stack or in the heap.
bool isExtern() const
Checks if the block is extern.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
Wrapper around boolean types.
static Boolean from(T Value)
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
const Function * getOrCreateFunction(const FunctionDecl *FuncDecl)
unsigned getEvalID() const
Manages dynamic memory allocations done during bytecode interpretation.
Block * allocate(const Descriptor *D, unsigned EvalID, Form AllocForm)
Allocate ONE element of the given descriptor.
Wrapper around fixed point types.
llvm::FixedPointSemantics getSemantics() const
static bool shiftRight(const FixedPoint A, const FixedPoint B, unsigned OpBits, FixedPoint *R)
static FixedPoint deserialize(const std::byte *Buff)
static bool shiftLeft(const FixedPoint A, const FixedPoint B, unsigned OpBits, FixedPoint *R)
static FixedPoint from(const APSInt &I, llvm::FixedPointSemantics Sem, bool *Overflow)
size_t bytesToSerialize() const
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
static APFloat::opStatus div(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static llvm::APFloatBase::Semantics deserializeSemantics(const std::byte *Buff)
void copy(const APFloat &F)
static APFloat::opStatus fromIntegral(APSInt Val, const llvm::fltSemantics &Sem, llvm::RoundingMode RM, Floating *Result)
static APFloat::opStatus sub(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus increment(const Floating &A, llvm::RoundingMode RM, Floating *R)
static APFloat::opStatus add(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
static void deserialize(const std::byte *Buff, Floating *Result)
static APFloat::opStatus mul(const Floating &A, const Floating &B, llvm::RoundingMode RM, Floating *R)
void toSemantics(const llvm::fltSemantics *Sem, llvm::RoundingMode RM, Floating *Result) const
const llvm::fltSemantics & getSemantics() const
static APFloat::opStatus decrement(const Floating &A, llvm::RoundingMode RM, Floating *R)
APFloat::opStatus convertToInteger(APSInt &Result) const
static void bitcastFromMemory(const std::byte *Buff, const llvm::fltSemantics &Sem, Floating *Result)
APFloat getAPFloat() const
const Function * getFunction() const
Scope & getScope(unsigned Idx)
Returns a specific scope.
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool hasRVO() const
Checks if the first argument is a RVO pointer.
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
static uint32_t deserializeSize(const std::byte *Buff)
static void deserialize(const std::byte *Buff, IntegralAP< Signed > *Result)
void copy(const APInt &V)
Wrapper around numeric types.
Frame storing local variables.
static void free(InterpFrame *F)
const Expr * getExpr(CodePtr PC) const
bool isLocalEnabled(unsigned Idx) const
InterpFrame * Caller
The frame of the previous function.
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
CodePtr getRetPC() const
Returns the return address of the frame.
void enableLocal(unsigned Idx)
Block * getLocalBlock(unsigned Offset) const
SourceLocation getLocation(CodePtr PC) const
const Pointer & getThis() const
Returns the 'this' pointer.
const Function * getFunction() const
Returns the current function.
size_t getFrameOffset() const
Returns the offset on the stack at which the frame starts.
SourceRange getRange(CodePtr PC) const
void setLocal(unsigned Offset, const T &Value)
Mutates a local variable.
const T & getParam(unsigned Offset) const
Returns the value of an argument.
bool isBottomFrame() const
bool hasThisPointer() const
Pointer getLocalPointer(unsigned Offset) const
Returns a pointer to a local variables.
unsigned getDepth() const
void setParam(unsigned Offset, const T &Value)
Mutates a local copy of a parameter.
void destroy(unsigned Idx)
Invokes the destructors for a scope.
const Pointer & getRVOPtr() const
Returns the RVO pointer, if the Function has one.
Pointer getParamPointer(unsigned Offset)
Returns a pointer to an argument - lazily creates a block.
const FunctionDecl * getCallee() const override
Returns the caller.
void initScope(unsigned Idx)
T pop()
Returns the value from the top of the stack and removes it.
void push(Tys &&...Args)
Constructs a value in place on the top of the stack.
void dump() const
dump the stack contents to stderr.
size_t size() const
Returns the size of the stack in bytes.
void discard()
Discards the top value from the stack.
T & peek() const
Returns a reference to the value on the top of the stack.
SmallVectorImpl< PartialDiagnosticAt > * PrevDiags
Things needed to do speculative execution.
Expr::EvalStatus & getEvalStatus() const override
Context & getContext() const
bool noteUndefinedBehavior() override
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
Floating allocFloat(const llvm::fltSemantics &Sem)
ASTContext & getASTContext() const override
llvm::SmallVector< std::pair< const Expr *, const LifetimeExtendedTemporaryDecl * > > SeenGlobalTemporaries
InterpStack & Stk
Temporary stack.
bool maybeDiagnoseDanglingAllocations()
Diagnose any dynamic allocations that haven't been freed yet.
bool noteSideEffect() override
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
std::optional< bool > ConstantContextOverride
T allocAP(unsigned BitWidth)
const LangOptions & getLangOpts() const
unsigned SpeculationDepth
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
bool inConstantContext() const
Program & P
Reference to the module containing all bytecode.
ComparisonCategoryResult compare(const MemberPointer &RHS) const
A pointer to a memory block, live or dead.
static bool hasSameBase(const Pointer &A, const Pointer &B)
Checks if two pointers are comparable.
Pointer narrow() const
Restricts the scope of an array element pointer.
bool isInitialized() const
Checks if an object was initialized.
bool isZeroSizeArray() const
Checks if the pointer is pointing to a zero-size array.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
Pointer atFieldSub(unsigned Off) const
Subtract the given offset from the current Base and Offset of the pointer.
int64_t getIndex() const
Returns the index into an array.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
unsigned getNumElems() const
Returns the number of elements.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
void activate() const
Activats a field.
static std::optional< std::pair< Pointer, Pointer > > computeSplitPoint(const Pointer &A, const Pointer &B)
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool pointsToStringLiteral() const
bool inArray() const
Checks if the innermost field is an array.
T & elem(unsigned I) const
Dereferences the element at index I.
uint64_t getByteOffset() const
Returns the byte offset from the start.
bool isTypeidPointer() const
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
bool isZero() const
Checks if the pointer is null.
const IntPointer & asIntPointer() const
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
unsigned getOffset() const
Returns the offset into an array.
bool isOnePastEnd() const
Checks if the index is one past end.
uint64_t getIntegerRepresentation() const
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
bool isBlockPointer() const
const FunctionPointer & asFunctionPointer() const
bool isFunctionPointer() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
size_t elemSize() const
Returns the element size of the innermost field.
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Lifetime getLifetime() const
size_t computeOffsetForComparison() const
Compute an integer that can be used to compare this pointer to another one.
const BlockPointer & asBlockPointer() const
void initialize() const
Initializes a field.
void initializeElement(unsigned Index) const
Initialized the given element of a primitive array.
const Record * getRecord() const
Returns the record descriptor of a class.
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
const void * getNativePointer(unsigned Idx) const
Returns the value of a marshalled native pointer.
Structure/Class descriptor.
const RecordDecl * getDecl() const
Returns the underlying declaration.
llvm::iterator_range< LocalVectorTy::const_reverse_iterator > locals_reverse() const
Describes the statement/declaration an opcode was generated from.
bool checkingForUndefinedBehavior() const
Are we checking an expression for overflow?
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS, const Pointer &RHS)
bool EndSpeculation(InterpState &S, CodePtr OpPC)
Definition Interp.h:3271
static bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left)
Definition Interp.h:3003
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool InitPop(InterpState &S, CodePtr OpPC)
Definition Interp.h:2092
bool Shr(InterpState &S, CodePtr OpPC)
Definition Interp.h:2966
bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I, const LifetimeExtendedTemporaryDecl *Temp)
- Converts the value on top of the stack to an APValue 2) Sets that APValue on \Temp 3) Initializes ...
Definition Interp.h:1503
bool CheckDestruction(InterpState &S, CodePtr OpPC)
Definition Interp.h:3730
bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index)
Definition Interp.h:3150
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool PopCC(InterpState &S, CodePtr OpPC)
Definition Interp.h:3285
bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index)
Definition Interp.h:3138
bool GT(InterpState &S, CodePtr OpPC)
Definition Interp.h:1257
bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be initialized.
static bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
Definition Interp.h:2598
bool GetMemberPtrBase(InterpState &S, CodePtr OpPC)
Definition Interp.h:3231
bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1415
bool PreInc(InterpState &S, CodePtr OpPC, bool CanOverflow)
Definition Interp.h:820
bool NarrowPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:3053
bool CheckFunctionDecl(InterpState &S, CodePtr OpPC, const FunctionDecl *FD)
Opcode. Check if the function decl can be called at compile time.
bool GetMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off)
Definition Interp.h:1812
bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1535
bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, uint32_t ResultBitWidth, const llvm::fltSemantics *Sem, const Type *TargetType)
Definition Interp.h:3638
Floating ReadArg< Floating >(InterpState &S, CodePtr &OpPC)
Definition Interp.h:3748
bool Incf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:925
bool SideEffect(InterpState &S, CodePtr OpPC)
Definition Interp.h:3293
static bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Definition Interp.h:2773
bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS, LT *Result)
Definition Interp.h:2842
bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1352
bool EndLifetimePop(InterpState &S, CodePtr OpPC)
Ends the lifetime of the pop'd pointer.
bool Sub(InterpState &S, CodePtr OpPC)
Definition Interp.h:330
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
bool Mulf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:358
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx)
The same as InitElem, but pops the pointer as well.
Definition Interp.h:2140
bool StoreBitField(InterpState &S, CodePtr OpPC)
Definition Interp.h:2014
bool LT(InterpState &S, CodePtr OpPC)
Definition Interp.h:1242
ArithOp
Definition Interp.h:214
@ Sub
Definition Interp.h:214
@ Add
Definition Interp.h:214
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Offset)
Checks if the dowcast using the given offset is possible with the given pointer.
bool BitCast(InterpState &S, CodePtr OpPC)
Definition Interp.h:3711
bool LoadPop(InterpState &S, CodePtr OpPC)
Definition Interp.h:1927
bool Null(InterpState &S, CodePtr OpPC, uint64_t Value, const Descriptor *Desc)
Definition Interp.h:2782
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B)
Checks a direct load of a primitive value from a global or local variable.
static llvm::RoundingMode getRoundingMode(FPOptions FPO)
static bool IncPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:2369
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR)
We aleady know the given DeclRefExpr is invalid for some reason, now figure out why and print appropr...
bool EndLifetime(InterpState &S, CodePtr OpPC)
Ends the lifetime of the peek'd pointer.
bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
bool Dup(InterpState &S, CodePtr OpPC)
Definition Interp.h:1276
bool SetField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1383
bool CheckNonNullArg(InterpState &S, CodePtr OpPC)
Definition Interp.h:3451
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, const APSInt &IntValue)
Sets the given integral value to the pointer, which is of a std::{weak,partial,strong}...
static bool IncDecPtrHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Definition Interp.h:2344
bool FinishInitActivate(InterpState &S, CodePtr OpPC)
Definition Interp.h:1842
bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1702
bool Addf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:318
bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS)
Checks if Div/Rem operation on LHS and RHS is valid.
Definition Interp.h:178
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
static bool IsOpaqueConstantCall(const CallExpr *E)
Definition Interp.h:1040
bool CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD)
Definition Interp.h:3503
bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned BitWidth)
bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS, const T &RHS)
Definition Interp.h:269
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
- Peeks a Pointer 2) Pushes Pointer.atField(Off) on the stack
bool StoreActivate(InterpState &S, CodePtr OpPC)
Definition Interp.h:1984
bool Div(InterpState &S, CodePtr OpPC)
- Pops the RHS from the stack.
Definition Interp.h:597
bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func)
Definition Interp.h:3208
bool FinishInitActivatePop(InterpState &S, CodePtr OpPC)
Definition Interp.h:1851
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I)
Same as GetGlobal, but without the checks.
Definition Interp.h:1456
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1714
static bool Activate(InterpState &S, CodePtr OpPC)
Definition Interp.h:1964
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC, const FixedPoint &FP)
bool Mulc(InterpState &S, CodePtr OpPC)
Definition Interp.h:372
bool RetVoid(InterpState &S, CodePtr &PC)
Definition Interp.h:246
bool ArrayElemPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:3077
bool NE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1235
bool NoRet(InterpState &S, CodePtr OpPC)
Definition Interp.h:3043
bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Definition Interp.h:3215
llvm::FixedPointSemantics FixedPointSemantics
Definition Interp.h:42
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
static bool FnPtrCast(InterpState &S, CodePtr OpPC)
Definition Interp.h:2712
static bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Definition Interp.h:2765
bool Shl(InterpState &S, CodePtr OpPC)
Definition Interp.h:2985
bool RVOPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:2829
IncDecOp
Definition Interp.h:700
@ Inc
Definition Interp.h:701
@ Dec
Definition Interp.h:702
bool CastPointerIntegral(InterpState &S, CodePtr OpPC)
Definition Interp.h:2646
constexpr bool isPtrType(PrimType T)
bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:949
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, ArrayRef< int64_t > ArrayIndices, int64_t &IntResult)
Interpret an offsetof operation.
bool SubOffset(InterpState &S, CodePtr OpPC)
Definition Interp.h:2331
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool BitXor(InterpState &S, CodePtr OpPC)
- Pops the RHS from the stack.
Definition Interp.h:553
bool CheckBCPResult(InterpState &S, const Pointer &Ptr)
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Definition Interp.h:2541
bool ExpandPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:3059
bool Store(InterpState &S, CodePtr OpPC)
Definition Interp.h:1941
bool Divc(InterpState &S, CodePtr OpPC)
Definition Interp.h:429
bool DoBitCastPtr(InterpState &S, CodePtr OpPC, const Pointer &FromPtr, Pointer &ToPtr)
bool GetField(InterpState &S, CodePtr OpPC, uint32_t I)
- Peeks a pointer on the stack 2) Pushes the value of the pointer's field on the stack
Definition Interp.h:1369
bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC)
Definition Interp.h:3108
bool This(InterpState &S, CodePtr OpPC)
Definition Interp.h:2803
bool InitScope(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:2472
PushVal
Definition Interp.h:696
@ Yes
Definition Interp.h:698
@ No
Definition Interp.h:697
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC)
Checks if dynamic memory allocation is available in the current language mode.
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I)
- Pops the value from the stack 2) Peeks a pointer from the stack 3) Pushes the value to field I of ...
Definition Interp.h:1604
bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition Interp.h:993
T ReadArg(InterpState &S, CodePtr &OpPC)
Definition Interp.h:3739
bool PreDecBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
Definition Interp.h:895
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
bool CastFloatingIntegral(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:2568
bool ArrayDecay(InterpState &S, CodePtr OpPC)
Just takes a pointer and checks if it's an incomplete array type.
Definition Interp.h:3184
bool PushCC(InterpState &S, CodePtr OpPC, bool Value)
Definition Interp.h:3281
bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK, const Type *TargetType)
Definition Interp.h:1734
bool DiagTypeid(InterpState &S, CodePtr OpPC)
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
This is not used by any of the opcodes directly.
bool InitGlobalTempComp(InterpState &S, CodePtr OpPC, const LifetimeExtendedTemporaryDecl *Temp)
- Converts the value on top of the stack to an APValue 2) Sets that APValue on \Temp 3) Initialized ...
Definition Interp.h:1522
bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits, bool TargetIsUCharOrByte)
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1330
bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E)
Definition Interp.h:3436
bool BitAnd(InterpState &S, CodePtr OpPC)
- Pops the RHS from the stack.
Definition Interp.h:513
bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, unsigned Bits)
Checks if the shift operation is legal.
Definition Interp.h:131
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
FixedPoint ReadArg< FixedPoint >(InterpState &S, CodePtr &OpPC)
Definition Interp.h:3783
static bool CastFloatingFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
Definition Interp.h:2673
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
bool StartLifetime(InterpState &S, CodePtr OpPC)
bool LE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1249
bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E)
Definition Interp.h:3631
bool Zero(InterpState &S, CodePtr OpPC)
Definition Interp.h:2760
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F, uint32_t FieldOffset)
Definition Interp.h:1566
bool Unsupported(InterpState &S, CodePtr OpPC)
Just emit a diagnostic.
Definition Interp.h:3254
bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR, bool InitializerFailed)
Definition Interp.h:3392
bool DecPop(InterpState &S, CodePtr OpPC, bool CanOverflow)
- Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value decreased by ...
Definition Interp.h:867
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if a pointer is null.
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source, const Pointer &Ptr)
Check the source of the pointer passed to delete/delete[] has actually been heap allocated by us.
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status, FPOptions FPO)
Checks if the result of a floating-point operation is valid in the current context.
bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, llvm::RoundingMode RM)
- Pops a Floating from the stack.
Definition Interp.h:2502
ComparisonCategoryResult Compare(const T &X, const T &Y)
Helper to compare two comparable types.
PrimType
Enumeration of the primitive types of the VM.
bool DecPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
Definition Interp.h:876
bool InitThisBitFieldActivate(InterpState &S, CodePtr OpPC, const Record::Field *F, uint32_t FieldOffset)
Definition Interp.h:1583
bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1429
bool StoreBitFieldPop(InterpState &S, CodePtr OpPC)
Definition Interp.h:2030
bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool CanOverflow, UnsignedOrNone BitWidth=std::nullopt)
Definition Interp.h:706
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
static bool DecPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:2378
constexpr bool needsAlloc()
static bool CheckAllocations(InterpState &S, CodePtr OpPC)
Definition Interp.h:3621
bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Definition Interp.h:3522
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
bool ToMemberPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:2182
static bool CastIntegralFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
Definition Interp.h:2657
bool Rem(InterpState &S, CodePtr OpPC)
- Pops the RHS from the stack.
Definition Interp.h:574
bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl, const Pointer &Ptr)
Definition Interp.h:1877
bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E, std::optional< uint64_t > ArraySize)
Check if the initializer and storage types of a placement-new expression match.
bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D)
Definition Interp.h:3226
bool Dump(InterpState &S, CodePtr OpPC)
Definition Interp.h:1862
bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC)
Definition Interp.h:3407
static bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr)
Definition Interp.h:2720
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
bool IsNonNull(InterpState &S, CodePtr OpPC)
Definition Interp.h:2791
bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition Interp.h:1724
bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F)
Definition Interp.h:1318
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
bool InitThisFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1549
bool IncBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, unsigned BitWidth)
Definition Interp.h:786
bool SubPtr(InterpState &S, CodePtr OpPC, bool ElemSizeIsZero)
- Pops a Pointer from the stack.
Definition Interp.h:2391
bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition Interp.h:1768
bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1361
bool StoreActivatePop(InterpState &S, CodePtr OpPC)
Definition Interp.h:1999
bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC)
Definition Interp.h:3241
bool Comp(InterpState &S, CodePtr OpPC)
- Pops the value from the stack.
Definition Interp.h:960
static bool CastFixedPointFloating(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem)
Definition Interp.h:2689
bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:623
bool CheckThis(InterpState &S, CodePtr OpPC)
Checks the 'this' pointer.
bool FinishInitGlobal(InterpState &S, CodePtr OpPC)
bool DecayPtr(InterpState &S, CodePtr OpPC)
OldPtr -> Integer -> NewPtr.
Definition Interp.h:3479
static bool ActivateThisField(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1971
bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC, const RecordDecl *D)
Definition Interp.h:1888
bool StorePop(InterpState &S, CodePtr OpPC)
Definition Interp.h:1953
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, const Function *Func)
bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I)
- Pops the value from the stack.
Definition Interp.h:1346
bool FinishInit(InterpState &S, CodePtr OpPC)
Definition Interp.h:1835
bool InvalidStore(InterpState &S, CodePtr OpPC, const Type *T)
Definition Interp.h:3380
static bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth, uint32_t FPOI)
Definition Interp.h:2619
bool Mul(InterpState &S, CodePtr OpPC)
Definition Interp.h:350
bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx)
- Pops the value from the stack 2) Peeks a pointer and gets its index \Idx 3) Sets the value on the ...
Definition Interp.h:2106
bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:2444
bool Pop(InterpState &S, CodePtr OpPC)
Definition Interp.h:1282
bool DecBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
Definition Interp.h:853
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F)
Definition Interp.h:1635
bool PreIncBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
Definition Interp.h:829
bool Dec(InterpState &S, CodePtr OpPC, bool CanOverflow)
- Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value decreased by ...
Definition Interp.h:844
bool StoreBitFieldActivate(InterpState &S, CodePtr OpPC)
Definition Interp.h:2045
bool CheckPseudoDtor(InterpState &S, CodePtr OpPC)
Definition Interp.h:3416
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
bool PreDec(InterpState &S, CodePtr OpPC, bool CanOverflow)
Definition Interp.h:887
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems)
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE, uint32_t BuiltinID)
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B)
bool FinishInitPop(InterpState &S, CodePtr OpPC)
Definition Interp.h:1828
bool Neg(InterpState &S, CodePtr OpPC)
Definition Interp.h:654
bool StartSpeculation(InterpState &S, CodePtr OpPC)
Definition Interp.h:3261
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
std::optional< Pointer > OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, const Pointer &Ptr, bool IsPointerArith=false)
Definition Interp.h:2205
bool BitOr(InterpState &S, CodePtr OpPC)
- Pops the RHS from the stack.
Definition Interp.h:533
llvm::function_ref< bool(ComparisonCategoryResult)> CompareFn
Definition Interp.h:978
bool Inv(InterpState &S, CodePtr OpPC)
Definition Interp.h:643
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr, bool WillBeActivated)
Checks if a value can be stored in a block.
bool Load(InterpState &S, CodePtr OpPC)
Definition Interp.h:1913
bool isConstexprUnknown(const Pointer &P)
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1469
bool Cast(InterpState &S, CodePtr OpPC)
Definition Interp.h:2493
bool StoreBitFieldActivatePop(InterpState &S, CodePtr OpPC)
Definition Interp.h:2063
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
- Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Definition Interp.h:776
bool EQ(InterpState &S, CodePtr OpPC)
Definition Interp.h:1203
bool IncfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:933
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off, bool NullOK)
Definition Interp.h:1789
bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I)
- Pops a pointer from the stack 2) Pushes the value of the pointer's field on the stack
Definition Interp.h:1401
bool Add(InterpState &S, CodePtr OpPC)
Definition Interp.h:310
bool CmpHelperEQ< MemberPointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition Interp.h:1161
bool AddOffset(InterpState &S, CodePtr OpPC)
Definition Interp.h:2318
ShiftDir
Definition Interp.h:127
@ Right
Definition Interp.h:127
@ Left
Definition Interp.h:127
bool Const(InterpState &S, CodePtr OpPC, const T &Arg)
Definition Interp.h:1307
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest)
Copy the contents of Src into Dest.
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
bool IncPop(InterpState &S, CodePtr OpPC, bool CanOverflow)
- Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Definition Interp.h:800
bool Memcpy(InterpState &S, CodePtr OpPC)
Definition Interp.h:2172
bool GE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1264
bool DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, std::byte *Buff, Bits BitWidth, Bits FullBitWidth, bool &HasIndeterminateBits)
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool CmpHelperEQ< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition Interp.h:1052
static bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC)
Definition Interp.h:2699
constexpr bool isIntegralType(PrimType T)
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
bool CastIntegralFloating(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, uint32_t FPOI)
Definition Interp.h:2553
bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition Interp.h:981
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
bool CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS)
Definition Interp.h:2511
bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1707
bool EnableLocal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:2477
bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, bool IsNoThrow)
Definition Interp.h:3577
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1444
bool Subf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:338
bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC, const RecordDecl *D)
Definition Interp.h:1897
bool GetLocalEnabled(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:2483
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1475
bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, bool Fatal)
Same here, but only for casts.
Definition Interp.h:3344
bool DoShiftAP(InterpState &S, CodePtr OpPC, const APSInt &LHS, APSInt RHS, LT *Result)
A version of DoShift that works on IntegralAP.
Definition Interp.h:2922
bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC)
Definition Interp.h:2190
bool Ret(InterpState &S, CodePtr &PC)
Definition Interp.h:224
bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I)
Definition Interp.h:1619
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
bool IncPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, uint32_t BitWidth)
Definition Interp.h:809
bool Flip(InterpState &S, CodePtr OpPC)
[Value1, Value2] -> [Value2, Value1]
Definition Interp.h:1289
bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo)
Definition Interp.h:1210
bool InitBitFieldActivate(InterpState &S, CodePtr OpPC, const Record::Field *F)
Definition Interp.h:1666
bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need to know what bitwidth the resu...
Definition Interp.h:2529
bool Invalid(InterpState &S, CodePtr OpPC)
bool CmpHelper< Pointer >(InterpState &S, CodePtr OpPC, CompareFn Fn)
Definition Interp.h:998
bool Decf(InterpState &S, CodePtr OpPC, uint32_t FPOI)
Definition Interp.h:941
bool Assume(InterpState &S, CodePtr OpPC)
Definition Interp.h:3423
bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off)
Definition Interp.h:1818
bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t FPOI)
Definition Interp.h:905
static bool IsConstantContext(InterpState &S, CodePtr OpPC)
Definition Interp.h:3616
bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, bool IsNoThrow)
Definition Interp.h:3537
bool CheckEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED)
Definition Interp.h:3466
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
CheckSubobjectKind
The order of this enum is important for diagnostics.
@ Result
The result type of a method or function.
AccessKinds
Kinds of access we can perform on an object, for diagnostics.
const FunctionProtoType * T
@ ConstantFold
Fold the expression to a constant.
U cast(CodeGen::Address addr)
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
size_t getQuantity() const
unsigned Base
Start of the current subfield.
Block * Pointee
The block the pointer is pointing to.
Describes a memory block created by an allocation site.
unsigned getSize() const
Returns the size of the object without metadata.
const Decl * asDecl() const
SourceLocation getLocation() const
PrimType getPrimType() const
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
Descriptor used for global variables.
Mapping from primitive types to their representation.