@@ -840,20 +840,27 @@ ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state,
840
840
const RefCountBug &
841
841
RetainCountChecker::errorKindToBugKind (RefVal::Kind ErrorKind,
842
842
SymbolRef Sym) const {
843
+ const RefCountFrontend &FE = getPreferredFrontend ();
844
+
843
845
switch (ErrorKind) {
844
846
case RefVal::ErrorUseAfterRelease:
845
- return * UseAfterRelease;
847
+ return FE. UseAfterRelease ;
846
848
case RefVal::ErrorReleaseNotOwned:
847
- return * ReleaseNotOwned;
849
+ return FE. ReleaseNotOwned ;
848
850
case RefVal::ErrorDeallocNotOwned:
849
851
if (Sym->getType ()->getPointeeCXXRecordDecl ())
850
- return * FreeNotOwned;
851
- return * DeallocNotOwned;
852
+ return FE. FreeNotOwned ;
853
+ return FE. DeallocNotOwned ;
852
854
default :
853
855
llvm_unreachable (" Unhandled error." );
854
856
}
855
857
}
856
858
859
+ bool RetainCountChecker::isReleaseUnownedError (RefVal::Kind ErrorKind) const {
860
+ return ErrorKind == RefVal::ErrorReleaseNotOwned ||
861
+ ErrorKind == RefVal::ErrorDeallocNotOwned;
862
+ }
863
+
857
864
void RetainCountChecker::processNonLeakError (ProgramStateRef St,
858
865
SourceRange ErrorRange,
859
866
RefVal::Kind ErrorKind,
@@ -874,8 +881,8 @@ void RetainCountChecker::processNonLeakError(ProgramStateRef St,
874
881
return ;
875
882
876
883
auto report = std::make_unique<RefCountReport>(
877
- errorKindToBugKind (ErrorKind, Sym),
878
- C. getASTContext (). getLangOpts (), N, Sym );
884
+ errorKindToBugKind (ErrorKind, Sym), C. getASTContext (). getLangOpts (), N,
885
+ Sym, /* isLeak= */ false , isReleaseUnownedError (ErrorKind) );
879
886
report->addRange (ErrorRange);
880
887
C.emitReport (std::move (report));
881
888
}
@@ -1090,8 +1097,8 @@ ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
1090
1097
ExplodedNode *N = C.addTransition (state, Pred);
1091
1098
if (N) {
1092
1099
const LangOptions &LOpts = C.getASTContext ().getLangOpts ();
1093
- auto R =
1094
- std::make_unique<RefLeakReport>(* LeakAtReturn, LOpts, N, Sym, C);
1100
+ auto R = std::make_unique<RefLeakReport>(
1101
+ getPreferredFrontend (). LeakAtReturn , LOpts, N, Sym, C);
1095
1102
C.emitReport (std::move (R));
1096
1103
}
1097
1104
return N;
@@ -1113,7 +1120,8 @@ ExplodedNode * RetainCountChecker::checkReturnWithRetEffect(const ReturnStmt *S,
1113
1120
ExplodedNode *N = C.addTransition (state, Pred);
1114
1121
if (N) {
1115
1122
auto R = std::make_unique<RefCountReport>(
1116
- *ReturnNotOwnedForOwned, C.getASTContext ().getLangOpts (), N, Sym);
1123
+ getPreferredFrontend ().ReturnNotOwnedForOwned ,
1124
+ C.getASTContext ().getLangOpts (), N, Sym);
1117
1125
C.emitReport (std::move (R));
1118
1126
}
1119
1127
return N;
@@ -1261,8 +1269,8 @@ ProgramStateRef RetainCountChecker::handleAutoreleaseCounts(
1261
1269
os << " has a +" << V.getCount () << " retain count" ;
1262
1270
1263
1271
const LangOptions &LOpts = Ctx.getASTContext ().getLangOpts ();
1264
- auto R = std::make_unique<RefCountReport>(*OverAutorelease, LOpts, N, Sym,
1265
- os.str ());
1272
+ auto R = std::make_unique<RefCountReport>(
1273
+ getPreferredFrontend (). OverAutorelease , LOpts, N, Sym, os.str ());
1266
1274
Ctx.emitReport (std::move (R));
1267
1275
}
1268
1276
@@ -1307,8 +1315,10 @@ RetainCountChecker::processLeaks(ProgramStateRef state,
1307
1315
const LangOptions &LOpts = Ctx.getASTContext ().getLangOpts ();
1308
1316
1309
1317
if (N) {
1318
+ const RefCountFrontend &FE = getPreferredFrontend ();
1319
+ const RefCountBug &BT = Pred ? FE.LeakWithinFunction : FE.LeakAtReturn ;
1320
+
1310
1321
for (SymbolRef L : Leaked) {
1311
- const RefCountBug &BT = Pred ? *LeakWithinFunction : *LeakAtReturn;
1312
1322
Ctx.emitReport (std::make_unique<RefLeakReport>(BT, LOpts, N, L, Ctx));
1313
1323
}
1314
1324
}
@@ -1463,44 +1473,31 @@ std::unique_ptr<SimpleProgramPointTag> RetainCountChecker::DeallocSentTag;
1463
1473
std::unique_ptr<SimpleProgramPointTag> RetainCountChecker::CastFailTag;
1464
1474
1465
1475
void ento::registerRetainCountBase (CheckerManager &Mgr) {
1466
- auto *Chk = Mgr.registerChecker <RetainCountChecker>();
1476
+ auto *Chk = Mgr.getChecker <RetainCountChecker>();
1467
1477
Chk->DeallocSentTag = std::make_unique<SimpleProgramPointTag>(
1468
1478
" RetainCountChecker" , " DeallocSent" );
1469
1479
Chk->CastFailTag = std::make_unique<SimpleProgramPointTag>(
1470
1480
" RetainCountChecker" , " DynamicCastFail" );
1471
1481
}
1472
1482
1473
- bool ento::shouldRegisterRetainCountBase (const CheckerManager &mgr ) {
1483
+ bool ento::shouldRegisterRetainCountBase (const CheckerManager &) {
1474
1484
return true ;
1475
1485
}
1486
+
1476
1487
void ento::registerRetainCountChecker (CheckerManager &Mgr) {
1477
1488
auto *Chk = Mgr.getChecker <RetainCountChecker>();
1478
- Chk->TrackObjCAndCFObjects = true ;
1489
+ Chk->RetainCount . enable (Mgr) ;
1479
1490
Chk->TrackNSCFStartParam = Mgr.getAnalyzerOptions ().getCheckerBooleanOption (
1480
1491
Mgr.getCurrentCheckerName (), " TrackNSCFStartParam" );
1481
-
1482
- #define INIT_BUGTYPE (KIND ) \
1483
- Chk->KIND = std::make_unique<RefCountBug>(Mgr.getCurrentCheckerName (), \
1484
- RefCountBug::KIND);
1485
- // TODO: Ideally, we should have a checker for each of these bug types.
1486
- INIT_BUGTYPE (UseAfterRelease)
1487
- INIT_BUGTYPE (ReleaseNotOwned)
1488
- INIT_BUGTYPE (DeallocNotOwned)
1489
- INIT_BUGTYPE (FreeNotOwned)
1490
- INIT_BUGTYPE (OverAutorelease)
1491
- INIT_BUGTYPE (ReturnNotOwnedForOwned)
1492
- INIT_BUGTYPE (LeakWithinFunction)
1493
- INIT_BUGTYPE (LeakAtReturn)
1494
- #undef INIT_BUGTYPE
1495
1492
}
1496
1493
1497
- bool ento::shouldRegisterRetainCountChecker (const CheckerManager &mgr ) {
1494
+ bool ento::shouldRegisterRetainCountChecker (const CheckerManager &) {
1498
1495
return true ;
1499
1496
}
1500
1497
1501
1498
void ento::registerOSObjectRetainCountChecker (CheckerManager &Mgr) {
1502
1499
auto *Chk = Mgr.getChecker <RetainCountChecker>();
1503
- Chk->TrackOSObjects = true ;
1500
+ Chk->OSObjectRetainCount . enable (Mgr) ;
1504
1501
1505
1502
// FIXME: We want bug reports to always have the same checker name associated
1506
1503
// with them, yet here, if RetainCountChecker is disabled but
@@ -1511,21 +1508,8 @@ void ento::registerOSObjectRetainCountChecker(CheckerManager &Mgr) {
1511
1508
// diagnostics, and **hidden checker options** with the fine-tuning of
1512
1509
// modeling. Following this logic, OSObjectRetainCountChecker should be the
1513
1510
// latter, but we can't just remove it for backward compatibility reasons.
1514
- #define LAZY_INIT_BUGTYPE (KIND ) \
1515
- if (!Chk->KIND ) \
1516
- Chk->KIND = std::make_unique<RefCountBug>(Mgr.getCurrentCheckerName (), \
1517
- RefCountBug::KIND);
1518
- LAZY_INIT_BUGTYPE (UseAfterRelease)
1519
- LAZY_INIT_BUGTYPE (ReleaseNotOwned)
1520
- LAZY_INIT_BUGTYPE (DeallocNotOwned)
1521
- LAZY_INIT_BUGTYPE (FreeNotOwned)
1522
- LAZY_INIT_BUGTYPE (OverAutorelease)
1523
- LAZY_INIT_BUGTYPE (ReturnNotOwnedForOwned)
1524
- LAZY_INIT_BUGTYPE (LeakWithinFunction)
1525
- LAZY_INIT_BUGTYPE (LeakAtReturn)
1526
- #undef LAZY_INIT_BUGTYPE
1527
1511
}
1528
1512
1529
- bool ento::shouldRegisterOSObjectRetainCountChecker (const CheckerManager &mgr ) {
1513
+ bool ento::shouldRegisterOSObjectRetainCountChecker (const CheckerManager &) {
1530
1514
return true ;
1531
1515
}
0 commit comments