clang: lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

16#include

17

18using namespace clang;

19using namespace ento;

21

23

25namespace ento {

27

29 return State->get(Sym);

30}

31

32}

33}

34}

35

38 assert(Sym != nullptr);

39 return State->set(Sym, Val);

40}

41

43 return State->remove(Sym);

44}

45

47 if (!T.isNull())

48 Out << "Tracked " << T << " | ";

49

51 default: llvm_unreachable("Invalid RefVal kind");

53 Out << "Owned";

55 if (cnt) Out << " (+ " << cnt << ")";

56 break;

57 }

58

60 Out << "NotOwned";

62 if (cnt) Out << " (+ " << cnt << ")";

63 break;

64 }

65

67 Out << "ReturnedOwned";

69 if (cnt) Out << " (+ " << cnt << ")";

70 break;

71 }

72

74 Out << "ReturnedNotOwned";

76 if (cnt) Out << " (+ " << cnt << ")";

77 break;

78 }

79

81 Out << "Released";

82 break;

83

85 Out << "-dealloc (not-owned)";

86 break;

87

89 Out << "Leaked";

90 break;

91

93 Out << "Leaked (Bad naming)";

94 break;

95

97 Out << "Use-After-Release [ERROR]";

98 break;

99

101 Out << "Release of Not-Owned [ERROR]";

102 break;

103

105 Out << "Over-autoreleased";

106 break;

107

109 Out << "Non-owned object returned instead of owned";

110 break;

111 }

112

115 break;

117 Out << " [direct ivar access]";

118 break;

120 Out << " [released after direct ivar access]";

121 }

122

123 if (ACnt) {

124 Out << " [autorelease -" << ACnt << ']';

125 }

126}

127

128namespace {

129class StopTrackingCallback final : public SymbolVisitor {

131public:

134

135 bool VisitSymbol(SymbolRef sym) override {

137 return true;

138 }

139};

140}

141

142

143

144

145

148

149

150

152 return;

153

156

157 auto ReferencedVars = R->referenced_vars();

158 if (ReferencedVars.empty())

159 return;

160

161

162

163

166 MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();

167

168 for (auto Var : ReferencedVars) {

169 const VarRegion *VR = Var.getCapturedRegion();

172 }

173 Regions.push_back(VR);

174 }

175

176 state = state->scanReachableSymbols(Regions).getState();

177 C.addTransition(state);

178}

179

183 if (!BE)

184 return;

185

190 } else {

192 }

193

195

198

199 return;

202 break;

205 break;

206 }

207

209 SymbolRef Sym = C.getSVal(CE).getAsLocSymbol();

210 if (!Sym)

211 return;

213 if (T)

214 return;

215

218

219 if (hasErr) {

220

221 return;

222 }

223

224 C.addTransition(state);

225}

226

228 const Expr *Ex) const {

238 if (hasErr) {

240 return;

241 }

242 }

243 }

244

245

246

252 }

253

254 C.addTransition(state);

255}

256

262

268

273

278 }

279

280 C.addTransition(State);

281}

282

285 std::optional IVarLoc = C.getSVal(IRE).getAs<Loc>();

286 if (!IVarLoc)

287 return;

288

290 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();

291 if (!Sym || !isa_and_nonnull(Sym->getOriginRegion()))

292 return;

293

294

295

296

303 else

304 return;

305

306

309 return;

310

312

313

316 return;

317 }

318

319

320 C.addTransition(setRefBinding(State, Sym, RV->withIvarAccess()));

321 return;

322 }

323

325

326

328 C.addTransition(setRefBinding(State, Sym, PlusZero));

329 return;

330 }

331

333 C.addTransition(State);

334}

335

337 if (const auto *MC = dyn_cast(&Call)) {

338

339

340

341 return MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper() &&

342 Call.getLocationContext()

343 ->getAnalysisDeclContext()

344 ->getParentMap()

345 .isConsumedExpr(Call.getOriginExpr());

346 }

347 return false;

348}

349

360

364

365

367 if (const auto *MC = dyn_cast(&Call)) {

368 if (MC->isInstanceMessage()) {

369 SVal ReceiverV = MC->getReceiverSVal();

372 ReceiverType = T->getType();

373 }

374 }

375

377

378 if (C.wasInlined) {

380 return;

381 }

383}

384

385

386

387

388

389

390

391

394

395

396

397 if (const ObjCMessageExpr *ME = dyn_cast(RetE))

399 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||

400 PT->isObjCClassType()) {

401

402

403

404

406 return !D ? RetTy :

408 }

409

410 return RetTy;

411}

412

419 }

420

421 return std::nullopt;

422}

423

428 return true;

429 return false;

430}

431

432

433

435 const RefVal *TrackedValue) {

437 return false;

438 if (ArgIdx >= CE.parameters().size())

439 return false;

441}

442

443

444

445

450

451

452 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {

454

455 if (SymbolRef Sym = V.getAsLocSymbol()) {

459 ShouldRemoveBinding = true;

460

461 if (ShouldRemoveBinding)

463 }

464 }

465

466

467 if (const auto *MsgInvocation = dyn_cast(&CallOrMsg)) {

468 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {

471 }

472 }

473 }

474

475

477

481 }

482

483 C.addTransition(state);

484}

485

487 const auto *TR = dyn_cast(

490}

491

492

493

494

495

496

497

498

499

500

501

502

505 return false;

506

507 const auto *VR = dyn_cast(R);

508

510 return true;

511

512 const VarDecl *VD = VR->getDecl();

513 if (!VD->hasAttr())

514 return false;

515 return true;

516}

517

518static SmallVector<ProgramStateRef, 2>

521

523

524

525

526

527

528 bool SplitNecessary = false;

532 SplitNecessary = true;

533

536

537 if (SplitNecessary) {

539

540

541 return {State};

542 }

544 AssumeNonZeroReturn = AssumeNonZeroReturn->assume(*DL, true);

545 AssumeZeroReturn = AssumeZeroReturn->assume(*DL, false);

546 }

547 }

548

549 for (unsigned idx = 0, e = CE.getNumArgs(); idx != e; ++idx) {

552

553 auto *ArgRegion = dyn_cast_or_null(ArgVal.getAsRegion());

554 if (!ArgRegion)

555 continue;

556

557 QualType PointeeTy = ArgRegion->getValueType();

558 SVal PointeeVal = State->getSVal(ArgRegion);

560 if (!Pointee)

561 continue;

562

564 continue;

565

569 };

573 };

574

577 AssumeNonZeroReturn = makeNotOwnedParameter(AssumeNonZeroReturn);

578 AssumeZeroReturn = makeNotOwnedParameter(AssumeZeroReturn);

579 break;

581 AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);

582 AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);

583 break;

585 AssumeNonZeroReturn = makeOwnedParameter(AssumeNonZeroReturn);

586 break;

588 AssumeZeroReturn = makeOwnedParameter(AssumeZeroReturn);

589 break;

590 default:

591 break;

592 }

593 }

594

595 if (SplitNecessary) {

596 return {AssumeNonZeroReturn, AssumeZeroReturn};

597 } else {

598 assert(AssumeZeroReturn == AssumeNonZeroReturn);

599 return {AssumeZeroReturn};

600 }

601}

602

607

608

612

613

614

615 bool DeallocSent = false;

616

617 for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {

619

621 if (SymbolRef Sym = V.getAsLocSymbol()) {

623

626

627 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);

628 if (hasErr) {

630 ErrorSym = Sym;

631 break;

633 DeallocSent = true;

634 }

635 }

636 }

637 }

638

639

640 bool ReceiverIsTracked = false;

641 if (!hasErr) {

642 if (const auto *MsgInvocation = dyn_cast(&CallOrMsg)) {

643 if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {

645 ReceiverIsTracked = true;

648 if (hasErr) {

649 ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();

650 ErrorSym = Sym;

652 DeallocSent = true;

653 }

654 }

655 }

656 } else if (const auto *MCall = dyn_cast(&CallOrMsg)) {

657 if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {

660 hasErr, C);

661 if (hasErr) {

662 ErrorRange = MCall->getOriginExpr()->getSourceRange();

663 ErrorSym = Sym;

664 }

665 }

666 }

667 }

668 }

669

670

671 if (hasErr) {

673 return;

674 }

675

676

678

680 if (ReceiverIsTracked)

682 else

684 }

685

690 assert(Ex);

692 }

