blob: 26dba4e7e870b888863e551816bd3f670892bc53 [file] [log] [blame]
Ted Kremenek7d882202008-04-03 04:42:52 +00001// BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- 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 file defines BugReporter, a utility class for generating
11// PathDiagnostics for analyses based on GRSimpleVals.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenek0e80dea2008-04-09 21:41:14 +000016#include "clang/Analysis/PathSensitive/GRExprEngine.h"
Ted Kremenek7d882202008-04-03 04:42:52 +000017#include "clang/Basic/SourceManager.h"
18#include "clang/Basic/SourceLocation.h"
19#include "clang/AST/ASTContext.h"
20#include "clang/AST/CFG.h"
21#include "clang/AST/Expr.h"
22#include "clang/Analysis/ProgramPoint.h"
23#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenekf05eec42008-06-18 05:34:07 +000024#include "llvm/ADT/DenseMap.h"
Ted Kremenek7d882202008-04-03 04:42:52 +000025#include <sstream>
26
27using namespace clang;
28
29BugReporter::~BugReporter() {}
Ted Kremenek0e80dea2008-04-09 21:41:14 +000030BugType::~BugType() {}
31BugReport::~BugReport() {}
Ted Kremenek965c2fd2008-04-11 18:40:29 +000032RangedBugReport::~RangedBugReport() {}
33
Ted Kremenek86953652008-05-22 23:45:19 +000034ExplodedGraph<ValueState>& BugReporter::getGraph() {
35 return Eng.getGraph();
36}
37
38ValueStateManager& BugReporter::getStateManager() {
39 return Eng.getStateManager();
40}
Ted Kremenek7d882202008-04-03 04:42:52 +000041
Ted Kremenek72f52c02008-06-20 21:45:25 +000042ParentMap& BugReporter::getParentMap() {
43 return Eng.getParentMap();
44}
45
Ted Kremenek7d882202008-04-03 04:42:52 +000046static inline Stmt* GetStmt(const ProgramPoint& P) {
47 if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
48 return PS->getStmt();
49 }
50 else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
51 return BE->getSrc()->getTerminator();
52 }
53 else if (const BlockEntrance* BE = dyn_cast<BlockEntrance>(&P)) {
54 return BE->getFirstStmt();
55 }
56
57 assert (false && "Unsupported ProgramPoint.");
58 return NULL;
59}
60
Ted Kremenekb1217642008-04-07 23:35:17 +000061static inline Stmt* GetStmt(const CFGBlock* B) {
Ted Kremenek71160882008-05-06 18:11:09 +000062 if (B->empty())
Ted Kremeneke90e3232008-04-25 19:01:27 +000063 return const_cast<Stmt*>(B->getTerminator());
Ted Kremeneke90e3232008-04-25 19:01:27 +000064 else
65 return (*B)[0];
Ted Kremenekb1217642008-04-07 23:35:17 +000066}
67
Ted Kremenek215d9fb2008-04-17 23:44:37 +000068static inline ExplodedNode<ValueState>*
69GetNextNode(ExplodedNode<ValueState>* N) {
70 return N->pred_empty() ? NULL : *(N->pred_begin());
71}
Ted Kremeneke90e3232008-04-25 19:01:27 +000072
Ted Kremenek215d9fb2008-04-17 23:44:37 +000073static Stmt* GetLastStmt(ExplodedNode<ValueState>* N) {
74 assert (isa<BlockEntrance>(N->getLocation()));
75
76 for (N = GetNextNode(N); N; N = GetNextNode(N)) {
77
78 ProgramPoint P = N->getLocation();
79
80 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
81 return PS->getStmt();
82 }
83
84 return NULL;
85}
86
Ted Kremenek71160882008-05-06 18:11:09 +000087static void ExecutionContinues(std::ostringstream& os, SourceManager& SMgr,
88 Stmt* S) {
Ted Kremenek5c3407a2008-05-01 22:50:36 +000089
90 if (!S)
91 return;
Ted Kremenek71160882008-05-06 18:11:09 +000092
93 // Slow, but probably doesn't matter.
94 if (os.str().empty())
95 os << ' ';
96
97 os << "Execution continues on line "
Ted Kremenek5c3407a2008-05-01 22:50:36 +000098 << SMgr.getLogicalLineNumber(S->getLocStart()) << '.';
99}
Ted Kremenek71160882008-05-06 18:11:09 +0000100
101
102static inline void ExecutionContinues(std::ostringstream& os,
103 SourceManager& SMgr,
104 ExplodedNode<ValueState>* N) {
105
106 ExecutionContinues(os, SMgr, GetStmt(N->getLocation()));
107}
108
109static inline void ExecutionContinues(std::ostringstream& os,
110 SourceManager& SMgr,
111 const CFGBlock* B) {
Ted Kremenek5c3407a2008-05-01 22:50:36 +0000112
Ted Kremenek71160882008-05-06 18:11:09 +0000113 ExecutionContinues(os, SMgr, GetStmt(B));
114}
115
Ted Kremenek5c3407a2008-05-01 22:50:36 +0000116
117Stmt* BugReport::getStmt(BugReporter& BR) const {
118
Ted Kremenek0f352422008-05-02 23:21:21 +0000119 ProgramPoint ProgP = EndNode->getLocation();
Ted Kremenek215d9fb2008-04-17 23:44:37 +0000120 Stmt *S = NULL;
121
122 if (BlockEntrance* BE = dyn_cast<BlockEntrance>(&ProgP))
123 if (BE->getBlock() == &BR.getCFG().getExit())
Ted Kremenek0f352422008-05-02 23:21:21 +0000124 S = GetLastStmt(EndNode);
Ted Kremenek215d9fb2008-04-17 23:44:37 +0000125 if (!S)
Ted Kremenek5c3407a2008-05-01 22:50:36 +0000126 S = GetStmt(ProgP);
127
128 return S;
129}
130
131PathDiagnosticPiece*
132BugReport::getEndPath(BugReporter& BR,
133 ExplodedNode<ValueState>* EndPathNode) {
134
135 Stmt* S = getStmt(BR);
Ted Kremenek7d882202008-04-03 04:42:52 +0000136
137 if (!S)
138 return NULL;
139
Ted Kremenekfe4d2312008-05-01 23:13:35 +0000140 FullSourceLoc L(S->getLocStart(), BR.getContext().getSourceManager());
141 PathDiagnosticPiece* P = new PathDiagnosticPiece(L, getDescription());
Ted Kremenek7d882202008-04-03 04:42:52 +0000142
Ted Kremenek521b2942008-04-03 18:00:37 +0000143 const SourceRange *Beg, *End;
Ted Kremenek5c3407a2008-05-01 22:50:36 +0000144 getRanges(BR, Beg, End);
145
146 for (; Beg != End; ++Beg)
147 P->addRange(*Beg);
Ted Kremenek7d882202008-04-03 04:42:52 +0000148
149 return P;
150}
151
Ted Kremenek5c3407a2008-05-01 22:50:36 +0000152void BugReport::getRanges(BugReporter& BR, const SourceRange*& beg,
153 const SourceRange*& end) {
154
155 if (Expr* E = dyn_cast_or_null<Expr>(getStmt(BR))) {
156 R = E->getSourceRange();
157 beg = &R;
158 end = beg+1;
159 }
160 else
161 beg = end = 0;
Ted Kremenekf00daf02008-04-03 17:57:38 +0000162}
163
Ted Kremeneke3ef1c72008-04-14 17:39:48 +0000164FullSourceLoc BugReport::getLocation(SourceManager& Mgr) {
165
Ted Kremenek0f352422008-05-02 23:21:21 +0000166 if (!EndNode)
Ted Kremeneke3ef1c72008-04-14 17:39:48 +0000167 return FullSourceLoc();
168
Ted Kremenek0f352422008-05-02 23:21:21 +0000169 Stmt* S = GetStmt(EndNode->getLocation());
Ted Kremeneke3ef1c72008-04-14 17:39:48 +0000170
171 if (!S)
172 return FullSourceLoc();
173
174 return FullSourceLoc(S->getLocStart(), Mgr);
175}
176
Ted Kremenek0e80dea2008-04-09 21:41:14 +0000177PathDiagnosticPiece* BugReport::VisitNode(ExplodedNode<ValueState>* N,
178 ExplodedNode<ValueState>* PrevN,
179 ExplodedGraph<ValueState>& G,
Ted Kremenek2be7ddb2008-04-18 03:39:05 +0000180 BugReporter& BR) {
Ted Kremenek0e80dea2008-04-09 21:41:14 +0000181 return NULL;
182}
183
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000184static std::pair<ExplodedGraph<ValueState>*, ExplodedNode<ValueState>*>
185MakeReportGraph(ExplodedGraph<ValueState>* G, ExplodedNode<ValueState>* N) {
Ted Kremeneke3ef1c72008-04-14 17:39:48 +0000186
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000187 llvm::OwningPtr<ExplodedGraph<ValueState> > GTrim(G->Trim(&N, &N+1));
188
Ted Kremenekac91ce92008-04-25 01:25:15 +0000189 // Find the error node in the trimmed graph.
Ted Kremenek7d8674e2008-04-03 04:59:14 +0000190
Ted Kremenekac91ce92008-04-25 01:25:15 +0000191 ExplodedNode<ValueState>* NOld = N;
192 N = 0;
Ted Kremenek7d8674e2008-04-03 04:59:14 +0000193
Ted Kremenek0e80dea2008-04-09 21:41:14 +0000194 for (ExplodedGraph<ValueState>::node_iterator
Ted Kremenek215d9fb2008-04-17 23:44:37 +0000195 I = GTrim->nodes_begin(), E = GTrim->nodes_end(); I != E; ++I) {
Ted Kremenek7d8674e2008-04-03 04:59:14 +0000196
Ted Kremenekac91ce92008-04-25 01:25:15 +0000197 if (I->getState() == NOld->getState() &&
198 I->getLocation() == NOld->getLocation()) {
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000199 N = &*I;
Ted Kremenek7d8674e2008-04-03 04:59:14 +0000200 break;
201 }
202 }
203
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000204 assert(N);
Ted Kremenek215d9fb2008-04-17 23:44:37 +0000205
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000206 // Create a new graph with a single path.
207
208 G = new ExplodedGraph<ValueState>(GTrim->getCFG(), GTrim->getCodeDecl(),
209 GTrim->getContext());
210
Ted Kremenekf05eec42008-06-18 05:34:07 +0000211 // Sometimes TrimGraph can contain a cycle. Perform a reverse DFS
212 // to the root node, and then construct a new graph that contains only
213 // a single path.
214 llvm::DenseMap<void*,unsigned> Visited;
215 llvm::SmallVector<ExplodedNode<ValueState>*, 10> WS;
216 WS.push_back(N);
217 unsigned cnt = 0;
218 ExplodedNode<ValueState>* Root = 0;
Ted Kremenekfaf410f2008-06-17 19:14:06 +0000219
Ted Kremenekf05eec42008-06-18 05:34:07 +0000220 while (!WS.empty()) {
221 ExplodedNode<ValueState>* Node = WS.back();
222 WS.pop_back();
223
224 if (Visited.find(Node) != Visited.end())
225 continue;
226
227 Visited[Node] = cnt++;
228
229 if (Node->pred_empty()) {
230 Root = Node;
231 break;
232 }
233
234 for (ExplodedNode<ValueState>::pred_iterator I=Node->pred_begin(),
235 E=Node->pred_end(); I!=E; ++I)
236 WS.push_back(*I);
237 }
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000238
Ted Kremenekf05eec42008-06-18 05:34:07 +0000239 assert (Root);
240
241 // Now walk from the root down the DFS path, always taking the successor
242 // with the lowest number.
243 ExplodedNode<ValueState> *Last = 0, *First = 0;
Ted Kremenekfaf410f2008-06-17 19:14:06 +0000244
Ted Kremenekf05eec42008-06-18 05:34:07 +0000245 for ( N = Root ;;) {
246
247 // Lookup the number associated with the current node.
248 llvm::DenseMap<void*,unsigned>::iterator I=Visited.find(N);
249 assert (I != Visited.end());
250
251 // Create the equivalent node in the new graph with the same state
252 // and location.
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000253 ExplodedNode<ValueState>* NewN =
Ted Kremenekf05eec42008-06-18 05:34:07 +0000254 G->getNode(N->getLocation(), N->getState());
255
256 // Link up the new node with the previous node.
257 if (Last)
258 NewN->addPredecessor(Last);
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000259
260 Last = NewN;
Ted Kremenekf05eec42008-06-18 05:34:07 +0000261
262 // Are we at the final node?
263 if (I->second == 0) {
264 First = NewN;
Ted Kremenekfaf410f2008-06-17 19:14:06 +0000265 break;
Ted Kremenekf05eec42008-06-18 05:34:07 +0000266 }
267
268 // Find the next successor node. We choose the node that is marked
269 // with the lowest DFS number.
270 ExplodedNode<ValueState>::succ_iterator SI = N->succ_begin();
271 ExplodedNode<ValueState>::succ_iterator SE = N->succ_end();
Ted Kremenekfaf410f2008-06-17 19:14:06 +0000272 N = 0;
273
Ted Kremenekf05eec42008-06-18 05:34:07 +0000274 for (unsigned MinVal = 0; SI != SE; ++SI) {
Ted Kremenekfaf410f2008-06-17 19:14:06 +0000275
Ted Kremenekf05eec42008-06-18 05:34:07 +0000276 I = Visited.find(*SI);
277
278 if (I == Visited.end())
279 continue;
280
281 if (!N || I->second < MinVal) {
282 N = *SI;
283 MinVal = I->second;
Ted Kremenekfaf410f2008-06-17 19:14:06 +0000284 }
Ted Kremenekf05eec42008-06-18 05:34:07 +0000285 }
286
287 assert (N);
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000288 }
Ted Kremenekf05eec42008-06-18 05:34:07 +0000289
290 assert (First);
Ted Kremenek8b335662008-04-23 23:04:32 +0000291 return std::make_pair(G, First);
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000292}
293
Ted Kremenek86953652008-05-22 23:45:19 +0000294static VarDecl* GetMostRecentVarDeclBinding(ExplodedNode<ValueState>* N,
295 ValueStateManager& VMgr,
296 RVal X) {
297
298 for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) {
299
300 ProgramPoint P = N->getLocation();
301
302 if (!isa<PostStmt>(P))
303 continue;
304
305 DeclRefExpr* DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt());
306
307 if (!DR)
308 continue;
309
310 RVal Y = VMgr.GetRVal(N->getState(), DR);
311
312 if (X != Y)
313 continue;
314
315 VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl());
316
317 if (!VD)
318 continue;
319
320 return VD;
321 }
322
323 return 0;
324}
325
326
327static void HandleNotableSymbol(ExplodedNode<ValueState>* N, Stmt* S,
328 SymbolID Sym, BugReporter& BR,
329 PathDiagnostic& PD) {
330
331 ExplodedNode<ValueState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
332 ValueState* PrevSt = Pred ? Pred->getState() : 0;
333
334 if (!PrevSt)
335 return;
336
337 // Look at the variable bindings of the current state that map to the
338 // specified symbol. Are any of them not in the previous state.
339
340 ValueState* St = N->getState();
341 ValueStateManager& VMgr = BR.getStateManager();
342
343 // FIXME: Later generalize for a broader memory model.
344
345 // FIXME: This is quadratic, since its nested in another loop. Probably
346 // doesn't matter, but keep an eye out for performance issues. It's
347 // also a bunch of copy-paste. Bad. Cleanup later.
348
349 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
350
351 RVal V = I.getData();
352 SymbolID ScanSym;
353
354 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
355 ScanSym = SV->getSymbol();
356 else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
357 ScanSym = SV->getSymbol();
358 else
359 continue;
360
361 if (ScanSym != Sym)
362 continue;
363
364 // Check if the previous state has this binding.
365
366 RVal X = VMgr.GetRVal(PrevSt, lval::DeclVal(I.getKey()));
367
368 if (X == V) // Same binding?
369 continue;
370
371 // Different binding. Only handle assignments for now. We don't pull
372 // this check out of the loop because we will eventually handle other
373 // cases.
374
375 VarDecl *VD = 0;
376
377 if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
378 if (!B->isAssignmentOp())
379 continue;
380
381 // What variable did we assign to?
382 DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
383
384 if (!DR)
385 continue;
386
387 VD = dyn_cast<VarDecl>(DR->getDecl());
388 }
389 else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
390 VD = dyn_cast<VarDecl>(DS->getDecl());
391
392 if (!VD)
393 continue;
394
395 // What is the most recently referenced variable with this binding?
396 VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
397
398 if (!MostRecent)
399 continue;
400
401 // Create the diagnostic.
402
403 FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
404
405 if (VD->getType()->isPointerLikeType()) {
406 std::string msg = "'" + std::string(VD->getName()) +
407 "' now aliases '" + MostRecent->getName() + "'";
408
409 PD.push_front(new PathDiagnosticPiece(L, msg));
410 }
411 }
412}
413
Ted Kremenekb9b15bf2008-04-23 23:02:12 +0000414void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
415 BugReport& R) {
416
417 ExplodedNode<ValueState>* N = R.getEndNode();
418
419 if (!N) return;
420
421 // Construct a new graph that contains only a single path from the error
422 // node to a root.
423
424 const std::pair<ExplodedGraph<ValueState>*,ExplodedNode<ValueState>*>
425 GPair = MakeReportGraph(&getGraph(), N);
426
427 llvm::OwningPtr<ExplodedGraph<ValueState> > ReportGraph(GPair.first);
428 assert(GPair.second->getLocation() == N->getLocation());
429 N = GPair.second;
430
431 // Start building the path diagnostic...
432
Ted Kremenek215d9fb2008-04-17 23:44:37 +0000433 if (PathDiagnosticPiece* Piece = R.getEndPath(*this, N))
434 PD.push_back(Piece);
435 else
436 return;
Ted Kremenek40674802008-04-09 00:20:43 +0000437
438 ExplodedNode<ValueState>* NextNode = N->pred_empty()
439 ? NULL : *(N->pred_begin());
440
Ted Kremenek215d9fb2008-04-17 23:44:37 +0000441 SourceManager& SMgr = Ctx.getSourceManager();
442
Ted Kremenek40674802008-04-09 00:20:43 +0000443 while (NextNode) {
Ted Kremenek7d882202008-04-03 04:42:52 +0000444
445 ExplodedNode<ValueState>* LastNode = N;
Ted Kremenek40674802008-04-09 00:20:43 +0000446 N = NextNode;
Ted Kremenek215d9fb2008-04-17 23:44:37 +0000447 NextNode = GetNextNode(N);
Ted Kremenek7d882202008-04-03 04:42:52 +0000448
449 ProgramPoint P = N->getLocation();
450
451 if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
452
453 CFGBlock* Src = BE->getSrc();
454 CFGBlock* Dst = BE->getDst();
455
456 Stmt* T = Src->getTerminator();
457
458 if (!T)
459 continue;
460
461 FullSourceLoc L(T->getLocStart(), SMgr);
462
463 switch (T->getStmtClass()) {
464 default:
465 break;
466
467 case Stmt::GotoStmtClass:
468 case Stmt::IndirectGotoStmtClass: {
469
470 Stmt* S = GetStmt(LastNode->getLocation());
471
472 if (!S)
473 continue;
474
475 std::ostringstream os;
476
477 os << "Control jumps to line "
Ted Kremenekb1217642008-04-07 23:35:17 +0000478 << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
Ted Kremenek7d882202008-04-03 04:42:52 +0000479
480 PD.push_front(new PathDiagnosticPiece(L, os.str()));
481 break;
482 }
483
484 case Stmt::SwitchStmtClass: {
485
486 // Figure out what case arm we took.
Ted Kremenek854b7762008-04-23 23:35:07 +0000487
Ted Kremenek7d882202008-04-03 04:42:52 +0000488 std::ostringstream os;
Ted Kremenek854b7762008-04-23 23:35:07 +0000489
490 if (Stmt* S = Dst->getLabel())
491 switch (S->getStmtClass()) {
492
Ted Kremenek7d882202008-04-03 04:42:52 +0000493 default:
Ted Kremenek854b7762008-04-23 23:35:07 +0000494 assert(false && "Not a valid switch label.");
495 continue;
496
Ted Kremenek47e61382008-04-22 22:29:46 +0000497 case Stmt::DefaultStmtClass: {
Ted Kremenek7d882202008-04-03 04:42:52 +0000498
499 os << "Control jumps to the 'default' case at line "
Ted Kremenek40674802008-04-09 00:20:43 +0000500 << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
Ted Kremenek7d882202008-04-03 04:42:52 +0000501
502 break;
503 }
504
505 case Stmt::CaseStmtClass: {
506
507 os << "Control jumps to 'case ";
508
Ted Kremenek854b7762008-04-23 23:35:07 +0000509 CaseStmt* Case = cast<CaseStmt>(S);
510 Expr* LHS = Case->getLHS()->IgnoreParenCasts();
Ted Kremenek7d882202008-04-03 04:42:52 +0000511
Ted Kremenek854b7762008-04-23 23:35:07 +0000512 // Determine if it is an enum.
Ted Kremenek7d882202008-04-03 04:42:52 +0000513
Ted Kremenek854b7762008-04-23 23:35:07 +0000514 bool GetRawInt = true;
Ted Kremenek7d882202008-04-03 04:42:52 +0000515
Ted Kremenek854b7762008-04-23 23:35:07 +0000516 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
517
518 // FIXME: Maybe this should be an assertion. Are there cases
519 // were it is not an EnumConstantDecl?
520
521 EnumConstantDecl* D = dyn_cast<EnumConstantDecl>(DR->getDecl());
522
523 if (D) {
524 GetRawInt = false;
525 os << D->getName();
526 }
Ted Kremenek7d882202008-04-03 04:42:52 +0000527 }
Ted Kremenek854b7762008-04-23 23:35:07 +0000528
529 if (GetRawInt) {
Ted Kremenek7d882202008-04-03 04:42:52 +0000530
Ted Kremenek854b7762008-04-23 23:35:07 +0000531 // Not an enum.
532 Expr* CondE = cast<SwitchStmt>(T)->getCond();
533 unsigned bits = Ctx.getTypeSize(CondE->getType());
534 llvm::APSInt V(bits, false);
Ted Kremenek7d882202008-04-03 04:42:52 +0000535
Ted Kremenek854b7762008-04-23 23:35:07 +0000536 if (!LHS->isIntegerConstantExpr(V, Ctx, 0, true)) {
537 assert (false && "Case condition must be constant.");
Ted Kremenek7d882202008-04-03 04:42:52 +0000538 continue;
539 }
540
Ted Kremenek854b7762008-04-23 23:35:07 +0000541 os << V.toString();
Ted Kremeneke90e3232008-04-25 19:01:27 +0000542 }
Ted Kremenek854b7762008-04-23 23:35:07 +0000543
Ted Kremenek7d882202008-04-03 04:42:52 +0000544 os << ":' at line "
Ted Kremenek854b7762008-04-23 23:35:07 +0000545 << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
Ted Kremenek7d882202008-04-03 04:42:52 +0000546
547 break;
548
549 }
550 }
Ted Kremenek3fb72962008-04-25 01:29:56 +0000551 else {
Ted Kremeneke90e3232008-04-25 19:01:27 +0000552 os << "'Default' branch taken.";
553 ExecutionContinues(os, SMgr, LastNode);
Ted Kremenek3fb72962008-04-25 01:29:56 +0000554 }
Ted Kremenek7d882202008-04-03 04:42:52 +0000555
556 PD.push_front(new PathDiagnosticPiece(L, os.str()));
557 break;
558 }
Ted Kremeneke90e3232008-04-25 19:01:27 +0000559
560 case Stmt::BreakStmtClass:
561 case Stmt::ContinueStmtClass: {
562 std::ostringstream os;
563 ExecutionContinues(os, SMgr, LastNode);
564 PD.push_front(new PathDiagnosticPiece(L, os.str()));
565 break;
566 }
Ted Kremenekb1217642008-04-07 23:35:17 +0000567
568 case Stmt::ConditionalOperatorClass: {
Ted Kremenek7d882202008-04-03 04:42:52 +0000569
Ted Kremenekb1217642008-04-07 23:35:17 +0000570 std::ostringstream os;
571 os << "'?' condition evaluates to ";
572
573 if (*(Src->succ_begin()+1) == Dst)
574 os << "false.";
575 else
576 os << "true.";
Ted Kremenek7d882202008-04-03 04:42:52 +0000577
Ted Kremenekb1217642008-04-07 23:35:17 +0000578 PD.push_front(new PathDiagnosticPiece(L, os.str()));
579
580 break;
581 }
582
583 case Stmt::DoStmtClass: {
584
585 if (*(Src->succ_begin()) == Dst) {
586
587 std::ostringstream os;
588
Ted Kremenek71160882008-05-06 18:11:09 +0000589 os << "Loop condition is true.";
590 ExecutionContinues(os, SMgr, Dst);
Ted Kremenekb1217642008-04-07 23:35:17 +0000591
592 PD.push_front(new PathDiagnosticPiece(L, os.str()));
593 }
594 else
595 PD.push_front(new PathDiagnosticPiece(L,
596 "Loop condition is false. Exiting loop."));
597
598 break;
599 }
600
Ted Kremenek7d882202008-04-03 04:42:52 +0000601 case Stmt::WhileStmtClass:
Ted Kremenekb1217642008-04-07 23:35:17 +0000602 case Stmt::ForStmtClass: {
603
604 if (*(Src->succ_begin()+1) == Dst) {
605
606 std::ostringstream os;
607
Ted Kremenek71160882008-05-06 18:11:09 +0000608 os << "Loop condition is false.";
609 ExecutionContinues(os, SMgr, Dst);
Ted Kremenekb1217642008-04-07 23:35:17 +0000610
611 PD.push_front(new PathDiagnosticPiece(L, os.str()));
612 }
613 else
614 PD.push_front(new PathDiagnosticPiece(L,
615 "Loop condition is true. Entering loop body."));
616
617 break;
618 }
619
Ted Kremenek7d882202008-04-03 04:42:52 +0000620 case Stmt::IfStmtClass: {
621
622 if (*(Src->succ_begin()+1) == Dst)
623 PD.push_front(new PathDiagnosticPiece(L, "Taking false branch."));
624 else
625 PD.push_front(new PathDiagnosticPiece(L, "Taking true branch."));
626
627 break;
628 }
629 }
Ted Kremenek40674802008-04-09 00:20:43 +0000630 }
Ted Kremenek854b7762008-04-23 23:35:07 +0000631
632 if (PathDiagnosticPiece* p = R.VisitNode(N, NextNode, *ReportGraph, *this))
Ted Kremenek86953652008-05-22 23:45:19 +0000633 PD.push_front(p);
634
635 if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
636
637 ValueState* St = N->getState();
638
639 // Scan the lval bindings, and see if a "notable" symbol has a new
640 // lval binding.
641
642 // FIXME: In the future, when we generalize the memory model, we'll
643 // need a way to iterate over binded locations.
644
645 llvm::SmallSet<SymbolID, 10> AlreadyProcessed;
646
647 for (ValueState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
648
649 RVal V = I.getData();
650 SymbolID ScanSym;
651
652 if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
653 ScanSym = SV->getSymbol();
654 else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
655 ScanSym = SV->getSymbol();
656 else
657 continue;
658
659 assert (ScanSym.isInitialized());
660
661 if (!isNotable(ScanSym))
662 continue;
663
664 if (AlreadyProcessed.count(ScanSym))
665 continue;
666
667 AlreadyProcessed.insert(ScanSym);
668
669 HandleNotableSymbol(N, PS->getStmt(), ScanSym, *this, PD);
670 }
671 }
Ted Kremenek7d882202008-04-03 04:42:52 +0000672 }
673}
674
Ted Kremenek86953652008-05-22 23:45:19 +0000675
Ted Kremeneke3769852008-04-18 20:54:29 +0000676bool BugTypeCacheLocation::isCached(BugReport& R) {
677
678 ExplodedNode<ValueState>* N = R.getEndNode();
Ted Kremenek7d882202008-04-03 04:42:52 +0000679
Ted Kremenekac5e9822008-04-18 02:24:50 +0000680 if (!N)
681 return false;
Ted Kremeneke3769852008-04-18 20:54:29 +0000682
683 // Cache the location of the error. Don't emit the same
Ted Kremenek7d882202008-04-03 04:42:52 +0000684 // warning for the same error type that occurs at the same program
685 // location but along a different path.
686
Ted Kremenek789c0b32008-05-16 18:33:14 +0000687 return isCached(N->getLocation());
688}
689
690bool BugTypeCacheLocation::isCached(ProgramPoint P) {
691
692 void* p = P.getRawData();
Ted Kremenek7d882202008-04-03 04:42:52 +0000693
694 if (CachedErrors.count(p))
695 return true;
696
Ted Kremeneke3769852008-04-18 20:54:29 +0000697 CachedErrors.insert(p);
Ted Kremenek7d882202008-04-03 04:42:52 +0000698 return false;
699}
700
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000701void BugReporter::EmitWarning(BugReport& R) {
702
Ted Kremeneke3769852008-04-18 20:54:29 +0000703 if (R.getBugType().isCached(R))
Ted Kremenek7d882202008-04-03 04:42:52 +0000704 return;
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000705
Ted Kremenekf309cf92008-04-22 16:15:03 +0000706 llvm::OwningPtr<PathDiagnostic> D(new PathDiagnostic(R.getName()));
707 GeneratePathDiagnostic(*D.get(), R);
Ted Kremenekfe30beb2008-04-30 23:47:44 +0000708
709 // Get the meta data.
710
711 std::pair<const char**, const char**> Meta = R.getExtraDescriptiveText();
712
713 for (const char** s = Meta.first; s != Meta.second; ++s)
714 D->addMeta(*s);
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000715
716 // Emit a full diagnostic for the path if we have a PathDiagnosticClient.
Ted Kremenek1f997b12008-04-03 07:33:55 +0000717
Ted Kremenekf309cf92008-04-22 16:15:03 +0000718 if (PD && !D->empty()) {
719 PD->HandlePathDiagnostic(D.take());
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000720 return;
721 }
Ted Kremeneke3ef1c72008-04-14 17:39:48 +0000722
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000723 // We don't have a PathDiagnosticClient, but we can still emit a single
724 // line diagnostic. Determine the location.
Ted Kremenek7d882202008-04-03 04:42:52 +0000725
Ted Kremenekf309cf92008-04-22 16:15:03 +0000726 FullSourceLoc L = D->empty() ? R.getLocation(Ctx.getSourceManager())
727 : D->back()->getLocation();
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000728
729
730 // Determine the range.
Ted Kremenek05d5da82008-04-14 18:06:42 +0000731
Ted Kremenek651f2852008-04-10 16:12:38 +0000732 const SourceRange *Beg, *End;
Ted Kremenek05d5da82008-04-14 18:06:42 +0000733
Ted Kremenekf309cf92008-04-22 16:15:03 +0000734 if (!D->empty()) {
735 Beg = D->back()->ranges_begin();
736 End = D->back()->ranges_end();
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000737 }
738 else
Ted Kremenek5c3407a2008-05-01 22:50:36 +0000739 R.getRanges(*this, Beg, End);
Ted Kremenek270ab7d2008-04-18 01:56:37 +0000740
Ted Kremenek58143102008-04-18 22:56:53 +0000741 if (PD) {
Ted Kremenek58143102008-04-18 22:56:53 +0000742 PathDiagnosticPiece* piece = new PathDiagnosticPiece(L, R.getDescription());
743
744 for ( ; Beg != End; ++Beg)
745 piece->addRange(*Beg);
746
Ted Kremenekf309cf92008-04-22 16:15:03 +0000747 D->push_back(piece);
748 PD->HandlePathDiagnostic(D.take());
Ted Kremenek58143102008-04-18 22:56:53 +0000749 }
750 else {
751 std::ostringstream os;
752 os << "[CHECKER] ";
753
Ted Kremenekf309cf92008-04-22 16:15:03 +0000754 if (D->empty())
Ted Kremenek58143102008-04-18 22:56:53 +0000755 os << R.getDescription();
756 else
Ted Kremenekf309cf92008-04-22 16:15:03 +0000757 os << D->back()->getString();
Ted Kremenek58143102008-04-18 22:56:53 +0000758
759
760 unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning,
761 os.str().c_str());
762
763 Diag.Report(L, ErrorDiag, NULL, 0, Beg, End - Beg);
764 }
Ted Kremenek7d882202008-04-03 04:42:52 +0000765}