clang: lib/AST/ByteCode/Interp.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
25#include "llvm/ADT/StringExtras.h"
26
27using namespace clang;
29
31 llvm::report_fatal_error("Interpreter cannot return values");
32}
33
34
35
36
37
39 PC += Offset;
40 return true;
41}
42
44 if (S.Stk.pop<bool>()) {
45 PC += Offset;
46 }
47 return true;
48}
49
51 if (!S.Stk.pop<bool>()) {
52 PC += Offset;
53 }
54 return true;
55}
56
59 const SourceInfo &E = S.Current->getSource(OpPC);
60 S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
62}
63
68 const SourceInfo &E = S.Current->getSource(OpPC);
69
70 if (isa(D)) {
72 S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
74 } else {
75 S.FFDiag(E);
76 }
77 return false;
78 }
79
80 if (->getType().isConstQualified()) {
82 } else if (const auto *VD = dyn_cast(D)) {
83 if (!VD->getAnyInitializer()) {
85 } else {
86 const SourceInfo &Loc = S.Current->getSource(OpPC);
87 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
88 S.Note(VD->getLocation(), diag::note_declared_at);
89 }
90 }
91
92 return false;
93}
94
97 const SourceInfo &Loc = S.Current->getSource(OpPC);
99 S.FFDiag(Loc);
100 return;
101 }
102
103 if (const auto *VarD = dyn_cast(VD);
104 VarD && VarD->getType().isConstQualified() &&
105 !VarD->getAnyInitializer()) {
107 return;
108 }
109
110
111
112 if (isa(VD))
113 return;
114
116 S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
117 S.Note(VD->getLocation(), diag::note_declared_at);
118 return;
119 }
120
121 S.FFDiag(Loc,
122 S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
123 : diag::note_constexpr_ltor_non_integral,
124 1)
126 S.Note(VD->getLocation(), diag::note_declared_at);
127}
128
132 return true;
133
136
139 while (.isRoot() && U.inUnion() &&
.isActive()) {
140 if (U.getField())
143 }
144 assert(C.isField());
145
146
147 const FieldDecl *InactiveField = C.getField();
148 assert(InactiveField);
149
150
151
152
153
154
155
156
157
158
159
160
161
162 if (.getFieldDesc()->isUnion())
163 return true;
164
165
166 const Record *R = U.getRecord();
167 assert(R && R->isUnion() && "Not a union");
168
169 const FieldDecl *ActiveField = nullptr;
170 for (const Record::Field &F : R->fields()) {
171 const Pointer &Field = U.atField(F.Offset);
172 if (Field.isActive()) {
173 ActiveField = Field.getField();
174 break;
175 }
176 }
177
178 const SourceInfo &Loc = S.Current->getSource(OpPC);
179 S.FFDiag(Loc, diag::note_constexpr_access_inactive_union_member)
180 << AK << InactiveField << !ActiveField << ActiveField;
181 return false;
182}
183
188 return true;
189
190 const auto *MTE = dyn_cast_if_present(
192 if (!MTE)
193 return true;
194
195
196
197
198 if (!MTE->isUsableInConstantExpressions(S.getASTContext()) &&
200 const SourceInfo &E = S.Current->getSource(OpPC);
201 S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
202 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
203 return false;
204 }
205 }
206 return true;
207}
208
212 return true;
213
214 if (S.P.getCurrentDecl() == ID)
215 return true;
216
217 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_modify_global);
218 return false;
219 }
220 return true;
221}
222
224namespace interp {
226 PrimType Ty = S.getContext().classify(Arg).value_or(PT_Ptr);
228}
229
232 assert(S.Current);
233 assert(Func);
234
235 if (Func->isUnevaluatedBuiltin())
236 return;
237
238
239
240 if (unsigned BID = Func->getBuiltinID();
242 const auto *CE =
243 cast(S.Current->Caller->getExpr(S.Current->getRetPC()));
244 for (int32_t I = CE->getNumArgs() - 1; I >= 0; --I) {
245 const Expr *A = CE->getArg(I);
247 }
248 return;
249 }
250
251 if (S.Current->Caller && Func->isVariadic()) {
252
253
254
255 unsigned NumVarArgs;
256 const Expr *const *Args = nullptr;
257 unsigned NumArgs = 0;
258 const Expr *CallSite = S.Current->Caller->getExpr(S.Current->getRetPC());
259 if (const auto *CE = dyn_cast(CallSite)) {
260 Args = CE->getArgs();
261 NumArgs = CE->getNumArgs();
262 } else if (const auto *CE = dyn_cast(CallSite)) {
263 Args = CE->getArgs();
264 NumArgs = CE->getNumArgs();
265 } else
266 assert(false && "Can't get arguments from that expression type");
267
268 assert(NumArgs >= Func->getNumWrittenParams());
269 NumVarArgs = NumArgs - (Func->getNumWrittenParams() +
270 isa(CallSite));
271 for (unsigned I = 0; I != NumVarArgs; ++I) {
272 const Expr *A = Args[NumArgs - 1 - I];
274 }
275 }
276
277
278
281}
282
285 return true;
286
289 return true;
290
291 if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
294 }
295 return false;
296}
297
300 return true;
301 const SourceInfo &E = S.Current->getSource(OpPC);
302 S.FFDiag(E, diag::note_constexpr_unsized_array_indexed);
303 return false;
304}
305
309 const auto &Src = S.Current->getSource(OpPC);
310
312 S.FFDiag(Src, diag::note_constexpr_null_subobject) << CSK_Field;
313 else
314 S.FFDiag(Src, diag::note_constexpr_access_null) << AK;
315
316 return false;
317 }
318
320 const auto &Src = S.Current->getSource(OpPC);
321
323 S.FFDiag(Src, diag::note_constexpr_access_deleted_object) << AK;
324 } else if (!S.checkingPotentialConstantExpression()) {
326 S.FFDiag(Src, diag::note_constexpr_lifetime_ended, 1) << AK << !IsTemp;
327
328 if (IsTemp)
329 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
330 else
331 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
332 }
333
334 return false;
335 }
336
337 return true;
338}
339
341 assert(Desc);
342
344 if ( ||
->hasGlobalStorage())
345 return true;
346
347 if (D == S.EvaluatingDecl)
348 return true;
349
350 if (D->isConstexpr())
351 return true;
352
353
354
355
356 if (const auto *VD = dyn_cast_if_present(S.EvaluatingDecl);
357 VD && VD->isConstexpr() && S.getLangOpts().C23)
359
363 if (!IsConstant) {
365 return false;
366 }
367 return true;
368 }
369
370 if (IsConstant) {
372 S.CCEDiag(S.Current->getLocation(OpPC),
374 ? diag::note_constexpr_ltor_non_constexpr
375 : diag::note_constexpr_ltor_non_integral,
376 1)
378 S.Note(D->getLocation(), diag::note_declared_at);
379 } else {
380 S.CCEDiag(S.Current->getLocation(OpPC));
381 }
382 return true;
383 }
384
389 return false;
390 }
391 return true;
392 }
393
395 return false;
396}
397
400 return true;
402}
403
407 return true;
408 const SourceInfo &Loc = S.Current->getSource(OpPC);
409 S.FFDiag(Loc, diag::note_constexpr_null_subobject)
410 << CSK << S.Current->getRange(OpPC);
411
412 return false;
413}
414
418 return true;
420 const SourceInfo &Loc = S.Current->getSource(OpPC);
421 S.FFDiag(Loc, diag::note_constexpr_access_past_end)
422 << AK << S.Current->getRange(OpPC);
423 }
424 return false;
425}
426
430 return true;
431 const SourceInfo &Loc = S.Current->getSource(OpPC);
432 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
433 << CSK << S.Current->getRange(OpPC);
434 return false;
435}
436
440 return true;
441
442 const SourceInfo &Loc = S.Current->getSource(OpPC);
443 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
444 << CSK << S.Current->getRange(OpPC);
445 return false;
446}
447
449 uint32_t Offset) {
452
453
454
455 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
456 return true;
457
458 const auto *E = cast(S.Current->getExpr(OpPC));
461
462 S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
463 << MostDerivedQT << TargetQT;
464
465 return false;
466}
467
469 assert(Ptr.isLive() && "Pointer is not live");
471 return true;
472
473
474
475
476
477 if (S.Current->getFunction()) {
480 Func && (Func->isConstructor() || Func->isDestructor()) &&
481 Ptr.block() == Frame->getThis().block()) {
482 return true;
483 }
484 }
485 }
486
488 return false;
489
491 const SourceInfo &Loc = S.Current->getSource(OpPC);
492 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
493 return false;
494}
495
497 assert(Ptr.isLive() && "Pointer is not live");
499 return true;
500
501
502
505 return true;
506
507 const SourceInfo &Loc = S.Current->getSource(OpPC);
509 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
510 S.Note(Field->getLocation(), diag::note_declared_at);
511 return false;
512}
513
516 assert(Ptr.isLive());
517
518
519
521 return true;
522
525 return true;
526
527 const SourceInfo &Loc = S.Current->getSource(OpPC);
529 S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
530 else
531 S.FFDiag(Loc);
532 return false;
533}
534
537 assert(Ptr.isLive());
538
540 return true;
541
543 VD && (VD->isConstexpr() || VD->hasGlobalStorage())) {
544 const SourceInfo &Loc = S.Current->getSource(OpPC);
545 if (VD->getAnyInitializer()) {
546 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
547 S.Note(VD->getLocation(), diag::note_declared_at);
548 } else {
550 }
551 return false;
552 }
553
554 if (!S.checkingPotentialConstantExpression()) {
555 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
556 << AK << true << S.Current->getRange(OpPC);
557 }
558 return false;
559}
560
563 return true;
564
567 if ((!VD->hasConstantInitialization() &&
568 VD->mightBeUsableInConstantExpressions(S.getASTContext())) ||
571 const SourceInfo &Loc = S.Current->getSource(OpPC);
572 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
573 S.Note(VD->getLocation(), diag::note_declared_at);
574 }
575 return false;
576}
577
580 return true;
581
583 assert(VD);
584 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
585 << VD;
586 S.Note(VD->getLocation(), diag::note_declared_at);
587
588 return false;
589}
590
593 if ((S, OpPC, Ptr, AK))
594 return false;
596 return false;
598 return false;
600 return false;
602 return false;
604 return false;
606 return false;
608 return false;
610 return false;
612 return false;
614 return false;
615 return true;
616}
617
618
619
622 return false;
624 return false;
625
627 return false;
629 return false;
631 return false;
633 return false;
635 return false;
637 return false;
639 return false;
641 return false;
642 return true;
643}
644
647 return false;
649 return false;
651 return false;
653 return false;
655 return false;
657 return false;
658 return true;
659}
660
663 return false;
666 return false;
668 return false;
669 }
670 return true;
671}
672
675 return false;
677 return false;
678 return true;
679}
680
682
685 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
686 return false;
687 }
688
691 return true;
692
693
695 return true;
696
700
701
703 return false;
704
705
706
707 const auto *CD = dyn_cast(DiagDecl);
708 if (CD && CD->isInheritingConstructor()) {
709 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
710 if (!Inherited->isConstexpr())
711 DiagDecl = CD = Inherited;
712 }
713
714
715
716
717 if (CD && CD->isInheritingConstructor()) {
718 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
719 << CD->getInheritedConstructor().getConstructor()->getParent();
720 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
721 } else {
722
723
724
727 S.checkingPotentialConstantExpression())
728 return false;
729
730
731
734 return false;
735
736 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
738
741 diag::note_declared_at);
742 else
743 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
744 }
745 } else {
746 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
747 }
748
749 return false;
750}
751
753 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
754 S.FFDiag(S.Current->getSource(OpPC),
755 diag::note_constexpr_depth_limit_exceeded)
757 return false;
758 }
759
760 return true;
761}
762
764 if (.isZero())
765 return true;
766
767 const SourceInfo &Loc = S.Current->getSource(OpPC);
768
769 bool IsImplicit = false;
770 if (const auto *E = dyn_cast_if_present(Loc.asExpr()))
771 IsImplicit = E->isImplicit();
772
774 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
775 else
776 S.FFDiag(Loc);
777
778 return false;
779}
780
783 return true;
784 const SourceInfo &E = S.Current->getSource(OpPC);
785 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
786 S.Note(MD->getLocation(), diag::note_declared_at);
787 return false;
788}
789
791 APFloat::opStatus Status, FPOptions FPO) {
792
793
794
795
796 if (Result.isNan()) {
797 const SourceInfo &E = S.Current->getSource(OpPC);
798 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
799 << true << S.Current->getRange(OpPC);
800 return S.noteUndefinedBehavior();
801 }
802
803
804
805 if (S.inConstantContext())
806 return true;
807
808 if ((Status & APFloat::opInexact) &&
810
811
812 const SourceInfo &E = S.Current->getSource(OpPC);
813 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
814 return false;
815 }
816
817 if ((Status != APFloat::opOK) &&
820 FPO.getAllowFEnvAccess())) {
821 const SourceInfo &E = S.Current->getSource(OpPC);
822 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
823 return false;
824 }
825
826 if ((Status & APFloat::opStatus::opInvalidOp) &&
828 const SourceInfo &E = S.Current->getSource(OpPC);
829
830 S.FFDiag(E);
831 return false;
832 }
833
834 return true;
835}
836
839 return true;
840
841 const SourceInfo &E = S.Current->getSource(OpPC);
842 S.CCEDiag(E, diag::note_constexpr_new);
843 return true;
844}
845
849 const Expr *NewExpr) {
850 if (AllocForm == DeleteForm)
851 return true;
852
854
855
856
857 if (D->isArray()) {
858 QualType ElemQT = D->getType()->getPointeeType();
860 ElemQT, APInt(64, static_cast<uint64_t>(D->getNumElems()), false),
862 } else
863 TypeToDiagnose = D->getType()->getPointeeType();
864
865 const SourceInfo &E = S.Current->getSource(OpPC);
866 S.FFDiag(E, diag::note_constexpr_new_delete_mismatch)
867 << static_cast<int>(DeleteForm) << static_cast<int>(AllocForm)
868 << TypeToDiagnose;
869 S.Note(NewExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
871 return false;
872}
873
876
877
878 if (isa_and_nonnull(Source))
879 return true;
880 if (const CallExpr *CE = dyn_cast_if_present(Source);
881 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
882 return true;
883
884
885 const SourceInfo &Loc = S.Current->getSource(OpPC);
886 S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
888
890 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
891 else
892 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
893 return false;
894}
895
896
897
901}
902
906 return true;
907
910 if ()
911 return false;
912
915
918 const SourceInfo &E = S.Current->getSource(OpPC);
919 S.FFDiag(E, diag::note_constexpr_modify_global);
920 }
921 return false;
922}
923
925 const CallExpr *CE, unsigned ArgSize) {
928 unsigned Offset = 0;
929 unsigned Index = 0;
930 for (const Expr *Arg : Args) {
931 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
932 const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
933 if (ArgPtr.isZero()) {
935 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
936 return false;
937 }
938 }
939
941 ++Index;
942 }
943 return true;
944}
945
946
947
948
949
950
956 assert(R);
957
959 const SourceInfo &Loc = S.Current->getSource(OpPC);
960 S.FFDiag(Loc, diag::note_constexpr_double_destroy);
961 return false;
962 }
963
964
967 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
968 if (!DtorFunc)
969 return false;
970
971 S.Stk.push<Pointer>(BasePtr);
972 if ((S, OpPC, DtorFunc, 0))
973 return false;
974 }
975 return true;
976}
977
979 assert(B);
981
983 return true;
984
986
989 assert(ElemDesc->isRecord());
990
992 for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
994 return false;
995 }
996 return true;
997 }
998
1001}
1002
1006 return DD->isVirtual();
1007 return false;
1008}
1009
1011 bool IsGlobalDelete) {
1013 return false;
1014
1015 const Expr *Source = nullptr;
1016 const Block *BlockToDelete = nullptr;
1017 {
1018
1019
1021
1022
1024 return true;
1025
1026
1030
1031
1032
1033 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1035 S.FFDiag(S.Current->getSource(OpPC),
1036 diag::note_constexpr_delete_base_nonvirt_dtor)
1037 << InitialType << Ptr.getType();
1038 return false;
1039 }
1040
1042 const SourceInfo &Loc = S.Current->getSource(OpPC);
1043 S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
1045 return false;
1046 }
1047
1049 BlockToDelete = Ptr.block();
1050
1052 return false;
1053
1054
1055
1057 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1061 return DD->isVirtual() ? DD->getOperatorDelete() : nullptr;
1062 return nullptr;
1063 };
1064
1067 VirtualDelete &&
1069 S.FFDiag(S.Current->getSource(OpPC),
1070 diag::note_constexpr_new_non_replaceable)
1071 << isa(VirtualDelete) << VirtualDelete;
1072 return false;
1073 }
1074 }
1075 }
1076 assert(Source);
1077 assert(BlockToDelete);
1078
1079
1081 return false;
1082
1085 std::optionalDynamicAllocator::Form AllocForm =
1086 Allocator.getAllocationForm(Source);
1087
1088 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1089
1090 const SourceInfo &Loc = S.Current->getSource(OpPC);
1091 S.FFDiag(Loc, diag::note_constexpr_double_delete);
1092 return false;
1093 }
1094
1095 assert(AllocForm);
1100 Source);
1101}
1102
1105 llvm::APInt Min;
1106 llvm::APInt Max;
1107
1108 if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
1109 return;
1110
1113
1115 (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) {
1117 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1118 << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue()
1119 << ED;
1122 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1123 << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue()
1124 << ED;
1125 }
1126}
1127
1129 assert(T);
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146 if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() &&
1147 S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl) {
1148 return true;
1149 }
1150
1151 const Expr *E = S.Current->getExpr(OpPC);
1153 S.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType();
1154 else
1155 S.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1156 return false;
1157}
1158
1160 uint32_t Off) {
1161 if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
1163 return false;
1164
1166 return false;
1168 return false;
1170 return false;
1172 return false;
1173
1176 return true;
1177 }
1178
1180
1181
1182
1183 S.FFDiag(S.Current->getSource(OpPC),
1184 diag::note_constexpr_access_unreadable_object)
1186 return false;
1187 }
1188
1190 return false;
1191
1193 return true;
1194}
1195
1197 const auto &Ptr = S.Stk.peek<Pointer>();
1198 return getField(S, OpPC, Ptr, Off);
1199}
1200
1202 const auto &Ptr = S.Stk.pop<Pointer>();
1203 return getField(S, OpPC, Ptr, Off);
1204}
1205
1207 const Pointer &ThisPtr) {
1208 assert(Func->isConstructor());
1209
1211
1212
1213
1214 if (->ElemRecord)
1215 return true;
1216
1217 if (D->ElemRecord->getNumVirtualBases() == 0)
1218 return true;
1219
1220 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1221 << Func->getParentDecl();
1222 return false;
1223}
1224
1226 uint32_t VarArgSize) {
1227 if (Func->hasThisPointer()) {
1228 size_t ArgSize = Func->getArgSize() + VarArgSize;
1229 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1230 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1231
1232
1233
1234
1235
1236 if (!(S.Current->getFunction() &&
1237 S.Current->getFunction()->isLambdaStaticInvoker() &&
1238 Func->isLambdaCallOperator())) {
1240 return false;
1241 }
1242
1243 if (S.checkingPotentialConstantExpression())
1244 return false;
1245 }
1246
1248 return false;
1249
1251 return false;
1252
1253 auto NewFrame = std::make_unique(S, Func, OpPC, VarArgSize);
1255 S.Current = NewFrame.get();
1256
1257
1258
1259
1261 NewFrame.release();
1262 assert(S.Current == FrameBefore);
1263 return true;
1264 }
1265
1266
1267
1268 S.Current = FrameBefore;
1269 return false;
1270}
1271
1273 uint32_t VarArgSize) {
1274 assert(Func);
1275 auto cleanup = [&]() -> bool {
1277 return false;
1278 };
1279
1280 if (Func->hasThisPointer()) {
1281 size_t ArgSize = Func->getArgSize() + VarArgSize;
1282 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1283
1284 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1285
1286
1287
1288
1289
1290 if (S.Current->getFunction() &&
1291 S.Current->getFunction()->isLambdaStaticInvoker() &&
1292 Func->isLambdaCallOperator()) {
1293 assert(ThisPtr.isZero());
1294 } else {
1296 return cleanup();
1297 }
1298
1300 return false;
1301 }
1302
1304 return cleanup();
1305
1306
1307
1308
1309 if (Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
1310 ->isConstructor())
1311 return cleanup();
1312
1314 return cleanup();
1315
1316 auto NewFrame = std::make_unique(S, Func, OpPC, VarArgSize);
1318 S.Current = NewFrame.get();
1319
1321
1322
1323
1325 NewFrame.release();
1326 assert(S.Current == FrameBefore);
1327 return true;
1328 }
1329
1330
1331
1332 S.Current = FrameBefore;
1333 return false;
1334}
1335
1337 uint32_t VarArgSize) {
1338 assert(Func->hasThisPointer());
1339 assert(Func->isVirtual());
1340 size_t ArgSize = Func->getArgSize() + VarArgSize;
1341 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1343
1345 {
1346 Pointer TypePtr = ThisPtr;
1348 TypePtr = TypePtr.getBase();
1349
1352 DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
1353 else
1354 DynamicDecl = DynamicType->getAsCXXRecordDecl();
1355 }
1356 assert(DynamicDecl);
1357
1358 const auto *StaticDecl = cast(Func->getParentDecl());
1359 const auto *InitialFunction = cast(Func->getDecl());
1360 const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1361 DynamicDecl, StaticDecl, InitialFunction);
1362
1363 if (Overrider != InitialFunction) {
1364
1365
1366
1368 const Expr *E = S.Current->getExpr(OpPC);
1369 S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
1370 }
1371
1372 Func = S.getContext().getOrCreateFunction(Overrider);
1373
1375 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1376 if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1377
1378
1379
1380 while (ThisPtr.isBaseClass())
1381 ThisPtr = ThisPtr.getBase();
1382 }
1383 }
1384
1385 if ((S, OpPC, Func, VarArgSize))
1386 return false;
1387
1388
1389
1390 if (Overrider != InitialFunction &&
1392 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1393 QualType OverriderPointeeType =
1395 QualType InitialPointeeType =
1397
1398
1399
1400
1401 unsigned Offset = S.getContext().collectBaseOffset(
1405 }
1406
1407 return true;
1408}
1409
1411 const CallExpr *CE, uint32_t BuiltinID) {
1412
1413
1414 if (BuiltinID == Builtin::BI__builtin_operator_new &&
1415 S.checkingPotentialConstantExpression())
1416 return false;
1417 auto NewFrame = std::make_unique(S, Func, OpPC);
1418
1420 S.Current = NewFrame.get();
1421
1423
1424 NewFrame.release();
1425
1426 assert(S.Current == FrameBefore);
1427 return true;
1428 }
1429
1430
1431
1432 S.Current = FrameBefore;
1433 return false;
1434}
1435
1439
1441 if (!F) {
1442 const auto *E = cast(S.Current->getExpr(OpPC));
1443 S.FFDiag(E, diag::note_constexpr_null_callee)
1445 return false;
1446 }
1447
1448 if (!FuncPtr.isValid() || !F->getDecl())
1449 return Invalid(S, OpPC);
1450
1451 assert(F);
1452
1453
1454
1455 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
1456 S.Ctx.classify(CE->getType()))
1457 return false;
1458
1459
1460 if (F->hasNonNullAttr()) {
1462 return false;
1463 }
1464
1465 assert(ArgSize >= F->getWrittenArgSize());
1466 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
1467
1468
1469
1470 if (F->isThisPointerExplicit())
1472
1473 if (F->isVirtual())
1474 return CallVirt(S, OpPC, F, VarArgSize);
1475
1476 return Call(S, OpPC, F, VarArgSize);
1477}
1478
1480 std::optional<uint64_t> ArraySize) {
1482
1484 return false;
1485
1487 return false;
1488
1489 const auto *NewExpr = cast(E);
1491
1494
1496 }
1497
1500 if (ArraySize) {
1502 NewExpr->getAllocatedType(),
1503 APInt(64, static_cast<uint64_t>(*ArraySize), false), nullptr,
1505 } else {
1506 AllocType = NewExpr->getAllocatedType();
1507 }
1508
1509 unsigned StorageSize = 1;
1510 unsigned AllocSize = 1;
1511 if (const auto *CAT = dyn_cast(AllocType))
1512 AllocSize = CAT->getZExtSize();
1513 if (const auto *CAT = dyn_cast(StorageType))
1514 StorageSize = CAT->getZExtSize();
1515
1516 if (AllocSize > StorageSize ||
1519 S.FFDiag(S.Current->getLocation(OpPC),
1520 diag::note_constexpr_placement_new_wrong_type)
1521 << StorageType << AllocType;
1522 return false;
1523 }
1524
1525
1528
1529 return true;
1530}
1531
1533 assert(E);
1534
1536 return true;
1537
1538 const auto &Loc = S.Current->getSource(OpPC);
1539
1540 if (const auto *NewExpr = dyn_cast(E)) {
1541 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
1542
1543 if (!S.getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) {
1544
1545 if (S.Current->isStdFunction())
1546 return true;
1547 S.FFDiag(Loc, diag::note_constexpr_new_placement)
1549 } else if (NewExpr->getNumPlacementArgs() == 1 &&
1550 !OperatorNew->isReservedGlobalPlacementOperator()) {
1551 S.FFDiag(Loc, diag::note_constexpr_new_placement)
1553 } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
1554 S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
1555 << isa(OperatorNew) << OperatorNew;
1556 }
1557 } else {
1558 const auto *DeleteExpr = cast(E);
1559 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
1560 if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) {
1561 S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
1562 << isa(OperatorDelete) << OperatorDelete;
1563 }
1564 }
1565
1566 return false;
1567}
1568
1571 const Expr *E = S.Current->getExpr(OpPC);
1572 if (S.checkingForUndefinedBehavior()) {
1574 E->getExprLoc(), diag::warn_fixedpoint_constant_overflow)
1576 }
1577 S.CCEDiag(E, diag::note_constexpr_overflow)
1579 return S.noteUndefinedBehavior();
1580}
1581
1583 const SourceInfo &Loc = S.Current->getSource(OpPC);
1584 S.FFDiag(Loc,
1585 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
1586 << Index;
1587 return false;
1588}
1589
1591 const Pointer &Ptr, unsigned BitWidth) {
1593 return false;
1594
1595 const SourceInfo &E = S.Current->getSource(OpPC);
1596 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
1597 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1598
1600
1602 BitWidth)
1603 return Invalid(S, OpPC);
1604 }
1605 return true;
1606}
1607
1610
1612 return false;
1613
1616 return true;
1617}
1618
1621
1623 return false;
1624
1627 return true;
1628}
1629
1631 bool TargetIsUCharOrByte) {
1632
1633 if (!HasIndeterminateBits)
1634 return true;
1635
1636
1637 if (TargetIsUCharOrByte)
1638 return true;
1639
1640 const Expr *E = S.Current->getExpr(OpPC);
1642 S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
1644 return false;
1645}
1646
1648 const Type *TypeInfoType) {
1649 S.Stk.push<Pointer>(TypePtr, TypeInfoType);
1650 return true;
1651}
1652
1654 const auto &P = S.Stk.pop<Pointer>();
1655
1656 if (.isBlockPointer())
1657 return false;
1658
1659 if (P.isDummy()) {
1662 S.FFDiag(S.Current->getSource(OpPC),
1663 diag::note_constexpr_polymorphic_unknown_dynamic_type)
1667 return false;
1668 }
1669
1670 S.Stk.push<Pointer>(P.getType().getTypePtr(), TypeInfoType);
1671 return true;
1672}
1673
1675 const auto *E = cast(S.Current->getExpr(OpPC));
1676 S.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
1677 << E->getExprOperand()->getType()
1679 return false;
1680}
1681
1682
1683#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1684#pragma optimize("", off)
1685#endif
1687
1688
1689
1690
1691 const InterpFrame *StartFrame = S.Current;
1692 assert(!S.Current->isRoot());
1693 CodePtr PC = S.Current->getPC();
1694
1695
1696 if (!PC)
1697 return true;
1698
1699 for (;;) {
1702
1703 switch (Op) {
1704#define GET_INTERP
1705#include "Opcodes.inc"
1706#undef GET_INTERP
1707 }
1708 }
1709}
1710
1711#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1712#pragma optimize("", on)
1713#endif
1714
1715}
1716}
Defines the clang::ASTContext interface.
Defines the clang::Expr interface and subclasses for C++ expressions.
static const FunctionDecl * getVirtualOperatorDelete(QualType T)
static bool Jmp(InterpState &S, CodePtr &PC, int32_t Offset)
static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
static bool Jt(InterpState &S, CodePtr &PC, int32_t Offset)
static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, const ValueDecl *D)
static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset)
static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC, const ValueDecl *VD)
static bool RetValue(InterpState &S, CodePtr &Pt)
#define TYPE_SWITCH(Expr, B)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
Builtin::Context & BuiltinInfo
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.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool hasSimilarType(QualType T1, QualType T2) const
Determine if two types are similar, according to the C++ rules.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
bool hasCustomTypechecking(unsigned ID) const
Determines whether this builtin has custom typechecking.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
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.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
A reference to a declared variable, function, enum, etc.
bool isInvalidDecl() const
SourceLocation getLocation() const
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getNumNegativeBits() const
Returns the width in bits required to store all the negative enumerators of this enum.
void getValueRange(llvm::APInt &Max, llvm::APInt &Min) const
Calculates the [Min,Max) values the enum can store based on the NumPositiveBits and NumNegativeBits.
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...
LangOptions::FPExceptionModeKind getExceptionMode() const
RoundingMode getRoundingMode() const
Represents a member of a struct/union/class.
Represents a function declaration or definition.
QualType getReturnType() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
bool isPureVirtual() const
Whether this virtual function is pure, i.e.
FunctionDecl * getDefinition()
Get the definition for this declaration.
bool isReplaceableGlobalAllocationFunction(std::optional< unsigned > *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions: void *operato...
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
@ FPE_Ignore
Assume that floating-point exceptions are masked.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isConstant(const ASTContext &Ctx) const
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
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...
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isPointerOrReferenceType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
A memory block, either on the stack or in the heap.
unsigned getSize() const
Returns the size of the block.
const Descriptor * getDescriptor() const
Returns the block's descriptor.
unsigned getEvalID() const
The Evaluation ID this block was created in.
Pointer into the code segment.
std::enable_if_t<!std::is_pointer< T >::value, T > read()
Reads data and advances the pointer.
Manages dynamic memory allocations done during bytecode interpretation.
Wrapper around fixed point types.
std::string toDiagnosticString(const ASTContext &Ctx) const
Base class for stack frames, shared between VM and walker.
const Function * getFunction() const
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
bool hasBody() const
Checks if the function already has a body attached.
bool isVirtual() const
Checks if the function is virtual.
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
bool isLambdaStaticInvoker() const
Returns whether this function is a lambda static invoker, which we generate custom byte code for.
static IntegralAP from(T Value, unsigned NumBits=0)
Frame storing local variables.
A pointer to a memory block, live or dead.
Pointer narrow() const
Restricts the scope of an array element pointer.
bool isInitialized() const
Checks if an object was initialized.
bool isStatic() const
Checks if the storage is static.
bool isDynamic() const
Checks if the storage has been dynamically allocated.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isDummy() const
Checks if the pointer points to a dummy value.
bool isExtern() const
Checks if the storage is extern.
bool isActive() const
Checks if the object is active.
bool isConst() const
Checks if an object or a subfield is mutable.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
bool isMutable() const
Checks if the field is mutable.
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
bool isIntegralPointer() const
QualType getType() const
Returns the type of the innermost field.
bool isArrayElement() const
Checks if the pointer points to an array.
bool isLive() const
Checks if the pointer is live.
bool isStaticTemporary() const
Checks if the storage is a static temporary.
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
uint64_t getByteOffset() const
Returns the byte offset from the start.
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.
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
bool isOnePastEnd() const
Checks if the index is one past end.
uint64_t getIntegerRepresentation() const
const FieldDecl * getField() const
Returns the field information.
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
bool isBlockPointer() const
bool isTemporary() const
Checks if the storage is temporary.
SourceLocation getDeclLoc() const
const Block * block() const
Pointer getDeclPtr() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
std::optional< unsigned > getDeclID() const
Returns the declaration ID.
bool isBaseClass() const
Checks if a structure is a base class.
bool isField() const
Checks if the item is a field in an object.
const Record * getRecord() const
Returns the record descriptor of a class.
Structure/Class descriptor.
bool isUnion() const
Checks if the record is a union.
const CXXDestructorDecl * getDestructor() const
Returns the destructor of the record, if any.
llvm::iterator_range< const_field_iter > fields() const
Describes the statement/declaration an opcode was generated from.
Defines the clang::TargetInfo interface.
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off)
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth)
static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
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 runRecordDestructor(InterpState &S, CodePtr OpPC, const Pointer &BasePtr, const Descriptor *Desc)
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType)
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 CheckNewDeleteForms(InterpState &S, CodePtr OpPC, DynamicAllocator::Form AllocForm, DynamicAllocator::Form DeleteForm, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
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 GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr, const Type *TypeInfoType)
Typeid support.
bool CheckCallDepth(InterpState &S, CodePtr OpPC)
Checks if calling the currently active function would exceed the allowed call depth.
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This)
Checks the 'this' pointer.
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Checks if the Descriptor is of a constexpr or const global variable.
bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr, unsigned BitWidth)
static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B)
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off)
- Peeks a Pointer 2) Pushes Pointer.atField(Off) on the stack
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr, CheckSubobjectKind CSK)
Checks if Ptr is a one-past-the-end pointer.
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC, const FixedPoint &FP)
static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, uint32_t Off)
static bool hasVirtualDestructor(QualType T)
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD)
Checks if a method is pure virtual.
bool This(InterpState &S, CodePtr OpPC)
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC)
Checks if dynamic memory allocation is available in the current language mode.
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
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 CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits, bool TargetIsUCharOrByte)
static void popArg(InterpState &S, const Expr *Arg)
static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func, const Pointer &ThisPtr)
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED, const APSInt &Value)
PrimType
Enumeration of the primitive types of the VM.
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a value can be stored in a block.
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 CallVar(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index)
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 CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T)
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
bool CheckGlobalInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Check if a global variable is initialized.
bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *CE, unsigned ArgSize)
Checks if all the arguments annotated as 'nonnull' are in fact not null.
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC, const Function *Func)
llvm::BitVector collectNonNullArgs(const FunctionDecl *F, const llvm::ArrayRef< const Expr * > &Args)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func, const CallExpr *CE, uint32_t BuiltinID)
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm, bool IsGlobalDelete)
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E)
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call, uint32_t BuiltinID)
Interpret a builtin function.
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the variable has externally defined storage.
bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F)
Checks if a method can be called.
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE)
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to const storage.
bool Interpret(InterpState &S)
Interpreter entry point.
bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a method can be invoked on an object.
The JSON file list parser is used to communicate input to InstallAPI.
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
llvm::StringRef getAsString(SyncScope S)
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
const ValueDecl * asValueDecl() const
const Descriptor *const ElemDesc
Descriptor of the array element.
unsigned getMetadataSize() const
Returns the size of the metadata.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
const VarDecl * asVarDecl() const
bool isRecord() const
Checks if the descriptor is of a record.
const Record *const ElemRecord
Pointer to the record, if block contains records.
const Expr * asExpr() const
IntPointer atOffset(const ASTContext &ASTCtx, unsigned Offset) const