693 if (std::optional updatedRefVal = refValFromRetEffect(RE, ResultTy))

694 state = setRefBinding(state, Sym, *updatedRefVal);

695 }

696

699

701 if (DeallocSent) {

703 } else {

704 C.addTransition(St);

705 }

706 }

707}

708

714 bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;

717 default:

718 break;

721 break;

724 break;

727 break;

728 }

729 }

730

731

734 hasErr = V.getKind();

736 }

737

743 llvm_unreachable("Applies to pointer-to-pointer parameters, which should "

744 "not have ref state.");

745

746 case Dealloc:

747 switch (V.getKind()) {

748 default:

749 llvm_unreachable("Invalid RefVal state for an explicit dealloc.");

751

753 V.clearCounts();

757 hasErr = V.getKind();

758 break;

759 }

760 break;

761

765 break;

766 }

767

768 [[fallthrough]];

769

771 return state;

772

774

775 V = V.autorelease();

776 break;

777

781

783 switch (V.getKind()) {

784 default:

785 llvm_unreachable("Invalid RefVal state for a retain.");

788 V = V + 1;

789 break;

790 }

791 break;

792

796 switch (V.getKind()) {

797 default:

798

799 llvm_unreachable("Invalid RefVal state for a release.");

800

802 assert(V.getCount() > 0);

803 if (V.getCount() == 1) {

805 V.getIvarAccessHistory() ==

808 else

812 }

813

814 V = V - 1;

815 break;

816

818 if (V.getCount() > 0) {

821 V = V - 1;

822 } else if (V.getIvarAccessHistory() ==

824

825

829 } else {

831 hasErr = V.getKind();

832 }

833 break;

834 }

835 break;

836 }

838}

839

844

845 switch (ErrorKind) {

854 default:

855 llvm_unreachable("Unhandled error.");

856 }

857}

858

863

869

870

871

872

873

874

877 return;

878

880 if (!N)

881 return;

882

883 auto report = std::make_unique(

886 report->addRange(ErrorRange);

887 C.emitReport(std::move(report));

888}

889

890

891

892

893

897 const auto *FD = dyn_cast_or_null(Call.getDecl());

898 if (!FD)

899 return false;

900

901 const auto *CE = dyn_cast_or_null(Call.getOriginExpr());

902 if (!CE)

903 return false;

904

907

908

909

910 bool hasTrustedImplementationAnnotation = false;

911

913

915 std::optional BSmr =

916 SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation);

917

918

919 if (!BSmr)

920 return false;

921

922

923 if (BSmr == BehaviorSummary::Identity ||

924 BSmr == BehaviorSummary::IdentityOrZero ||

925 BSmr == BehaviorSummary::IdentityThis) {

926

927 const Expr *BindReturnTo =

928 (BSmr == BehaviorSummary::IdentityThis)

930 : CE->getArg(0);

931 SVal RetVal = state->getSVal(BindReturnTo, LCtx);

932

933

934

935

936

938 (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {

941 }

942

943

944 state = state->BindExpr(CE, LCtx, RetVal, false);

945

946 if (BSmr == BehaviorSummary::IdentityOrZero) {

947

949

950

951 NullOutputState = NullOutputState->BindExpr(

952 CE, LCtx, C.getSValBuilder().makeNullWithType(ResultTy),

953 false);

955

956

957

959 state = state->assume(*L, true);

960

961 }

962 }

963

964 C.addTransition(state);

965 return true;

966}

967

971

972

973

974

975

976

977 if (C.inTopFrame())

978 return Pred;

979

980 if (!S)

981 return Pred;

982

984 if (!RetE)

985 return Pred;

986

988

989

990 SymbolRef Sym = state->getSValAsScalarOrLoc(RetE, C.getLocationContext())

991 .getAsLocSymbol(true);

992 if (!Sym)

993 return Pred;

994

995

997 if (T)

998 return Pred;

999

1000

1002

1003 switch (X.getKind()) {

1005 unsigned cnt = X.getCount();

1006 assert(cnt > 0);

1007 X.setCount(cnt - 1);

1009 break;

1010 }

1011

1013 unsigned cnt = X.getCount();

1014 if (cnt) {

1015 X.setCount(cnt - 1);

1017 } else {

1019 }

1020 break;

1021 }

1022

