 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
50.0% |
78 / 156 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
83.3% |
130 / 156 |
| |
|
Line Coverage: |
71.7% |
175 / 244 |
| |
 |
|
 |
1 : //===--- HTMLDiagnostics.cpp - HTML Diagnostics for Paths ----*- 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 HTMLDiagnostics object.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Frontend/PathDiagnosticClients.h"
15 : #include "clang/Checker/BugReporter/PathDiagnostic.h"
16 : #include "clang/AST/ASTContext.h"
17 : #include "clang/AST/Decl.h"
18 : #include "clang/Basic/SourceManager.h"
19 : #include "clang/Basic/FileManager.h"
20 : #include "clang/Rewrite/Rewriter.h"
21 : #include "clang/Rewrite/HTMLRewrite.h"
22 : #include "clang/Lex/Lexer.h"
23 : #include "clang/Lex/Preprocessor.h"
24 : #include "llvm/Support/MemoryBuffer.h"
25 : #include "llvm/Support/raw_ostream.h"
26 : #include "llvm/System/Path.h"
27 :
28 : using namespace clang;
29 :
30 : //===----------------------------------------------------------------------===//
31 : // Boilerplate.
32 : //===----------------------------------------------------------------------===//
33 :
34 : namespace {
35 :
36 : class HTMLDiagnostics : public PathDiagnosticClient {
37 : llvm::sys::Path Directory, FilePrefix;
38 : bool createdDir, noDir;
39 : const Preprocessor &PP;
40 : std::vector<const PathDiagnostic*> BatchedDiags;
41 : public:
42 : HTMLDiagnostics(const std::string& prefix, const Preprocessor &pp);
43 :
1: branch 5 taken
0: branch 6 not taken
0: branch 13 not taken
0: branch 14 not taken
44 1: virtual ~HTMLDiagnostics() { FlushDiagnostics(NULL); }
45 :
46 : virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
47 :
48 : virtual void HandlePathDiagnostic(const PathDiagnostic* D);
49 :
50 0: virtual llvm::StringRef getName() const {
51 0: return "HTMLDiagnostics";
52 : }
53 :
54 : unsigned ProcessMacroPiece(llvm::raw_ostream& os,
55 : const PathDiagnosticMacroPiece& P,
56 : unsigned num);
57 :
58 : void HandlePiece(Rewriter& R, FileID BugFileID,
59 : const PathDiagnosticPiece& P, unsigned num, unsigned max);
60 :
61 : void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range,
62 : const char *HighlightStart = "<span class=\"mrange\">",
63 : const char *HighlightEnd = "</span>");
64 :
65 : void ReportDiag(const PathDiagnostic& D,
66 : llvm::SmallVectorImpl<std::string> *FilesMade);
67 : };
68 :
69 : } // end anonymous namespace
70 :
71 : HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix,
72 1: const Preprocessor &pp)
73 : : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
74 1: PP(pp) {
75 : // All html files begin with "report"
76 1: FilePrefix.appendComponent("report");
77 1: }
78 :
79 : PathDiagnosticClient*
80 : clang::CreateHTMLDiagnosticClient(const std::string& prefix,
81 1: const Preprocessor &PP) {
82 1: return new HTMLDiagnostics(prefix, PP);
83 : }
84 :
85 : //===----------------------------------------------------------------------===//
86 : // Report processing.
87 : //===----------------------------------------------------------------------===//
88 :
89 1: void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
0: branch 0 not taken
1: branch 1 taken
90 1: if (!D)
91 0: return;
92 :
0: branch 1 not taken
1: branch 2 taken
93 1: if (D->empty()) {
0: branch 0 not taken
0: branch 1 not taken
94 0: delete D;
95 0: return;
96 : }
97 :
98 1: const_cast<PathDiagnostic*>(D)->flattenLocations();
99 1: BatchedDiags.push_back(D);
100 : }
101 :
102 : void
103 2: HTMLDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade)
104 : {
1: branch 1 taken
2: branch 2 taken
105 5: while (!BatchedDiags.empty()) {
106 1: const PathDiagnostic* D = BatchedDiags.back();
107 1: BatchedDiags.pop_back();
108 1: ReportDiag(*D, FilesMade);
1: branch 0 taken
0: branch 1 not taken
109 1: delete D;
110 : }
111 :
112 2: BatchedDiags.clear();
113 2: }
114 :
115 : void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
116 1: llvm::SmallVectorImpl<std::string> *FilesMade){
117 : // Create the HTML directory if it is missing.
1: branch 0 taken
0: branch 1 not taken
118 1: if (!createdDir) {
119 1: createdDir = true;
120 1: std::string ErrorMsg;
121 1: Directory.createDirectoryOnDisk(true, &ErrorMsg);
122 :
0: branch 1 not taken
1: branch 2 taken
123 1: if (!Directory.isDirectory()) {
124 : llvm::errs() << "warning: could not create directory '"
125 : << Directory.str() << "'\n"
126 0: << "reason: " << ErrorMsg << '\n';
127 :
128 0: noDir = true;
129 :
130 0: return;
1: branch 1 taken
0: branch 2 not taken
131 1: }
132 : }
133 :
0: branch 0 not taken
1: branch 1 taken
134 1: if (noDir)
135 0: return;
136 :
137 1: const SourceManager &SMgr = D.begin()->getLocation().getManager();
138 1: FileID FID;
139 :
140 : // Verify that the entire path is from the same FileID.
4: branch 4 taken
1: branch 5 taken
141 5: for (PathDiagnostic::const_iterator I = D.begin(), E = D.end(); I != E; ++I) {
142 4: FullSourceLoc L = I->getLocation().asLocation().getInstantiationLoc();
143 :
1: branch 1 taken
3: branch 2 taken
144 4: if (FID.isInvalid()) {
145 1: FID = SMgr.getFileID(L);
0: branch 2 not taken
3: branch 3 taken
146 3: } else if (SMgr.getFileID(L) != FID)
147 0: return; // FIXME: Emit a warning?
148 :
149 : // Check the source ranges.
2: branch 2 taken
4: branch 3 taken
150 10: for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
151 4: RE=I->ranges_end(); RI!=RE; ++RI) {
152 :
153 2: SourceLocation L = SMgr.getInstantiationLoc(RI->getBegin());
154 :
2: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
2: branch 6 taken
0: branch 7 not taken
2: branch 8 taken
155 2: if (!L.isFileID() || SMgr.getFileID(L) != FID)
156 0: return; // FIXME: Emit a warning?
157 :
158 2: L = SMgr.getInstantiationLoc(RI->getEnd());
159 :
2: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
2: branch 6 taken
0: branch 7 not taken
2: branch 8 taken
160 2: if (!L.isFileID() || SMgr.getFileID(L) != FID)
161 0: return; // FIXME: Emit a warning?
162 : }
163 : }
164 :
0: branch 1 not taken
1: branch 2 taken
165 1: if (FID.isInvalid())
166 0: return; // FIXME: Emit a warning?
167 :
168 : // Create a new rewriter to generate HTML.
169 1: Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOptions());
170 :
171 : // Process the path.
172 1: unsigned n = D.size();
173 1: unsigned max = n;
174 :
4: branch 4 taken
1: branch 5 taken
175 5: for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
176 : I!=E; ++I, --n)
177 4: HandlePiece(R, FID, *I, n, max);
178 :
179 : // Add line numbers, header, footer, etc.
180 :
181 : // unsigned FID = R.getSourceMgr().getMainFileID();
182 1: html::EscapeText(R, FID);
183 1: html::AddLineNumbers(R, FID);
184 :
185 : // If we have a preprocessor, relex the file and syntax highlight.
186 : // We might not have a preprocessor if we come from a deserialized AST file,
187 : // for example.
188 :
189 1: html::SyntaxHighlight(R, FID, PP);
190 1: html::HighlightMacros(R, FID, PP);
191 :
192 : // Get the full directory name of the analyzed file.
193 :
194 1: const FileEntry* Entry = SMgr.getFileEntryForID(FID);
195 :
196 : // This is a cludge; basically we want to append either the full
197 : // working directory if we have no directory information. This is
198 : // a work in progress.
199 :
200 1: std::string DirName = "";
201 :
0: branch 5 not taken
1: branch 6 taken
202 1: if (!llvm::sys::Path(Entry->getName()).isAbsolute()) {
203 0: llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
204 0: DirName = P.str() + "/";
205 : }
206 :
207 : // Add the name of the file as an <h1> tag.
208 :
209 : {
210 1: std::string s;
211 1: llvm::raw_string_ostream os(s);
212 :
213 : os << "<!-- REPORTHEADER -->\n"
214 : << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
215 : "<tr><td class=\"rowname\">File:</td><td>"
216 : << html::EscapeText(DirName)
217 : << html::EscapeText(Entry->getName())
218 : << "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>"
219 : "<a href=\"#EndPath\">line "
220 : << (*D.rbegin()).getLocation().asLocation().getInstantiationLineNumber()
221 : << ", column "
222 : << (*D.rbegin()).getLocation().asLocation().getInstantiationColumnNumber()
223 : << "</a></td></tr>\n"
224 : "<tr><td class=\"rowname\">Description:</td><td>"
225 1: << D.getDescription() << "</td></tr>\n";
226 :
227 : // Output any other meta data.
228 :
0: branch 4 not taken
1: branch 5 taken
229 1: for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end();
230 : I!=E; ++I) {
231 0: os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
232 : }
233 :
234 : os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n"
235 1: "<h3>Annotated Source Code</h3>\n";
236 :
237 1: R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
238 : }
239 :
240 : // Embed meta-data tags.
241 : {
242 1: std::string s;
243 1: llvm::raw_string_ostream os(s);
244 :
245 1: const std::string& BugDesc = D.getDescription();
1: branch 1 taken
0: branch 2 not taken
246 1: if (!BugDesc.empty())
247 1: os << "\n<!-- BUGDESC " << BugDesc << " -->\n";
248 :
249 1: const std::string& BugType = D.getBugType();
1: branch 1 taken
0: branch 2 not taken
250 1: if (!BugType.empty())
251 1: os << "\n<!-- BUGTYPE " << BugType << " -->\n";
252 :
253 1: const std::string& BugCategory = D.getCategory();
1: branch 1 taken
0: branch 2 not taken
254 1: if (!BugCategory.empty())
255 1: os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
256 :
257 1: os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
258 :
259 : os << "\n<!-- BUGLINE "
260 : << D.back()->getLocation().asLocation().getInstantiationLineNumber()
261 1: << " -->\n";
262 :
263 1: os << "\n<!-- BUGPATHLENGTH " << D.size() << " -->\n";
264 :
265 : // Mark the end of the tags.
266 1: os << "\n<!-- BUGMETAEND -->\n";
267 :
268 : // Insert the text.
269 1: R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
270 : }
271 :
272 : // Add CSS, header, and footer.
273 :
274 1: html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
275 :
276 : // Get the rewrite buffer.
277 1: const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
278 :
0: branch 0 not taken
1: branch 1 taken
279 1: if (!Buf) {
280 0: llvm::errs() << "warning: no diagnostics generated for main file.\n";
281 0: return;
282 : }
283 :
284 : // Create a path for the target HTML file.
285 1: llvm::sys::Path F(FilePrefix);
286 1: F.makeUnique(false, NULL);
287 :
288 : // Rename the file with an HTML extension.
289 1: llvm::sys::Path H(F);
290 1: H.appendSuffix("html");
291 1: F.renamePathOnDisk(H, NULL);
292 :
293 1: std::string ErrorMsg;
294 1: llvm::raw_fd_ostream os(H.c_str(), ErrorMsg);
295 :
0: branch 1 not taken
1: branch 2 taken
296 1: if (!ErrorMsg.empty()) {
297 : (llvm::errs() << "warning: could not create file '" << F.str()
298 0: << "'\n").flush();
299 : return;
300 : }
301 :
0: branch 0 not taken
1: branch 1 taken
302 1: if (FilesMade)
303 0: FilesMade->push_back(H.getLast());
304 :
305 : // Emit the HTML to disk.
6106: branch 4 taken
1: branch 5 taken
306 6107: for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
1: branch 3 taken
0: branch 4 not taken
1: branch 6 taken
0: branch 7 not taken
1: branch 9 taken
0: branch 10 not taken
1: branch 12 taken
0: branch 13 not taken
1: branch 15 taken
0: branch 16 not taken
1: branch 18 taken
0: branch 19 not taken
307 6107: os << *I;
308 : }
309 :
310 : void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
311 : const PathDiagnosticPiece& P,
312 4: unsigned num, unsigned max) {
313 :
314 : // For now, just draw a box above the line in question, and emit the
315 : // warning.
316 4: FullSourceLoc Pos = P.getLocation().asLocation();
317 :
0: branch 1 not taken
4: branch 2 taken
318 4: if (!Pos.isValid())
319 0: return;
320 :
321 4: SourceManager &SM = R.getSourceMgr();
4: branch 1 taken
0: branch 2 not taken
322 4: assert(&Pos.getManager() == &SM && "SourceManagers are different!");
323 4: std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedInstantiationLoc(Pos);
324 :
0: branch 1 not taken
4: branch 2 taken
325 4: if (LPosInfo.first != BugFileID)
326 0: return;
327 :
328 4: const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
329 4: const char* FileStart = Buf->getBufferStart();
330 :
331 : // Compute the column number. Rewind from the current position to the start
332 : // of the line.
333 4: unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second);
334 4: const char *TokInstantiationPtr =Pos.getInstantiationLoc().getCharacterData();
335 4: const char *LineStart = TokInstantiationPtr-ColNo;
336 :
337 : // Compute LineEnd.
338 4: const char *LineEnd = TokInstantiationPtr;
339 4: const char* FileEnd = Buf->getBufferEnd();
39: branch 0 taken
4: branch 1 taken
39: branch 2 taken
0: branch 3 not taken
340 47: while (*LineEnd != '\n' && LineEnd != FileEnd)
341 39: ++LineEnd;
342 :
343 : // Compute the margin offset by counting tabs and non-tabs.
344 4: unsigned PosNo = 0;
18: branch 0 taken
4: branch 1 taken
345 22: for (const char* c = LineStart; c != TokInstantiationPtr; ++c)
0: branch 0 not taken
18: branch 1 taken
346 18: PosNo += *c == '\t' ? 8 : 1;
347 :
348 : // Create the html for the message.
349 :
350 4: const char *Kind = 0;
2: branch 1 taken
2: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
351 4: switch (P.getKind()) {
352 2: case PathDiagnosticPiece::Event: Kind = "Event"; break;
353 2: case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
354 : // Setting Kind to "Control" is intentional.
355 0: case PathDiagnosticPiece::Macro: Kind = "Control"; break;
356 : }
357 :
358 4: std::string sbuf;
359 4: llvm::raw_string_ostream os(sbuf);
360 :
361 4: os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";
362 :
1: branch 0 taken
3: branch 1 taken
363 4: if (num == max)
364 1: os << "EndPath";
365 : else
366 3: os << "Path" << num;
367 :
368 4: os << "\" class=\"msg";
4: branch 0 taken
0: branch 1 not taken
369 4: if (Kind)
370 4: os << " msg" << Kind;
371 4: os << "\" style=\"margin-left:" << PosNo << "ex";
372 :
373 : // Output a maximum size.
4: branch 1 taken
0: branch 2 not taken
374 4: if (!isa<PathDiagnosticMacroPiece>(P)) {
375 : // Get the string and determining its maximum substring.
376 4: const std::string& Msg = P.getString();
377 4: unsigned max_token = 0;
378 4: unsigned cnt = 0;
379 4: unsigned len = Msg.size();
380 :
120: branch 4 taken
4: branch 5 taken
381 124: for (std::string::const_iterator I=Msg.begin(), E=Msg.end(); I!=E; ++I)
104: branch 1 taken
16: branch 2 taken
382 120: switch (*I) {
383 : default:
384 104: ++cnt;
385 104: continue;
386 : case ' ':
387 : case '\t':
388 : case '\n':
5: branch 0 taken
11: branch 1 taken
389 16: if (cnt > max_token) max_token = cnt;
390 16: cnt = 0;
391 : }
392 :
0: branch 0 not taken
4: branch 1 taken
393 4: if (cnt > max_token)
394 0: max_token = cnt;
395 :
396 : // Determine the approximate size of the message bubble in em.
397 : unsigned em;
398 4: const unsigned max_line = 120;
399 :
0: branch 0 not taken
4: branch 1 taken
400 4: if (max_token >= max_line)
401 0: em = max_token / 2;
402 : else {
403 4: unsigned characters = max_line;
404 4: unsigned lines = len / max_line;
405 :
0: branch 0 not taken
4: branch 1 taken
406 4: if (lines > 0) {
0: branch 0 not taken
0: branch 1 not taken
407 0: for (; characters > max_token; --characters)
0: branch 0 not taken
0: branch 1 not taken
408 0: if (len / characters > lines) {
409 0: ++characters;
410 0: break;
411 : }
412 : }
413 :
414 4: em = characters / 2;
415 : }
416 :
0: branch 0 not taken
4: branch 1 taken
417 4: if (em < max_line/2)
418 0: os << "; max-width:" << em << "em";
419 : }
420 : else
421 0: os << "; max-width:100em";
422 :
423 4: os << "\">";
424 :
4: branch 0 taken
0: branch 1 not taken
425 4: if (max > 1) {
426 4: os << "<table class=\"msgT\"><tr><td valign=\"top\">";
427 4: os << "<div class=\"PathIndex";
4: branch 0 taken
0: branch 1 not taken
428 4: if (Kind) os << " PathIndex" << Kind;
429 4: os << "\">" << num << "</div>";
430 4: os << "</td><td>";
431 : }
432 :
0: branch 0 not taken
4: branch 1 taken
433 4: if (const PathDiagnosticMacroPiece *MP =
434 4: dyn_cast<PathDiagnosticMacroPiece>(&P)) {
435 :
436 0: os << "Within the expansion of the macro '";
437 :
438 : // Get the name of the macro by relexing it.
439 : {
440 0: FullSourceLoc L = MP->getLocation().asLocation().getInstantiationLoc();
0: branch 1 not taken
0: branch 2 not taken
441 0: assert(L.isFileID());
442 0: std::pair<const char*, const char*> BufferInfo = L.getBufferData();
443 0: const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first;
444 : Lexer rawLexer(L, PP.getLangOptions(), BufferInfo.first,
445 0: MacroName, BufferInfo.second);
446 :
447 0: Token TheTok;
448 0: rawLexer.LexFromRawLexer(TheTok);
0: branch 1 not taken
0: branch 2 not taken
449 0: for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
450 0: os << MacroName[i];
451 : }
452 :
453 0: os << "':\n";
454 :
0: branch 0 not taken
0: branch 1 not taken
455 0: if (max > 1)
456 0: os << "</td></tr></table>";
457 :
458 : // Within a macro piece. Write out each event.
459 0: ProcessMacroPiece(os, *MP, 0);
460 : }
461 : else {
462 4: os << html::EscapeText(P.getString());
463 :
4: branch 0 taken
0: branch 1 not taken
464 4: if (max > 1)
465 4: os << "</td></tr></table>";
466 : }
467 :
468 4: os << "</div></td></tr>";
469 :
470 : // Insert the new html.
471 4: unsigned DisplayPos = LineEnd - FileStart;
472 : SourceLocation Loc =
473 4: SM.getLocForStartOfFile(LPosInfo.first).getFileLocWithOffset(DisplayPos);
474 :
475 4: R.InsertTextBefore(Loc, os.str());
476 :
477 : // Now highlight the ranges.
2: branch 2 taken
4: branch 3 taken
478 6: for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
479 : I != E; ++I)
480 6: HighlightRange(R, LPosInfo.first, *I);
481 :
482 : #if 0
483 : // If there is a code insertion hint, insert that code.
484 : // FIXME: This code is disabled because it seems to mangle the HTML
485 : // output. I'm leaving it here because it's generally the right idea,
486 : // but needs some help from someone more familiar with the rewriter.
487 : for (const CodeModificationHint *Hint = P.code_modifications_begin(),
488 : *HintEnd = P.code_modifications_end();
489 : Hint != HintEnd; ++Hint) {
490 : if (Hint->RemoveRange.isValid()) {
491 : HighlightRange(R, LPosInfo.first, Hint->RemoveRange,
492 : "<span class=\"CodeRemovalHint\">", "</span>");
493 : }
494 : if (Hint->InsertionLoc.isValid()) {
495 : std::string EscapedCode = html::EscapeText(Hint->CodeToInsert, true);
496 : EscapedCode = "<span class=\"CodeInsertionHint\">" + EscapedCode
497 : + "</span>";
498 : R.InsertTextBefore(Hint->InsertionLoc, EscapedCode);
499 : }
500 : }
501 : #endif
502 : }
503 :
504 0: static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) {
505 0: llvm::SmallVector<char, 10> buf;
506 :
0: branch 0 not taken
0: branch 1 not taken
507 0: do {
508 0: unsigned x = n % ('z' - 'a');
509 0: buf.push_back('a' + x);
510 0: n = n / ('z' - 'a');
511 : } while (n);
512 :
0: branch 1 not taken
0: branch 2 not taken
513 0: assert(!buf.empty());
514 :
0: branch 3 not taken
0: branch 4 not taken
515 0: for (llvm::SmallVectorImpl<char>::reverse_iterator I=buf.rbegin(),
516 0: E=buf.rend(); I!=E; ++I)
517 0: os << *I;
518 0: }
519 :
520 : unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os,
521 : const PathDiagnosticMacroPiece& P,
522 0: unsigned num) {
523 :
0: branch 4 not taken
0: branch 5 not taken
524 0: for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
525 : I!=E; ++I) {
526 :
0: branch 0 not taken
0: branch 1 not taken
527 0: if (const PathDiagnosticMacroPiece *MP =
528 0: dyn_cast<PathDiagnosticMacroPiece>(*I)) {
529 0: num = ProcessMacroPiece(os, *MP, num);
530 0: continue;
531 : }
532 :
0: branch 2 not taken
0: branch 3 not taken
533 0: if (PathDiagnosticEventPiece *EP = dyn_cast<PathDiagnosticEventPiece>(*I)) {
534 : os << "<div class=\"msg msgEvent\" style=\"width:94%; "
535 : "margin-left:5px\">"
536 : "<table class=\"msgT\"><tr>"
537 0: "<td valign=\"top\"><div class=\"PathIndex PathIndexEvent\">";
538 0: EmitAlphaCounter(os, num++);
539 : os << "</div></td><td valign=\"top\">"
540 : << html::EscapeText(EP->getString())
541 0: << "</td></tr></table></div>\n";
542 : }
543 : }
544 :
545 0: return num;
546 : }
547 :
548 : void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
549 : SourceRange Range,
550 : const char *HighlightStart,
551 2: const char *HighlightEnd) {
552 2: SourceManager &SM = R.getSourceMgr();
553 2: const LangOptions &LangOpts = R.getLangOpts();
554 :
555 2: SourceLocation InstantiationStart = SM.getInstantiationLoc(Range.getBegin());
556 2: unsigned StartLineNo = SM.getInstantiationLineNumber(InstantiationStart);
557 :
558 2: SourceLocation InstantiationEnd = SM.getInstantiationLoc(Range.getEnd());
559 2: unsigned EndLineNo = SM.getInstantiationLineNumber(InstantiationEnd);
560 :
0: branch 0 not taken
2: branch 1 taken
561 2: if (EndLineNo < StartLineNo)
562 0: return;
563 :
2: branch 2 taken
0: branch 3 not taken
0: branch 6 not taken
2: branch 7 taken
0: branch 8 not taken
2: branch 9 taken
564 2: if (SM.getFileID(InstantiationStart) != BugFileID ||
565 : SM.getFileID(InstantiationEnd) != BugFileID)
566 0: return;
567 :
568 : // Compute the column number of the end.
569 2: unsigned EndColNo = SM.getInstantiationColumnNumber(InstantiationEnd);
570 2: unsigned OldEndColNo = EndColNo;
571 :
2: branch 0 taken
0: branch 1 not taken
572 2: if (EndColNo) {
573 : // Add in the length of the token, so that we cover multi-char tokens.
574 2: EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM, LangOpts)-1;
575 : }
576 :
577 : // Highlight the range. Make the span tag the outermost tag for the
578 : // selected range.
579 :
580 : SourceLocation E =
581 2: InstantiationEnd.getFileLocWithOffset(EndColNo - OldEndColNo);
582 :
583 2: html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
584 : }
Generated: 2010-02-10 01:31 by zcov