blob: 471cf19717038d4798b09192af97a128a1219f38 [file] [log] [blame]
Zhongxing Xu94943b62009-11-03 07:35:33 +00001//===--- AttrNonNullChecker.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 AttrNonNullChecker, a builtin check in GRExprEngine that
11// performs checks for arguments declared to have nonnull attribute.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenekf493f492009-11-11 05:50:44 +000015#include "GRExprEngineInternalChecks.h"
Benjamin Kramer5e2d2c22010-03-27 21:19:47 +000016#include "clang/Checker/BugReporter/BugType.h"
17#include "clang/Checker/PathSensitive/CheckerVisitor.h"
Zhongxing Xu94943b62009-11-03 07:35:33 +000018
19using namespace clang;
20
Ted Kremenekf493f492009-11-11 05:50:44 +000021namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000022class AttrNonNullChecker
Ted Kremenekf493f492009-11-11 05:50:44 +000023 : public CheckerVisitor<AttrNonNullChecker> {
24 BugType *BT;
25public:
26 AttrNonNullChecker() : BT(0) {}
27 static void *getTag() {
28 static int x = 0;
29 return &x;
30 }
31 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
32};
33} // end anonymous namespace
34
35void clang::RegisterAttrNonNullChecker(GRExprEngine &Eng) {
36 Eng.registerCheck(new AttrNonNullChecker());
Zhongxing Xu94943b62009-11-03 07:35:33 +000037}
38
39void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
40 const CallExpr *CE) {
41 const GRState *state = C.getState();
Zhongxing Xu94943b62009-11-03 07:35:33 +000042
43 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek13976632010-02-08 16:18:51 +000044 SVal X = state->getSVal(CE->getCallee());
Zhongxing Xu94943b62009-11-03 07:35:33 +000045
46 const FunctionDecl* FD = X.getAsFunctionDecl();
47 if (!FD)
48 return;
49
50 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
51 if (!Att)
52 return;
53
54 // Iterate through the arguments of CE and check them for null.
55 unsigned idx = 0;
56
57 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
58 ++I, ++idx) {
59
60 if (!Att->isNonNull(idx))
61 continue;
62
Zhongxing Xu5126c602010-06-16 05:45:09 +000063 const DefinedSVal &V = cast<DefinedSVal>(state->getSVal(*I));
Zhongxing Xu94943b62009-11-03 07:35:33 +000064
65 ConstraintManager &CM = C.getConstraintManager();
66 const GRState *stateNotNull, *stateNull;
Zhongxing Xu5126c602010-06-16 05:45:09 +000067 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, V);
Zhongxing Xu94943b62009-11-03 07:35:33 +000068
69 if (stateNull && !stateNotNull) {
70 // Generate an error node. Check for a null node in case
71 // we cache out.
Ted Kremenek19d67b52009-11-23 22:22:01 +000072 if (ExplodedNode *errorNode = C.GenerateSink(stateNull)) {
Zhongxing Xu94943b62009-11-03 07:35:33 +000073
74 // Lazily allocate the BugType object if it hasn't already been
75 // created. Ownership is transferred to the BugReporter object once
76 // the BugReport is passed to 'EmitWarning'.
77 if (!BT)
78 BT = new BugType("Argument with 'nonnull' attribute passed null",
79 "API");
80
81 EnhancedBugReport *R =
82 new EnhancedBugReport(*BT,
83 "Null pointer passed as an argument to a "
84 "'nonnull' parameter", errorNode);
85
86 // Highlight the range of the argument that was null.
87 const Expr *arg = *I;
88 R->addRange(arg->getSourceRange());
89 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
90
91 // Emit the bug report.
92 C.EmitReport(R);
93 }
94
95 // Always return. Either we cached out or we just emitted an error.
96 return;
97 }
98
99 // If a pointer value passed the check we should assume that it is
100 // indeed not null from this point forward.
101 assert(stateNotNull);
102 state = stateNotNull;
103 }
104
105 // If we reach here all of the arguments passed the nonnull check.
106 // If 'state' has been updated generated a new node.
Ted Kremenek19d67b52009-11-23 22:22:01 +0000107 C.addTransition(state);
Zhongxing Xu94943b62009-11-03 07:35:33 +0000108}