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 ()
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 .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
776 break;
777
781
783 switch (V.getKind()) {
784 default:
785 llvm_unreachable("Invalid RefVal state for a retain.");
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
815 break;
816
818 if (V.getCount() > 0) {
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 (.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 ()
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);
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 &&
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)