summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/GRSimpleVals.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-07-22 00:46:16 +0000
committerTed Kremenek <kremenek@apple.com>2008-07-22 00:46:16 +0000
commit98f6e582f2f03500d9830287225fa5e1b09657f0 (patch)
treedac33fd431d7d7ea6739409be959da572428adfb /clang/lib/Analysis/GRSimpleVals.cpp
parentcf971f0513207738cf2cfde5aaf6b9352d47fb1d (diff)
downloadbcm5719-llvm-98f6e582f2f03500d9830287225fa5e1b09657f0.tar.gz
bcm5719-llvm-98f6e582f2f03500d9830287225fa5e1b09657f0.zip
Added path-sensitive checking for null pointer values passed to function arguments marked nonnull.
This implements <rdar://problem/6069935> llvm-svn: 53891
Diffstat (limited to 'clang/lib/Analysis/GRSimpleVals.cpp')
-rw-r--r--clang/lib/Analysis/GRSimpleVals.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/clang/lib/Analysis/GRSimpleVals.cpp b/clang/lib/Analysis/GRSimpleVals.cpp
index 36e7233f25f..38327cbad5b 100644
--- a/clang/lib/Analysis/GRSimpleVals.cpp
+++ b/clang/lib/Analysis/GRSimpleVals.cpp
@@ -335,6 +335,63 @@ void UndefBranch::EmitWarnings(BugReporter& BR) {
}
}
+//===----------------------------------------------------------------------===//
+// __attribute__(nonnull) checking
+
+class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
+ SimpleBugType BT;
+ std::list<RangedBugReport> Reports;
+
+public:
+ CheckAttrNonNull() :
+ BT("'nonnull' argument passed null",
+ "Null pointer passed as an argument to a 'nonnull' parameter") {}
+
+
+ virtual bool Audit(ExplodedNode<ValueState>* N, ValueStateManager& VMgr) {
+ CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
+ const ValueState* state = N->getState();
+
+ RVal X = VMgr.GetRVal(state, CE->getCallee());
+
+ if (!isa<lval::FuncVal>(X))
+ return false;
+
+ FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<lval::FuncVal>(X).getDecl());
+ const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
+
+ if (!Att)
+ return false;
+
+ // Iterate through the arguments of CE and check them for null.
+
+ unsigned idx = 0;
+ bool hasError = false;
+
+ for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
+ ++I, ++idx) {
+
+ if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
+ continue;
+
+ RangedBugReport R(BT, N);
+ R.addRange((*I)->getSourceRange());
+ Reports.push_back(R);
+ hasError = true;
+ }
+
+ return hasError;
+ }
+
+ virtual void EmitWarnings(BugReporter& BR) {
+ for (std::list<RangedBugReport>::iterator I=Reports.begin(),
+ E=Reports.end(); I!=E; ++I)
+ BR.EmitWarning(*I);
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Check registration.
void GRSimpleVals::RegisterChecks(GRExprEngine& Eng) {
@@ -360,6 +417,7 @@ void GRSimpleVals::RegisterChecks(GRExprEngine& Eng) {
Check = CreateAuditCFNumberCreate(Ctx, VMgr);
Eng.AddCheck(Check, Stmt::CallExprClass);
+ Eng.AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
}
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud