blob: aa21700c248352ef547d9971ddda1557f53b4a38 [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 "clang/Analysis/PathSensitive/CheckerVisitor.h"
Zhongxing Xu94943b62009-11-03 07:35:33 +000016#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenekf493f492009-11-11 05:50:44 +000017#include "GRExprEngineInternalChecks.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.
44 SVal X = state->getSVal(CE->getCallee());
45
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
63 const SVal &V = state->getSVal(*I);
64 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
65
66 if (!DV)
67 continue;
68
69 ConstraintManager &CM = C.getConstraintManager();
70 const GRState *stateNotNull, *stateNull;
71 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
72
73 if (stateNull && !stateNotNull) {
74 // Generate an error node. Check for a null node in case
75 // we cache out.
Ted Kremenek19d67b52009-11-23 22:22:01 +000076 if (ExplodedNode *errorNode = C.GenerateSink(stateNull)) {
Zhongxing Xu94943b62009-11-03 07:35:33 +000077
78 // Lazily allocate the BugType object if it hasn't already been
79 // created. Ownership is transferred to the BugReporter object once
80 // the BugReport is passed to 'EmitWarning'.
81 if (!BT)
82 BT = new BugType("Argument with 'nonnull' attribute passed null",
83 "API");
84
85 EnhancedBugReport *R =
86 new EnhancedBugReport(*BT,
87 "Null pointer passed as an argument to a "
88 "'nonnull' parameter", errorNode);
89
90 // Highlight the range of the argument that was null.
91 const Expr *arg = *I;
92 R->addRange(arg->getSourceRange());
93 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
94
95 // Emit the bug report.
96 C.EmitReport(R);
97 }
98
99 // Always return. Either we cached out or we just emitted an error.
100 return;
101 }
102
103 // If a pointer value passed the check we should assume that it is
104 // indeed not null from this point forward.
105 assert(stateNotNull);
106 state = stateNotNull;
107 }
108
109 // If we reach here all of the arguments passed the nonnull check.
110 // If 'state' has been updated generated a new node.
Ted Kremenek19d67b52009-11-23 22:22:01 +0000111 C.addTransition(state);
Zhongxing Xu94943b62009-11-03 07:35:33 +0000112}