[cfe-commits] r162637 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/CheckerManager.h include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/StaticAnalyzer/Core/BugReporterVisitors.cpp lib/StaticAnalyzer/Core/CheckerManager.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/initializer.cpp
Jordan Rose
jordan_rose at apple.com
Fri Aug 24 18:06:23 PDT 2012
Author: jrose
Date: Fri Aug 24 20:06:23 2012
New Revision: 162637
URL: http://llvm.org/viewvc/llvm-project?rev=162637&view=rev
Log:
[analyzer] Use the common evalBind infrastructure for initializers.
This allows checkers (like the MallocChecker) to process the effects of the
bind. Previously, using a memory-allocating function (like strdup()) in an
initializer would result in a leak warning.
This does bend the expectations of checkBind a bit; since there is no
assignment expression, the statement being used is the initializer value.
In most cases this shouldn't matter because we'll use a PostInitializer
program point (rather than PostStmt) for any checker-generated nodes, though
we /will/ generate a PostStore node referencing the internal statement.
(In theory this could have funny effects if someone actually does an
assignment within an initializer; in practice, that seems like it would be
very rare.)
<rdar://problem/12171711>
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Analysis/initializer.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=162637&r1=162636&r2=162637&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Fri Aug 24 20:06:23 2012
@@ -258,7 +258,7 @@
const ExplodedNodeSet &Src,
SVal location, SVal val,
const Stmt *S, ExprEngine &Eng,
- ProgramPoint::Kind PointKind);
+ const ProgramPoint &PP);
/// \brief Run checkers for end of analysis.
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=162637&r1=162636&r2=162637&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Fri Aug 24 20:06:23 2012
@@ -434,7 +434,8 @@
/// evalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by evalStore, VisitDeclStmt, and others.
void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
- SVal location, SVal Val, bool atDeclInit = false);
+ SVal location, SVal Val, bool atDeclInit = false,
+ const ProgramPoint *PP = 0);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp?rev=162637&r1=162636&r2=162637&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp Fri Aug 24 20:06:23 2012
@@ -32,7 +32,11 @@
const Stmt *bugreporter::GetDerefExpr(const ExplodedNode *N) {
// Pattern match for a few useful cases (do something smarter later):
// a[0], p->f, *p
- const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
+ const PostStmt *Loc = N->getLocationAs<PostStmt>();
+ if (!Loc)
+ return 0;
+
+ const Stmt *S = Loc->getStmt();
while (true) {
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=162637&r1=162636&r2=162637&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Fri Aug 24 20:06:23 2012
@@ -314,20 +314,19 @@
SVal Val;
const Stmt *S;
ExprEngine &Eng;
- ProgramPoint::Kind PointKind;
+ const ProgramPoint &PP;
CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
CheckBindContext(const CheckersTy &checkers,
SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
- ProgramPoint::Kind PK)
- : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {}
+ const ProgramPoint &pp)
+ : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
void runChecker(CheckerManager::CheckBindFunc checkFn,
NodeBuilder &Bldr, ExplodedNode *Pred) {
- const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind,
- Pred->getLocationContext(), checkFn.Checker);
+ const ProgramPoint &L = PP.withTag(checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
checkFn(Loc, Val, S, C);
@@ -340,8 +339,8 @@
const ExplodedNodeSet &Src,
SVal location, SVal val,
const Stmt *S, ExprEngine &Eng,
- ProgramPoint::Kind PointKind) {
- CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind);
+ const ProgramPoint &PP) {
+ CheckBindContext C(BindCheckers, location, val, S, Eng, PP);
expandGraphWithCheckers(C, Dst, Src);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=162637&r1=162636&r2=162637&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Aug 24 20:06:23 2012
@@ -354,11 +354,6 @@
void ExprEngine::ProcessInitializer(const CFGInitializer Init,
ExplodedNode *Pred) {
- ExplodedNodeSet Dst;
- NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
-
- ProgramStateRef State = Pred->getState();
-
const CXXCtorInitializer *BMI = Init.getInitializer();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
@@ -370,13 +365,19 @@
cast<StackFrameContext>(Pred->getLocationContext());
const CXXConstructorDecl *decl =
cast<CXXConstructorDecl>(stackFrame->getDecl());
+
+ ProgramStateRef State = Pred->getState();
SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
+ PostInitializer PP(BMI, stackFrame);
+ ExplodedNodeSet Tmp(Pred);
+
// Evaluate the initializer, if necessary
if (BMI->isAnyMemberInitializer()) {
// Constructors build the object directly in the field,
// but non-objects must be copied in from the initializer.
- if (!isa<CXXConstructExpr>(BMI->getInit())) {
+ const Expr *Init = BMI->getInit();
+ if (!isa<CXXConstructExpr>(Init)) {
SVal FieldLoc;
if (BMI->isIndirectMemberInitializer())
FieldLoc = State->getLValue(BMI->getIndirectMember(), thisVal);
@@ -384,19 +385,23 @@
FieldLoc = State->getLValue(BMI->getMember(), thisVal);
SVal InitVal = State->getSVal(BMI->getInit(), stackFrame);
- State = State->bindLoc(FieldLoc, InitVal);
+
+ Tmp.clear();
+ evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);
}
} else {
assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer());
// We already did all the work when visiting the CXXConstructExpr.
}
- // Construct a PostInitializer node whether the state changed or not,
+ // Construct PostInitializer nodes whether the state changed or not,
// so that the diagnostics don't get confused.
- PostInitializer PP(BMI, stackFrame);
- // Builder automatically add the generated node to the deferred set,
- // which are processed in the builder's dtor.
- Bldr.generateNode(PP, State, Pred);
+ ExplodedNodeSet Dst;
+ NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
+ ExplodedNode *N = *I;
+ Bldr.generateNode(PP, N->getState(), N);
+ }
// Enqueue the new nodes onto the work list.
Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
@@ -1541,13 +1546,17 @@
void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
ExplodedNode *Pred,
SVal location, SVal Val,
- bool atDeclInit) {
+ bool atDeclInit, const ProgramPoint *PP) {
+
+ const LocationContext *LC = Pred->getLocationContext();
+ PostStmt PS(StoreE, LC);
+ if (!PP)
+ PP = &PS;
// Do a previsit of the bind.
ExplodedNodeSet CheckedSet;
getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
- StoreE, *this,
- ProgramPoint::PostStmtKind);
+ StoreE, *this, *PP);
// If the location is not a 'Loc', it will already be handled by
// the checkers. There is nothing left to do.
@@ -1559,7 +1568,6 @@
ExplodedNodeSet TmpDst;
StmtNodeBuilder Bldr(CheckedSet, TmpDst, *currBldrCtx);
- const LocationContext *LC = Pred->getLocationContext();
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
ExplodedNode *PredI = *I;
@@ -1575,6 +1583,7 @@
if (loc::MemRegionVal *LocRegVal = dyn_cast<loc::MemRegionVal>(&location)) {
LocReg = LocRegVal->getRegion();
}
+
const ProgramPoint L = PostStore(StoreE, LC, LocReg, 0);
Bldr.generateNode(L, state, PredI);
}
Modified: cfe/trunk/test/Analysis/initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/initializer.cpp?rev=162637&r1=162636&r2=162637&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/initializer.cpp (original)
+++ cfe/trunk/test/Analysis/initializer.cpp Fri Aug 24 20:06:23 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -cfg-add-implicit-dtors -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-ipa=inlining -cfg-add-implicit-dtors -std=c++11 -verify %s
// We don't inline constructors unless we have destructors turned on.
@@ -57,10 +57,6 @@
}
-// ------------------------------------
-// False negatives
-// ------------------------------------
-
struct RefWrapper {
RefWrapper(int *p) : x(*p) {}
RefWrapper(int &r) : x(r) {}
@@ -69,10 +65,20 @@
void testReferenceMember() {
int *p = 0;
- RefWrapper X(p); // should warn in the constructor
+ RefWrapper X(p); // expected-warning at 61 {{Dereference of null pointer}}
}
void testReferenceMember2() {
int *p = 0;
- RefWrapper X(*p); // should warn here
+ // FIXME: We should warn here, since we're creating the reference here.
+ RefWrapper X(*p); // expected-warning at 62 {{Dereference of null pointer}}
}
+
+
+extern "C" char *strdup(const char *);
+
+class StringWrapper {
+ char *str;
+public:
+ StringWrapper(const char *input) : str(strdup(input)) {} // no-warning
+};
More information about the cfe-commits
mailing list