clang: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

23#include "llvm/Support/Casting.h"

24#include "llvm/Support/Compiler.h"

25#include "llvm/Support/SaveAndRestore.h"

26#include

27

28using namespace clang;

29using namespace ento;

30

31#define DEBUG_TYPE "ExprEngine"

32

34 NumOfDynamicDispatchPathSplits,

35 "The # of times we split the path due to imprecise dynamic dispatch info");

36

37STAT_COUNTER(NumInlinedCalls, "The # of times we inlined a call");

38

40 "The # of times we reached inline count maximum");

41

44

46

47

48 assert(Entry->empty());

50

51

53

54

56

58

59

60

61 bool isNew;

62 ExplodedNode *Node = G.getNode(Loc, state, false, &isNew);

64 if (isNew) {

67 Engine.enqueue(DstBegin);

68 }

69}

70

71

72

73static std::pair<const Stmt*,

75 const Stmt *S = nullptr;

76 const CFGBlock *Blk = nullptr;

78

79

80

81 while (Node) {

83

85 if (std::optional SP = PP.getAs<StmtPoint>()) {

86 S = SP->getStmt();

87 break;

88 } else if (std::optional CEE = PP.getAs<CallExitEnd>()) {

89 S = CEE->getCalleeContext()->getCallSite();

90 if (S)

91 break;

92

93

94

95

96 std::optional CE;

97 do {

100 } while (!CE || CE->getCalleeContext() != CEE->getCalleeContext());

101

102

103 } else if (std::optional BE = PP.getAs<BlockEdge>()) {

104 Blk = BE->getSrc();

105 }

106 } else if (std::optional CE = PP.getAs<CallEnter>()) {

107

108 if (CE->getCalleeContext() == SF)

109 break;

110 }

111

113 return std::make_pair(nullptr, nullptr);

114

116 }

117

118 return std::make_pair(S, Blk);

119}

120

121

122

123

124

125

128

130 return V;

131

132

135 if (ExpectedTy == ActualTy)

136 return V;

137

138

141 return V;

142

143

147 CXXBasePaths Paths(true, true,

148 false);

152 }

153 }

154

155

156

157

159}

160

164

165 const Stmt *LastSt = nullptr;

166 const CFGBlock *Blk = nullptr;

167 std::tie(LastSt, Blk) = getLastStmt(Pred);

168 if (!Blk || !LastSt) {

169 Dst.Add(Pred);

170 return;

171 }

172

173

174

175

176

177

180 removeDead(Pred, Dst, dyn_cast(LastSt), LCtx,

183}

184

187 const Decl *RuntimeCallee = calleeCtx->getDecl();

188 const Decl *StaticDecl = Call->getDecl();

189 assert(RuntimeCallee);

190 if (!StaticDecl)

191 return true;

193}

194

195

196

200 "The call event is not a destructor call!");

201

203

204 auto ThisVal = DtorCall.getCXXThisVal();

205

206 if (auto ThisElementRegion = dyn_cast(ThisVal.getAsRegion())) {

207 auto ArrayRegion = ThisElementRegion->getAsArrayOffset().getRegion();

208 auto ElementType = ThisElementRegion->getElementType();

209

210 auto ElementCount =

212

213 if (!ElementCount.isConstant())

214 return 0;

215

216 return ElementCount.getAsInteger()->getLimitedValue();

217 }

218

219 return 0;

220}

221

222ProgramStateRef ExprEngine::removeStateTraitsUsedForArrayEvaluation(

224 const LocationContext *LCtx) {

225

226 assert(LCtx && "Location context must be provided!");

227

228 if (E) {

230 State = removePendingInitLoop(State, E, LCtx);

231

233 State = removeIndexOfElementToConstruct(State, E, LCtx);

234 }

235

237 State = removePendingArrayDestruction(State, LCtx);

238

239 return State;

240}

241

242

243

244

245

246

247

248

249

251

253

254

255

258

261

262 const Stmt *LastSt = nullptr;

263 const CFGBlock *Blk = nullptr;

264 std::tie(LastSt, Blk) = getLastStmt(CEBNode);

265

266

267

270

271

272

273

274

275

276

277

278 bool ShouldRepeatCall = false;

279

280 if (const auto *DtorDecl =

281 dyn_cast_or_null(Call->getDecl())) {

283 ShouldRepeatCall = *Idx > 0;

284

285 auto ThisVal = svalBuilder.getCXXThis(DtorDecl->getParent(), calleeCtx);

286 state = state->killBinding(ThisVal);

287 }

288 }

289

290