1023 default:

1024 return Pred;

1025 }

1026

1027

1029 Pred = C.addTransition(state);

1030

1031

1032

1033

1034

1035

1036 if (!Pred)

1037 return nullptr;

1038

1039

1041

1042

1043 if (!state)

1044 return nullptr;

1045

1046

1048 assert(T);

1049 X = *T;

1050

1051

1055

1056

1057 if (const ObjCMethodDecl *MD = dyn_cast(CD)) {

1058 const RetainSummary *Summ = Summaries.getSummary(AnyCall(MD));

1060 } else if (const FunctionDecl *FD = dyn_cast(CD)) {

1062 const RetainSummary *Summ = Summaries.getSummary(AnyCall(FD));

1064 }

1065 }

1066

1068}

1069

1076

1077

1078

1079

1080

1081

1083 return Pred;

1084

1085

1086 if (X.isReturnedOwned() && X.getCount() == 0) {

1089

1090

1091

1093

1094

1096

1098 if (N) {

1099 const LangOptions &LOpts = C.getASTContext().getLangOpts();

1100 auto R = std::make_unique(

1102 C.emitReport(std::move(R));

1103 }

1104 return N;

1105 }

1106 }

1107 } else if (X.isReturnedNotOwned()) {

1109 if (X.getIvarAccessHistory() ==

1111

1112

1115 } else {

1116

1117

1119

1121 if (N) {

1122 auto R = std::make_unique(

1124 C.getASTContext().getLangOpts(), N, Sym);

1125 C.emitReport(std::move(R));

1126 }

1127 return N;

1128 }

1129 }

1130 }

1131 return Pred;

1132}

1133

1134

1135

1136

1137

1142

1143

1144

1146 state = state->scanReachableSymbols(val).getState();

1147 C.addTransition(state);

1148 }

1149}

1150

1153 bool Assumption) const {

1154

1155

1156

1157

1158

1159

1160 RefBindingsTy B = state->get();

1161

1162 if (B.isEmpty())

1163 return state;

1164

1165 bool changed = false;

1166 RefBindingsTy::Factory &RefBFactory = state->get_context();

1168

1169 for (auto &I : B) {

1170

1173 changed = true;

1174 B = RefBFactory.remove(B, I.first);

1175 }

1176 }

1177

1178 if (changed)

1179 state = state->set(B);

1180

1181 return state;

1182}

1183

1189 if (!invalidated)

1190 return state;

1191

1193

1194 for (const MemRegion *I : ExplicitRegions)

1196 AllowedSymbols.insert(SR->getSymbol());

1197

1198 for (SymbolRef sym : *invalidated) {

1199 if (AllowedSymbols.count(sym))

1200 continue;

1201

1203 }

1204 return state;

1205}

1206

1210 unsigned ACnt = V.getAutoreleaseCount();

1211

1212

1213 if (!ACnt)

1214 return state;

1215

1216 unsigned Cnt = V.getCount();

1217

1218

1219

1221 ++Cnt;

1222

1223

1224

1225 if (ACnt > Cnt &&

1227 V = V.releaseViaIvar();

1228 --ACnt;

1229 }

1230

1231 if (ACnt <= Cnt) {

1232 if (ACnt == Cnt) {

1233 V.clearCounts();

1236 } else {

1238 }

1239 } else {

1240 V.setCount(V.getCount() - ACnt);

1241 V.setAutoreleaseCount(0);

1242 }

1244 }

1245

1246

1247

1248

1249

1250

1251

1253 return state;

1254

1255

1256

1259

1261 if (N) {

1263 llvm::raw_svector_ostream os(sbuf);

1264 os << "Object was autoreleased ";

1265 if (V.getAutoreleaseCount() > 1)

1266 os << V.getAutoreleaseCount() << " times but the object ";

1267 else

1268 os << "but ";

1269 os << "has a +" << V.getCount() << " retain count";

1270

1272 auto R = std::make_unique(

1275 }

1276

1277 return nullptr;

1278}

1279

1284 bool hasLeak;

1285

1286

1287

1288

1289

1290

1291

1293 hasLeak = false;

1294 else if (V.isOwned())

1295 hasLeak = true;

1296 else if (V.isNotOwned() || V.isReturnedOwned())

