clang  5.0.0
HTMLDiagnostics.cpp
Go to the documentation of this file.
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/AST/ASTContext.h"
15 #include "clang/AST/Decl.h"
18 #include "clang/Lex/Lexer.h"
19 #include "clang/Lex/Preprocessor.h"
26 #include "llvm/Support/Errc.h"
27 #include "llvm/Support/FileSystem.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include "llvm/Support/Path.h"
30 #include "llvm/Support/raw_ostream.h"
31 #include <sstream>
32 
33 using namespace clang;
34 using namespace ento;
35 
36 //===----------------------------------------------------------------------===//
37 // Boilerplate.
38 //===----------------------------------------------------------------------===//
39 
40 namespace {
41 
42 class HTMLDiagnostics : public PathDiagnosticConsumer {
43  std::string Directory;
44  bool createdDir, noDir;
45  const Preprocessor &PP;
46  AnalyzerOptions &AnalyzerOpts;
47 public:
48  HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts, const std::string& prefix, const Preprocessor &pp);
49 
50  ~HTMLDiagnostics() override { FlushDiagnostics(nullptr); }
51 
52  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
53  FilesMade *filesMade) override;
54 
55  StringRef getName() const override {
56  return "HTMLDiagnostics";
57  }
58 
59  unsigned ProcessMacroPiece(raw_ostream &os,
61  unsigned num);
62 
63  void HandlePiece(Rewriter& R, FileID BugFileID,
64  const PathDiagnosticPiece& P, unsigned num, unsigned max);
65 
66  void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range,
67  const char *HighlightStart = "<span class=\"mrange\">",
68  const char *HighlightEnd = "</span>");
69 
70  void ReportDiag(const PathDiagnostic& D,
71  FilesMade *filesMade);
72 };
73 
74 } // end anonymous namespace
75 
76 HTMLDiagnostics::HTMLDiagnostics(AnalyzerOptions &AnalyzerOpts,
77  const std::string& prefix,
78  const Preprocessor &pp)
79  : Directory(prefix), createdDir(false), noDir(false), PP(pp), AnalyzerOpts(AnalyzerOpts) {
80 }
81 
82 void ento::createHTMLDiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,
84  const std::string& prefix,
85  const Preprocessor &PP) {
86  C.push_back(new HTMLDiagnostics(AnalyzerOpts, prefix, PP));
87 }
88 
89 //===----------------------------------------------------------------------===//
90 // Report processing.
91 //===----------------------------------------------------------------------===//
92 
93 void HTMLDiagnostics::FlushDiagnosticsImpl(
94  std::vector<const PathDiagnostic *> &Diags,
95  FilesMade *filesMade) {
96  for (std::vector<const PathDiagnostic *>::iterator it = Diags.begin(),
97  et = Diags.end(); it != et; ++it) {
98  ReportDiag(**it, filesMade);
99  }
100 }
101 
103  FilesMade *filesMade) {
104 
105  // Create the HTML directory if it is missing.
106  if (!createdDir) {
107  createdDir = true;
108  if (std::error_code ec = llvm::sys::fs::create_directories(Directory)) {
109  llvm::errs() << "warning: could not create directory '"
110  << Directory << "': " << ec.message() << '\n';
111 
112  noDir = true;
113 
114  return;
115  }
116  }
117 
118  if (noDir)
119  return;
120 
121  // First flatten out the entire path to make it easier to use.
122  PathPieces path = D.path.flatten(/*ShouldFlattenMacros=*/false);
123 
124  // The path as already been prechecked that all parts of the path are
125  // from the same file and that it is non-empty.
126  const SourceManager &SMgr = path.front()->getLocation().getManager();
127  assert(!path.empty());
128  FileID FID =
129  path.front()->getLocation().asLocation().getExpansionLoc().getFileID();
130  assert(FID.isValid());
131 
132  // Create a new rewriter to generate HTML.
133  Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOpts());
134 
135  // Get the function/method name
136  SmallString<128> declName("unknown");
137  int offsetDecl = 0;
138  if (const Decl *DeclWithIssue = D.getDeclWithIssue()) {
139  if (const NamedDecl *ND = dyn_cast<NamedDecl>(DeclWithIssue)) {
140  declName = ND->getDeclName().getAsString();
141  }
142 
143  if (const Stmt *Body = DeclWithIssue->getBody()) {
144  // Retrieve the relative position of the declaration which will be used
145  // for the file name
146  FullSourceLoc L(
147  SMgr.getExpansionLoc(path.back()->getLocation().asLocation()),
148  SMgr);
149  FullSourceLoc FunL(SMgr.getExpansionLoc(Body->getLocStart()), SMgr);
150  offsetDecl = L.getExpansionLineNumber() - FunL.getExpansionLineNumber();
151  }
152  }
153 
154  // Process the path.
155  // Maintain the counts of extra note pieces separately.
156  unsigned TotalPieces = path.size();
157  unsigned TotalNotePieces =
158  std::count_if(path.begin(), path.end(),
159  [](const std::shared_ptr<PathDiagnosticPiece> &p) {
160  return isa<PathDiagnosticNotePiece>(*p);
161  });
162 
163  unsigned TotalRegularPieces = TotalPieces - TotalNotePieces;
164  unsigned NumRegularPieces = TotalRegularPieces;
165  unsigned NumNotePieces = TotalNotePieces;
166 
167  for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
168  if (isa<PathDiagnosticNotePiece>(I->get())) {
169  // This adds diagnostic bubbles, but not navigation.
170  // Navigation through note pieces would be added later,
171  // as a separate pass through the piece list.
172  HandlePiece(R, FID, **I, NumNotePieces, TotalNotePieces);
173  --NumNotePieces;
174  } else {
175  HandlePiece(R, FID, **I, NumRegularPieces, TotalRegularPieces);
176  --NumRegularPieces;
177  }
178  }
179 
180  // Add line numbers, header, footer, etc.
181 
182  // unsigned FID = R.getSourceMgr().getMainFileID();
183  html::EscapeText(R, FID);
184  html::AddLineNumbers(R, FID);
185 
186  // If we have a preprocessor, relex the file and syntax highlight.
187  // We might not have a preprocessor if we come from a deserialized AST file,
188  // for example.
189 
190  html::SyntaxHighlight(R, FID, PP);
191  html::HighlightMacros(R, FID, PP);
192 
193  // Get the full directory name of the analyzed file.
194 
195  const FileEntry* Entry = SMgr.getFileEntryForID(FID);
196 
197  // This is a cludge; basically we want to append either the full
198  // working directory if we have no directory information. This is
199  // a work in progress.
200 
201  llvm::SmallString<0> DirName;
202 
203  if (llvm::sys::path::is_relative(Entry->getName())) {
204  llvm::sys::fs::current_path(DirName);
205  DirName += '/';
206  }
207 
208  int LineNumber = path.back()->getLocation().asLocation().getExpansionLineNumber();
209  int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber();
210 
211  // Add the name of the file as an <h1> tag.
212  {
213  std::string s;
214  llvm::raw_string_ostream os(s);
215 
216  os << "<!-- REPORTHEADER -->\n"
217  << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
218  "<tr><td class=\"rowname\">File:</td><td>"
219  << html::EscapeText(DirName)
220  << html::EscapeText(Entry->getName())
221  << "</td></tr>\n<tr><td class=\"rowname\">Warning:</td><td>"
222  "<a href=\"#EndPath\">line "
223  << LineNumber
224  << ", column "
225  << ColumnNumber
226  << "</a><br />"
227  << D.getVerboseDescription() << "</td></tr>\n";
228 
229  // The navigation across the extra notes pieces.
230  unsigned NumExtraPieces = 0;
231  for (const auto &Piece : path) {
232  if (const auto *P = dyn_cast<PathDiagnosticNotePiece>(Piece.get())) {
233  int LineNumber =
234  P->getLocation().asLocation().getExpansionLineNumber();
235  int ColumnNumber =
236  P->getLocation().asLocation().getExpansionColumnNumber();
237  os << "<tr><td class=\"rowname\">Note:</td><td>"
238  << "<a href=\"#Note" << NumExtraPieces << "\">line "
239  << LineNumber << ", column " << ColumnNumber << "</a><br />"
240  << P->getString() << "</td></tr>";
241  ++NumExtraPieces;
242  }
243  }
244 
245  // Output any other meta data.
246 
248  I!=E; ++I) {
249  os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
250  }
251 
252  os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n"
253  "<h3>Annotated Source Code</h3>\n";
254 
255  R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
256  }
257 
258  // Embed meta-data tags.
259  {
260  std::string s;
261  llvm::raw_string_ostream os(s);
262 
263  StringRef BugDesc = D.getVerboseDescription();
264  if (!BugDesc.empty())
265  os << "\n<!-- BUGDESC " << BugDesc << " -->\n";
266 
267  StringRef BugType = D.getBugType();
268  if (!BugType.empty())
269  os << "\n<!-- BUGTYPE " << BugType << " -->\n";
270 
272  FullSourceLoc L(SMgr.getExpansionLoc(UPDLoc.isValid()
273  ? UPDLoc.asLocation()
274  : D.getLocation().asLocation()),
275  SMgr);
276  const Decl *DeclWithIssue = D.getDeclWithIssue();
277 
278  StringRef BugCategory = D.getCategory();
279  if (!BugCategory.empty())
280  os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
281 
282  os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
283 
284  os << "\n<!-- FILENAME " << llvm::sys::path::filename(Entry->getName()) << " -->\n";
285 
286  os << "\n<!-- FUNCTIONNAME " << declName << " -->\n";
287 
288  os << "\n<!-- ISSUEHASHCONTENTOFLINEINCONTEXT "
289  << GetIssueHash(SMgr, L, D.getCheckName(), D.getBugType(), DeclWithIssue,
290  PP.getLangOpts()) << " -->\n";
291 
292  os << "\n<!-- BUGLINE "
293  << LineNumber
294  << " -->\n";
295 
296  os << "\n<!-- BUGCOLUMN "
297  << ColumnNumber
298  << " -->\n";
299 
300  os << "\n<!-- BUGPATHLENGTH " << path.size() << " -->\n";
301 
302  // Mark the end of the tags.
303  os << "\n<!-- BUGMETAEND -->\n";
304 
305  // Insert the text.
306  R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str());
307  }
308 
309  // Add CSS, header, and footer.
310 
312 
313  // Get the rewrite buffer.
314  const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
315 
316  if (!Buf) {
317  llvm::errs() << "warning: no diagnostics generated for main file.\n";
318  return;
319  }
320 
321  // Create a path for the target HTML file.
322  int FD;
323  SmallString<128> Model, ResultPath;
324 
325  if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
326  llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
327  if (std::error_code EC =
328  llvm::sys::fs::make_absolute(Model)) {
329  llvm::errs() << "warning: could not make '" << Model
330  << "' absolute: " << EC.message() << '\n';
331  return;
332  }
333  if (std::error_code EC =
334  llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
335  llvm::errs() << "warning: could not create file in '" << Directory
336  << "': " << EC.message() << '\n';
337  return;
338  }
339 
340  } else {
341  int i = 1;
342  std::error_code EC;
343  do {
344  // Find a filename which is not already used
345  std::stringstream filename;
346  Model = "";
347  filename << "report-"
348  << llvm::sys::path::filename(Entry->getName()).str()
349  << "-" << declName.c_str()
350  << "-" << offsetDecl
351  << "-" << i << ".html";
352  llvm::sys::path::append(Model, Directory,
353  filename.str());
354  EC = llvm::sys::fs::openFileForWrite(Model,
355  FD,
356  llvm::sys::fs::F_RW |
357  llvm::sys::fs::F_Excl);
358  if (EC && EC != llvm::errc::file_exists) {
359  llvm::errs() << "warning: could not create file '" << Model
360  << "': " << EC.message() << '\n';
361  return;
362  }
363  i++;
364  } while (EC);
365  }
366 
367  llvm::raw_fd_ostream os(FD, true);
368 
369  if (filesMade)
370  filesMade->addDiagnostic(D, getName(),
371  llvm::sys::path::filename(ResultPath));
372 
373  // Emit the HTML to disk.
374  for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
375  os << *I;
376 }
377 
378 void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
379  const PathDiagnosticPiece& P,
380  unsigned num, unsigned max) {
381 
382  // For now, just draw a box above the line in question, and emit the
383  // warning.
385 
386  if (!Pos.isValid())
387  return;
388 
390  assert(&Pos.getManager() == &SM && "SourceManagers are different!");
391  std::pair<FileID, unsigned> LPosInfo = SM.getDecomposedExpansionLoc(Pos);
392 
393  if (LPosInfo.first != BugFileID)
394  return;
395 
396  const llvm::MemoryBuffer *Buf = SM.getBuffer(LPosInfo.first);
397  const char* FileStart = Buf->getBufferStart();
398 
399  // Compute the column number. Rewind from the current position to the start
400  // of the line.
401  unsigned ColNo = SM.getColumnNumber(LPosInfo.first, LPosInfo.second);
402  const char *TokInstantiationPtr =Pos.getExpansionLoc().getCharacterData();
403  const char *LineStart = TokInstantiationPtr-ColNo;
404 
405  // Compute LineEnd.
406  const char *LineEnd = TokInstantiationPtr;
407  const char* FileEnd = Buf->getBufferEnd();
408  while (*LineEnd != '\n' && LineEnd != FileEnd)
409  ++LineEnd;
410 
411  // Compute the margin offset by counting tabs and non-tabs.
412  unsigned PosNo = 0;
413  for (const char* c = LineStart; c != TokInstantiationPtr; ++c)
414  PosNo += *c == '\t' ? 8 : 1;
415 
416  // Create the html for the message.
417 
418  const char *Kind = nullptr;
419  bool IsNote = false;
420  bool SuppressIndex = (max == 1);
421  switch (P.getKind()) {
423  llvm_unreachable("Calls and extra notes should already be handled");
424  case PathDiagnosticPiece::Event: Kind = "Event"; break;
425  case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
426  // Setting Kind to "Control" is intentional.
427  case PathDiagnosticPiece::Macro: Kind = "Control"; break;
429  Kind = "Note";
430  IsNote = true;
431  SuppressIndex = true;
432  break;
433  }
434 
435  std::string sbuf;
436  llvm::raw_string_ostream os(sbuf);
437 
438  os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";
439 
440  if (IsNote)
441  os << "Note" << num;
442  else if (num == max)
443  os << "EndPath";
444  else
445  os << "Path" << num;
446 
447  os << "\" class=\"msg";
448  if (Kind)
449  os << " msg" << Kind;
450  os << "\" style=\"margin-left:" << PosNo << "ex";
451 
452  // Output a maximum size.
453  if (!isa<PathDiagnosticMacroPiece>(P)) {
454  // Get the string and determining its maximum substring.
455  const auto &Msg = P.getString();
456  unsigned max_token = 0;
457  unsigned cnt = 0;
458  unsigned len = Msg.size();
459 
460  for (char C : Msg)
461  switch (C) {
462  default:
463  ++cnt;
464  continue;
465  case ' ':
466  case '\t':
467  case '\n':
468  if (cnt > max_token) max_token = cnt;
469  cnt = 0;
470  }
471 
472  if (cnt > max_token)
473  max_token = cnt;
474 
475  // Determine the approximate size of the message bubble in em.
476  unsigned em;
477  const unsigned max_line = 120;
478 
479  if (max_token >= max_line)
480  em = max_token / 2;
481  else {
482  unsigned characters = max_line;
483  unsigned lines = len / max_line;
484 
485  if (lines > 0) {
486  for (; characters > max_token; --characters)
487  if (len / characters > lines) {
488  ++characters;
489  break;
490  }
491  }
492 
493  em = characters / 2;
494  }
495 
496  if (em < max_line/2)
497  os << "; max-width:" << em << "em";
498  }
499  else
500  os << "; max-width:100em";
501 
502  os << "\">";
503 
504  if (!SuppressIndex) {
505  os << "<table class=\"msgT\"><tr><td valign=\"top\">";
506  os << "<div class=\"PathIndex";
507  if (Kind) os << " PathIndex" << Kind;
508  os << "\">" << num << "</div>";
509 
510  if (num > 1) {
511  os << "</td><td><div class=\"PathNav\"><a href=\"#Path"
512  << (num - 1)
513  << "\" title=\"Previous event ("
514  << (num - 1)
515  << ")\">&#x2190;</a></div></td>";
516  }
517 
518  os << "</td><td>";
519  }
520 
521  if (const PathDiagnosticMacroPiece *MP =
522  dyn_cast<PathDiagnosticMacroPiece>(&P)) {
523 
524  os << "Within the expansion of the macro '";
525 
526  // Get the name of the macro by relexing it.
527  {
528  FullSourceLoc L = MP->getLocation().asLocation().getExpansionLoc();
529  assert(L.isFileID());
530  StringRef BufferInfo = L.getBufferData();
531  std::pair<FileID, unsigned> LocInfo = L.getDecomposedLoc();
532  const char* MacroName = LocInfo.second + BufferInfo.data();
533  Lexer rawLexer(SM.getLocForStartOfFile(LocInfo.first), PP.getLangOpts(),
534  BufferInfo.begin(), MacroName, BufferInfo.end());
535 
536  Token TheTok;
537  rawLexer.LexFromRawLexer(TheTok);
538  for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i)
539  os << MacroName[i];
540  }
541 
542  os << "':\n";
543 
544  if (!SuppressIndex) {
545  os << "</td>";
546  if (num < max) {
547  os << "<td><div class=\"PathNav\"><a href=\"#";
548  if (num == max - 1)
549  os << "EndPath";
550  else
551  os << "Path" << (num + 1);
552  os << "\" title=\"Next event ("
553  << (num + 1)
554  << ")\">&#x2192;</a></div></td>";
555  }
556 
557  os << "</tr></table>";
558  }
559 
560  // Within a macro piece. Write out each event.
561  ProcessMacroPiece(os, *MP, 0);
562  }
563  else {
564  os << html::EscapeText(P.getString());
565 
566  if (!SuppressIndex) {
567  os << "</td>";
568  if (num < max) {
569  os << "<td><div class=\"PathNav\"><a href=\"#";
570  if (num == max - 1)
571  os << "EndPath";
572  else
573  os << "Path" << (num + 1);
574  os << "\" title=\"Next event ("
575  << (num + 1)
576  << ")\">&#x2192;</a></div></td>";
577  }
578 
579  os << "</tr></table>";
580  }
581  }
582 
583  os << "</div></td></tr>";
584 
585  // Insert the new html.
586  unsigned DisplayPos = LineEnd - FileStart;
588  SM.getLocForStartOfFile(LPosInfo.first).getLocWithOffset(DisplayPos);
589 
590  R.InsertTextBefore(Loc, os.str());
591 
592  // Now highlight the ranges.
593  ArrayRef<SourceRange> Ranges = P.getRanges();
594  for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
595  E = Ranges.end(); I != E; ++I) {
596  HighlightRange(R, LPosInfo.first, *I);
597  }
598 }
599 
600 static void EmitAlphaCounter(raw_ostream &os, unsigned n) {
601  unsigned x = n % ('z' - 'a');
602  n /= 'z' - 'a';
603 
604  if (n > 0)
605  EmitAlphaCounter(os, n);
606 
607  os << char('a' + x);
608 }
609 
610 unsigned HTMLDiagnostics::ProcessMacroPiece(raw_ostream &os,
611  const PathDiagnosticMacroPiece& P,
612  unsigned num) {
613 
614  for (PathPieces::const_iterator I = P.subPieces.begin(), E=P.subPieces.end();
615  I!=E; ++I) {
616 
617  if (const PathDiagnosticMacroPiece *MP =
618  dyn_cast<PathDiagnosticMacroPiece>(I->get())) {
619  num = ProcessMacroPiece(os, *MP, num);
620  continue;
621  }
622 
623  if (PathDiagnosticEventPiece *EP =
624  dyn_cast<PathDiagnosticEventPiece>(I->get())) {
625  os << "<div class=\"msg msgEvent\" style=\"width:94%; "
626  "margin-left:5px\">"
627  "<table class=\"msgT\"><tr>"
628  "<td valign=\"top\"><div class=\"PathIndex PathIndexEvent\">";
629  EmitAlphaCounter(os, num++);
630  os << "</div></td><td valign=\"top\">"
631  << html::EscapeText(EP->getString())
632  << "</td></tr></table></div>\n";
633  }
634  }
635 
636  return num;
637 }
638 
640  SourceRange Range,
641  const char *HighlightStart,
642  const char *HighlightEnd) {
643  SourceManager &SM = R.getSourceMgr();
644  const LangOptions &LangOpts = R.getLangOpts();
645 
646  SourceLocation InstantiationStart = SM.getExpansionLoc(Range.getBegin());
647  unsigned StartLineNo = SM.getExpansionLineNumber(InstantiationStart);
648 
649  SourceLocation InstantiationEnd = SM.getExpansionLoc(Range.getEnd());
650  unsigned EndLineNo = SM.getExpansionLineNumber(InstantiationEnd);
651 
652  if (EndLineNo < StartLineNo)
653  return;
654 
655  if (SM.getFileID(InstantiationStart) != BugFileID ||
656  SM.getFileID(InstantiationEnd) != BugFileID)
657  return;
658 
659  // Compute the column number of the end.
660  unsigned EndColNo = SM.getExpansionColumnNumber(InstantiationEnd);
661  unsigned OldEndColNo = EndColNo;
662 
663  if (EndColNo) {
664  // Add in the length of the token, so that we cover multi-char tokens.
665  EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM, LangOpts)-1;
666  }
667 
668  // Highlight the range. Make the span tag the outermost tag for the
669  // selected range.
670 
671  SourceLocation E =
672  InstantiationEnd.getLocWithOffset(EndColNo - OldEndColNo);
673 
674  html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd);
675 }
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
Defines the clang::ASTContext interface.
SourceLocation getEnd() const
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
Definition: Lexer.h:46
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
SourceManager & getSourceMgr() const
Definition: Rewriter.h:64
Defines the clang::FileManager interface and associated types.
std::deque< std::string >::const_iterator meta_iterator
Stmt - This represents one statement.
Definition: Stmt.h:60
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
PathPieces flatten(bool ShouldFlattenMacros) const
StringRef getCategory() const
StringRef P
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
const SourceManager & getManager() const
llvm::SmallString< 32 > GetIssueHash(const SourceManager &SM, FullSourceLoc &IssueLoc, llvm::StringRef CheckerName, llvm::StringRef BugType, const Decl *D, const LangOptions &LangOpts)
Get an MD5 hash to help identify bugs.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
PathDiagnosticLocation getLocation() const
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
Definition: RewriteBuffer.h:27
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
FullSourceLoc asLocation() const
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
void HighlightMacros(Rewriter &R, FileID FID, const Preprocessor &PP)
HighlightMacros - This uses the macro table state from the end of the file, to reexpand macros and in...
void AddLineNumbers(Rewriter &R, FileID FID)
bool isFileID() const
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:725
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
std::pair< FileID, unsigned > getDecomposedLoc() const
Decompose the specified location into a raw FileID + Offset pair.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
StringRef getName() const
Definition: FileManager.h:84
void SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP)
SyntaxHighlight - Relex the specified FileID and annotate the HTML with information about keywords...
meta_iterator meta_begin() const
detail::InMemoryDirectory::const_iterator I
virtual PathDiagnosticLocation getLocation() const =0
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool shouldWriteStableReportFilename()
Returns whether or not the report filename should be random or not.
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Definition: Lexer.cpp:417
static void EmitAlphaCounter(raw_ostream &os, unsigned n)
Defines the clang::Preprocessor interface.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
static void ReportDiag(raw_ostream &o, const PathDiagnosticPiece &P, const FIDMap &FM, const SourceManager &SM, const LangOptions &LangOpts)
unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Return the column # for the specified file position.
const SourceManager & SM
Definition: Format.cpp:1293
meta_iterator meta_end() const
#define false
Definition: stdbool.h:33
Kind
Encodes a location in the source.
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
const char * getCharacterData(bool *Invalid=nullptr) const
bool isValid() const
Return true if this is a valid SourceLocation object.
StringRef getVerboseDescription() const
void EscapeText(Rewriter &R, FileID FID, bool EscapeSpaces=false, bool ReplaceTabs=false)
EscapeText - HTMLize a specified file so that special characters are are translated so that they are ...
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:59
SourceLocation getBegin() const
bool InsertTextBefore(SourceLocation Loc, StringRef Str)
InsertText - Insert the specified string at the specified location in the original buffer...
Definition: Rewriter.h:115
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
RopePieceBTreeIterator - This class provides read-only forward iteration over bytes that are in a Rop...
Definition: RewriteRope.h:88
detail::InMemoryDirectory::const_iterator E
void AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID, StringRef title)
const LangOptions & getLangOpts() const
Definition: Rewriter.h:65
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
StringRef getBufferData(bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
Rewriter - This is the main interface to the rewrite buffers.
Definition: Rewriter.h:31
A SourceLocation and its associated SourceManager.
StringRef getBugType() const
FullSourceLoc getExpansionLoc() const
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
StringRef getCheckName() const
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:98
void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, const char *StartTag, const char *EndTag)
HighlightRange - Highlight a range in the source code with the specified start/end tags...
Definition: HTMLRewrite.cpp:32