summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorGabor Horvath <xazax.hun@gmail.com>2015-03-04 17:59:34 +0000
committerGabor Horvath <xazax.hun@gmail.com>2015-03-04 17:59:34 +0000
commite40c71c10a5ca1c95c43b4cb7380306a6584d0db (patch)
tree7bd03e0967f3750e9a382f98a992b24dcb3ab929 /clang/lib/StaticAnalyzer
parente1d882c726b53eebe4dbece9fdf7fb8dc6469f72 (diff)
downloadbcm5719-llvm-e40c71c10a5ca1c95c43b4cb7380306a6584d0db.tar.gz
bcm5719-llvm-e40c71c10a5ca1c95c43b4cb7380306a6584d0db.zip
[analyzer] Individual configuration options can be specified for checkers.
Reviewed by: Anna Zaks Original patch by: Aleksei Sidorin Differential Revision: http://reviews.llvm.org/D7905 llvm-svn: 231266
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/Checkers.td6
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp44
-rw-r--r--clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp59
3 files changed, 71 insertions, 38 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/clang/lib/StaticAnalyzer/Checkers/Checkers.td
index ba5b4fa3c66..d1d6ac277ff 100644
--- a/clang/lib/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -295,7 +295,7 @@ def UnixAPIChecker : Checker<"API">,
HelpText<"Check calls to various UNIX/Posix functions">,
DescFile<"UnixAPIChecker.cpp">;
-def MallocPessimistic : Checker<"Malloc">,
+def MallocChecker: Checker<"Malloc">,
HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free().">,
DescFile<"MallocChecker.cpp">;
@@ -315,10 +315,6 @@ def ChrootChecker : Checker<"Chroot">,
HelpText<"Check improper use of chroot">,
DescFile<"ChrootChecker.cpp">;
-def MallocOptimistic : Checker<"MallocWithAnnotations">,
- HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free(). Assumes that all user-defined functions which might free a pointer are annotated.">,
- DescFile<"MallocChecker.cpp">;
-
def PthreadLockChecker : Checker<"PthreadLock">,
HelpText<"Simple lock -> unlock checker">,
DescFile<"PthreadLockChecker.cpp">;
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index c2ace7b35db..d77af6a4fb2 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -170,8 +170,7 @@ public:
/// In pessimistic mode, the checker assumes that it does not know which
/// functions might free the memory.
enum CheckKind {
- CK_MallocPessimistic,
- CK_MallocOptimistic,
+ CK_MallocChecker,
CK_NewDeleteChecker,
CK_NewDeleteLeaksChecker,
CK_MismatchedDeallocatorChecker,
@@ -184,6 +183,8 @@ public:
MOK_Any
};
+ DefaultBool IsOptimistic;
+
DefaultBool ChecksEnabled[CK_NumCheckKinds];
CheckName CheckNames[CK_NumCheckKinds];
typedef llvm::SmallVector<CheckKind, CK_NumCheckKinds> CKVecTy;
@@ -584,7 +585,7 @@ bool MallocChecker::isCMemFunction(const FunctionDecl *FD,
if (Family != AF_Malloc)
return false;
- if (ChecksEnabled[CK_MallocOptimistic] && FD->hasAttrs()) {
+ if (IsOptimistic && FD->hasAttrs()) {
for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind();
if(OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds) {
@@ -791,8 +792,7 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
}
}
- if (ChecksEnabled[CK_MallocOptimistic] ||
- ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
+ if (IsOptimistic || ChecksEnabled[CK_MismatchedDeallocatorChecker]) {
// Check all the attributes, if there are any.
// There can be multiple of these attributes.
if (FD->hasAttrs())
@@ -1362,8 +1362,7 @@ MallocChecker::getCheckIfTracked(MallocChecker::CheckKind CK,
case AF_IfNameIndex:
case AF_Alloca: {
// C checkers.
- if (CK == CK_MallocOptimistic ||
- CK == CK_MallocPessimistic) {
+ if (CK == CK_MallocChecker) {
return CK;
}
return Optional<MallocChecker::CheckKind>();
@@ -1516,8 +1515,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
SourceRange Range,
const Expr *DeallocExpr) const {
- auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
- CK_MallocPessimistic,
+ auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocChecker,
CK_NewDeleteChecker),
C, DeallocExpr);
if (!CheckKind.hasValue())
@@ -1559,8 +1557,7 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
SourceRange Range) const {
- auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
- CK_MallocPessimistic,
+ auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocChecker,
CK_MismatchedDeallocatorChecker),
AF_Alloca);
if (!CheckKind.hasValue())
@@ -1639,8 +1636,7 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
const Expr *AllocExpr) const {
- auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
- CK_MallocPessimistic,
+ auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocChecker,
CK_NewDeleteChecker),
C, AllocExpr);
if (!CheckKind.hasValue())
@@ -1692,8 +1688,7 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
SymbolRef Sym) const {
- auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
- CK_MallocPessimistic,
+ auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocChecker,
CK_NewDeleteChecker),
C, Sym);
if (!CheckKind.hasValue())
@@ -1718,8 +1713,7 @@ void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
bool Released, SymbolRef Sym,
SymbolRef PrevSym) const {
- auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
- CK_MallocPessimistic,
+ auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocChecker,
CK_NewDeleteChecker),
C, Sym);
if (!CheckKind.hasValue())
@@ -1934,8 +1928,7 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
CheckerContext &C) const {
- auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
- CK_MallocPessimistic,
+ auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocChecker,
CK_NewDeleteLeaksChecker),
C, Sym);
if (!CheckKind.hasValue())
@@ -2058,8 +2051,7 @@ void MallocChecker::checkPreCall(const CallEvent &Call,
return;
ASTContext &Ctx = C.getASTContext();
- if ((ChecksEnabled[CK_MallocOptimistic] ||
- ChecksEnabled[CK_MallocPessimistic]) &&
+ if (ChecksEnabled[CK_MallocChecker] &&
(isCMemFunction(FD, Ctx, AF_Malloc, MemoryOperationKind::MOK_Free) ||
isCMemFunction(FD, Ctx, AF_IfNameIndex,
MemoryOperationKind::MOK_Free)))
@@ -2551,8 +2543,7 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
const RefState *RefS = State->get<RegionState>(I.getKey());
AllocationFamily Family = RefS->getAllocationFamily();
- auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocOptimistic,
- CK_MallocPessimistic,
+ auto CheckKind = getCheckIfTracked(MakeVecFromCK(CK_MallocChecker,
CK_NewDeleteChecker),
Family);
I.getKey()->dumpToStream(Out);
@@ -2568,6 +2559,8 @@ void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
registerCStringCheckerBasic(mgr);
MallocChecker *checker = mgr.registerChecker<MallocChecker>();
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption(
+ "Optimistic", false, checker);
checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] = true;
checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
mgr.getCurrentCheckName();
@@ -2581,11 +2574,12 @@ void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
void ento::register##name(CheckerManager &mgr) { \
registerCStringCheckerBasic(mgr); \
MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \
+ "Optimistic", false, checker); \
checker->ChecksEnabled[MallocChecker::CK_##name] = true; \
checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
}
-REGISTER_CHECKER(MallocPessimistic)
-REGISTER_CHECKER(MallocOptimistic)
+REGISTER_CHECKER(MallocChecker)
REGISTER_CHECKER(NewDeleteChecker)
REGISTER_CHECKER(MismatchedDeallocatorChecker)
diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index d717e3fe86d..1696bcfac9c 100644
--- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -13,12 +13,14 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+using namespace ento;
using namespace llvm;
AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
@@ -100,12 +102,37 @@ AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) {
static StringRef toString(bool b) { return b ? "true" : "false"; }
-bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) {
+StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
+ StringRef OptionName,
+ StringRef Default,
+ bool SearchInParents) {
+ // Search for a package option if the option for the checker is not specified
+ // and search in parents is enabled.
+ ConfigTable::const_iterator E = Config.end();
+ do {
+ ConfigTable::const_iterator I =
+ Config.find((Twine(CheckerName) + ":" + OptionName).str());
+ if (I != E)
+ return StringRef(I->getValue());
+ size_t Pos = CheckerName.rfind('.');
+ if (Pos == StringRef::npos)
+ return Default;
+ CheckerName = CheckerName.substr(0, Pos);
+ } while (!CheckerName.empty() && SearchInParents);
+ return Default;
+}
+
+bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) {
// FIXME: We should emit a warning here if the value is something other than
// "true", "false", or the empty string (meaning the default value),
// but the AnalyzerOptions doesn't have access to a diagnostic engine.
+ StringRef Default = toString(DefaultVal);
StringRef V =
- Config.insert(std::make_pair(Name, toString(DefaultVal))).first->second;
+ C ? getCheckerOption(C->getTagDescription(), Name, Default,
+ SearchInParents)
+ : StringRef(Config.insert(std::make_pair(Name, Default)).first->second);
return llvm::StringSwitch<bool>(V)
.Case("true", true)
.Case("false", false)
@@ -113,9 +140,10 @@ bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) {
}
bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
- bool DefaultVal) {
+ bool DefaultVal, const CheckerBase *C,
+ bool SearchInParents) {
if (!V.hasValue())
- V = getBooleanOption(Name, DefaultVal);
+ V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
return V.getValue();
}
@@ -199,19 +227,35 @@ bool AnalyzerOptions::shouldWriteStableReportFilename() {
/* Default = */ false);
}
-int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) {
+int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) {
SmallString<10> StrBuf;
llvm::raw_svector_ostream OS(StrBuf);
OS << DefaultVal;
- StringRef V = Config.insert(std::make_pair(Name, OS.str())).first->second;
+ StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
+ SearchInParents)
+ : StringRef(Config.insert(std::make_pair(Name, OS.str()))
+ .first->second);
+
int Res = DefaultVal;
bool b = V.getAsInteger(10, Res);
assert(!b && "analyzer-config option should be numeric");
- (void) b;
+ (void)b;
return Res;
}
+StringRef AnalyzerOptions::getOptionAsString(StringRef Name,
+ StringRef DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) {
+ return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
+ SearchInParents)
+ : StringRef(
+ Config.insert(std::make_pair(Name, DefaultVal)).first->second);
+}
+
unsigned AnalyzerOptions::getAlwaysInlineSize() {
if (!AlwaysInlineSize.hasValue())
AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
@@ -281,4 +325,3 @@ bool AnalyzerOptions::shouldPrunePaths() {
bool AnalyzerOptions::shouldConditionalizeStaticInitializers() {
return getBooleanOption("cfg-conditional-static-initializers", true);
}
-
OpenPOWER on IntegriCloud