1297 hasLeak = (V.getCount() > 0);

1298 else

1299 hasLeak = false;

1300

1301 if (!hasLeak)

1303

1304 Leaked.push_back(sid);

1306}

1307

1313

1316

1317 if (N) {

1320

1322 Ctx.emitReport(std::make_unique(BT, LOpts, N, L, Ctx));

1323 }

1324 }

1325

1326 return N;

1327}

1328

1331 return;

1332

1337

1339 return;

1340

1344

1345 for (unsigned idx = 0, e = C->param_size(); idx != e; ++idx) {

1346 const ParmVarDecl *Param = C->parameters()[idx];

1347 SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();

1348

1349 QualType Ty = Param->getType();

1350 const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);

1351 if (AE) {

1358 }

1359 }

1360 }

1361

1363}

1364

1367 ExplodedNode *Pred = processReturn(RS, Ctx);

1368

1369

1370 if (!Pred) {

1371 return;

1372 }

1373

1375 RefBindingsTy B = state->get();

1376

1377

1379 if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {

1380 assert(!LCtx->inTopFrame());

1381 return;

1382 }

1383

1384 for (auto &I : B) {

1386 if (!state)

1387 return;

1388 }

1389

1390

1391

1392

1393

1394 if (LCtx->getParent())

1395 return;

1396

1397 B = state->get();

1399

1400 for (auto &I : B)

1402

1404}

1405

1409

1412

1413

1414 for (const auto &I: state->get()) {

1416 if (SymReaper.isDead(Sym)) {

1417 const RefVal &V = I.second;

1419 if (!state)

1420 return;

1421

1422

1423

1425 }

1426 }

1427

1428 if (Leaked.empty()) {

1429 C.addTransition(state);

1430 return;

1431 }

1432

1434

1435

1436 if (!Pred)

1437 return;

1438

1439

1440

1441 RefBindingsTy::Factory &F = state->get_context();

1442 RefBindingsTy B = state->get();

1443

1445 B = F.remove(B, L);

1446

1447 state = state->set(B);

1448 C.addTransition(state, Pred);

1449}

1450

1452 const char *NL, const char *Sep) const {

1453

1454 RefBindingsTy B = State->get();

1455

1456 if (B.isEmpty())

1457 return;

1458

1459 Out << Sep << NL;

1460

1461 for (auto &I : B) {

1462 Out << I.first << " : ";

1463 I.second.print(Out);

1464 Out << NL;

1465 }

1466}

1467

1468

1469

1470

1471

1474

1475void ento::registerRetainCountBase(CheckerManager &Mgr) {

1477 Chk->DeallocSentTag = std::make_unique(

1478 "RetainCountChecker", "DeallocSent");

1479 Chk->CastFailTag = std::make_unique(

1480 "RetainCountChecker", "DynamicCastFail");

1481}

1482

1483bool ento::shouldRegisterRetainCountBase(const CheckerManager &) {

1484 return true;

1485}

1486

1487void ento::registerRetainCountChecker(CheckerManager &Mgr) {

1490 Chk->TrackNSCFStartParam = Mgr.getAnalyzerOptions().getCheckerBooleanOption(

1492}

1493

1494bool ento::shouldRegisterRetainCountChecker(const CheckerManager &) {

1495 return true;

1496}

1497

1498void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {

1501

1502

1503

1504

1505

1506

1507

1508

1509

1510

1511}

1512

1513bool ento::shouldRegisterOSObjectRetainCountChecker(const CheckerManager &) {

1514 return true;

1515}

static CanQualType GetReturnType(QualType RetTy)

Returns the "extra-canonicalized" return type, which discards qualifiers on the return type.

#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)

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

static const RetainSummary * getSummary(RetainSummaryManager &Summaries, const CallEvent &Call, QualType ReceiverType)

Definition RetainCountChecker.cpp:350

static std::optional< RefVal > refValFromRetEffect(RetEffect RE, QualType ResultTy)

Definition RetainCountChecker.cpp:413

static ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, RefVal Val)

Definition RetainCountChecker.cpp:36

static bool shouldEscapeRegion(ProgramStateRef State, const MemRegion *R)

A value escapes in these possible cases:

Definition RetainCountChecker.cpp:503

static bool isReceiverUnconsumedSelf(const CallEvent &Call)

