From 9a5bca34ca09d3a88c2ccb4f53b27cf99de4f182 Mon Sep 17 00:00:00 2001 From: Zhongxing Xu Date: Sat, 29 Aug 2009 02:11:01 +0000 Subject: [PATCH] Refactor undefined argument checking into a Checker. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80417 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/GRExprEngine.cpp | 25 +---------- lib/Analysis/GRExprEngineInternalChecks.cpp | 47 ++++++++++++++++++++- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index de0209a3a1..d66dfffd31 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1626,30 +1626,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred, default: break; } - } - - // Check any arguments passed-by-value against being undefined. - - bool badArg = false; - - for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); - I != E; ++I) { - - if (GetState(*DI)->getSVal(*I).isUndef()) { - ExplodedNode* N = Builder->generateNode(CE, GetState(*DI), *DI); - - if (N) { - N->markAsSink(); - UndefArgs[N] = *I; - } - - badArg = true; - break; - } - } - - if (badArg) - continue; + } // Dispatch to the plug-in transfer function. diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index 1b2fd1cb9f..35ca0c5dfb 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -245,7 +245,12 @@ public: ExplodedNode *n, const Stmt *arg) : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {} - const Stmt *getArg() const { return Arg; } + const Stmt *getArg() const { return Arg; } + + void registerInitialVisitors(BugReporterContext& BRC, + const ExplodedNode* N) { + registerTrackNullOrUndefValue(BRC, getArg(), N); + } }; class VISIBILITY_HIDDEN BadArg : public BuiltinBug { @@ -629,6 +634,44 @@ public: }; } // end anonymous namespace +// Undefined arguments checking. +namespace { +class VISIBILITY_HIDDEN CheckUndefinedArg + : public CheckerVisitor { + + BugType *BT; + +public: + CheckUndefinedArg() : BT(0) {} + ~CheckUndefinedArg() {} + + const void *getTag() { + static int x = 0; + return &x; + } + + void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); +}; + +void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){ + for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); + I != E; ++I) { + if (C.getState()->getSVal(*I).isUndef()) { + if (ExplodedNode *ErrorNode = C.generateNode(CE, C.getState(), true)) { + if (!BT) + BT = new BugType("Uninitialized argument.", "Logic Errors."); + // Generate a report for this bug. + ArgReport *Report = new ArgReport(*BT, + "Pass-by-value argument in function call is undefined.", + ErrorNode, *I); + Report->addRange((*I)->getSourceRange()); + C.EmitReport(Report); + } + } + } +} + +} //===----------------------------------------------------------------------===// // Check registration. //===----------------------------------------------------------------------===// @@ -647,7 +690,6 @@ void GRExprEngine::RegisterInternalChecks() { BR.Register(new BadCall(this)); BR.Register(new RetStack(this)); BR.Register(new RetUndef(this)); - BR.Register(new BadArg(this)); BR.Register(new BadMsgExprArg(this)); BR.Register(new BadReceiver(this)); BR.Register(new OutOfBoundMemoryAccess(this)); @@ -661,4 +703,5 @@ void GRExprEngine::RegisterInternalChecks() { // automatically. Note that the check itself is owned by the GRExprEngine // object. registerCheck(new CheckAttrNonNull()); + registerCheck(new CheckUndefinedArg()); }