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 {
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;
419 const SourceInfo &Loc = S.Current->getSource(OpPC);
420 S.FFDiag(Loc, diag::note_constexpr_access_past_end)
421 << AK << S.Current->getRange(OpPC);
422 return false;
423}
424
428 return true;
429 const SourceInfo &Loc = S.Current->getSource(OpPC);
430 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
431 << CSK << S.Current->getRange(OpPC);
432 return false;
433}
434
438 return true;
439
440 const SourceInfo &Loc = S.Current->getSource(OpPC);
441 S.FFDiag(Loc, diag::note_constexpr_past_end_subobject)
442 << CSK << S.Current->getRange(OpPC);
443 return false;
444}
445
447 uint32_t Offset) {
450
451
452
453 if (Offset < PtrOffset && (PtrOffset - Offset) >= MinOffset)
454 return true;
455
456 const auto *E = cast(S.Current->getExpr(OpPC));
459
460 S.CCEDiag(E, diag::note_constexpr_invalid_downcast)
461 << MostDerivedQT << TargetQT;
462
463 return false;
464}
465
467 assert(Ptr.isLive() && "Pointer is not live");
469 return true;
470
471
472
473
474
475 if (S.Current->getFunction()) {
478 Func && (Func->isConstructor() || Func->isDestructor()) &&
479 Ptr.block() == Frame->getThis().block()) {
480 return true;
481 }
482 }
483 }
484
486 return false;
487
489 const SourceInfo &Loc = S.Current->getSource(OpPC);
490 S.FFDiag(Loc, diag::note_constexpr_modify_const_type) << Ty;
491 return false;
492}
493
495 assert(Ptr.isLive() && "Pointer is not live");
497 return true;
498
499
500
503 return true;
504
505 const SourceInfo &Loc = S.Current->getSource(OpPC);
507 S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK_Read << Field;
508 S.Note(Field->getLocation(), diag::note_declared_at);
509 return false;
510}
511
514 assert(Ptr.isLive());
515
516
517
519 return true;
520
523 return true;
524
525 const SourceInfo &Loc = S.Current->getSource(OpPC);
527 S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
528 else
529 S.FFDiag(Loc);
530 return false;
531}
532
535 assert(Ptr.isLive());
536
538 return true;
539
542 const SourceInfo &Loc = S.Current->getSource(OpPC);
543 if (VD->getAnyInitializer()) {
544 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
545 S.Note(VD->getLocation(), diag::note_declared_at);
546 } else {
548 }
549 return false;
550 }
551
552 if (!S.checkingPotentialConstantExpression()) {
553 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
554 << AK << true << S.Current->getRange(OpPC);
555 }
556 return false;
557}
558
561 return true;
562
565 if ((!VD->hasConstantInitialization() &&
566 VD->mightBeUsableInConstantExpressions(S.getASTContext())) ||
569 const SourceInfo &Loc = S.Current->getSource(OpPC);
570 S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
571 S.Note(VD->getLocation(), diag::note_declared_at);
572 }
573 return false;
574}
575
578 return true;
579
581 assert(VD);
582 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_var_init_weak)
583 << VD;
584 S.Note(VD->getLocation(), diag::note_declared_at);
585
586 return false;
587}
588
591 if ((S, OpPC, Ptr, AK))
592 return false;
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;
613 return true;
614}
615
616
617
620 return false;
622 return false;
623
625 return false;
627 return false;
629 return false;
631 return false;
633 return false;
635 return false;
637 return false;
639 return false;
640 return true;
641}
642
645 return false;
647 return false;
649 return false;
651 return false;
653 return false;
655 return false;
656 return true;
657}
658
661 return false;
664 return false;
666 return false;
667 }
668 return true;
669}
670
673 return false;
675 return false;
676 return true;
677}
678
680
683 S.CCEDiag(Loc, diag::note_constexpr_virtual_call);
684 return false;
685 }
686
689 return true;
690
691
693 return true;
694
698
699
701 return false;
702
703
704
705 const auto *CD = dyn_cast(DiagDecl);
706 if (CD && CD->isInheritingConstructor()) {
707 const auto *Inherited = CD->getInheritedConstructor().getConstructor();
708 if (!Inherited->isConstexpr())
709 DiagDecl = CD = Inherited;
710 }
711
712
713
714
715 if (CD && CD->isInheritingConstructor()) {
716 S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
717 << CD->getInheritedConstructor().getConstructor()->getParent();
718 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
719 } else {
720
721
722
725 S.checkingPotentialConstantExpression())
726 return false;
727
728
729
732 return false;
733
734 S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
736
739 diag::note_declared_at);
740 else
741 S.Note(DiagDecl->getLocation(), diag::note_declared_at);
742 }
743 } else {
744 S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
745 }
746
747 return false;
748}
749
751 if ((S.Current->getDepth() + 1) > S.getLangOpts().ConstexprCallDepth) {
752 S.FFDiag(S.Current->getSource(OpPC),
753 diag::note_constexpr_depth_limit_exceeded)
755 return false;
756 }
757
758 return true;
759}
760
762 if (.isZero())
763 return true;
764
765 const SourceInfo &Loc = S.Current->getSource(OpPC);
766
767 bool IsImplicit = false;
768 if (const auto *E = dyn_cast_if_present(Loc.asExpr()))
769 IsImplicit = E->isImplicit();
770
772 S.FFDiag(Loc, diag::note_constexpr_this) << IsImplicit;
773 else
774 S.FFDiag(Loc);
775
776 return false;
777}
778
781 return true;
782 const SourceInfo &E = S.Current->getSource(OpPC);
783 S.FFDiag(E, diag::note_constexpr_pure_virtual_call, 1) << MD;
784 S.Note(MD->getLocation(), diag::note_declared_at);
785 return false;
786}
787
789 APFloat::opStatus Status, FPOptions FPO) {
790
791
792
793
794 if (Result.isNan()) {
795 const SourceInfo &E = S.Current->getSource(OpPC);
796 S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
797 << true << S.Current->getRange(OpPC);
798 return S.noteUndefinedBehavior();
799 }
800
801
802
803 if (S.inConstantContext())
804 return true;
805
806 if ((Status & APFloat::opInexact) &&
808
809
810 const SourceInfo &E = S.Current->getSource(OpPC);
811 S.FFDiag(E, diag::note_constexpr_dynamic_rounding);
812 return false;
813 }
814
815 if ((Status != APFloat::opOK) &&
818 FPO.getAllowFEnvAccess())) {
819 const SourceInfo &E = S.Current->getSource(OpPC);
820 S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict);
821 return false;
822 }
823
824 if ((Status & APFloat::opStatus::opInvalidOp) &&
826 const SourceInfo &E = S.Current->getSource(OpPC);
827
828 S.FFDiag(E);
829 return false;
830 }
831
832 return true;
833}
834
837 return true;
838
839 const SourceInfo &E = S.Current->getSource(OpPC);
840 S.CCEDiag(E, diag::note_constexpr_new);
841 return true;
842}
843
847 const Expr *NewExpr) {
848 if (AllocForm == DeleteForm)
849 return true;
850
852
853
854
855 if (D->isArray()) {
856 QualType ElemQT = D->getType()->getPointeeType();
858 ElemQT, APInt(64, static_cast<uint64_t>(D->getNumElems()), false),
860 } else
861 TypeToDiagnose = D->getType()->getPointeeType();
862
863 const SourceInfo &E = S.Current->getSource(OpPC);
864 S.FFDiag(E, diag::note_constexpr_new_delete_mismatch)
865 << static_cast<int>(DeleteForm) << static_cast<int>(AllocForm)
866 << TypeToDiagnose;
867 S.Note(NewExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here)
869 return false;
870}
871
874
875
876 if (isa_and_nonnull(Source))
877 return true;
878 if (const CallExpr *CE = dyn_cast_if_present(Source);
879 CE && CE->getBuiltinCallee() == Builtin::BI__builtin_operator_new)
880 return true;
881
882
883 const SourceInfo &Loc = S.Current->getSource(OpPC);
884 S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
886
888 S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
889 else
890 S.Note(Ptr.getDeclLoc(), diag::note_declared_at);
891 return false;
892}
893
894
895
899}
900
904 return true;
905
908 if ()
909 return false;
910
913
916 const SourceInfo &E = S.Current->getSource(OpPC);
917 S.FFDiag(E, diag::note_constexpr_modify_global);
918 }
919 return false;
920}
921
923 const CallExpr *CE, unsigned ArgSize) {
926 unsigned Offset = 0;
927 unsigned Index = 0;
928 for (const Expr *Arg : Args) {
929 if (NonNullArgs[Index] && Arg->getType()->isPointerType()) {
930 const Pointer &ArgPtr = S.Stk.peek<Pointer>(ArgSize - Offset);
931 if (ArgPtr.isZero()) {
933 S.CCEDiag(Loc, diag::note_non_null_attribute_failed);
934 return false;
935 }
936 }
937
939 ++Index;
940 }
941 return true;
942}
943
944
945
946
947
948
954 assert(R);
955
957 const SourceInfo &Loc = S.Current->getSource(OpPC);
958 S.FFDiag(Loc, diag::note_constexpr_double_destroy);
959 return false;
960 }
961
962
965 const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
966 if (!DtorFunc)
967 return false;
968
969 S.Stk.push<Pointer>(BasePtr);
970 if ((S, OpPC, DtorFunc, 0))
971 return false;
972 }
973 return true;
974}
975
977 assert(B);
979
981 return true;
982
984
987 assert(ElemDesc->isRecord());
988
990 for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
992 return false;
993 }
994 return true;
995 }
996
999}
1000
1004 return DD->isVirtual();
1005 return false;
1006}
1007
1009 bool IsGlobalDelete) {
1011 return false;
1012
1013 const Expr *Source = nullptr;
1014 const Block *BlockToDelete = nullptr;
1015 {
1016
1017
1019
1020
1022 return true;
1023
1024
1028
1029
1030
1031 if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
1033 S.FFDiag(S.Current->getSource(OpPC),
1034 diag::note_constexpr_delete_base_nonvirt_dtor)
1035 << InitialType << Ptr.getType();
1036 return false;
1037 }
1038
1040 const SourceInfo &Loc = S.Current->getSource(OpPC);
1041 S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
1043 return false;
1044 }
1045
1047 BlockToDelete = Ptr.block();
1048
1050 return false;
1051
1052
1053
1055 if (!DeleteIsArrayForm && !IsGlobalDelete) {
1059 return DD->isVirtual() ? DD->getOperatorDelete() : nullptr;
1060 return nullptr;
1061 };
1062
1065 VirtualDelete &&
1067 S.FFDiag(S.Current->getSource(OpPC),
1068 diag::note_constexpr_new_non_replaceable)
1069 << isa(VirtualDelete) << VirtualDelete;
1070 return false;
1071 }
1072 }
1073 }
1074 assert(Source);
1075 assert(BlockToDelete);
1076
1077
1079 return false;
1080
1083 std::optionalDynamicAllocator::Form AllocForm =
1084 Allocator.getAllocationForm(Source);
1085
1086 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1087
1088 const SourceInfo &Loc = S.Current->getSource(OpPC);
1089 S.FFDiag(Loc, diag::note_constexpr_double_delete);
1090 return false;
1091 }
1092
1093 assert(AllocForm);
1098 Source);
1099}
1100
1103 llvm::APInt Min;
1104 llvm::APInt Max;
1105
1106 if (S.EvaluatingDecl && !S.EvaluatingDecl->isConstexpr())
1107 return;
1108
1111
1113 (Max.slt(Value.getSExtValue()) || Min.sgt(Value.getSExtValue()))) {
1115 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1116 << llvm::toString(Value, 10) << Min.getSExtValue() << Max.getSExtValue()
1117 << ED;
1120 S.CCEDiag(Loc, diag::note_constexpr_unscoped_enum_out_of_range)
1121 << llvm::toString(Value, 10) << Min.getZExtValue() << Max.getZExtValue()
1122 << ED;
1123 }
1124}
1125
1127 assert(T);
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 if (S.Current->getFunction() && S.Current->getFunction()->isConstructor() &&
1145 S.Current->getThis().getDeclDesc()->asDecl() == S.EvaluatingDecl) {
1146 return true;
1147 }
1148
1149 const Expr *E = S.Current->getExpr(OpPC);
1151 S.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType();
1152 else
1153 S.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
1154 return false;
1155}
1156
1158 uint32_t Off) {
1159 if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
1161 return false;
1162
1164 return false;
1166 return false;
1168 return false;
1170 return false;
1171
1174 return true;
1175 }
1176
1178
1179
1180
1181 S.FFDiag(S.Current->getSource(OpPC),
1182 diag::note_constexpr_access_unreadable_object)
1184 return false;
1185 }
1186
1188 return false;
1189
1191 return true;
1192}
1193
1195 const auto &Ptr = S.Stk.peek<Pointer>();
1196 return getField(S, OpPC, Ptr, Off);
1197}
1198
1200 const auto &Ptr = S.Stk.pop<Pointer>();
1201 return getField(S, OpPC, Ptr, Off);
1202}
1203
1205 const Pointer &ThisPtr) {
1206 assert(Func->isConstructor());
1207
1209
1210
1211
1212 if (->ElemRecord)
1213 return true;
1214
1215 if (D->ElemRecord->getNumVirtualBases() == 0)
1216 return true;
1217
1218 S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_virtual_base)
1219 << Func->getParentDecl();
1220 return false;
1221}
1222
1224 uint32_t VarArgSize) {
1225 if (Func->hasThisPointer()) {
1226 size_t ArgSize = Func->getArgSize() + VarArgSize;
1227 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1228 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1229
1230
1231
1232
1233
1234 if (!(S.Current->getFunction() &&
1235 S.Current->getFunction()->isLambdaStaticInvoker() &&
1236 Func->isLambdaCallOperator())) {
1238 return false;
1239 }
1240
1241 if (S.checkingPotentialConstantExpression())
1242 return false;
1243 }
1244
1246 return false;
1247
1249 return false;
1250
1251 auto NewFrame = std::make_unique(S, Func, OpPC, VarArgSize);
1253 S.Current = NewFrame.get();
1254
1255
1256
1257
1259 NewFrame.release();
1260 assert(S.Current == FrameBefore);
1261 return true;
1262 }
1263
1264
1265
1266 S.Current = FrameBefore;
1267 return false;
1268}
1269
1271 uint32_t VarArgSize) {
1272 assert(Func);
1273 auto cleanup = [&]() -> bool {
1275 return false;
1276 };
1277
1278 if (Func->hasThisPointer()) {
1279 size_t ArgSize = Func->getArgSize() + VarArgSize;
1280 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1281
1282 const Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
1283
1284
1285
1286
1287
1288 if (S.Current->getFunction() &&
1289 S.Current->getFunction()->isLambdaStaticInvoker() &&
1290 Func->isLambdaCallOperator()) {
1291 assert(ThisPtr.isZero());
1292 } else {
1294 return cleanup();
1295 }
1296
1298 return false;
1299 }
1300
1302 return cleanup();
1303
1304
1305
1306
1307 if (Func->hasThisPointer() && S.checkingPotentialConstantExpression() &&
1308 ->isConstructor())
1309 return cleanup();
1310
1312 return cleanup();
1313
1314 auto NewFrame = std::make_unique(S, Func, OpPC, VarArgSize);
1316 S.Current = NewFrame.get();
1317
1319
1320
1321
1323 NewFrame.release();
1324 assert(S.Current == FrameBefore);
1325 return true;
1326 }
1327
1328
1329
1330 S.Current = FrameBefore;
1331 return false;
1332}
1333
1335 uint32_t VarArgSize) {
1336 assert(Func->hasThisPointer());
1337 assert(Func->isVirtual());
1338 size_t ArgSize = Func->getArgSize() + VarArgSize;
1339 size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
1341
1343 {
1344 Pointer TypePtr = ThisPtr;
1346 TypePtr = TypePtr.getBase();
1347
1350 DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
1351 else
1352 DynamicDecl = DynamicType->getAsCXXRecordDecl();
1353 }
1354 assert(DynamicDecl);
1355
1356 const auto *StaticDecl = cast(Func->getParentDecl());
1357 const auto *InitialFunction = cast(Func->getDecl());
1358 const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
1359 DynamicDecl, StaticDecl, InitialFunction);
1360
1361 if (Overrider != InitialFunction) {
1362
1363
1364
1366 const Expr *E = S.Current->getExpr(OpPC);
1367 S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
1368 }
1369
1370 Func = S.getContext().getOrCreateFunction(Overrider);
1371
1373 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
1374 if (Func->getParentDecl()->isDerivedFrom(ThisFieldDecl)) {
1375
1376
1377
1378 while (ThisPtr.isBaseClass())
1379 ThisPtr = ThisPtr.getBase();
1380 }
1381 }
1382
1383 if ((S, OpPC, Func, VarArgSize))
1384 return false;
1385
1386
1387
1388 if (Overrider != InitialFunction &&
1390 InitialFunction->getReturnType()->isPointerOrReferenceType()) {
1391 QualType OverriderPointeeType =
1393 QualType InitialPointeeType =
1395
1396
1397
1398
1399 unsigned Offset = S.getContext().collectBaseOffset(
1403 }
1404
1405 return true;
1406}
1407
1409 const CallExpr *CE, uint32_t BuiltinID) {
1410
1411
1412 if (BuiltinID == Builtin::BI__builtin_operator_new &&
1413 S.checkingPotentialConstantExpression())
1414 return false;
1415 auto NewFrame = std::make_unique(S, Func, OpPC);
1416
1418 S.Current = NewFrame.get();
1419
1421
1422 NewFrame.release();
1423
1424 assert(S.Current == FrameBefore);
1425 return true;
1426 }
1427
1428
1429
1430 S.Current = FrameBefore;
1431 return false;
1432}
1433
1437
1439 if (!F) {
1440 const auto *E = cast(S.Current->getExpr(OpPC));
1441 S.FFDiag(E, diag::note_constexpr_null_callee)
1443 return false;
1444 }
1445
1446 if (!FuncPtr.isValid() || !F->getDecl())
1447 return Invalid(S, OpPC);
1448
1449 assert(F);
1450
1451
1452
1453 if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
1454 S.Ctx.classify(CE->getType()))
1455 return false;
1456
1457
1458 if (F->hasNonNullAttr()) {
1460 return false;
1461 }
1462
1463 assert(ArgSize >= F->getWrittenArgSize());
1464 uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();
1465
1466
1467
1468 if (F->isThisPointerExplicit())
1470
1471 if (F->isVirtual())
1472 return CallVirt(S, OpPC, F, VarArgSize);
1473
1474 return Call(S, OpPC, F, VarArgSize);
1475}
1476
1478 std::optional<uint64_t> ArraySize) {
1480
1482 return false;
1483
1485 return false;
1486
1487 const auto *NewExpr = cast(E);
1489
1492
1494 }
1495
1498 if (ArraySize) {
1500 NewExpr->getAllocatedType(),
1501 APInt(64, static_cast<uint64_t>(*ArraySize), false), nullptr,
1503 } else {
1504 AllocType = NewExpr->getAllocatedType();
1505 }
1506
1507 unsigned StorageSize = 1;
1508 unsigned AllocSize = 1;
1509 if (const auto *CAT = dyn_cast(AllocType))
1510 AllocSize = CAT->getZExtSize();
1511 if (const auto *CAT = dyn_cast(StorageType))
1512 StorageSize = CAT->getZExtSize();
1513
1514 if (AllocSize > StorageSize ||
1517 S.FFDiag(S.Current->getLocation(OpPC),
1518 diag::note_constexpr_placement_new_wrong_type)
1519 << StorageType << AllocType;
1520 return false;
1521 }
1522
1523
1526
1527 return true;
1528}
1529
1531 assert(E);
1532
1534 return true;
1535
1536 const auto &Loc = S.Current->getSource(OpPC);
1537
1538 if (const auto *NewExpr = dyn_cast(E)) {
1539 const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();
1540
1541 if (!S.getLangOpts().CPlusPlus26 && NewExpr->getNumPlacementArgs() > 0) {
1542
1543 if (S.Current->isStdFunction())
1544 return true;
1545 S.FFDiag(Loc, diag::note_constexpr_new_placement)
1547 } else if (NewExpr->getNumPlacementArgs() == 1 &&
1548 !OperatorNew->isReservedGlobalPlacementOperator()) {
1549 S.FFDiag(Loc, diag::note_constexpr_new_placement)
1551 } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
1552 S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
1553 << isa(OperatorNew) << OperatorNew;
1554 }
1555 } else {
1556 const auto *DeleteExpr = cast(E);
1557 const FunctionDecl *OperatorDelete = DeleteExpr->getOperatorDelete();
1558 if (!OperatorDelete->isReplaceableGlobalAllocationFunction()) {
1559 S.FFDiag(Loc, diag::note_constexpr_new_non_replaceable)
1560 << isa(OperatorDelete) << OperatorDelete;
1561 }
1562 }
1563
1564 return false;
1565}
1566
1569 const Expr *E = S.Current->getExpr(OpPC);
1570 if (S.checkingForUndefinedBehavior()) {
1572 E->getExprLoc(), diag::warn_fixedpoint_constant_overflow)
1574 }
1575 S.CCEDiag(E, diag::note_constexpr_overflow)
1577 return S.noteUndefinedBehavior();
1578}
1579
1581 const SourceInfo &Loc = S.Current->getSource(OpPC);
1582 S.FFDiag(Loc,
1583 diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
1584 << Index;
1585 return false;
1586}
1587
1589 const Pointer &Ptr, unsigned BitWidth) {
1591 return false;
1592
1593 const SourceInfo &E = S.Current->getSource(OpPC);
1594 S.CCEDiag(E, diag::note_constexpr_invalid_cast)
1595 << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
1596
1598
1600 BitWidth)
1601 return Invalid(S, OpPC);
1602 }
1603 return true;
1604}
1605
1608
1610 return false;
1611
1614 return true;
1615}
1616
1619
1621 return false;
1622
1625 return true;
1626}
1627
1629 bool TargetIsUCharOrByte) {
1630
1631 if (!HasIndeterminateBits)
1632 return true;
1633
1634
1635 if (TargetIsUCharOrByte)
1636 return true;
1637
1638 const Expr *E = S.Current->getExpr(OpPC);
1640 S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
1642 return false;
1643}
1644
1646 const Type *TypeInfoType) {
1647 S.Stk.push<Pointer>(TypePtr, TypeInfoType);
1648 return true;
1649}
1650
1652 const auto &P = S.Stk.pop<Pointer>();
1653
1654 if (.isBlockPointer())
1655 return false;
1656
1657 if (P.isDummy()) {
1660 S.FFDiag(S.Current->getSource(OpPC),
1661 diag::note_constexpr_polymorphic_unknown_dynamic_type)
1665 return false;
1666 }
1667
1668 S.Stk.push<Pointer>(P.getType().getTypePtr(), TypeInfoType);
1669 return true;
1670}
1671
1673 const auto *E = cast(S.Current->getExpr(OpPC));
1674 S.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
1675 << E->getExprOperand()->getType()
1677 return false;
1678}
1679
1680
1681#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1682#pragma optimize("", off)
1683#endif
1685
1686
1687
1688
1689 const InterpFrame *StartFrame = S.Current;
1690 assert(!S.Current->isRoot());
1691 CodePtr PC = S.Current->getPC();
1692
1693
1694 if (!PC)
1695 return true;
1696
1697 for (;;) {
1700
1701 switch (Op) {
1702#define GET_INTERP
1703#include "Opcodes.inc"
1704#undef GET_INTERP
1705 }
1706 }
1707}
1708
1709#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
1710#pragma optimize("", on)
1711#endif
1712
1713}
1714}
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 ...
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
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