Skip to content

Commit b73720c

Browse files
authored
[analyzer] Conversion to CheckerFamily: DynamicTypePropagation (#144735)
This commit converts the class DynamicTypePropagation to a very simple checker family, which has only one checker frontend -- but also supports enabling the backend ("modeling checker") without the frontend. As a tangentially related change, this commit adds the backend of DynamicTypePropagation as a dependency of alpha.core.DynamicTypeChecker in Checkers.td, because the header comment of DynamicTypeChecker.cpp claims that it depends on DynamicTypePropagation and the source code seems to confirm this. (The lack of this dependency relationship didn't cause problems, because 'core.DynamicTypePropagation' is in the group 'core', so it is practically always active. However, explicitly declaring the dependency clarifies the fact that the separate existence of the modeling checker is warranted.)
1 parent e33f13b commit b73720c

File tree

2 files changed

+32
-33
lines changed

2 files changed

+32
-33
lines changed

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,12 @@ def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
294294
"Either the comparison is useless or there is division by zero.">,
295295
Documentation<HasDocumentation>;
296296

297-
def DynamicTypeChecker : Checker<"DynamicTypeChecker">,
298-
HelpText<"Check for cases where the dynamic and the static type of an object "
299-
"are unrelated.">,
300-
Documentation<HasDocumentation>;
297+
def DynamicTypeChecker
298+
: Checker<"DynamicTypeChecker">,
299+
HelpText<"Check for cases where the dynamic and the static type of an "
300+
"object are unrelated.">,
301+
Dependencies<[DynamicTypePropagation]>,
302+
Documentation<HasDocumentation>;
301303

302304
def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
303305
HelpText<"Check that addresses to stack memory do not escape the function">,

clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,19 @@ REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef,
4949
const ObjCObjectPointerType *)
5050

5151
namespace {
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

114110
bool 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

Comments
 (0)