@@ -49,15 +49,19 @@ REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef,
4949 const ObjCObjectPointerType *)
5050
5151namespace {
52- class DynamicTypePropagation :
53- public Checker< check::PreCall,
54- check::PostCall,
55- check::DeadSymbols,
56- check::PostStmt<CastExpr>,
57- check::PostStmt<CXXNewExpr>,
58- check::PreObjCMessage,
59- check::PostObjCMessage > {
52+ class DynamicTypePropagation
53+ : public CheckerFamily<check::PreCall, check::PostCall, check::DeadSymbols,
54+ check::PostStmt<CastExpr>,
55+ check::PostStmt<CXXNewExpr>, check::PreObjCMessage,
56+ check::PostObjCMessage> {
57+ public:
58+ // This checker family implements only one frontend, but -- unlike a simple
59+ // Checker -- its backend can be enabled (by the checker DynamicTypeChecker
60+ // which depends on it) without enabling the frontend.
61+ CheckerFrontendWithBugType ObjCGenericsChecker{
62+ " Generics" , categories::CoreFoundationObjectiveC};
6063
64+ private:
6165 // / Return a better dynamic type if one can be derived from the cast.
6266 const ObjCObjectPointerType *getBetterObjCType (const Expr *CastE,
6367 CheckerContext &C) const ;
@@ -66,13 +70,6 @@ class DynamicTypePropagation:
6670 ProgramStateRef &State,
6771 CheckerContext &C) const ;
6872
69- mutable std::unique_ptr<BugType> ObjCGenericsBugType;
70- void initBugType () const {
71- if (!ObjCGenericsBugType)
72- ObjCGenericsBugType.reset (new BugType (
73- GenericCheckName, " Generics" , categories::CoreFoundationObjectiveC));
74- }
75-
7673 class GenericsBugVisitor : public BugReporterVisitor {
7774 public:
7875 GenericsBugVisitor (SymbolRef S) : Sym(S) {}
@@ -106,9 +103,8 @@ class DynamicTypePropagation:
106103 void checkPreObjCMessage (const ObjCMethodCall &M, CheckerContext &C) const ;
107104 void checkPostObjCMessage (const ObjCMethodCall &M, CheckerContext &C) const ;
108105
109- // / This value is set to true, when the Generics checker is turned on.
110- bool CheckGenerics = false ;
111- CheckerNameRef GenericCheckName;
106+ // / Identifies this checker family for debugging purposes.
107+ StringRef getDebugTag () const override { return " DynamicTypePropagation" ; }
112108};
113109
114110bool isObjCClassType (QualType Type) {
@@ -1026,18 +1022,17 @@ void DynamicTypePropagation::reportGenericsBug(
10261022 const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
10271023 ExplodedNode *N, SymbolRef Sym, CheckerContext &C,
10281024 const Stmt *ReportedNode) const {
1029- if (!CheckGenerics )
1025+ if (!ObjCGenericsChecker. isEnabled () )
10301026 return ;
10311027
1032- initBugType ();
10331028 SmallString<192 > Buf;
10341029 llvm::raw_svector_ostream OS (Buf);
10351030 OS << " Conversion from value of type '" ;
10361031 QualType::print (From, Qualifiers (), OS, C.getLangOpts (), llvm::Twine ());
10371032 OS << " ' to incompatible type '" ;
10381033 QualType::print (To, Qualifiers (), OS, C.getLangOpts (), llvm::Twine ());
10391034 OS << " '" ;
1040- auto R = std::make_unique<PathSensitiveBugReport>(*ObjCGenericsBugType ,
1035+ auto R = std::make_unique<PathSensitiveBugReport>(ObjCGenericsChecker ,
10411036 OS.str (), N);
10421037 R->markInteresting (Sym);
10431038 R->addVisitor (std::make_unique<GenericsBugVisitor>(Sym));
@@ -1102,20 +1097,22 @@ PathDiagnosticPieceRef DynamicTypePropagation::GenericsBugVisitor::VisitNode(
11021097}
11031098
11041099// / Register checkers.
1105- void ento::registerObjCGenericsChecker (CheckerManager &mgr) {
1106- DynamicTypePropagation *checker = mgr.getChecker <DynamicTypePropagation>();
1107- checker->CheckGenerics = true ;
1108- checker->GenericCheckName = mgr.getCurrentCheckerName ();
1100+ void ento::registerObjCGenericsChecker (CheckerManager &Mgr) {
1101+ Mgr.getChecker <DynamicTypePropagation>()->ObjCGenericsChecker .enable (Mgr);
11091102}
11101103
1111- bool ento::shouldRegisterObjCGenericsChecker (const CheckerManager &mgr ) {
1104+ bool ento::shouldRegisterObjCGenericsChecker (const CheckerManager &) {
11121105 return true ;
11131106}
11141107
1115- void ento::registerDynamicTypePropagation (CheckerManager &mgr) {
1116- mgr.registerChecker <DynamicTypePropagation>();
1108+ void ento::registerDynamicTypePropagation (CheckerManager &Mgr) {
1109+ // The checker 'core.DynamicTypeChecker' relies on the modeling implemented
1110+ // in the class 'DynamicTypePropagation', so this "modeling checker" can
1111+ // register the 'DynamicTypePropagation' backend for its callbacks without
1112+ // enabling its frontend.
1113+ Mgr.getChecker <DynamicTypePropagation>();
11171114}
11181115
1119- bool ento::shouldRegisterDynamicTypePropagation (const CheckerManager &mgr ) {
1116+ bool ento::shouldRegisterDynamicTypePropagation (const CheckerManager &) {
11201117 return true ;
11211118}
0 commit comments