291 if (CE) {

292 if (const ReturnStmt *RS = dyn_cast_or_null(LastSt)) {

294 SVal V = state->getSVal(RS, LCtx);

295

296

300 if (!ReturnedTy.isNull()) {

301 if (const Expr *Ex = dyn_cast(CE)) {

304 }

305 }

306 }

307

308 state = state->BindExpr(CE, callerCtx, V);

309 }

310

311

312 if (const CXXConstructExpr *CCE = dyn_cast(CE)) {

314 svalBuilder.getCXXThis(CCE->getConstructor()->getParent(), calleeCtx);

315 SVal ThisV = state->getSVal(This);

316 ThisV = state->getSVal(ThisV.castAs<Loc>());

317 state = state->BindExpr(CCE, callerCtx, ThisV);

318

319 ShouldRepeatCall = shouldRepeatCtorCall(state, CCE, callerCtx);

320 }

321

322 if (const auto *CNE = dyn_cast(CE)) {

323

324

325

326

327

328 SVal AllocV = state->getSVal(CNE, callerCtx);

329 AllocV = svalBuilder.evalCast(

332

333 state = addObjectUnderConstruction(state, CNE, calleeCtx->getParent(),

334 AllocV);

335 }

336 }

337

338 if (!ShouldRepeatCall) {

339 state = removeStateTraitsUsedForArrayEvaluation(

340 state, dyn_cast_or_null(CE), callerCtx);

341 }

342

343

344

345

346

347

349 if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) {

354 nullptr, &retValBind)};

355 const CFGBlock *PrePurgeBlock =

357 bool isNew;

358 ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);

360 if (!isNew)

361 return;

362

364 currBldrCtx = &Ctx;

365

366

367

368

369 removeDead(BindedRetNode, CleanedNodes, nullptr, calleeCtx,

372 currBldrCtx = nullptr;

373 } else {

374 CleanedNodes.Add(CEBNode);

375 }

376

378

379

381 bool isNew;

382 ProgramStateRef CEEState = (N == CEBNode) ? state : N->getState();

383

384 ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew);

386 if (!isNew)

387 return;

388

389

390

391

395

397

399 if (llvm::isa_and_nonnull(CE)) {

402 CEENode, *UpdatedCall, *this,

403 true);

404 for (ExplodedNode *I : DstPostPostCallCallback) {

407 true);

408 }

409 } else {

411 *UpdatedCall, *this,

412 true);

413 }

417 *this,

418 true);

419 } else if (CE &&

420 !(isa(CE) &&

421 AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {

423 *this, true);

424 } else {

425 Dst.insert(DstPostCall);

426 }

427

428

430 PSI != PSE; ++PSI) {

431 unsigned Idx = calleeCtx->getIndex() + (ShouldRepeatCall ? 0 : 1);

432

433 Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(), Idx);

434 }

435 }

436}

437

439

440

441

442

443

446}

447

450 return Cfg->size() >= AMgr.options.MinCFGSizeTreatFunctionsAsLarge;

451}

452

456}

457

458void ExprEngine::examineStackFrames(const Decl *D, const LocationContext *LCtx,

459 bool &IsRecursive, unsigned &StackDepth) {

460 IsRecursive = false;

461 StackDepth = 0;

462

463 while (LCtx) {

464 if (const StackFrameContext *SFC = dyn_cast(LCtx)) {

465 const Decl *DI = SFC->getDecl();

466

467

468

469 if (DI == D) {

470 IsRecursive = true;

471 ++StackDepth;

473 continue;

474 }

475

476

477 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);

478 if (!isSmall(CalleeADC))

479 ++StackDepth;

480 }

482 }

483}

484

485

486

487

488

489

490

491namespace {

492 enum DynamicDispatchMode {

493 DynamicDispatchModeInlined = 1,

494 DynamicDispatchModeConservative

495 };

496}

497

501

502void ExprEngine::ctuBifurcate(const CallEvent &Call, const Decl *D,

506 if (Call.isForeign() && !isSecondPhaseCTU()) {

511 if (DoInline) {

512 inlineCall(Engine.getWorkList(), Call, D, Bldr, Pred, State);

513 return;

514 }

515 const bool BState = State->get();

516 if (!BState) {

517

519

520 ConservativeEvalState = State->set(true);

521 conservativeEvalCall(Call, Bldr, Pred, ConservativeEvalState);

522 } else {

523 conservativeEvalCall(Call, Bldr, Pred, State);

524 }

525 return;

526 }

527 inlineCall(Engine.getWorkList(), Call, D, Bldr, Pred, State);

528}

529

533 assert(D);

534

536 const StackFrameContext *CallerSFC = CurLC->getStackFrame();

537 const LocationContext *ParentOfCallee = CallerSFC;

