 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
30.2% |
35 / 116 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
44.0% |
51 / 116 |
| |
|
Line Coverage: |
60.8% |
87 / 143 |
| |
 |
|
 |
1 : //===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- 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 the PathDiagnostic-related interfaces.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Checker/BugReporter/PathDiagnostic.h"
15 : #include "clang/AST/Expr.h"
16 : #include "clang/AST/Decl.h"
17 : #include "clang/AST/DeclObjC.h"
18 : #include "clang/AST/StmtCXX.h"
19 : #include "llvm/ADT/SmallString.h"
20 : #include "llvm/Support/Casting.h"
21 :
22 : using namespace clang;
23 : using llvm::dyn_cast;
24 : using llvm::isa;
25 :
26 0: bool PathDiagnosticMacroPiece::containsEvent() const {
0: branch 4 not taken
0: branch 5 not taken
27 0: for (const_iterator I = begin(), E = end(); I!=E; ++I) {
0: branch 2 not taken
0: branch 3 not taken
28 0: if (isa<PathDiagnosticEventPiece>(*I))
29 0: return true;
30 :
0: branch 2 not taken
0: branch 3 not taken
31 0: if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
0: branch 1 not taken
0: branch 2 not taken
32 0: if (MP->containsEvent())
33 0: return true;
34 : }
35 :
36 0: return false;
37 : }
38 :
39 3424: static llvm::StringRef StripTrailingDots(llvm::StringRef s) {
3993: branch 1 taken
1: branch 2 taken
40 3994: for (llvm::StringRef::size_type i = s.size(); i != 0; --i)
3423: branch 1 taken
570: branch 2 taken
41 3993: if (s[i - 1] != '.')
42 3423: return s.substr(0, i);
43 1: return "";
44 : }
45 :
46 : PathDiagnosticPiece::PathDiagnosticPiece(llvm::StringRef s,
47 1246: Kind k, DisplayHint hint)
48 1246: : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
49 :
50 1479: PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
51 1479: : kind(k), Hint(hint) {}
52 :
0: branch 3 not taken
0: branch 4 not taken
0: branch 9 not taken
0: branch 10 not taken
0: branch 15 not taken
2725: branch 16 taken
53 2725: PathDiagnosticPiece::~PathDiagnosticPiece() {}
1244: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 9 not taken
0: branch 10 not taken
54 1244: PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
1481: branch 2 taken
0: branch 3 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 12 not taken
0: branch 13 not taken
55 1481: PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
56 :
57 0: PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {
0: branch 3 not taken
0: branch 4 not taken
0: branch 8 not taken
0: branch 9 not taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 18 not taken
0: branch 19 not taken
0: branch 23 not taken
0: branch 24 not taken
0: branch 28 not taken
0: branch 29 not taken
58 0: for (iterator I = begin(), E = end(); I != E; ++I) delete *I;
0: branch 2 not taken
0: branch 3 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 12 not taken
0: branch 13 not taken
59 0: }
60 :
61 0: PathDiagnostic::PathDiagnostic() : Size(0) {}
62 :
63 726: PathDiagnostic::~PathDiagnostic() {
2725: branch 3 taken
0: branch 4 not taken
2725: branch 8 taken
726: branch 9 taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 18 not taken
0: branch 19 not taken
64 726: for (iterator I = begin(), E = end(); I != E; ++I) delete &*I;
65 726: }
66 :
67 1: void PathDiagnostic::resetPath(bool deletePieces) {
68 1: Size = 0;
69 :
0: branch 0 not taken
1: branch 1 taken
70 1: if (deletePieces)
0: branch 4 not taken
0: branch 5 not taken
71 0: for (iterator I=begin(), E=end(); I!=E; ++I)
0: branch 1 not taken
0: branch 2 not taken
72 0: delete &*I;
73 :
74 1: path.clear();
75 1: }
76 :
77 :
78 : PathDiagnostic::PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc,
79 726: llvm::StringRef category)
80 : : Size(0),
81 : BugType(StripTrailingDots(bugtype)),
82 : Desc(StripTrailingDots(desc)),
83 726: Category(StripTrailingDots(category)) {}
84 :
85 : void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
86 0: const DiagnosticInfo &Info) {
87 :
88 : // Create a PathDiagnostic with a single piece.
89 :
90 0: PathDiagnostic* D = new PathDiagnostic();
91 :
92 : const char *LevelStr;
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
93 0: switch (DiagLevel) {
94 : default:
95 0: case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
96 0: case Diagnostic::Note: LevelStr = "note: "; break;
97 0: case Diagnostic::Warning: LevelStr = "warning: "; break;
98 0: case Diagnostic::Error: LevelStr = "error: "; break;
99 0: case Diagnostic::Fatal: LevelStr = "fatal error: "; break;
100 : }
101 :
102 0: llvm::SmallString<100> StrC;
103 0: StrC += LevelStr;
104 0: Info.FormatDiagnostic(StrC);
105 :
106 : PathDiagnosticPiece *P =
107 0: new PathDiagnosticEventPiece(Info.getLocation(), StrC.str());
108 :
0: branch 1 not taken
0: branch 2 not taken
109 0: for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
110 0: P->addRange(Info.getRange(i));
0: branch 1 not taken
0: branch 2 not taken
111 0: for (unsigned i = 0, e = Info.getNumCodeModificationHints(); i != e; ++i)
112 0: P->addCodeModificationHint(Info.getCodeModificationHint(i));
113 0: D->push_front(P);
114 :
115 0: HandlePathDiagnostic(D);
116 0: }
117 :
118 : //===----------------------------------------------------------------------===//
119 : // PathDiagnosticLocation methods.
120 : //===----------------------------------------------------------------------===//
121 :
122 12611: FullSourceLoc PathDiagnosticLocation::asLocation() const {
0: branch 1 not taken
12611: branch 2 taken
123 12611: assert(isValid());
124 : // Note that we want a 'switch' here so that the compiler can warn us in
125 : // case we add more cases.
4912: branch 0 taken
7699: branch 1 taken
0: branch 2 not taken
0: branch 3 not taken
126 12611: switch (K) {
127 : case SingleLocK:
128 : case RangeK:
129 4912: break;
130 : case StmtK:
131 7699: return FullSourceLoc(S->getLocStart(), const_cast<SourceManager&>(*SM));
132 : case DeclK:
133 0: return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
134 : }
135 :
136 4912: return FullSourceLoc(R.getBegin(), const_cast<SourceManager&>(*SM));
137 : }
138 :
139 1004: PathDiagnosticRange PathDiagnosticLocation::asRange() const {
0: branch 1 not taken
1004: branch 2 taken
140 1004: assert(isValid());
141 : // Note that we want a 'switch' here so that the compiler can warn us in
142 : // case we add more cases.
8: branch 0 taken
198: branch 1 taken
798: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
143 1004: switch (K) {
144 : case SingleLocK:
145 8: return PathDiagnosticRange(R, true);
146 : case RangeK:
147 198: break;
148 : case StmtK: {
149 798: const Stmt *S = asStmt();
631: branch 1 taken
166: branch 2 taken
1: branch 3 taken
150 798: switch (S->getStmtClass()) {
151 : default:
152 631: break;
153 : case Stmt::DeclStmtClass: {
154 166: const DeclStmt *DS = cast<DeclStmt>(S);
166: branch 1 taken
0: branch 2 not taken
155 166: if (DS->isSingleDecl()) {
156 : // Should always be the case, but we'll be defensive.
157 : return SourceRange(DS->getLocStart(),
158 166: DS->getSingleDecl()->getLocation());
159 : }
160 0: break;
161 : }
162 : // FIXME: Provide better range information for different
163 : // terminators.
164 : case Stmt::IfStmtClass:
165 : case Stmt::WhileStmtClass:
166 : case Stmt::DoStmtClass:
167 : case Stmt::ForStmtClass:
168 : case Stmt::ChooseExprClass:
169 : case Stmt::IndirectGotoStmtClass:
170 : case Stmt::SwitchStmtClass:
171 : case Stmt::ConditionalOperatorClass:
172 : case Stmt::ObjCForCollectionStmtClass: {
173 1: SourceLocation L = S->getLocStart();
174 1: return SourceRange(L, L);
175 : }
176 : }
177 :
178 631: return S->getSourceRange();
179 : }
180 : case DeclK:
0: branch 1 not taken
0: branch 2 not taken
181 0: if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
182 0: return MD->getSourceRange();
0: branch 1 not taken
0: branch 2 not taken
183 0: if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
184 : // FIXME: We would like to always get the function body, even
185 : // when it needs to be de-serialized, but getting the
186 : // ASTContext here requires significant changes.
0: branch 1 not taken
0: branch 2 not taken
187 0: if (Stmt *Body = FD->getBody()) {
0: branch 1 not taken
0: branch 2 not taken
188 0: if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
189 0: return CS->getSourceRange();
190 : else
191 0: return cast<CXXTryStmt>(Body)->getSourceRange();
192 : }
193 : }
194 : else {
195 0: SourceLocation L = D->getLocation();
196 0: return PathDiagnosticRange(SourceRange(L, L), true);
197 : }
198 : }
199 :
200 198: return R;
201 : }
202 :
203 41: void PathDiagnosticLocation::flatten() {
30: branch 0 taken
11: branch 1 taken
204 41: if (K == StmtK) {
205 30: R = asRange();
206 30: K = RangeK;
207 30: S = 0;
208 30: D = 0;
209 : }
0: branch 0 not taken
11: branch 1 taken
210 11: else if (K == DeclK) {
211 0: SourceLocation L = D->getLocation();
212 0: R = SourceRange(L, L);
213 0: K = SingleLocK;
214 0: S = 0;
215 0: D = 0;
216 : }
217 41: }
218 :
219 : //===----------------------------------------------------------------------===//
220 : // FoldingSet profiling methods.
221 : //===----------------------------------------------------------------------===//
222 :
223 4206: void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
224 4206: ID.AddInteger((unsigned) K);
393: branch 0 taken
1304: branch 1 taken
2509: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
225 4206: switch (K) {
226 : case RangeK:
227 393: ID.AddInteger(R.getBegin().getRawEncoding());
228 393: ID.AddInteger(R.getEnd().getRawEncoding());
229 393: break;
230 : case SingleLocK:
231 1304: ID.AddInteger(R.getBegin().getRawEncoding());
232 1304: break;
233 : case StmtK:
234 2509: ID.Add(S);
235 2509: break;
236 : case DeclK:
237 0: ID.Add(D);
238 : break;
239 : }
240 : return;
241 : }
242 :
243 2725: void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
244 2725: ID.AddInteger((unsigned) getKind());
245 2725: ID.AddString(str);
246 : // FIXME: Add profiling support for code hints.
247 2725: ID.AddInteger((unsigned) getDisplayHint());
1479: branch 2 taken
2725: branch 3 taken
248 4204: for (range_iterator I = ranges_begin(), E = ranges_end(); I != E; ++I) {
249 1479: ID.AddInteger(I->getBegin().getRawEncoding());
250 1479: ID.AddInteger(I->getEnd().getRawEncoding());
251 : }
252 2725: }
253 :
254 1244: void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
255 1244: PathDiagnosticPiece::Profile(ID);
256 1244: ID.Add(Pos);
257 1244: }
258 :
259 1481: void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
260 1481: PathDiagnosticPiece::Profile(ID);
1481: branch 4 taken
1481: branch 5 taken
261 2962: for (const_iterator I = begin(), E = end(); I != E; ++I)
262 1481: ID.Add(*I);
263 1481: }
264 :
265 0: void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
266 0: PathDiagnosticSpotPiece::Profile(ID);
0: branch 4 not taken
0: branch 5 not taken
267 0: for (const_iterator I = begin(), E = end(); I != E; ++I)
268 0: ID.Add(**I);
269 0: }
270 :
271 726: void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
272 726: ID.AddInteger(Size);
273 726: ID.AddString(BugType);
274 726: ID.AddString(Desc);
275 726: ID.AddString(Category);
2725: branch 4 taken
726: branch 5 taken
276 3451: for (const_iterator I = begin(), E = end(); I != E; ++I)
277 2725: ID.Add(*I);
278 :
0: branch 4 not taken
726: branch 5 taken
279 726: for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
280 0: ID.AddString(*I);
281 726: }
Generated: 2010-02-10 01:31 by zcov