Definition RetainCountChecker.cpp:336

static SmallVector< ProgramStateRef, 2 > updateOutParameters(ProgramStateRef State, const RetainSummary &Summ, const CallEvent &CE)

Definition RetainCountChecker.cpp:519

static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym)

Definition RetainCountChecker.cpp:42

static bool isPointerToObject(QualType QT)

Definition RetainCountChecker.cpp:424

static bool isSmartPtrField(const MemRegion *MR)

Definition RetainCountChecker.cpp:486

static bool shouldEscapeOSArgumentOnCall(const CallEvent &CE, unsigned ArgIdx, const RefVal *TrackedValue)

Whether the tracked value should be escaped on a given call.

Definition RetainCountChecker.cpp:434

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

QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const

getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl.

const LangOptions & getLangOpts() const

QualType getObjCObjectPointerType(QualType OIT) const

Return a ObjCObjectPointerType type for the given ObjCObjectType.

An instance of this class corresponds to a call.

static std::optional< AnyCall > forDecl(const Decl *D)

If D is a callable (Objective-C method or a function), return a constructed AnyCall object.

static std::optional< AnyCall > forExpr(const Expr *E)

If E is a generic call (to ObjC method /function/block/etc), return a constructed AnyCall object.

bool hasCaptures() const

True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...

BlockExpr - Adaptor class for mixing a BlockDecl with expressions.

const BlockDecl * getBlockDecl() const

CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...

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

This represents one expression.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

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

const Decl * getDecl() const

ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp,...

ObjCBoxedExpr - used for generalized expression boxing.

An Objective-C "bridged" cast expression, which casts between Objective-C pointers and C pointers,...

ObjCBridgeCastKind getBridgeKind() const

Determine which kind of bridge is being performed via this cast.

ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...

Represents an ObjC class declaration.

ObjCIvarRefExpr - A reference to an ObjC instance variable.

An expression that sends a message to the given Objective-C object or class.

Represents a pointer to an Objective C object.

Represents a parameter to a function.

A (possibly-)qualified type.

bool isNull() const

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

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

A trivial tuple used to represent a source range.

Stmt - This represents one statement.

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isScalarType() 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

const T * getAs() const

Member-template getAs'.

bool isObjCRetainableType() const

Represents a variable declaration or definition.

An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method.

ArgEffect withKind(ArgEffectKind NewK)

ObjKind getObjKind() const

ArgEffectKind getKind() const

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

virtual SourceRange getArgSourceRange(unsigned Index) const

Returns the source range for errors associated with this argument.

virtual const Expr * getOriginExpr() const

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

QualType getResultType() const

Returns the result type, adjusted for references.

virtual SVal getArgSVal(unsigned Index) const

Returns the value of a given argument at the time of the call.

virtual unsigned getNumArgs() const =0

Returns the number of arguments (explicit and implicit).

SVal getReturnValue() const

Returns the return value of the call.

virtual ArrayRef< ParmVarDecl * > parameters() const =0

Return call's formal parameters.

ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)

Generate a sink node.

ASTContext & getASTContext()

const ProgramStateRef & getState() const

ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)

Generates a new transition in the program state graph (ExplodedGraph).

bool inTopFrame() const

Return true if the current LocationContext has no caller context.

const LocationContext * getLocationContext() const

void emitReport(std::unique_ptr< BugReport > R)

Emit the diagnostics report.

void enable(CheckerManager &Mgr)

const AnalyzerOptions & getAnalyzerOptions() const

CheckerNameRef getCurrentCheckerName() const

CHECKER * getChecker(AT &&...Args)

If the the singleton instance of a checker class is not yet constructed, then construct it (with the ...

bool isConstrainedTrue() const

Return true if the constraint is perfectly constrained to 'true'.

ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)

Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...

const ProgramStateRef & getState() const

SVal getSVal(const Stmt *S) const

Get the value of an arbitrary expression at this node.

const LocationContext * getLocationContext() const

const Decl & getCodeDecl() const

const VarRegion * getVarRegion(const VarDecl *VD, const LocationContext *LC)

getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and LocationC...

MemRegion - The root abstract class for all memory regions.

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

bool hasMemorySpace(ProgramStateRef State) const

const RegionTy * getAs() const