541 assert(BR && "If we have the block definition we should have its region");

542 AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(D);

545 BR);

546 }

547

548

549 const Expr *CallE = Call.getOriginExpr();

550

551

552 AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D);

553 const StackFrameContext *CalleeSFC =

554 CalleeADC->getStackFrame(ParentOfCallee, CallE, currBldrCtx->getBlock(),

555 currBldrCtx->blockCount(), currStmtIdx);

556

557 CallEnter Loc(CallE, CalleeSFC, CurLC);

558

559

560

561 State = State->enterStackFrame(Call, CalleeSFC);

562

563 bool isNew;

564 if (ExplodedNode *N = G.getNode(Loc, State, false, &isNew)) {

565 N->addPredecessor(Pred, G);

566 if (isNew)

568 }

569

570

571

573

574 NumInlinedCalls++;

575 Engine.FunctionSummaries->bumpNumTimesInlined(D);

576

577

578

579

580

581

582

583

584 if (!isSecondPhaseCTU())

585

586 if (VisitedCallees)

587 VisitedCallees->insert(D);

588}

589

591 const Stmt *CallE) {

593 if (!ReplayState)

594 return nullptr;

595

596 assert(ReplayState == CallE && "Backtracked to the wrong call.");

597 (void)CallE;

598

600}

601

604

607

608

609

613

614

615

618 evalCall(dstCallEvaluated, N, *CallTemplate);

619 }

620

621

622

623

624

626 *this);

627}

628

631

632

633 const Expr *E = Call.getOriginExpr();

634

635

637 return State;

638

640 for (unsigned CallI = 0, CallN = Call.getNumArgs(); CallI != CallN; ++CallI) {

641 unsigned I = Call.getASTArgumentIndex(CallI);

644 (void)VV;

646 ->getStackFrame()->getParent()

648 State = finishObjectConstruction(State, {E, I}, LC);

649 }

650 }

651

652 return State;

653}

654

655void ExprEngine::finishArgumentConstruction(ExplodedNodeSet &Dst,

658

659

662 if (CleanedState == State) {

664 return;

665 }

666

667 const Expr *E = Call.getOriginExpr();

668 const LocationContext *LC = Call.getLocationContext();

669 NodeBuilder B(Pred, Dst, *currBldrCtx);

670 static SimpleProgramPointTag Tag("ExprEngine",

671 "Finish argument construction");

672 PreStmt PP(E, LC, &Tag);

673 B.generateNode(PP, CleanedState, Pred);

674}

675

678

679

680

681

682

683

686 *this);

687

688

689

690

693 dstCallEvaluated, dstPreVisit, CallTemplate, *this, EvalCallOptions());

694

695

696

699 finishArgumentConstruction(dstArgumentCleanup, I, CallTemplate);

700

703 CallTemplate, *this);

704

705

706

707

708

709

710

716 Escaped.clear();

717 {

718 unsigned Arg = -1;

720 ++Arg;

721 QualType ParamTy = PVD->getType();

722 if (ParamTy.isNull() ||

724 continue;

727 continue;

728 if (const MemRegion *MR = Call->getArgSVal(Arg).getAsRegion())

729 Escaped.emplace_back(loc::MemRegionVal(MR), State->getSVal(MR, Pointee));

730 }

731 }

732

735

736 if (State == I->getState())

738 else

740 }

741}

742

746 const Expr *E = Call.getOriginExpr();

748 if (!E)

749 return State;

750

751

753 switch (Msg->getMethodFamily()) {

754 default:

755 break;

759

760 return State->BindExpr(E, LCtx, Msg->getReceiverSVal());

761 }

762 }

764 SVal ThisV = C->getCXXThisVal();

765 ThisV = State->getSVal(ThisV.castAs<Loc>());

766 return State->BindExpr(E, LCtx, ThisV);

767 }

768

771 unsigned Count = currBldrCtx->blockCount();

773

775 assert(RTC->getStmt() == Call.getOriginExpr());

776 EvalCallOptions CallOpts;

778 Call.getOriginExpr(), State, currBldrCtx, LCtx,

779 RTC->getConstructionContext(), CallOpts);

781 assert(TargetR);

782

783

784

785

786

790 State = State->invalidateRegions(TargetR, Elem, Count, LCtx,

791 false, nullptr,

792 &Call, &ITraits);

793

