BugReporter.h revision c095997b853270d8adb6fe55209a4dbc42803d16
1// BugReporter.h - Generate PathDiagnostics  ----------*- 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 ValueState.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
16#define LLVM_CLANG_ANALYSIS_BUGREPORTER
17
18#include "clang/Basic/SourceLocation.h"
19#include "clang/Analysis/PathSensitive/ValueState.h"
20#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/ADT/SmallSet.h"
23#include <vector>
24
25namespace clang {
26
27class PathDiagnostic;
28class PathDiagnosticPiece;
29class PathDiagnosticClient;
30class ASTContext;
31class Diagnostic;
32class BugReporter;
33class GRExprEngine;
34class ValueState;
35class Stmt;
36class BugReport;
37class ParentMap;
38
39class BugType {
40public:
41  BugType() {}
42  virtual ~BugType();
43
44  virtual const char* getName() const = 0;
45  virtual const char* getDescription() const { return getName(); }
46
47  virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
48    return std::pair<const char**, const char**>(0, 0);
49  }
50
51  virtual void EmitWarnings(BugReporter& BR) {}
52  virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {}
53
54  virtual bool isCached(BugReport& R) = 0;
55};
56
57class BugTypeCacheLocation : public BugType {
58  llvm::SmallPtrSet<void*,10> CachedErrors;
59public:
60  BugTypeCacheLocation() {}
61  virtual ~BugTypeCacheLocation() {}
62  virtual bool isCached(BugReport& R);
63  bool isCached(ProgramPoint P);
64};
65
66
67class BugReport {
68  BugType& Desc;
69  ExplodedNode<ValueState> *EndNode;
70  SourceRange R;
71public:
72  BugReport(BugType& D, ExplodedNode<ValueState> *n) : Desc(D), EndNode(n) {}
73  virtual ~BugReport();
74
75  const BugType& getBugType() const { return Desc; }
76  BugType& getBugType() { return Desc; }
77
78  ExplodedNode<ValueState>* getEndNode() const { return EndNode; }
79
80  Stmt* getStmt(BugReporter& BR) const;
81
82  const char* getName() const { return getBugType().getName(); }
83
84  virtual const char* getDescription() const {
85    return getBugType().getDescription();
86  }
87
88  virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
89    return getBugType().getExtraDescriptiveText();
90  }
91
92  virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
93                                          ExplodedNode<ValueState>* N);
94
95  virtual FullSourceLoc getLocation(SourceManager& Mgr);
96
97  virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
98                         const SourceRange*& end);
99
100  virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
101                                         ExplodedNode<ValueState>* PrevN,
102                                         ExplodedGraph<ValueState>& G,
103                                         BugReporter& BR);
104};
105
106class RangedBugReport : public BugReport {
107  std::vector<SourceRange> Ranges;
108public:
109  RangedBugReport(BugType& D, ExplodedNode<ValueState> *n)
110    : BugReport(D, n) {}
111
112  virtual ~RangedBugReport();
113
114  void addRange(SourceRange R) { Ranges.push_back(R); }
115
116  virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
117                         const SourceRange*& end) {
118
119    if (Ranges.empty()) {
120      beg = NULL;
121      end = NULL;
122    }
123    else {
124      beg = &Ranges[0];
125      end = beg + Ranges.size();
126    }
127  }
128};
129
130class BugReporterData {
131public:
132  virtual ~BugReporterData();
133  virtual Diagnostic& getDiagnostic() = 0;
134  virtual PathDiagnosticClient* getPathDiagnosticClient() = 0;
135  virtual ASTContext& getContext() = 0;
136  virtual SourceManager& getSourceManager() = 0;
137  virtual CFG& getCFG() = 0;
138  virtual ParentMap& getParentMap() = 0;
139  virtual LiveVariables& getLiveVariables() = 0;
140};
141
142class BugReporter {
143public:
144  enum Kind { BaseBRKind, GRBugReporterKind };
145
146protected:
147  Kind kind;
148  BugReporterData& D;
149
150  BugReporter(BugReporterData& d, Kind k) : kind(k), D(d) {}
151
152public:
153  BugReporter(BugReporterData& d) : kind(BaseBRKind), D(d) {}
154  virtual ~BugReporter();
155
156  Kind getKind() const { return kind; }
157
158  Diagnostic& getDiagnostic() {
159    return D.getDiagnostic();
160  }
161
162  PathDiagnosticClient* getPathDiagnosticClient() {
163    return D.getPathDiagnosticClient();
164  }
165
166  ASTContext& getContext() {
167    return D.getContext();
168  }
169
170  SourceManager& getSourceManager() {
171    return getContext().getSourceManager();
172  }
173
174  CFG& getCFG() {
175    return D.getCFG();
176  }
177
178  ParentMap& getParentMap() {
179    return D.getParentMap();
180  }
181
182  LiveVariables& getLiveVariables() {
183    return D.getLiveVariables();
184  }
185
186  virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R) {}
187
188  void EmitWarning(BugReport& R);
189
190  static bool classof(const BugReporter* R) { return true; }
191};
192
193class GRBugReporter : public BugReporter {
194  GRExprEngine& Eng;
195  llvm::SmallSet<SymbolID, 10> NotableSymbols;
196public:
197
198  GRBugReporter(BugReporterData& d, GRExprEngine& eng)
199    : BugReporter(d, GRBugReporterKind), Eng(eng) {}
200
201  virtual ~GRBugReporter();
202
203  GRExprEngine& getEngine() {
204    return Eng;
205  }
206
207  ExplodedGraph<ValueState>& getGraph();
208
209  ValueStateManager& getStateManager();
210
211  virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R);
212
213  void addNotableSymbol(SymbolID Sym) {
214    NotableSymbols.insert(Sym);
215  }
216
217  bool isNotable(SymbolID Sym) const {
218    return (bool) NotableSymbols.count(Sym);
219  }
220
221  static bool classof(const BugReporter* R) {
222    return R->getKind() == GRBugReporterKind;
223  }
224};
225
226} // end clang namespace
227
228#endif
229