RetEffect summarizes a call's retain/release behavior with respect to its return value.

ObjKind getObjKind() const

@ OwnedWhenTrackedReceiver

Indicates that the return value is an owned object when the receiver is also a tracked object.

@ NoRet

Indicates that no retain count information is tracked for the return value.

static RetEffect MakeNoRet()

bool isTrustedReferenceCountImplementation(const Decl *FD)

std::optional< BehaviorSummary > canEval(const CallExpr *CE, const FunctionDecl *FD, bool &hasTrustedImplementationAnnotation)

static bool isKnownSmartPointer(QualType QT)

const RetainSummary * getSummary(AnyCall C, bool HasNonZeroCallbackArg=false, bool IsReceiverUnconsumedSelf=false, QualType ReceiverType={})

RetEffect getObjAllocRetEffect() const

Summary for a function with respect to ownership changes.

ArgEffect getThisEffect() const

ArgEffect getReceiverEffect() const

getReceiverEffect - Returns the effect on the receiver of the call.

RetEffect getRetEffect() const

getRetEffect - Returns the effect on the return value of the call.

ArgEffects getArgEffects() const

ArgEffect getArg(unsigned idx) const

getArg - Return the argument effect on the argument specified by idx (starting from 0).

DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const LocationContext *LCtx, unsigned count)

Create a new symbol with a unique 'name'.

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

SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const

If this SVal wraps a symbol return that SymbolRef.

std::optional< T > getAs() const

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

SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const

If this SVal is a location and wraps a symbol, return that SymbolRef.

const MemRegion * getAsRegion() const

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const

virtual const MemRegion * getOriginRegion() const

Find the region from which this symbol originates.

virtual QualType getType() const =0

A class responsible for cleaning up unused symbols.

bool isDead(SymbolRef sym)

Returns whether or not a symbol has been confirmed dead.

SymbolicRegion - A special, "non-concrete" region.

const VarDecl * getDecl() const override=0

const RefCountBug DeallocNotOwned

const RefCountBug LeakWithinFunction

const RefCountBug ReleaseNotOwned

const RefCountBug FreeNotOwned

const RefCountBug LeakAtReturn

const RefCountBug UseAfterRelease

unsigned getCount() const

@ ReleasedAfterDirectAccess

IvarAccessHistory getIvarAccessHistory() const

Returns what the analyzer knows about direct accesses to a particular instance variable.

void print(raw_ostream &Out) const

Definition RetainCountChecker.cpp:46

RefVal withIvarAccess() const

static RefVal makeOwned(ObjKind o, QualType t)

Create a state for an object whose lifetime is the responsibility of the current function,...

ObjKind getObjKind() const

static RefVal makeNotOwned(ObjKind o, QualType t)

Create a state for an object whose lifetime is not the responsibility of the current function.

RefCountFrontend RetainCount

void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const

Definition RetainCountChecker.cpp:146

void checkSummary(const RetainSummary &Summ, const CallEvent &Call, CheckerContext &C) const

Definition RetainCountChecker.cpp:603

ProgramStateRef handleSymbolDeath(ProgramStateRef state, SymbolRef sid, RefVal V, SmallVectorImpl< SymbolRef > &Leaked) const

Definition RetainCountChecker.cpp:1281

ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, bool Assumption) const

Definition RetainCountChecker.cpp:1151

static const SimpleProgramPointTag & getCastFailTag()

void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange, RefVal::Kind ErrorKind, SymbolRef Sym, CheckerContext &C) const

Definition RetainCountChecker.cpp:864

const RefCountBug & errorKindToBugKind(RefVal::Kind ErrorKind, SymbolRef Sym) const

Definition RetainCountChecker.cpp:841

static std::unique_ptr< SimpleProgramPointTag > DeallocSentTag

ExplodedNode * checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C, ExplodedNode *Pred, RetEffect RE, RefVal X, SymbolRef Sym, ProgramStateRef state) const

Definition RetainCountChecker.cpp:1070

ProgramStateRef handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred, CheckerContext &Ctx, SymbolRef Sym, RefVal V, const ReturnStmt *S=nullptr) const

Definition RetainCountChecker.cpp:1207

bool isReleaseUnownedError(RefVal::Kind ErrorKind) const

Definition RetainCountChecker.cpp:859