795 } else {

796

797

798

799

800 const auto *CNE = dyn_cast(E);

801 if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {

802 R = svalBuilder.getConjuredHeapSymbolVal(Elem, LCtx, E->getType(), Count);

804

805

806 SVal ElementCount;

807 if (const Expr *SizeExpr = CNE->getArraySize().value_or(nullptr)) {

808 ElementCount = State->getSVal(SizeExpr, LCtx);

809 } else {

810 ElementCount = svalBuilder.makeIntVal(1, true);

811 }

812

814

816 svalBuilder.evalBinOp(State, BO_Mul, ElementCount, ElementSize,

817 svalBuilder.getArrayIndexType());

818

819

820

821 if (Size.isUndef())

823

825 } else {

826 R = svalBuilder.conjureSymbolVal(Elem, LCtx, ResultTy, Count);

827 }

828 }

829 return State->BindExpr(E, LCtx, R);

830}

831

832

833

836 State = Call.invalidateRegions(currBldrCtx->blockCount(), State);

838

839

841 Bldr.generateNode(Call.getProgramPoint(false, &PT), State, Pred);

842}

843

844ExprEngine::CallInlinePolicy

850 switch (Call.getKind()) {

854 break;

858 return CIP_DisallowedAlways;

859 break;

862 return CIP_DisallowedAlways;

863

865

867

870 : nullptr;

871

872 if (llvm::isa_and_nonnull(CC) &&

873 !Opts.MayInlineCXXAllocator)

874 return CIP_DisallowedOnce;

875

877 if (!shouldInlineArrayConstruction(Pred->getState(), CtorExpr, CurLC))

878 return CIP_DisallowedOnce;

879 }

880

881

884 (void)ADC;

885

886

888 break;

889

890

891

893 return CIP_DisallowedAlways;

894

896

897

899 !Opts.ShouldIncludeTemporaryDtorsInCFG)

900 return CIP_DisallowedOnce;

901

902

903

904

906 return CIP_DisallowedOnce;

907

908

909

911 return CIP_DisallowedOnce;

912 }

913

914 break;

915 }

917

918

919 return CIP_Allowed;

920 }

923 return CIP_DisallowedAlways;

924

925

928 (void)ADC;

929

933 return CIP_DisallowedOnce;

934 }

935 }

936

937

939 !Opts.MayInlineCXXTemporaryDtors)

940 return CIP_DisallowedOnce;

941

942

943

944

946 return CIP_DisallowedOnce;

947 break;

948 }

950 [[fallthrough]];

952 if (Opts.MayInlineCXXAllocator)

953 break;

954

955

956 return CIP_DisallowedAlways;

958 if (!Opts.MayInlineObjCMethod)

959 return CIP_DisallowedAlways;

962 return CIP_DisallowedAlways;

963 break;

964 }

965

966 return CIP_Allowed;

967}

968

969

971 StringRef Name) {

974}

975

976

977

978

979

985

986

987

988

989

990

993 if (const CXXMethodDecl *MD = dyn_cast(FD))

995 return false;

996}

997

998

999

1001 const CXXDestructorDecl *Dtor = dyn_cast(FD);

1002 if (!Dtor)

1003 return false;

1004

1007 if (II->isStr("shared_ptr"))

1008 return true;

1009

1010 return false;

1011}

1012

1013

1014

1015

1016

1017

1018bool ExprEngine::mayInlineDecl(AnalysisDeclContext *CalleeADC) const {

1019 AnalyzerOptions &Opts = AMgr.getAnalyzerOptions();

1020

1022 return false;

1023

1024

1027 if (const FunctionDecl *FD = dyn_cast(CalleeADC->getDecl())) {

1028

1029 if (!Opts.MayInlineTemplateFunctions)

1031 return false;

1032

1033

1034 if (!Opts.MayInlineCXXStandardLibrary)

1037 return false;

1038

1039

1040

1041 if (!Opts.MayInlineCXXContainerMethods)

1042 if (!AMgr.isInCodeFile(FD->getLocation()))

1044 return false;

1045

1046

1047

1048

1049

1050 if (!Opts.MayInlineCXXSharedPtrDtor)

1052 return false;

1053 }

1054 }

1055

1056

1057

1058 const CFG *CalleeCFG = CalleeADC->getCFG();

1059 if (!CalleeCFG)

1060 return false;

1061

1062

1063 if (isHuge(CalleeADC))

1064 return false;

1065

1066

1067

1068 if (!CalleeADC->getAnalysis())

1069 return false;

1070

1071 return true;

1072}

1073

1074bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,

1077 if (!D)

1078 return false;

1079

1081 AnalyzerOptions &Opts = AMgr.options;

1082 AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();

1083 AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);

1084

1085

1086

1087

1089 return true;

1090

1091 if (!AMgr.shouldInlineCall())

1092 return false;

1093

1094

1095 std::optional MayInline = Engine.FunctionSummaries->mayInline(D);

