 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
79.3% |
23 / 29 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
93.1% |
27 / 29 |
| |
|
Line Coverage: |
97.4% |
37 / 38 |
| |
 |
|
 |
1 : //===--- 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 :
15 : #include "clang/Checker/PathSensitive/CheckerVisitor.h"
16 : #include "clang/Checker/BugReporter/BugReporter.h"
17 : #include "GRExprEngineInternalChecks.h"
18 :
19 : using namespace clang;
20 :
21 : namespace {
22 : class AttrNonNullChecker
2138: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
23 2138: : public CheckerVisitor<AttrNonNullChecker> {
24 : BugType *BT;
25 : public:
26 2138: AttrNonNullChecker() : BT(0) {}
27 2138: static void *getTag() {
28 : static int x = 0;
29 2138: return &x;
30 : }
31 : void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
32 : };
33 : } // end anonymous namespace
34 :
35 2138: void clang::RegisterAttrNonNullChecker(GRExprEngine &Eng) {
36 2138: Eng.registerCheck(new AttrNonNullChecker());
37 2138: }
38 :
39 : void AttrNonNullChecker::PreVisitCallExpr(CheckerContext &C,
40 1678: const CallExpr *CE) {
41 1678: const GRState *state = C.getState();
42 :
43 : // Check if the callee has a 'nonnull' attribute.
44 1678: SVal X = state->getSVal(CE->getCallee());
45 :
46 1678: const FunctionDecl* FD = X.getAsFunctionDecl();
58: branch 0 taken
1620: branch 1 taken
47 1678: if (!FD)
48 1654: return;
49 :
50 1620: const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
1584: branch 0 taken
36: branch 1 taken
51 1620: if (!Att)
52 : return;
53 :
54 : // Iterate through the arguments of CE and check them for null.
55 36: unsigned idx = 0;
56 :
30: branch 3 taken
4: branch 4 taken
12: branch 5 taken
70: branch 8 taken
24: branch 9 taken
57 140: for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
58 : ++I, ++idx) {
59 :
46: branch 1 taken
24: branch 2 taken
60 70: if (!Att->isNonNull(idx))
61 24: continue;
62 :
63 46: const SVal &V = state->getSVal(*I);
64 46: const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
65 :
4: branch 0 taken
42: branch 1 taken
66 46: if (!DV)
67 4: continue;
68 :
69 42: ConstraintManager &CM = C.getConstraintManager();
70 : const GRState *stateNotNull, *stateNull;
71 42: llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
72 :
26: branch 0 taken
16: branch 1 taken
12: branch 2 taken
14: branch 3 taken
73 42: if (stateNull && !stateNotNull) {
74 : // Generate an error node. Check for a null node in case
75 : // we cache out.
12: branch 1 taken
0: branch 2 not taken
76 12: if (ExplodedNode *errorNode = C.GenerateSink(stateNull)) {
77 :
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'.
12: branch 0 taken
0: branch 1 not taken
81 12: if (!BT)
82 : BT = new BugType("Argument with 'nonnull' attribute passed null",
83 12: "API");
84 :
85 : EnhancedBugReport *R =
86 : new EnhancedBugReport(*BT,
87 : "Null pointer passed as an argument to a "
88 12: "'nonnull' parameter", errorNode);
89 :
90 : // Highlight the range of the argument that was null.
91 12: const Expr *arg = *I;
92 12: R->addRange(arg->getSourceRange());
93 12: R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, arg);
94 :
95 : // Emit the bug report.
96 12: 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.
0: branch 0 not taken
30: branch 1 taken
105 30: assert(stateNotNull);
106 30: 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.
24: branch 2 taken
1654: branch 3 taken
111 24: C.addTransition(state);
112 0: }
Generated: 2010-02-10 01:31 by zcov