diff options
| author | Ted Kremenek <kremenek@apple.com> | 2012-07-26 00:22:32 +0000 |
|---|---|---|
| committer | Ted Kremenek <kremenek@apple.com> | 2012-07-26 00:22:32 +0000 |
| commit | faef9cb6941a3033dc731e1e37d89ec017c5939c (patch) | |
| tree | a708fde3c505c4b562718c7865a2873f23865ad1 /clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp | |
| parent | 4bfc35509405ff7db4de3003f863d4eeea13ea19 (diff) | |
| download | llvm-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.cpp | 27 |
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)) |