1096 if (MayInline) {

1097 if (!*MayInline)

1098 return false;

1099

1100 } else {

1101

1102

1103 if (mayInlineDecl(CalleeADC)) {

1104 Engine.FunctionSummaries->markMayInline(D);

1105 } else {

1106 Engine.FunctionSummaries->markShouldNotInline(D);

1107 return false;

1108 }

1109 }

1110

1111

1112

1113

1114

1115 CallInlinePolicy CIP = mayInlineCallKind(Call, Pred, Opts, CallOpts);

1116 if (CIP != CIP_Allowed) {

1117 if (CIP == CIP_DisallowedAlways) {

1118 assert(!MayInline || *MayInline);

1119 Engine.FunctionSummaries->markShouldNotInline(D);

1120 }

1121 return false;

1122 }

1123

1124

1125 bool IsRecursive = false;

1126 unsigned StackDepth = 0;

1127 examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);

1129 (!isSmall(CalleeADC) || IsRecursive))

1130 return false;

1131

1132

1133 if ((Engine.FunctionSummaries->getNumTimesInlined(D) >

1134 Opts.MaxTimesInlineLarge) &&

1135 isLarge(CalleeADC)) {

1136 NumReachedInlineCountMax++;

1137 return false;

1138 }

1139

1140 if (HowToInline == Inline_Minimal && (!isSmall(CalleeADC) || IsRecursive))

1141 return false;

1142

1143 return true;

1144}

1145

1146bool ExprEngine::shouldInlineArrayConstruction(const ProgramStateRef State,

1147 const CXXConstructExpr *CE,

1148 const LocationContext *LCtx) {

1149 if (!CE)

1150 return false;

1151

1152

1153 if (const auto *CAT = dyn_cast(CE->getType())) {

1155

1156

1157

1158

1159

1160

1161

1162

1163

1164 return shouldInlineArrayDestruction(ArrSize);

1165 }

1166

1167

1169 return shouldInlineArrayDestruction(*Size);

1170

1171 return false;

1172}

1173

1174bool ExprEngine::shouldInlineArrayDestruction(uint64_t Size) {

1175

1176 uint64_t maxAllowedSize = AMgr.options.maxBlockVisitOnPath;

1177

1178

1179 return Size <= maxAllowedSize && Size > 0;

1180}

1181

1182bool ExprEngine::shouldRepeatCtorCall(ProgramStateRef State,

1183 const CXXConstructExpr *E,

1184 const LocationContext *LCtx) {

1185

1186 if (!E)

1187 return false;

1188

1190

1191

1192 if (const auto *CAT = dyn_cast(Ty)) {

1195 }

1196

1199

1200 return false;

1201}

1202

1205 if (!ICall)

1206 return false;

1207

1208 const CXXMethodDecl *MD = dyn_cast_or_null(ICall->getDecl());

1209 if (!MD)

1210 return false;

1212 return false;

1213

1215}

1216

1220

1222

1223

1225 performTrivialCopy(Bldr, Pred, Call);

1226 return;

1227 }

1228

1229

1230

1231

1232 const Expr *E = Call.getOriginExpr();

1233

1235 if (InlinedFailedState) {

1236

1237 State = InlinedFailedState;

1238 } else {

1242 if (shouldInlineCall(Call, D, Pred, CallOpts)) {

1245

1246

1249 return;

1250 }

1251

1252

1254 conservativeEvalCall(Call, Bldr, Pred, State);

1255 return;

1256 }

1257 }

1258 ctuBifurcate(Call, D, Bldr, Pred, State);

1259 return;

1260 }

1261 }

1262

1263

1264

1265 State = removeStateTraitsUsedForArrayEvaluation(

1266 State, dyn_cast_or_null(E), Call.getLocationContext());

1267

1268

1269 conservativeEvalCall(Call, Bldr, Pred, State);

1270}

1271

1272void ExprEngine::BifurcateCall(const MemRegion *BifurReg,

1275 assert(BifurReg);

1277

1278

1279

1281 const unsigned *BState =

1282 State->get(BifurReg);

1283 if (BState) {

1284

1285 if (*BState == DynamicDispatchModeInlined)

1286 ctuBifurcate(Call, D, Bldr, Pred, State);

1287

1288

1289

1290 conservativeEvalCall(Call, Bldr, Pred, State);

1291 return;

1292 }

1293

1294

1295

1297 State->set(BifurReg,

1298 DynamicDispatchModeInlined);

1299 ctuBifurcate(Call, D, Bldr, Pred, IState);

1300

1302 State->set(BifurReg,

1303 DynamicDispatchModeConservative);

1304 conservativeEvalCall(Call, Bldr, Pred, NoIState);

1305

1306 NumOfDynamicDispatchPathSplits++;

1307}

