diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-11-21 00:49:41 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-11-21 00:49:41 +0000 |
commit | 64fa85855638d69e56ed1b2fad7ed65deb3ecdfd (patch) | |
tree | e36a30cd73b3e01dfac5715112ae8e16bd2967f0 | |
parent | 75ee3bd6e7ed2b4286d5e717ae7b94411f90b3b9 (diff) |
More checker refactoring. Passing undefined values in a message expression is now handled by UndefinedArgChecker.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89519 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 14 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 20 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngineInternalChecks.cpp | 39 | ||||
-rw-r--r-- | lib/Analysis/UndefinedArgChecker.cpp | 40 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 20 |
5 files changed, 54 insertions, 79 deletions
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 58a894e458..75f04b6234 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -89,7 +89,6 @@ class GRExprEngine : public GRSubEngine { public: typedef llvm::SmallPtrSet<ExplodedNode*,2> ErrorNodes; - typedef llvm::DenseMap<ExplodedNode*, Expr*> UndefArgsTy; /// NilReceiverStructRetExplicit - Nodes in the ExplodedGraph that resulted /// from [x ...] with 'x' definitely being nil and the result was a 'struct' @@ -131,11 +130,6 @@ public: /// ObjC message expressions where the receiver is undefined (uninitialized). ErrorNodes UndefReceivers; - /// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from - /// message expressions where a pass-by-value argument has an undefined - /// value. - UndefArgsTy MsgExprUndefArgs; - public: GRExprEngine(AnalysisManager &mgr); @@ -229,14 +223,6 @@ public: undef_result_iterator undef_results_begin() { return UndefResults.begin(); } undef_result_iterator undef_results_end() { return UndefResults.end(); } - typedef UndefArgsTy::iterator undef_arg_iterator; - undef_arg_iterator msg_expr_undef_arg_begin() { - return MsgExprUndefArgs.begin(); - } - undef_arg_iterator msg_expr_undef_arg_end() { - return MsgExprUndefArgs.end(); - } - typedef ErrorNodes::iterator undef_receivers_iterator; undef_receivers_iterator undef_receivers_begin() { diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 2b4b5ae1a5..047e27dabd 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1998,26 +1998,6 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, } } - // Check for any arguments that are uninitialized/undefined. - - for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end(); - I != E; ++I) { - - if (state->getSVal(*I).isUndef()) { - - // Generate an error node for passing an uninitialized/undefined value - // as an argument to a message expression. This node is a sink. - ExplodedNode* N = Builder->generateNode(ME, state, Pred); - - if (N) { - N->markAsSink(); - MsgExprUndefArgs[N] = *I; - } - - return; - } - } - // Handle previsits checks. ExplodedNodeSet Src, DstTmp; Src.Add(Pred); diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index d0f60fde5b..50e855fda9 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -34,11 +34,6 @@ ExplodedNode* GetNode(ITERATOR I) { return *I; } -template <> inline -ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) { - return I->first; -} - //===----------------------------------------------------------------------===// // Bug Descriptions. //===----------------------------------------------------------------------===// @@ -224,39 +219,6 @@ public: const Stmt *getArg() const { return Arg; } }; -class VISIBILITY_HIDDEN BadArg : public BuiltinBug { -public: - BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument", - "Pass-by-value argument in function call is undefined") {} - - BadArg(GRExprEngine* eng, const char* d) - : BuiltinBug(eng,"Uninitialized argument", d) {} - - void registerInitialVisitors(BugReporterContext& BRC, - const ExplodedNode* N, - BuiltinBugReport *R) { - registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(), - N); - } -}; - -class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg { -public: - BadMsgExprArg(GRExprEngine* eng) - : BadArg(eng,"Pass-by-value argument in message expression is undefined"){} - - void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) { - for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(), - E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) { - // Generate a report for this bug. - ArgReport *report = new ArgReport(*this, desc.c_str(), I->first, - I->second); - report->addRange(I->second->getSourceRange()); - BR.EmitReport(report); - } - } -}; - class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug { public: BadReceiver(GRExprEngine* eng) @@ -375,7 +337,6 @@ void GRExprEngine::RegisterInternalChecks() { // to 'FlushReports' from BugReporter. BR.Register(new UndefBranch(this)); BR.Register(new UndefResult(this)); - BR.Register(new BadMsgExprArg(this)); BR.Register(new BadReceiver(this)); BR.Register(new NilReceiverStructRet(this)); BR.Register(new NilReceiverLargerThanVoidPtrRet(this)); diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp index 923a7e1bed..a0c0d48712 100644 --- a/lib/Analysis/UndefinedArgChecker.cpp +++ b/lib/Analysis/UndefinedArgChecker.cpp @@ -21,14 +21,16 @@ using namespace clang; namespace { class VISIBILITY_HIDDEN UndefinedArgChecker : public CheckerVisitor<UndefinedArgChecker> { - BugType *BT; + BugType *BT_call; + BugType *BT_msg; public: - UndefinedArgChecker() : BT(0) {} + UndefinedArgChecker() : BT_call(0), BT_msg(0) {} static void *getTag() { static int x = 0; return &x; } void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); + void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME); }; } // end anonymous namespace @@ -42,14 +44,40 @@ void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C, I != E; ++I) { if (C.getState()->getSVal(*I).isUndef()) { if (ExplodedNode *N = C.GenerateNode(CE, true)) { - if (!BT) - BT = new BuiltinBug("Pass-by-value argument in function call is " - "undefined"); + if (!BT_call) + BT_call = new BuiltinBug("Pass-by-value argument in function call is " + "undefined"); // Generate a report for this bug. - EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N); + EnhancedBugReport *R = new EnhancedBugReport(*BT_call, + BT_call->getName(), N); R->addRange((*I)->getSourceRange()); R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I); C.EmitReport(R); + return; + } + } + } +} + +void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C, + const ObjCMessageExpr *ME) { + + // Check for any arguments that are uninitialized/undefined. + const GRState *state = C.getState(); + for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(), E = ME->arg_end(); + I != E; ++I) { + if (state->getSVal(*I).isUndef()) { + if (ExplodedNode *N = C.GenerateNode(ME, true)) { + if (!BT_msg) + BT_msg = new BuiltinBug("Pass-by-value argument in message expression" + " is undefined"); + // Generate a report for this bug. + EnhancedBugReport *R = new EnhancedBugReport(*BT_msg, BT_msg->getName(), + N); + R->addRange((*I)->getSourceRange()); + R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I); + C.EmitReport(R); + return; } } } diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index d2eef0d7fd..85095f4e07 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -750,3 +750,23 @@ void test_undefined_array_subscript() { int *p = &a[i]; // expected-warning{{Array subscript is undefined}} } @end + +//===----------------------------------------------------------------------===// +// Test passing an undefined value in a message or function call. +//===----------------------------------------------------------------------===// + +void test_bad_call_aux(int x); +void test_bad_call(void) { + int y; + test_bad_call_aux(y); // expected-warning{{Pass-by-value argument in function call is undefined}} +} + +@interface TestBadArg {} +- (void) testBadArg:(int) x; +@end + +void test_bad_msg(TestBadArg *p) { + int y; + [p testBadArg:y]; // expected-warning{{Pass-by-value argument in message expression is undefined}} +} + |