//=-- GRExprEngineInternalChecks.cpp - Builtin GRExprEngine Checks---*- C++ -*-=
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the BugType classes used by GRExprEngine to report
// bugs derived from builtin checks in the path-sensitive engine.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
template <typename ITERATOR> inline
ExplodedNode<GRState>* GetNode(ITERATOR I) {
return *I;
}
template <> inline
ExplodedNode<GRState>* GetNode(GRExprEngine::undef_arg_iterator I) {
return I->first;
}
//===----------------------------------------------------------------------===//
// Forward declarations for bug reporter visitors.
//===----------------------------------------------------------------------===//
static const Stmt *GetDerefExpr(const ExplodedNode<GRState> *N);
static const Stmt *GetReceiverExpr(const ExplodedNode<GRState> *N);
static const Stmt *GetDenomExpr(const ExplodedNode<GRState> *N);
static const Stmt *GetCalleeExpr(const ExplodedNode<GRState> *N);
static const Stmt *GetRetValExpr(const ExplodedNode<GRState> *N);
static void registerTrackNullOrUndefValue(BugReporterContext& BRC,
const Stmt *ValExpr,
const ExplodedNode<GRState>* N);
//===----------------------------------------------------------------------===//
// Bug Descriptions.
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN BuiltinBugReport : public RangedBugReport {
public:
BuiltinBugReport(BugType& bt, const char* desc,
ExplodedNode<GRState> *n)
: RangedBugReport(bt, desc, n) {}
BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
ExplodedNode<GRState> *n)
: RangedBugReport(bt, shortDesc, desc, n) {}
void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode<GRState>* N);
};
class VISIBILITY_HIDDEN BuiltinBug : public BugType {
GRExprEngine &Eng;
protected:
const std::string desc;
public:
BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
: BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
BuiltinBug(GRExprEngine *eng, const char* n)
: BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) = 0;
void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
virtual void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode<GRState>* N,
BuiltinBugReport *R) {}
template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
};
template <typename ITER>
void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
GetNode(I)));
}
void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode<GRState>* N) {
static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
}
class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
public:
NullDeref(GRExprEngine* eng)
: BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
}
void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode<GRState>* N,
BuiltinBugReport *R) {
registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
}
};
class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
public:
NilReceiverStructRet(GRExprEngine* eng) :
BuiltinBug(eng, "'nil' receiver with struct return type") {}