1308

1313

1315

1318 ei = dstPreVisit.end(); it != ei; ++it) {

1320 }

1321 }

1322}

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

#define STAT_COUNTER(VARNAME, DESC)

static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD)

Returns true if the given C++ class is a container or iterator.

Definition ExprEngineCallAndReturn.cpp:980

static ProgramStateRef getInlineFailedState(ProgramStateRef State, const Stmt *CallE)

Definition ExprEngineCallAndReturn.cpp:590

static std::pair< const Stmt *, const CFGBlock * > getLastStmt(const ExplodedNode *Node)

Definition ExprEngineCallAndReturn.cpp:74

static bool isTrivialObjectAssignment(const CallEvent &Call)

Definition ExprEngineCallAndReturn.cpp:1203

static bool isCXXSharedPtrDtor(const FunctionDecl *FD)

Returns true if the given function is the destructor of a class named "shared_ptr".

Definition ExprEngineCallAndReturn.cpp:1000

static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD, StringRef Name)

Returns true if the given C++ class contains a member with the given name.

Definition ExprEngineCallAndReturn.cpp:970

static bool wasDifferentDeclUsedForInlining(CallEventRef<> Call, const StackFrameContext *calleeCtx)

Definition ExprEngineCallAndReturn.cpp:185

static SVal adjustReturnValue(SVal V, QualType ExpectedTy, QualType ActualTy, StoreManager &StoreMgr)

Adjusts a return value when the called function's return type does not match the caller's expression ...

Definition ExprEngineCallAndReturn.cpp:126

static bool isContainerMethod(const ASTContext &Ctx, const FunctionDecl *FD)

Returns true if the given function refers to a method of a C++ container or iterator.

Definition ExprEngineCallAndReturn.cpp:991

static unsigned getElementCountOfArrayBeingDestructed(const CallEvent &Call, const ProgramStateRef State, SValBuilder &SVB)

Definition ExprEngineCallAndReturn.cpp:197

#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)

Declares an immutable map of type NameTy, suitable for placement into the ProgramState.

#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)

Declares a program state trait for type Type called Name, and introduce a type named NameTy.

a trap message and trap category.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

SourceManager & getSourceManager()

DeclarationNameTable DeclarationNames

const LangOptions & getLangOpts() const

uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const

Return number of constant array elements.

AnalysisDeclContext * getContext(const Decl *D)

AnalysisDeclContext contains the context data for the function, method or block under analysis.

const BlockInvocationContext * getBlockInvocationContext(const LocationContext *ParentLC, const BlockDecl *BD, const void *Data)

Obtain a context of the block invocation using its parent context.

const Decl * getDecl() const

static bool isInStdNamespace(const Decl *D)

const StackFrameContext * getStackFrame(LocationContext const *ParentLC, const Stmt *S, const CFGBlock *Blk, unsigned BlockCount, unsigned Index)

Obtain a context of the call stack using its parent context.

ASTContext & getASTContext() const

bool isBodyAutosynthesized() const

CFG::BuildOptions & getCFGBuildOptions()

Stores options for the analyzer from the command line.

bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const

Returns the option controlling which C++ member functions will be considered for inlining.

IPAKind getIPAMode() const

Returns the inter-procedural analysis mode.

CTUPhase1InliningKind getCTUPhase1Inlining() const

unsigned InlineMaxStackDepth

The inlining stack depth limit.

Represents a single basic block in a source-level CFG.

succ_iterator succ_begin()

unsigned succ_size() const

Represents C++ constructor call.

std::optional< T > getAs() const

Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...

Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.

unsigned size() const

Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...

bool isLinear() const

Returns true if the CFG has no branches.

unsigned getNumBlockIDs() const

Returns the total number of BlockIDs allocated (which start at 0).

BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...

bool isAmbiguous(CanQualType BaseType) const

Determine whether the path from the most-derived type to the given base type is ambiguous (i....

Represents a call to a C++ constructor.

CXXConstructionKind getConstructionKind() const

Determine whether this constructor is actually constructing a base class (rather than a complete obje...

Represents a C++ destructor within a class.

Represents a static or instance method of a struct/union/class.

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

bool isMoveAssignmentOperator() const

Determine whether this is a move assignment operator.

bool isCopyAssignmentOperator() const

Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...

Represents a C++ struct/union/class.

bool hasTrivialDestructor() const

Determine whether this class has a trivial destructor (C++ [class.dtor]p3)

bool hasMemberName(DeclarationName N) const

Determine whether this class has a member with the given name, possibly in a non-dependent base class...

bool isDerivedFrom(const CXXRecordDecl *Base) const

Determine whether this class is derived from the class Base.

Represents a point when we begin processing an inlined call.

const CFGBlock * getEntry() const

Returns the entry block in the CFG for the entered function.

const StackFrameContext * getCalleeContext() const

Represents a point when we finish the call exit sequence (for inlined call).

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

ConstructionContext's subclasses describe different ways of constructing an object in C++.

Decl - This represents one declaration (or definition), e.g.

virtual Decl * getCanonicalDecl()

Retrieves the "canonical" declaration of the given declaration.

IdentifierInfo * getAsIdentifierInfo() const

Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...

This is a meta program point, which should be skipped by all the diagnostic reasoning etc.

This represents one expression.

Represents a function declaration or definition.

bool isTrivial() const

Whether this function is "trivial" in some specialized C++ senses.

One of these records is kept for each identifier that is lexed.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...

const Decl * getDecl() const

LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const

const LocationContext * getParent() const

It might return null.

const StackFrameContext * getStackFrame() const

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

Represents a parameter to a function.

@ PostStmtPurgeDeadSymbolsKind

const StackFrameContext * getStackFrame() const

std::optional< T > getAs() const

Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType getCanonicalType() const

bool isConstQualified() const

Determine whether this type is const-qualified.

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

bool isInSystemHeader(SourceLocation Loc) const

Returns if a SourceLocation is in a system header.

It represents a stack frame of the call stack (based on CallEvent).

unsigned getIndex() const

const Stmt * getCallSite() const

const CFGBlock * getCallSiteBlock() const

Stmt - This represents one statement.

bool isPointerType() const

CanQualType getCanonicalTypeUnqualified() const

bool isReferenceType() const

const CXXRecordDecl * getPointeeCXXRecordDecl() const

If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isObjCObjectPointerType() const

AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)

AnalyzerOptions & options

Represents a call to a C++ constructor.

const CXXConstructorDecl * getDecl() const override

Returns the declaration of the function or method that will be called.

const CXXConstructExpr * getOriginExpr() const override

Returns the expression whose value will be the result of this call.

Represents a non-static C++ member function call, no matter how it is written.

const FunctionDecl * getDecl() const override

Returns the declaration of the function or method that will be called.

Manages the lifetime of CallEvent objects.

CallEventRef getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)

CallEventRef getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State)

Gets an outside caller given a callee context.

Represents an abstract call to a function or method along a particular path.

CallEventRef< T > cloneWithState(ProgramStateRef NewState) const

Returns a copy of this CallEvent, but using the given state.

static QualType getDeclaredResultType(const Decl *D)

Returns the result type of a function or method declaration.

static bool isVariadic(const Decl *D)

Returns true if the given decl is known to be variadic.

void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng)

Run checkers for pre-visiting obj-c messages.

void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng, const EvalCallOptions &CallOpts)

Run checkers for evaluating a call.

void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined=false)

Run checkers for post-visiting obj-c messages.

void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)

Run checkers for post-visiting Stmts.

void runCheckersForNewAllocator(const CXXAllocatorCall &Call, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, bool wasInlined=false)

Run checkers between C++ operator new and constructor calls.

void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)

Run checkers for pre-visiting Stmts.

void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined=false)

Run checkers for post-visiting obj-c messages.

WorkList * getCTUWorkList() const

WorkList * getWorkList() const

ImplTy::iterator iterator

void insert(const ExplodedNodeSet &S)

void Add(ExplodedNode *N)

const ProgramStateRef & getState() const

pred_iterator pred_begin()

ProgramPoint getLocation() const

getLocation - Returns the edge associated with the given node.

void addPredecessor(ExplodedNode *V, ExplodedGraph &G)

addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...

const StackFrameContext * getStackFrame() const

const LocationContext * getLocationContext() const

std::optional< T > getLocationAs() const &

ExplodedNode * getFirstPred()

ProgramStateManager & getStateManager()

void processCallEnter(NodeBuilderContext &BC, CallEnter CE, ExplodedNode *Pred)

Generate the entry node of the callee.

Definition ExprEngineCallAndReturn.cpp:42

void processBeginOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)

Called by CoreEngine.

void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)

Run the analyzer's garbage collection - remove dead symbols and bindings from the state.

std::pair< ProgramStateRef, SVal > handleConstructionContext(const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx, const LocationContext *LCtx, const ConstructionContext *CC, EvalCallOptions &CallOpts, unsigned Idx=0)

A convenient wrapper around computeObjectUnderConstruction and updateObjectsUnderConstruction.

void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitReturnStmt - Transfer function logic for return statements.

Definition ExprEngineCallAndReturn.cpp:1309

const CoreEngine & getCoreEngine() const

void processCallExit(ExplodedNode *Pred)

