aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-07-26 00:22:32 +0000
committerTed Kremenek <kremenek@apple.com>2012-07-26 00:22:32 +0000
commitfaef9cb6941a3033dc731e1e37d89ec017c5939c (patch)
treea708fde3c505c4b562718c7865a2873f23865ad1 /clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
parent4bfc35509405ff7db4de3003f863d4eeea13ea19 (diff)
downloadllvm-faef9cb6941a3033dc731e1e37d89ec017c5939c.zip
llvm-faef9cb6941a3033dc731e1e37d89ec017c5939c.tar.gz
llvm-faef9cb6941a3033dc731e1e37d89ec017c5939c.tar.bz2
Add static analyzer check for calling a C++ instance method with a null/uninitialized pointer.
llvm-svn: 160767
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp27
1 files changed, 25 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 17ed692a..f3f169b4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -31,6 +31,8 @@ class CallAndMessageChecker
check::PreCall > {
mutable OwningPtr<BugType> BT_call_null;
mutable OwningPtr<BugType> BT_call_undef;
+ mutable OwningPtr<BugType> BT_cxx_call_null;
+ mutable OwningPtr<BugType> BT_cxx_call_undef;
mutable OwningPtr<BugType> BT_call_arg;
mutable OwningPtr<BugType> BT_msg_undef;
mutable OwningPtr<BugType> BT_objc_prop_undef;
@@ -239,14 +241,35 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
+ // If this is a call to a C++ method, check if the callee is null or
+ // undefined.
+ // FIXME: Generalize this to CXXInstanceCall once it supports
+ // getCXXThisVal().
+ if (const CXXMemberCall *CC = dyn_cast<CXXMemberCall>(&Call)) {
+ SVal V = CC->getCXXThisVal();
+ if (V.isUndef()) {
+ if (!BT_cxx_call_undef)
+ BT_cxx_call_undef.reset(new BuiltinBug("Called C++ object pointer is "
+ "uninitialized"));
+ EmitBadCall(BT_cxx_call_undef.get(), C, CC->getOriginExpr());
+ return;
+ }
+ if (V.isZeroConstant()) {
+ if (!BT_cxx_call_null)
+ BT_cxx_call_null.reset(new BuiltinBug("Called C++ object pointer "
+ "is null"));
+ EmitBadCall(BT_cxx_call_null.get(), C, CC->getOriginExpr());
+ return;
+ }
+ }
+
// Don't check for uninitialized field values in arguments if the
// caller has a body that is available and we have the chance to inline it.
// This is a hack, but is a reasonable compromise betweens sometimes warning
// and sometimes not depending on if we decide to inline a function.
const Decl *D = Call.getDecl();
const bool checkUninitFields =
- !(C.getAnalysisManager().shouldInlineCall() &&
- (D && D->getBody()));
+ !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));
OwningPtr<BugType> *BT;
if (isa<ObjCMethodCall>(Call))