const RefCountFrontend & getPreferredFrontend() const

ExplodedNode * processLeaks(ProgramStateRef state, SmallVectorImpl< SymbolRef > &Leaked, CheckerContext &Ctx, ExplodedNode *Pred=nullptr) const

Definition RetainCountChecker.cpp:1309

void checkBind(SVal loc, SVal val, const Stmt *S, bool AtDeclInit, CheckerContext &C) const

Definition RetainCountChecker.cpp:1138

ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym, RefVal V, ArgEffect E, RefVal::Kind &hasErr, CheckerContext &C) const

Definition RetainCountChecker.cpp:709

RefCountFrontend OSObjectRetainCount

void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const

Definition RetainCountChecker.cpp:1406

std::unique_ptr< RetainSummaryManager > Summaries

void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const override

Debug state dump callback, see CheckerManager::runCheckersForPrintState.

Definition RetainCountChecker.cpp:1451

bool evalCall(const CallEvent &Call, CheckerContext &C) const

Definition RetainCountChecker.cpp:894

void checkBeginFunction(CheckerContext &C) const

Definition RetainCountChecker.cpp:1329

void checkPostCall(const CallEvent &Call, CheckerContext &C) const

Definition RetainCountChecker.cpp:361

static std::unique_ptr< SimpleProgramPointTag > CastFailTag

ProgramStateRef checkRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call) const

Definition RetainCountChecker.cpp:1184

static const SimpleProgramPointTag & getDeallocSentTag()

void processObjCLiterals(CheckerContext &C, const Expr *Ex) const

Definition RetainCountChecker.cpp:227

void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const

Definition RetainCountChecker.cpp:1365

void processSummaryOfInlined(const RetainSummary &Summ, const CallEvent &Call, CheckerContext &C) const

Definition RetainCountChecker.cpp:446

RetainSummaryManager & getSummaryManager(ASTContext &Ctx) const

bool TrackNSCFStartParam

Track initial parameters (for the entry point) for NS/CF objects.

bool isCFObjectRef(QualType T)

const RefVal * getRefBinding(ProgramStateRef State, SymbolRef Sym)

Definition RetainCountChecker.cpp:28

bool isSynthesizedAccessor(const StackFrameContext *SFC)

Returns true if this stack frame is for an Objective-C method that is a property getter or setter who...

llvm::ImmutableMap< unsigned, ArgEffect > ArgEffects

ArgEffects summarizes the effects of a function/method call on all of its arguments.

llvm::DenseSet< SymbolRef > InvalidatedSymbols

IntrusiveRefCntPtr< const ProgramState > ProgramStateRef

const SymExpr * SymbolRef

ObjKind

Determines the object kind of a tracked object.

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

@ Generalized

Indicates that the tracked object is a generalized object.

@ CF

Indicates that the tracked object is a CF object.

@ ObjC

Indicates that the tracked object is an Objective-C object.

@ IncRef

The argument has its reference count increased by 1.

@ UnretainedOutParameter

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +0 v...

@ DoNothing

There is no effect.

@ RetainedOutParameter

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...

@ RetainedOutParameterOnZero

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...

@ MayEscape

The argument is treated as potentially escaping, meaning that even when its reference count hits 0 it...

@ StopTracking

All typestate tracking of the object ceases.

@ Dealloc

The argument is treated as if the referenced object was deallocated.

@ Autorelease

The argument is treated as if an -autorelease message had been sent to the referenced object.

@ RetainedOutParameterOnNonZero

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...

@ DecRef

The argument has its reference count decreased by 1.

@ StopTrackingHard

All typestate tracking of the object ceases.

@ DecRefAndStopTrackingHard

Performs the combined functionality of DecRef and StopTrackingHard.

@ DecRefBridgedTransferred

The argument has its reference count decreased by 1 to model a transferred bridge cast under ARC.

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)

const FunctionProtoType * T

@ OBC_Bridge

Bridging via __bridge, which does nothing but reinterpret the bits.

@ OBC_BridgeTransfer

Bridging via __bridge_transfer, which transfers ownership of an Objective-C pointer into ARC.

@ OBC_BridgeRetained

Bridging via __bridge_retain, which makes an ARC object available as a +1 C pointer.

U cast(CodeGen::Address addr)