Generate the sequence of nodes that simulate the call exit and the post visit for CallExpr.

Definition ExprEngineCallAndReturn.cpp:250

static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const LocationContext *LC)

By looking at a certain item that may be potentially part of an object's ConstructionContext,...

CFGElement getCurrentCFGElement()

Return the CFG element corresponding to the worklist element that is currently being processed by Exp...

@ Inline_Minimal

Do minimal inlining of callees.

ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, ArrayRef< std::pair< SVal, SVal > > LocAndVals, const LocationContext *LCtx, PointerEscapeKind Kind, const CallEvent *Call)

Call PointerEscape callback when a value escapes as a result of bind.

static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)

Retreives which element is being constructed in a non-POD type array.

void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitCall - Transfer function for function calls.

Definition ExprEngineCallAndReturn.cpp:602

ASTContext & getContext() const

getContext - Return the ASTContext associated with this analysis.

StoreManager & getStoreManager()

void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call)

Evaluate a call, running pre- and post-call checkers and allowing checkers to be responsible for hand...

Definition ExprEngineCallAndReturn.cpp:676

ConstCFGElementRef getCFGElementRef() const

static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const LocationContext *LCtx)

Retreives which element is being destructed in a non-POD type array.

CheckerManager & getCheckerManager() const

ProgramStateRef bindReturnValue(const CallEvent &Call, const LocationContext *LCtx, ProgramStateRef State)

Create a new state in which the call return value is binded to the call origin expression.

Definition ExprEngineCallAndReturn.cpp:743

void removeDeadOnEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Remove dead bindings/symbols before exiting a function.

Definition ExprEngineCallAndReturn.cpp:161

void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call, const EvalCallOptions &CallOpts={})

Default implementation of call evaluation.

Definition ExprEngineCallAndReturn.cpp:1217

AnalysisManager & getAnalysisManager()

static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)

Retreives the size of the array in the pending ArrayInitLoopExpr.

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const

unsigned blockCount() const

Returns the number of times the current basic block has been visited on the exploded graph path.

This is the simplest builder which generates nodes in the ExplodedGraph.

ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)

Generates a node in the ExplodedGraph.

void takeNodes(const ExplodedNodeSet &S)

Represents any expression that calls an Objective-C method.

CallEventManager & getCallEventManager()

Information about invalidation for a particular region/symbol.

@ TK_DoNotInvalidateSuperRegion

void setTrait(SymbolRef Sym, InvalidationKinds IK)

Defines the runtime definition of the called function.

const MemRegion * getDispatchRegion()

When other definitions are possible, returns the region whose runtime type determines the method defi...

bool mayHaveOtherDefinitions()

Check if the definition we have is precise.

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

QualType getType(const ASTContext &) const

Try to get a reasonable type for the given value.

const MemRegion * getAsRegion() const

T castAs() const

Convert to the specified SVal type, asserting that this SVal is of the desired type.

This builder class is useful for generating nodes that resulted from visiting a statement.

ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)

SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)

Evaluates a chain of derived-to-base casts through the path specified in Cast.

virtual void enqueue(const WorkListUnit &U)=0

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const

Get the underlining region.

@ PSK_EscapeOutParameters

Escape for a new symbol that was generated into a region that the analyzer cannot follow during a con...

DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)

IntrusiveRefCntPtr< const ProgramState > ProgramStateRef

ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, DefinedOrUnknownSVal Extent)

Set the dynamic extent Extent of the region MR.

@ CE_CXXInheritedConstructor

DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB)

std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl

All declarations that can appear in a module declaration.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

CFGBlock::ConstCFGElementRef ConstCFGElementRef

@ IPAK_DynamicDispatch

Enable inlining of dynamically dispatched methods.

@ IPAK_DynamicDispatchBifurcate

Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailabl...

@ CIMK_Destructors

Refers to destructors (implicit or explicit).

@ CIMK_MemberFunctions

Refers to regular member function and operator calls.

@ CIMK_Constructors

Refers to constructors (implicit or explicit).

U cast(CodeGen::Address addr)

Hints for figuring out of a call should be inlined during evalCall().

bool IsTemporaryLifetimeExtendedViaAggregate

This call is a constructor for a temporary that is lifetime-extended by binding it to a reference-typ...

bool IsTemporaryCtorOrDtor

This call is a constructor or a destructor of a temporary value.

bool IsArrayCtorOrDtor

This call is a constructor or a destructor for a single element within an array, a part of array cons...

bool IsCtorOrDtorWithImproperlyModeledTargetRegion

This call is a constructor or a destructor for which we do not currently compute the this-region corr...

Traits for storing the call processing policy inside GDM.