blob: a0c0d48712951cd40721932223481ddd98893c81 [file] [log] [blame]
Zhongxing Xu8958fff2009-11-03 06:46:03 +00001//===--- UndefinedArgChecker.h - Undefined arguments checker ----*- C++ -*--==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This defines BadCallChecker, a builtin check in GRExprEngine that performs
11// checks for undefined arguments.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenekf493f492009-11-11 05:50:44 +000015#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
Zhongxing Xu8958fff2009-11-03 06:46:03 +000016#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenekf493f492009-11-11 05:50:44 +000017#include "GRExprEngineInternalChecks.h"
Zhongxing Xu8958fff2009-11-03 06:46:03 +000018
19using namespace clang;
20
Ted Kremenekf493f492009-11-11 05:50:44 +000021namespace {
22class VISIBILITY_HIDDEN UndefinedArgChecker
23 : public CheckerVisitor<UndefinedArgChecker> {
Ted Kremenek64fa8582009-11-21 00:49:41 +000024 BugType *BT_call;
25 BugType *BT_msg;
Ted Kremenekf493f492009-11-11 05:50:44 +000026public:
Ted Kremenek64fa8582009-11-21 00:49:41 +000027 UndefinedArgChecker() : BT_call(0), BT_msg(0) {}
Ted Kremenekf493f492009-11-11 05:50:44 +000028 static void *getTag() {
29 static int x = 0;
30 return &x;
31 }
32 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
Ted Kremenek64fa8582009-11-21 00:49:41 +000033 void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
Ted Kremenekf493f492009-11-11 05:50:44 +000034};
35} // end anonymous namespace
36
37void clang::RegisterUndefinedArgChecker(GRExprEngine &Eng) {
38 Eng.registerCheck(new UndefinedArgChecker());
Zhongxing Xu8958fff2009-11-03 06:46:03 +000039}
40
41void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C,
42 const CallExpr *CE){
43 for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
44 I != E; ++I) {
45 if (C.getState()->getSVal(*I).isUndef()) {
46 if (ExplodedNode *N = C.GenerateNode(CE, true)) {
Ted Kremenek64fa8582009-11-21 00:49:41 +000047 if (!BT_call)
48 BT_call = new BuiltinBug("Pass-by-value argument in function call is "
49 "undefined");
Zhongxing Xu8958fff2009-11-03 06:46:03 +000050 // Generate a report for this bug.
Ted Kremenek64fa8582009-11-21 00:49:41 +000051 EnhancedBugReport *R = new EnhancedBugReport(*BT_call,
52 BT_call->getName(), N);
Zhongxing Xu8958fff2009-11-03 06:46:03 +000053 R->addRange((*I)->getSourceRange());
54 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
55 C.EmitReport(R);
Ted Kremenek64fa8582009-11-21 00:49:41 +000056 return;
57 }
58 }
59 }
60}
61
62void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C,
63 const ObjCMessageExpr *ME) {
64
65 // Check for any arguments that are uninitialized/undefined.
66 const GRState *state = C.getState();
67 for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(), E = ME->arg_end();
68 I != E; ++I) {
69 if (state->getSVal(*I).isUndef()) {
70 if (ExplodedNode *N = C.GenerateNode(ME, true)) {
71 if (!BT_msg)
72 BT_msg = new BuiltinBug("Pass-by-value argument in message expression"
73 " is undefined");
74 // Generate a report for this bug.
75 EnhancedBugReport *R = new EnhancedBugReport(*BT_msg, BT_msg->getName(),
76 N);
77 R->addRange((*I)->getSourceRange());
78 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I);
79 C.EmitReport(R);
80 return;
Zhongxing Xu8958fff2009-11-03 06:46:03 +000081 }
82 }
83 }
84}