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 (D->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 (U.isRoot() && U.inUnion() && U.isActive()) {

140 if (U.getField())

141 C = U;

142 U = U.getBase();

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 (U.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 (D || D->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)

377 << D << T;

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 (CheckLive(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 (This.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 (D)

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 (Call(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 (D->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 Func->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 (Call(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 (P.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)

  1. 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