class ExplodedGraph;
class GRState;
class EndOfFunctionNodeBuilder;
+ class BranchNodeBuilder;
class MemRegion;
class SymbolReaper;
/// \brief Run checkers for end of path.
void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
+ /// \brief Run checkers for branch condition.
+ void runCheckersForBranchCondition(const Stmt *condition,
+ BranchNodeBuilder &B, ExprEngine &Eng);
+
/// \brief Run checkers for live symbols.
void runCheckersForLiveSymbols(const GRState *state,
SymbolReaper &SymReaper);
typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &>
CheckDeclFunc;
- typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc;
typedef bool (*HandlesDeclFunc)(const Decl *D);
void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
// Internal registration functions for path-sensitive checking.
//===----------------------------------------------------------------------===//
+ typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc;
typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc;
typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &>
CheckLocationFunc;
typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &>
CheckEndAnalysisFunc;
typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc;
+ typedef CheckerFn<const Stmt *, BranchNodeBuilder &, ExprEngine &>
+ CheckBranchConditionFunc;
typedef CheckerFn<SymbolReaper &, CheckerContext &> CheckDeadSymbolsFunc;
typedef CheckerFn<const GRState *, SymbolReaper &> CheckLiveSymbolsFunc;
void _registerForEndPath(CheckEndPathFunc checkfn);
+ void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
+
void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
std::vector<CheckEndPathFunc> EndPathCheckers;
+ std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
+
std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
}
};
+class BranchCondition {
+ template <typename CHECKER>
+ static void _checkBranchCondition(void *checker, const Stmt *condition,
+ BranchNodeBuilder &B, ExprEngine &Eng) {
+ ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForBranchCondition(
+ CheckerManager::CheckBranchConditionFunc(checker,
+ _checkBranchCondition<CHECKER>));
+ }
+};
+
class LiveSymbols {
template <typename CHECKER>
static void _checkLiveSymbols(void *checker, const GRState *state,
let ParentPackage = Core in {
+def UndefBranchChecker : Checker<"UndefBranch">,
+ HelpText<"Check for undefined branch conditions">,
+ DescFile<"UndefBranchChecker.cpp">;
+
def UndefCapturedBlockVarChecker : Checker<"UndefBlockVar">,
HelpText<"Check for blocks that capture uninitialized values">,
DescFile<"UndefCapturedBlockVarChecker.cpp">;
RegisterReturnUndefChecker(Eng);
RegisterUndefinedArraySubscriptChecker(Eng);
RegisterUndefinedAssignmentChecker(Eng);
- RegisterUndefBranchChecker(Eng);
}
ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf)
checker->VisitBranchCondition(builder, *this, Condition, tag);
}
+ getCheckerManager().runCheckersForBranchCondition(Condition, builder, *this);
+
// If the branch condition is undefined, return;
if (!builder.isFeasible(true) && !builder.isFeasible(false))
return;
void RegisterDereferenceChecker(ExprEngine &Eng);
void RegisterDivZeroChecker(ExprEngine &Eng);
void RegisterReturnUndefChecker(ExprEngine &Eng);
-void RegisterUndefBranchChecker(ExprEngine &Eng);
void RegisterUndefinedArraySubscriptChecker(ExprEngine &Eng);
void RegisterUndefinedAssignmentChecker(ExprEngine &Eng);
void RegisterVLASizeChecker(ExprEngine &Eng);
//
//===----------------------------------------------------------------------===//
-#include "InternalChecks.h"
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerV2.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h"
using namespace clang;
using namespace ento;
namespace {
-class UndefBranchChecker : public Checker {
- BuiltinBug *BT;
+class UndefBranchChecker : public CheckerV2<check::BranchCondition> {
+ mutable llvm::OwningPtr<BuiltinBug> BT;
struct FindUndefExpr {
GRStateManager& VM;
};
public:
- UndefBranchChecker() : BT(0) {}
- static void *getTag();
- void VisitBranchCondition(BranchNodeBuilder &Builder, ExprEngine &Eng,
- const Stmt *Condition, void *tag);
+ void checkBranchCondition(const Stmt *Condition, BranchNodeBuilder &Builder,
+ ExprEngine &Eng) const;
};
}
-void ento::RegisterUndefBranchChecker(ExprEngine &Eng) {
- Eng.registerCheck(new UndefBranchChecker());
-}
-
-void *UndefBranchChecker::getTag() {
- static int x;
- return &x;
-}
-
-void UndefBranchChecker::VisitBranchCondition(BranchNodeBuilder &Builder,
- ExprEngine &Eng,
- const Stmt *Condition, void *tag){
+void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
+ BranchNodeBuilder &Builder,
+ ExprEngine &Eng) const {
const GRState *state = Builder.getState();
SVal X = state->getSVal(Condition);
if (X.isUndef()) {
if (N) {
N->markAsSink();
if (!BT)
- BT = new BuiltinBug("Branch condition evaluates to a garbage value");
+ BT.reset(
+ new BuiltinBug("Branch condition evaluates to a garbage value"));
// What's going on here: we want to highlight the subexpression of the
// condition that is the most likely source of the "uninitialized
Builder.markInfeasible(false);
}
}
+
+void ento::registerUndefBranchChecker(CheckerManager &mgr) {
+ mgr.registerChecker<UndefBranchChecker>();
+}
}
}
+/// \brief Run checkers for branch condition.
+void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
+ BranchNodeBuilder &B,
+ ExprEngine &Eng) {
+ for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
+ CheckBranchConditionFunc fn = BranchConditionCheckers[i];
+ fn(condition, B, Eng);
+ }
+}
+
/// \brief Run checkers for live symbols.
void CheckerManager::runCheckersForLiveSymbols(const GRState *state,
SymbolReaper &SymReaper) {
EndPathCheckers.push_back(checkfn);
}
+void CheckerManager::_registerForBranchCondition(
+ CheckBranchConditionFunc checkfn) {
+ BranchConditionCheckers.push_back(checkfn);
+}
+
void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
LiveSymbolsCheckers.push_back(checkfn);
}
-// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-checker=core -analyzer-store region -verify %s
void f1() {
int *n = new int;