From 55037cdc2e29b70df2fd1ca0ba9d4c36da1049e8 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Mon, 2 Jul 2012 19:27:46 +0000 Subject: [PATCH] [analyzer] Convert CallAndMessageChecker and ObjCSelfInitChecker to CallEvent. Both of these got uglier rather than cleaner because we don't have preCall and postCall yet; properly wrapping a CallExpr in a CallEvent requires doing a bit of deconstruction on the callee. Even when we have preCall and postCall we may want to expose the current CallEvent to pre/postStmt. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159556 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/CallAndMessageChecker.cpp | 43 ++++++++++------ .../Checkers/ObjCSelfInitChecker.cpp | 49 +++++++++++++++---- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 6d9ce0a6c5..11a9ab373c 100644 --- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -15,6 +15,7 @@ #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -41,7 +42,7 @@ public: void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; private: - static void PreVisitProcessArgs(CheckerContext &C,CallOrObjCMessage callOrMsg, + static void PreVisitProcessArgs(CheckerContext &C, const CallEvent &Call, const char *BT_desc, OwningPtr &BT); static bool PreVisitProcessArg(CheckerContext &C, SVal V,SourceRange argRange, const Expr *argEx, @@ -77,23 +78,22 @@ void CallAndMessageChecker::EmitBadCall(BugType *BT, CheckerContext &C, } void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C, - CallOrObjCMessage callOrMsg, + const CallEvent &Call, const char *BT_desc, OwningPtr &BT) { // 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 = callOrMsg.getDecl(); + const Decl *D = Call.getDecl(); const bool checkUninitFields = !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody())); - for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i) - if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i), - callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i), - checkUninitFields, - BT_desc, BT)) + for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) + if (PreVisitProcessArg(C, Call.getArgSVal(i), + Call.getArgSourceRange(i), Call.getArgExpr(i), + checkUninitFields, BT_desc, BT)) return; } @@ -210,8 +210,9 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const{ const Expr *Callee = CE->getCallee()->IgnoreParens(); + ProgramStateRef State = C.getState(); const LocationContext *LCtx = C.getLocationContext(); - SVal L = C.getState()->getSVal(Callee, LCtx); + SVal L = State->getSVal(Callee, LCtx); if (L.isUndef()) { if (!BT_call_undef) @@ -221,16 +222,30 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, return; } - if (isa(L)) { + if (L.isZeroConstant()) { if (!BT_call_null) BT_call_null.reset( new BuiltinBug("Called function pointer is null (null dereference)")); EmitBadCall(BT_call_null.get(), C, CE); } - PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState(), LCtx), - "Function call argument is an uninitialized value", - BT_call_arg); + // FIXME: This tree of switching can go away if/when we add a check::postCall. + if (dyn_cast_or_null(L.getAsRegion())) { + BlockCall Call(CE, State, LCtx); + PreVisitProcessArgs(C, Call, + "Block call argument is an uninitialized value", + BT_call_arg); + } else if (const CXXMemberCallExpr *me = dyn_cast(CE)) { + CXXMemberCall Call(me, State, LCtx); + PreVisitProcessArgs(C, Call, + "Function call argument is an uninitialized value", + BT_call_arg); + } else { + FunctionCall Call(CE, State, LCtx); + PreVisitProcessArgs(C, Call, + "Function call argument is an uninitialized value", + BT_call_arg); + } } void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, @@ -285,7 +300,7 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, "Argument for property setter is an uninitialized value" : "Argument in message expression is an uninitialized value"; // Check for any arguments that are uninitialized/undefined. - PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx), + PreVisitProcessArgs(C, ObjCMessageInvocation(msg, state, LCtx), bugDesc, BT_msg_arg); } diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 89340cc290..bb6ab6f2e3 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -39,6 +39,7 @@ #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" @@ -73,8 +74,8 @@ public: CheckerContext &C) const; void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const; - void checkPreStmt(const CallOrObjCMessage &CE, CheckerContext &C) const; - void checkPostStmt(const CallOrObjCMessage &CE, CheckerContext &C) const; + void checkPreStmt(const CallEvent &CE, CheckerContext &C) const; + void checkPostStmt(const CallEvent &CE, CheckerContext &C) const; }; } // end anonymous namespace @@ -208,7 +209,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg, return; } - CallOrObjCMessage MsgWrapper(msg, C.getState(), C.getLocationContext()); + ObjCMessageInvocation MsgWrapper(msg, C.getState(), C.getLocationContext()); checkPostStmt(MsgWrapper, C); // We don't check for an invalid 'self' in an obj-c message expression to cut @@ -259,23 +260,51 @@ void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S, void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { - CallOrObjCMessage CEWrapper(CE, C.getState(), C.getLocationContext()); - checkPreStmt(CEWrapper, C); + // FIXME: This tree of switching can go away if/when we add a check::postCall. + const Expr *Callee = CE->getCallee()->IgnoreParens(); + ProgramStateRef State = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); + SVal L = State->getSVal(Callee, LCtx); + + if (dyn_cast_or_null(L.getAsRegion())) { + BlockCall Call(CE, State, LCtx); + checkPreStmt(Call, C); + } else if (const CXXMemberCallExpr *me = dyn_cast(CE)) { + CXXMemberCall Call(me, State, LCtx); + checkPreStmt(Call, C); + } else { + FunctionCall Call(CE, State, LCtx); + checkPreStmt(Call, C); + } } void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { - CallOrObjCMessage CEWrapper(CE, C.getState(), C.getLocationContext()); - checkPostStmt(CEWrapper, C); + // FIXME: This tree of switching can go away if/when we add a check::postCall. + const Expr *Callee = CE->getCallee()->IgnoreParens(); + ProgramStateRef State = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); + SVal L = State->getSVal(Callee, LCtx); + + if (dyn_cast_or_null(L.getAsRegion())) { + BlockCall Call(CE, State, LCtx); + checkPostStmt(Call, C); + } else if (const CXXMemberCallExpr *me = dyn_cast(CE)) { + CXXMemberCall Call(me, State, LCtx); + checkPostStmt(Call, C); + } else { + FunctionCall Call(CE, State, LCtx); + checkPostStmt(Call, C); + } } void ObjCSelfInitChecker::checkPreObjCMessage(ObjCMessage Msg, CheckerContext &C) const { - CallOrObjCMessage MsgWrapper(Msg, C.getState(), C.getLocationContext()); + ObjCMessageInvocation MsgWrapper(Msg, C.getState(), C.getLocationContext()); checkPreStmt(MsgWrapper, C); } -void ObjCSelfInitChecker::checkPreStmt(const CallOrObjCMessage &CE, +void ObjCSelfInitChecker::checkPreStmt(const CallEvent &CE, CheckerContext &C) const { ProgramStateRef state = C.getState(); unsigned NumArgs = CE.getNumArgs(); @@ -298,7 +327,7 @@ void ObjCSelfInitChecker::checkPreStmt(const CallOrObjCMessage &CE, } } -void ObjCSelfInitChecker::checkPostStmt(const CallOrObjCMessage &CE, +void ObjCSelfInitChecker::checkPostStmt(const CallEvent &CE, CheckerContext &C) const { ProgramStateRef state = C.getState(); unsigned NumArgs = CE.getNumArgs(); -- 2.40.0