193a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose//==- ExprInspectionChecker.cpp - Used for regression tests ------*- C++ -*-==// 293a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose// 393a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose// The LLVM Compiler Infrastructure 493a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose// 593a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose// This file is distributed under the University of Illinois Open Source 693a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose// License. See LICENSE.TXT for details. 793a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose// 893a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose//===----------------------------------------------------------------------===// 993a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 1093a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose#include "ClangSACheckers.h" 1193a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 1255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/Checker.h" 1393a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 144967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar#include "clang/StaticAnalyzer/Checkers/SValExplainer.h" 159852f58f50b4fc20914fbce5b4454135a42343f4Benjamin Kramer#include "llvm/ADT/StringSwitch.h" 1693a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 1793a9d828378b5c969344f27aeb275b8c2a19d918Jordy Roseusing namespace clang; 1893a9d828378b5c969344f27aeb275b8c2a19d918Jordy Roseusing namespace ento; 1993a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 2093a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rosenamespace { 2187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarclass ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols> { 22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<BugType> BT; 23e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 24e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose void analyzerEval(const CallExpr *CE, CheckerContext &C) const; 25e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const; 26d000b852022bcd4fc14029b48d2fa873f63e4032Jordan Rose void analyzerWarnIfReached(const CallExpr *CE, CheckerContext &C) const; 27ac7cc2d37e82181e73fcc265c1d0a619d18b7605Jordan Rose void analyzerCrash(const CallExpr *CE, CheckerContext &C) const; 2887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const; 294967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar void analyzerExplain(const CallExpr *CE, CheckerContext &C) const; 304967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar void analyzerGetExtent(const CallExpr *CE, CheckerContext &C) const; 31e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 32e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *, 33e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose CheckerContext &C) const; 34e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 354967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar void reportBug(llvm::StringRef Msg, CheckerContext &C) const; 364967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 3793a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rosepublic: 3893a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose bool evalCall(const CallExpr *CE, CheckerContext &C) const; 3987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; 4093a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose}; 4193a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose} 4293a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 434967a710c84587c654b56c828382219c3937dacbPirama Arumuga NainarREGISTER_SET_WITH_PROGRAMSTATE(MarkedSymbols, SymbolRef) 4487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 4593a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rosebool ExprInspectionChecker::evalCall(const CallExpr *CE, 46e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose CheckerContext &C) const { 4793a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose // These checks should have no effect on the surrounding environment 48e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose // (globals should not be invalidated, etc), hence the use of evalCall. 49e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose FnCheck Handler = llvm::StringSwitch<FnCheck>(C.getCalleeName(CE)) 50e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose .Case("clang_analyzer_eval", &ExprInspectionChecker::analyzerEval) 51e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose .Case("clang_analyzer_checkInlined", 52e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose &ExprInspectionChecker::analyzerCheckInlined) 53ac7cc2d37e82181e73fcc265c1d0a619d18b7605Jordan Rose .Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash) 5487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar .Case("clang_analyzer_warnIfReached", 5587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar &ExprInspectionChecker::analyzerWarnIfReached) 5687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar .Case("clang_analyzer_warnOnDeadSymbol", 5787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar &ExprInspectionChecker::analyzerWarnOnDeadSymbol) 584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar .Case("clang_analyzer_explain", &ExprInspectionChecker::analyzerExplain) 594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar .Case("clang_analyzer_getExtent", &ExprInspectionChecker::analyzerGetExtent) 606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines .Default(nullptr); 61e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 62e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose if (!Handler) 63e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return false; 64e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 65e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose (this->*Handler)(CE, C); 66e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return true; 67e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose} 68e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 69e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rosestatic const char *getArgumentValueString(const CallExpr *CE, 70e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose CheckerContext &C) { 71e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose if (CE->getNumArgs() == 0) 72e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return "Missing assertion argument"; 73e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 7493a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose ExplodedNode *N = C.getPredecessor(); 7593a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose const LocationContext *LC = N->getLocationContext(); 76e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose ProgramStateRef State = N->getState(); 77e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 78e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose const Expr *Assertion = CE->getArg(0); 79e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose SVal AssertionVal = State->getSVal(Assertion, LC); 80e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 81e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose if (AssertionVal.isUndef()) 82e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return "UNDEFINED"; 83e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 84e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose ProgramStateRef StTrue, StFalse; 85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(StTrue, StFalse) = 865251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie State->assume(AssertionVal.castAs<DefinedOrUnknownSVal>()); 87e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 88e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose if (StTrue) { 89e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose if (StFalse) 90e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return "UNKNOWN"; 91e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose else 92e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return "TRUE"; 93e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose } else { 94e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose if (StFalse) 95e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return "FALSE"; 96e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose else 97e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose llvm_unreachable("Invalid constraint; neither true or false."); 98e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose } 99e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose} 10093a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 1014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarvoid ExprInspectionChecker::reportBug(llvm::StringRef Msg, 1024967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar CheckerContext &C) const { 1034967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!BT) 1044967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar BT.reset(new BugType(this, "Checking analyzer assumptions", "debug")); 1054967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1064967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ExplodedNode *N = C.generateNonFatalErrorNode(); 1074967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!N) 1084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return; 1094967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1104967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar C.emitReport(llvm::make_unique<BugReport>(*BT, Msg, N)); 1114967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 1124967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 113e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rosevoid ExprInspectionChecker::analyzerEval(const CallExpr *CE, 114e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose CheckerContext &C) const { 11587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar const LocationContext *LC = C.getPredecessor()->getLocationContext(); 11693a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 11793a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose // A specific instantiation of an inlined function may have more constrained 11893a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose // values than can generally be assumed. Skip the check. 1196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (LC->getCurrentStackFrame()->getParent() != nullptr) 120e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return; 12193a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 1224967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug(getArgumentValueString(CE, C), C); 123e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose} 124e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose 125d000b852022bcd4fc14029b48d2fa873f63e4032Jordan Rosevoid ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE, 126d000b852022bcd4fc14029b48d2fa873f63e4032Jordan Rose CheckerContext &C) const { 1274967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug("REACHABLE", C); 128d000b852022bcd4fc14029b48d2fa873f63e4032Jordan Rose} 129d000b852022bcd4fc14029b48d2fa873f63e4032Jordan Rose 130e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rosevoid ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE, 131e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose CheckerContext &C) const { 13287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar const LocationContext *LC = C.getPredecessor()->getLocationContext(); 13393a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 134e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose // An inlined function could conceivably also be analyzed as a top-level 135e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose // function. We ignore this case and only emit a message (TRUE or FALSE) 136e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose // when we are analyzing it as an inlined function. This means that 137e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose // clang_analyzer_checkInlined(true) should always print TRUE, but 138e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose // clang_analyzer_checkInlined(false) should never actually print anything. 1396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (LC->getCurrentStackFrame()->getParent() == nullptr) 140e5399f1375f8571bdd821ae08291af1c895adfd3Jordan Rose return; 14193a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 1424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug(getArgumentValueString(CE, C), C); 1434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 14493a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 1454967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarvoid ExprInspectionChecker::analyzerExplain(const CallExpr *CE, 1464967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar CheckerContext &C) const { 1474967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (CE->getNumArgs() == 0) 1484967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug("Missing argument for explaining", C); 1494967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1504967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SVal V = C.getSVal(CE->getArg(0)); 1514967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SValExplainer Ex(C.getASTContext()); 1524967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug(Ex.Visit(V), C); 1534967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} 1544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1554967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainarvoid ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE, 1564967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar CheckerContext &C) const { 1574967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (CE->getNumArgs() == 0) 1584967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug("Missing region for obtaining extent", C); 1594967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1604967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar auto MR = dyn_cast_or_null<SubRegion>(C.getSVal(CE->getArg(0)).getAsRegion()); 1614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar if (!MR) 1624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug("Obtaining extent of a non-region", C); 1634967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar 1644967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar ProgramStateRef State = C.getState(); 1654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar State = State->BindExpr(CE, C.getLocationContext(), 1664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar MR->getExtent(C.getSValBuilder())); 1674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar C.addTransition(State); 16887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 16987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 17087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarvoid ExprInspectionChecker::analyzerWarnOnDeadSymbol(const CallExpr *CE, 17187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CheckerContext &C) const { 17287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (CE->getNumArgs() == 0) 17387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return; 17487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SVal Val = C.getSVal(CE->getArg(0)); 17587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar SymbolRef Sym = Val.getAsSymbol(); 17687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!Sym) 17787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return; 17887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 17987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ProgramStateRef State = C.getState(); 18087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar State = State->add<MarkedSymbols>(Sym); 18187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar C.addTransition(State); 18287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar} 18387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 18487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarvoid ExprInspectionChecker::checkDeadSymbols(SymbolReaper &SymReaper, 18587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar CheckerContext &C) const { 18687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ProgramStateRef State = C.getState(); 18787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>(); 18887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) { 1894967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar SymbolRef Sym = *I; 19087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!SymReaper.isDead(Sym)) 19187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar continue; 19287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 1934967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar reportBug("SYMBOL DEAD", C); 1944967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar State = State->remove<MarkedSymbols>(Sym); 19587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 1964967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar C.addTransition(State); 19793a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose} 19893a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 199ac7cc2d37e82181e73fcc265c1d0a619d18b7605Jordan Rosevoid ExprInspectionChecker::analyzerCrash(const CallExpr *CE, 200ac7cc2d37e82181e73fcc265c1d0a619d18b7605Jordan Rose CheckerContext &C) const { 201ac7cc2d37e82181e73fcc265c1d0a619d18b7605Jordan Rose LLVM_BUILTIN_TRAP; 202ac7cc2d37e82181e73fcc265c1d0a619d18b7605Jordan Rose} 203ac7cc2d37e82181e73fcc265c1d0a619d18b7605Jordan Rose 20493a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rosevoid ento::registerExprInspectionChecker(CheckerManager &Mgr) { 20593a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose Mgr.registerChecker<ExprInspectionChecker>(); 20693a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose} 20793a9d828378b5c969344f27aeb275b8c2a19d918Jordy Rose 208