clang  9.0.0svn
VerifyDiagnosticConsumer.cpp
Go to the documentation of this file.
1 //===- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This is a concrete diagnostic client, which buffers the diagnostic messages.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "clang/Basic/CharInfo.h"
15 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Basic/LLVM.h"
21 #include "clang/Basic/TokenKinds.h"
24 #include "clang/Lex/HeaderSearch.h"
25 #include "clang/Lex/Lexer.h"
26 #include "clang/Lex/PPCallbacks.h"
27 #include "clang/Lex/Preprocessor.h"
28 #include "clang/Lex/Token.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/ADT/SmallPtrSet.h"
31 #include "llvm/ADT/SmallString.h"
32 #include "llvm/ADT/StringRef.h"
33 #include "llvm/ADT/Twine.h"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/Regex.h"
36 #include "llvm/Support/raw_ostream.h"
37 #include <algorithm>
38 #include <cassert>
39 #include <cstddef>
40 #include <cstring>
41 #include <iterator>
42 #include <memory>
43 #include <string>
44 #include <utility>
45 #include <vector>
46 
47 using namespace clang;
48 
52 
53 #ifndef NDEBUG
54 
55 namespace {
56 
57 class VerifyFileTracker : public PPCallbacks {
60 
61 public:
62  VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM)
63  : Verify(Verify), SM(SM) {}
64 
65  /// Hook into the preprocessor and update the list of parsed
66  /// files when the preprocessor indicates a new file is entered.
67  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
69  FileID PrevFID) override {
70  Verify.UpdateParsedFileStatus(SM, SM.getFileID(Loc),
72  }
73 };
74 
75 } // namespace
76 
77 #endif
78 
79 //===----------------------------------------------------------------------===//
80 // Checking diagnostics implementation.
81 //===----------------------------------------------------------------------===//
82 
85 
86 namespace {
87 
88 /// StandardDirective - Directive with string matching.
89 class StandardDirective : public Directive {
90 public:
91  StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
92  bool MatchAnyLine, StringRef Text, unsigned Min,
93  unsigned Max)
94  : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) {}
95 
96  bool isValid(std::string &Error) override {
97  // all strings are considered valid; even empty ones
98  return true;
99  }
100 
101  bool match(StringRef S) override {
102  return S.find(Text) != StringRef::npos;
103  }
104 };
105 
106 /// RegexDirective - Directive with regular-expression matching.
107 class RegexDirective : public Directive {
108 public:
109  RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
110  bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
111  StringRef RegexStr)
112  : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
113  Regex(RegexStr) {}
114 
115  bool isValid(std::string &Error) override {
116  return Regex.isValid(Error);
117  }
118 
119  bool match(StringRef S) override {
120  return Regex.match(S);
121  }
122 
123 private:
124  llvm::Regex Regex;
125 };
126 
127 class ParseHelper
128 {
129 public:
130  ParseHelper(StringRef S)
131  : Begin(S.begin()), End(S.end()), C(Begin), P(Begin) {}
132 
133  // Return true if string literal is next.
134  bool Next(StringRef S) {
135  P = C;
136  PEnd = C + S.size();
137  if (PEnd > End)
138  return false;
139  return memcmp(P, S.data(), S.size()) == 0;
140  }
141 
142  // Return true if number is next.
143  // Output N only if number is next.
144  bool Next(unsigned &N) {
145  unsigned TMP = 0;
146  P = C;
147  PEnd = P;
148  for (; PEnd < End && *PEnd >= '0' && *PEnd <= '9'; ++PEnd) {
149  TMP *= 10;
150  TMP += *PEnd - '0';
151  }
152  if (PEnd == C)
153  return false;
154  N = TMP;
155  return true;
156  }
157 
158  // Return true if a marker is next.
159  // A marker is the longest match for /#[A-Za-z0-9_-]+/.
160  bool NextMarker() {
161  P = C;
162  if (P == End || *P != '#')
163  return false;
164  PEnd = P;
165  ++PEnd;
166  while ((isAlphanumeric(*PEnd) || *PEnd == '-' || *PEnd == '_') &&
167  PEnd < End)
168  ++PEnd;
169  return PEnd > P + 1;
170  }
171 
172  // Return true if string literal S is matched in content.
173  // When true, P marks begin-position of the match, and calling Advance sets C
174  // to end-position of the match.
175  // If S is the empty string, then search for any letter instead (makes sense
176  // with FinishDirectiveToken=true).
177  // If EnsureStartOfWord, then skip matches that don't start a new word.
178  // If FinishDirectiveToken, then assume the match is the start of a comment
179  // directive for -verify, and extend the match to include the entire first
180  // token of that directive.
181  bool Search(StringRef S, bool EnsureStartOfWord = false,
182  bool FinishDirectiveToken = false) {
183  do {
184  if (!S.empty()) {
185  P = std::search(C, End, S.begin(), S.end());
186  PEnd = P + S.size();
187  }
188  else {
189  P = C;
190  while (P != End && !isLetter(*P))
191  ++P;
192  PEnd = P + 1;
193  }
194  if (P == End)
195  break;
196  // If not start of word but required, skip and search again.
197  if (EnsureStartOfWord
198  // Check if string literal starts a new word.
199  && !(P == Begin || isWhitespace(P[-1])
200  // Or it could be preceded by the start of a comment.
201  || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
202  && P[-2] == '/')))
203  continue;
204  if (FinishDirectiveToken) {
205  while (PEnd != End && (isAlphanumeric(*PEnd)
206  || *PEnd == '-' || *PEnd == '_'))
207  ++PEnd;
208  // Put back trailing digits and hyphens to be parsed later as a count
209  // or count range. Because -verify prefixes must start with letters,
210  // we know the actual directive we found starts with a letter, so
211  // we won't put back the entire directive word and thus record an empty
212  // string.
213  assert(isLetter(*P) && "-verify prefix must start with a letter");
214  while (isDigit(PEnd[-1]) || PEnd[-1] == '-')
215  --PEnd;
216  }
217  return true;
218  } while (Advance());
219  return false;
220  }
221 
222  // Return true if a CloseBrace that closes the OpenBrace at the current nest
223  // level is found. When true, P marks begin-position of CloseBrace.
224  bool SearchClosingBrace(StringRef OpenBrace, StringRef CloseBrace) {
225  unsigned Depth = 1;
226  P = C;
227  while (P < End) {
228  StringRef S(P, End - P);
229  if (S.startswith(OpenBrace)) {
230  ++Depth;
231  P += OpenBrace.size();
232  } else if (S.startswith(CloseBrace)) {
233  --Depth;
234  if (Depth == 0) {
235  PEnd = P + CloseBrace.size();
236  return true;
237  }
238  P += CloseBrace.size();
239  } else {
240  ++P;
241  }
242  }
243  return false;
244  }
245 
246  // Advance 1-past previous next/search.
247  // Behavior is undefined if previous next/search failed.
248  bool Advance() {
249  C = PEnd;
250  return C < End;
251  }
252 
253  // Return the text matched by the previous next/search.
254  // Behavior is undefined if previous next/search failed.
255  StringRef Match() { return StringRef(P, PEnd - P); }
256 
257  // Skip zero or more whitespace.
258  void SkipWhitespace() {
259  for (; C < End && isWhitespace(*C); ++C)
260  ;
261  }
262 
263  // Return true if EOF reached.
264  bool Done() {
265  return !(C < End);
266  }
267 
268  // Beginning of expected content.
269  const char * const Begin;
270 
271  // End of expected content (1-past).
272  const char * const End;
273 
274  // Position of next char in content.
275  const char *C;
276 
277  // Previous next/search subject start.
278  const char *P;
279 
280 private:
281  // Previous next/search subject end (1-past).
282  const char *PEnd = nullptr;
283 };
284 
285 // The information necessary to create a directive.
286 struct UnattachedDirective {
287  DirectiveList *DL = nullptr;
288  bool RegexKind = false;
289  SourceLocation DirectivePos, ContentBegin;
290  std::string Text;
291  unsigned Min = 1, Max = 1;
292 };
293 
294 // Attach the specified directive to the line of code indicated by
295 // \p ExpectedLoc.
296 void attachDirective(DiagnosticsEngine &Diags, const UnattachedDirective &UD,
297  SourceLocation ExpectedLoc, bool MatchAnyLine = false) {
298  // Construct new directive.
299  std::unique_ptr<Directive> D =
300  Directive::create(UD.RegexKind, UD.DirectivePos, ExpectedLoc,
301  MatchAnyLine, UD.Text, UD.Min, UD.Max);
302 
303  std::string Error;
304  if (!D->isValid(Error)) {
305  Diags.Report(UD.ContentBegin, diag::err_verify_invalid_content)
306  << (UD.RegexKind ? "regex" : "string") << Error;
307  }
308 
309  UD.DL->push_back(std::move(D));
310 }
311 
312 } // anonymous
313 
314 // Tracker for markers in the input files. A marker is a comment of the form
315 //
316 // n = 123; // #123
317 //
318 // ... that can be referred to by a later expected-* directive:
319 //
320 // // expected-error@#123 {{undeclared identifier 'n'}}
321 //
322 // Marker declarations must be at the start of a comment or preceded by
323 // whitespace to distinguish them from uses of markers in directives.
325  DiagnosticsEngine &Diags;
326 
327  struct Marker {
328  SourceLocation DefLoc;
329  SourceLocation RedefLoc;
330  SourceLocation UseLoc;
331  };
332  llvm::StringMap<Marker> Markers;
333 
334  // Directives that couldn't be created yet because they name an unknown
335  // marker.
336  llvm::StringMap<llvm::SmallVector<UnattachedDirective, 2>> DeferredDirectives;
337 
338 public:
339  MarkerTracker(DiagnosticsEngine &Diags) : Diags(Diags) {}
340 
341  // Register a marker.
342  void addMarker(StringRef MarkerName, SourceLocation Pos) {
343  auto InsertResult = Markers.insert(
344  {MarkerName, Marker{Pos, SourceLocation(), SourceLocation()}});
345 
346  Marker &M = InsertResult.first->second;
347  if (!InsertResult.second) {
348  // Marker was redefined.
349  M.RedefLoc = Pos;
350  } else {
351  // First definition: build any deferred directives.
352  auto Deferred = DeferredDirectives.find(MarkerName);
353  if (Deferred != DeferredDirectives.end()) {
354  for (auto &UD : Deferred->second) {
355  if (M.UseLoc.isInvalid())
356  M.UseLoc = UD.DirectivePos;
357  attachDirective(Diags, UD, Pos);
358  }
359  DeferredDirectives.erase(Deferred);
360  }
361  }
362  }
363 
364  // Register a directive at the specified marker.
365  void addDirective(StringRef MarkerName, const UnattachedDirective &UD) {
366  auto MarkerIt = Markers.find(MarkerName);
367  if (MarkerIt != Markers.end()) {
368  Marker &M = MarkerIt->second;
369  if (M.UseLoc.isInvalid())
370  M.UseLoc = UD.DirectivePos;
371  return attachDirective(Diags, UD, M.DefLoc);
372  }
373  DeferredDirectives[MarkerName].push_back(UD);
374  }
375 
376  // Ensure we have no remaining deferred directives, and no
377  // multiply-defined-and-used markers.
378  void finalize() {
379  for (auto &MarkerInfo : Markers) {
380  StringRef Name = MarkerInfo.first();
381  Marker &M = MarkerInfo.second;
382  if (M.RedefLoc.isValid() && M.UseLoc.isValid()) {
383  Diags.Report(M.UseLoc, diag::err_verify_ambiguous_marker) << Name;
384  Diags.Report(M.DefLoc, diag::note_verify_ambiguous_marker) << Name;
385  Diags.Report(M.RedefLoc, diag::note_verify_ambiguous_marker) << Name;
386  }
387  }
388 
389  for (auto &DeferredPair : DeferredDirectives) {
390  Diags.Report(DeferredPair.second.front().DirectivePos,
391  diag::err_verify_no_such_marker)
392  << DeferredPair.first();
393  }
394  }
395 };
396 
397 /// ParseDirective - Go through the comment and see if it indicates expected
398 /// diagnostics. If so, then put them in the appropriate directive list.
399 ///
400 /// Returns true if any valid directives were found.
401 static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
402  Preprocessor *PP, SourceLocation Pos,
405  DiagnosticsEngine &Diags = PP ? PP->getDiagnostics() : SM.getDiagnostics();
406 
407  // First, scan the comment looking for markers.
408  for (ParseHelper PH(S); !PH.Done();) {
409  if (!PH.Search("#", true))
410  break;
411  PH.C = PH.P;
412  if (!PH.NextMarker()) {
413  PH.Next("#");
414  PH.Advance();
415  continue;
416  }
417  PH.Advance();
418  Markers.addMarker(PH.Match(), Pos);
419  }
420 
421  // A single comment may contain multiple directives.
422  bool FoundDirective = false;
423  for (ParseHelper PH(S); !PH.Done();) {
424  // Search for the initial directive token.
425  // If one prefix, save time by searching only for its directives.
426  // Otherwise, search for any potential directive token and check it later.
427  const auto &Prefixes = Diags.getDiagnosticOptions().VerifyPrefixes;
428  if (!(Prefixes.size() == 1 ? PH.Search(*Prefixes.begin(), true, true)
429  : PH.Search("", true, true)))
430  break;
431 
432  StringRef DToken = PH.Match();
433  PH.Advance();
434 
435  // Default directive kind.
436  UnattachedDirective D;
437  const char *KindStr = "string";
438 
439  // Parse the initial directive token in reverse so we can easily determine
440  // its exact actual prefix. If we were to parse it from the front instead,
441  // it would be harder to determine where the prefix ends because there
442  // might be multiple matching -verify prefixes because some might prefix
443  // others.
444 
445  // Regex in initial directive token: -re
446  if (DToken.endswith("-re")) {
447  D.RegexKind = true;
448  KindStr = "regex";
449  DToken = DToken.substr(0, DToken.size()-3);
450  }
451 
452  // Type in initial directive token: -{error|warning|note|no-diagnostics}
453  bool NoDiag = false;
454  StringRef DType;
455  if (DToken.endswith(DType="-error"))
456  D.DL = ED ? &ED->Errors : nullptr;
457  else if (DToken.endswith(DType="-warning"))
458  D.DL = ED ? &ED->Warnings : nullptr;
459  else if (DToken.endswith(DType="-remark"))
460  D.DL = ED ? &ED->Remarks : nullptr;
461  else if (DToken.endswith(DType="-note"))
462  D.DL = ED ? &ED->Notes : nullptr;
463  else if (DToken.endswith(DType="-no-diagnostics")) {
464  NoDiag = true;
465  if (D.RegexKind)
466  continue;
467  }
468  else
469  continue;
470  DToken = DToken.substr(0, DToken.size()-DType.size());
471 
472  // What's left in DToken is the actual prefix. That might not be a -verify
473  // prefix even if there is only one -verify prefix (for example, the full
474  // DToken is foo-bar-warning, but foo is the only -verify prefix).
475  if (!std::binary_search(Prefixes.begin(), Prefixes.end(), DToken))
476  continue;
477 
478  if (NoDiag) {
480  Diags.Report(Pos, diag::err_verify_invalid_no_diags)
481  << /*IsExpectedNoDiagnostics=*/true;
482  else
484  continue;
485  }
487  Diags.Report(Pos, diag::err_verify_invalid_no_diags)
488  << /*IsExpectedNoDiagnostics=*/false;
489  continue;
490  }
492 
493  // If a directive has been found but we're not interested
494  // in storing the directive information, return now.
495  if (!D.DL)
496  return true;
497 
498  // Next optional token: @
499  SourceLocation ExpectedLoc;
500  StringRef Marker;
501  bool MatchAnyLine = false;
502  if (!PH.Next("@")) {
503  ExpectedLoc = Pos;
504  } else {
505  PH.Advance();
506  unsigned Line = 0;
507  bool FoundPlus = PH.Next("+");
508  if (FoundPlus || PH.Next("-")) {
509  // Relative to current line.
510  PH.Advance();
511  bool Invalid = false;
512  unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid);
513  if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
514  if (FoundPlus) ExpectedLine += Line;
515  else ExpectedLine -= Line;
516  ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);
517  }
518  } else if (PH.Next(Line)) {
519  // Absolute line number.
520  if (Line > 0)
521  ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);
522  } else if (PH.NextMarker()) {
523  Marker = PH.Match();
524  } else if (PP && PH.Search(":")) {
525  // Specific source file.
526  StringRef Filename(PH.C, PH.P-PH.C);
527  PH.Advance();
528 
529  // Lookup file via Preprocessor, like a #include.
530  const DirectoryLookup *CurDir;
531  const FileEntry *FE =
532  PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir,
533  nullptr, nullptr, nullptr, nullptr, nullptr);
534  if (!FE) {
535  Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
536  diag::err_verify_missing_file) << Filename << KindStr;
537  continue;
538  }
539 
540  if (SM.translateFile(FE).isInvalid())
541  SM.createFileID(FE, Pos, SrcMgr::C_User);
542 
543  if (PH.Next(Line) && Line > 0)
544  ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
545  else if (PH.Next("*")) {
546  MatchAnyLine = true;
547  ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
548  }
549  } else if (PH.Next("*")) {
550  MatchAnyLine = true;
551  ExpectedLoc = SourceLocation();
552  }
553 
554  if (ExpectedLoc.isInvalid() && !MatchAnyLine && Marker.empty()) {
555  Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
556  diag::err_verify_missing_line) << KindStr;
557  continue;
558  }
559  PH.Advance();
560  }
561 
562  // Skip optional whitespace.
563  PH.SkipWhitespace();
564 
565  // Next optional token: positive integer or a '+'.
566  if (PH.Next(D.Min)) {
567  PH.Advance();
568  // A positive integer can be followed by a '+' meaning min
569  // or more, or by a '-' meaning a range from min to max.
570  if (PH.Next("+")) {
571  D.Max = Directive::MaxCount;
572  PH.Advance();
573  } else if (PH.Next("-")) {
574  PH.Advance();
575  if (!PH.Next(D.Max) || D.Max < D.Min) {
576  Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
577  diag::err_verify_invalid_range) << KindStr;
578  continue;
579  }
580  PH.Advance();
581  } else {
582  D.Max = D.Min;
583  }
584  } else if (PH.Next("+")) {
585  // '+' on its own means "1 or more".
586  D.Max = Directive::MaxCount;
587  PH.Advance();
588  }
589 
590  // Skip optional whitespace.
591  PH.SkipWhitespace();
592 
593  // Next token: {{
594  if (!PH.Next("{{")) {
595  Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
596  diag::err_verify_missing_start) << KindStr;
597  continue;
598  }
599  PH.Advance();
600  const char* const ContentBegin = PH.C; // mark content begin
601  // Search for token: }}
602  if (!PH.SearchClosingBrace("{{", "}}")) {
603  Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
604  diag::err_verify_missing_end) << KindStr;
605  continue;
606  }
607  const char* const ContentEnd = PH.P; // mark content end
608  PH.Advance();
609 
610  D.DirectivePos = Pos;
611  D.ContentBegin = Pos.getLocWithOffset(ContentBegin - PH.Begin);
612 
613  // Build directive text; convert \n to newlines.
614  StringRef NewlineStr = "\\n";
615  StringRef Content(ContentBegin, ContentEnd-ContentBegin);
616  size_t CPos = 0;
617  size_t FPos;
618  while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) {
619  D.Text += Content.substr(CPos, FPos-CPos);
620  D.Text += '\n';
621  CPos = FPos + NewlineStr.size();
622  }
623  if (D.Text.empty())
624  D.Text.assign(ContentBegin, ContentEnd);
625 
626  // Check that regex directives contain at least one regex.
627  if (D.RegexKind && D.Text.find("{{") == StringRef::npos) {
628  Diags.Report(D.ContentBegin, diag::err_verify_missing_regex) << D.Text;
629  return false;
630  }
631 
632  if (Marker.empty())
633  attachDirective(Diags, D, ExpectedLoc, MatchAnyLine);
634  else
635  Markers.addDirective(Marker, D);
636  FoundDirective = true;
637  }
638 
639  return FoundDirective;
640 }
641 
643  : Diags(Diags_), PrimaryClient(Diags.getClient()),
644  PrimaryClientOwner(Diags.takeClient()),
645  Buffer(new TextDiagnosticBuffer()), Markers(new MarkerTracker(Diags)),
646  Status(HasNoDirectives) {
647  if (Diags.hasSourceManager())
648  setSourceManager(Diags.getSourceManager());
649 }
650 
652  assert(!ActiveSourceFiles && "Incomplete parsing of source files!");
653  assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
654  SrcManager = nullptr;
655  CheckDiagnostics();
656  assert(!Diags.ownsClient() &&
657  "The VerifyDiagnosticConsumer takes over ownership of the client!");
658 }
659 
660 // DiagnosticConsumer interface.
661 
663  const Preprocessor *PP) {
664  // Attach comment handler on first invocation.
665  if (++ActiveSourceFiles == 1) {
666  if (PP) {
667  CurrentPreprocessor = PP;
668  this->LangOpts = &LangOpts;
669  setSourceManager(PP->getSourceManager());
670  const_cast<Preprocessor *>(PP)->addCommentHandler(this);
671 #ifndef NDEBUG
672  // Debug build tracks parsed files.
673  const_cast<Preprocessor *>(PP)->addPPCallbacks(
674  llvm::make_unique<VerifyFileTracker>(*this, *SrcManager));
675 #endif
676  }
677  }
678 
679  assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!");
680  PrimaryClient->BeginSourceFile(LangOpts, PP);
681 }
682 
684  assert(ActiveSourceFiles && "No active source files!");
685  PrimaryClient->EndSourceFile();
686 
687  // Detach comment handler once last active source file completed.
688  if (--ActiveSourceFiles == 0) {
689  if (CurrentPreprocessor)
690  const_cast<Preprocessor *>(CurrentPreprocessor)->
691  removeCommentHandler(this);
692 
693  // Diagnose any used-but-not-defined markers.
694  Markers->finalize();
695 
696  // Check diagnostics once last file completed.
697  CheckDiagnostics();
698  CurrentPreprocessor = nullptr;
699  LangOpts = nullptr;
700  }
701 }
702 
704  DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
705  if (Info.hasSourceManager()) {
706  // If this diagnostic is for a different source manager, ignore it.
707  if (SrcManager && &Info.getSourceManager() != SrcManager)
708  return;
709 
710  setSourceManager(Info.getSourceManager());
711  }
712 
713 #ifndef NDEBUG
714  // Debug build tracks unparsed files for possible
715  // unparsed expected-* directives.
716  if (SrcManager) {
717  SourceLocation Loc = Info.getLocation();
718  if (Loc.isValid()) {
720 
721  Loc = SrcManager->getExpansionLoc(Loc);
722  FileID FID = SrcManager->getFileID(Loc);
723 
724  const FileEntry *FE = SrcManager->getFileEntryForID(FID);
725  if (FE && CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) {
726  // If the file is a modules header file it shall not be parsed
727  // for expected-* directives.
728  HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
729  if (HS.findModuleForHeader(FE))
731  }
732 
733  UpdateParsedFileStatus(*SrcManager, FID, PS);
734  }
735  }
736 #endif
737 
738  // Send the diagnostic to the buffer, we will check it once we reach the end
739  // of the source file (or are destructed).
740  Buffer->HandleDiagnostic(DiagLevel, Info);
741 }
742 
743 /// HandleComment - Hook into the preprocessor and extract comments containing
744 /// expected errors and warnings.
746  SourceRange Comment) {
748 
749  // If this comment is for a different source manager, ignore it.
750  if (SrcManager && &SM != SrcManager)
751  return false;
752 
753  SourceLocation CommentBegin = Comment.getBegin();
754 
755  const char *CommentRaw = SM.getCharacterData(CommentBegin);
756  StringRef C(CommentRaw, SM.getCharacterData(Comment.getEnd()) - CommentRaw);
757 
758  if (C.empty())
759  return false;
760 
761  // Fold any "<EOL>" sequences
762  size_t loc = C.find('\\');
763  if (loc == StringRef::npos) {
764  ParseDirective(C, &ED, SM, &PP, CommentBegin, Status, *Markers);
765  return false;
766  }
767 
768  std::string C2;
769  C2.reserve(C.size());
770 
771  for (size_t last = 0;; loc = C.find('\\', last)) {
772  if (loc == StringRef::npos || loc == C.size()) {
773  C2 += C.substr(last);
774  break;
775  }
776  C2 += C.substr(last, loc-last);
777  last = loc + 1;
778 
779  if (C[last] == '\n' || C[last] == '\r') {
780  ++last;
781 
782  // Escape \r\n or \n\r, but not \n\n.
783  if (last < C.size())
784  if (C[last] == '\n' || C[last] == '\r')
785  if (C[last] != C[last-1])
786  ++last;
787  } else {
788  // This was just a normal backslash.
789  C2 += '\\';
790  }
791  }
792 
793  if (!C2.empty())
794  ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status, *Markers);
795  return false;
796 }
797 
798 #ifndef NDEBUG
799 /// Lex the specified source file to determine whether it contains
800 /// any expected-* directives. As a Lexer is used rather than a full-blown
801 /// Preprocessor, directives inside skipped #if blocks will still be found.
802 ///
803 /// \return true if any directives were found.
805  const LangOptions &LangOpts) {
806  // Create a raw lexer to pull all the comments out of FID.
807  if (FID.isInvalid())
808  return false;
809 
810  // Create a lexer to lex all the tokens of the main file in raw mode.
811  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
812  Lexer RawLex(FID, FromFile, SM, LangOpts);
813 
814  // Return comments as tokens, this is how we find expected diagnostics.
815  RawLex.SetCommentRetentionState(true);
816 
817  Token Tok;
818  Tok.setKind(tok::comment);
821  while (Tok.isNot(tok::eof)) {
822  RawLex.LexFromRawLexer(Tok);
823  if (!Tok.is(tok::comment)) continue;
824 
825  std::string Comment = RawLex.getSpelling(Tok, SM, LangOpts);
826  if (Comment.empty()) continue;
827 
828  // We don't care about tracking markers for this phase.
830 
831  // Find first directive.
832  if (ParseDirective(Comment, nullptr, SM, nullptr, Tok.getLocation(),
833  Status, Markers))
834  return true;
835  }
836  return false;
837 }
838 #endif // !NDEBUG
839 
840 /// Takes a list of diagnostics that have been generated but not matched
841 /// by an expected-* directive and produces a diagnostic to the user from this.
842 static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
843  const_diag_iterator diag_begin,
844  const_diag_iterator diag_end,
845  const char *Kind) {
846  if (diag_begin == diag_end) return 0;
847 
848  SmallString<256> Fmt;
849  llvm::raw_svector_ostream OS(Fmt);
850  for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
851  if (I->first.isInvalid() || !SourceMgr)
852  OS << "\n (frontend)";
853  else {
854  OS << "\n ";
855  if (const FileEntry *File = SourceMgr->getFileEntryForID(
856  SourceMgr->getFileID(I->first)))
857  OS << " File " << File->getName();
858  OS << " Line " << SourceMgr->getPresumedLineNumber(I->first);
859  }
860  OS << ": " << I->second;
861  }
862 
863  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
864  << Kind << /*Unexpected=*/true << OS.str();
865  return std::distance(diag_begin, diag_end);
866 }
867 
868 /// Takes a list of diagnostics that were expected to have been generated
869 /// but were not and produces a diagnostic to the user from this.
870 static unsigned PrintExpected(DiagnosticsEngine &Diags,
871  SourceManager &SourceMgr,
872  std::vector<Directive *> &DL, const char *Kind) {
873  if (DL.empty())
874  return 0;
875 
876  SmallString<256> Fmt;
877  llvm::raw_svector_ostream OS(Fmt);
878  for (const auto *D : DL) {
879  if (D->DiagnosticLoc.isInvalid())
880  OS << "\n File *";
881  else
882  OS << "\n File " << SourceMgr.getFilename(D->DiagnosticLoc);
883  if (D->MatchAnyLine)
884  OS << " Line *";
885  else
886  OS << " Line " << SourceMgr.getPresumedLineNumber(D->DiagnosticLoc);
887  if (D->DirectiveLoc != D->DiagnosticLoc)
888  OS << " (directive at "
889  << SourceMgr.getFilename(D->DirectiveLoc) << ':'
890  << SourceMgr.getPresumedLineNumber(D->DirectiveLoc) << ')';
891  OS << ": " << D->Text;
892  }
893 
894  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
895  << Kind << /*Unexpected=*/false << OS.str();
896  return DL.size();
897 }
898 
899 /// Determine whether two source locations come from the same file.
900 static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc,
901  SourceLocation DiagnosticLoc) {
902  while (DiagnosticLoc.isMacroID())
903  DiagnosticLoc = SM.getImmediateMacroCallerLoc(DiagnosticLoc);
904 
905  if (SM.isWrittenInSameFile(DirectiveLoc, DiagnosticLoc))
906  return true;
907 
908  const FileEntry *DiagFile = SM.getFileEntryForID(SM.getFileID(DiagnosticLoc));
909  if (!DiagFile && SM.isWrittenInMainFile(DirectiveLoc))
910  return true;
911 
912  return (DiagFile == SM.getFileEntryForID(SM.getFileID(DirectiveLoc)));
913 }
914 
915 /// CheckLists - Compare expected to seen diagnostic lists and return the
916 /// the difference between them.
917 static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
918  const char *Label,
919  DirectiveList &Left,
920  const_diag_iterator d2_begin,
921  const_diag_iterator d2_end,
922  bool IgnoreUnexpected) {
923  std::vector<Directive *> LeftOnly;
924  DiagList Right(d2_begin, d2_end);
925 
926  for (auto &Owner : Left) {
927  Directive &D = *Owner;
928  unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
929 
930  for (unsigned i = 0; i < D.Max; ++i) {
931  DiagList::iterator II, IE;
932  for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
933  if (!D.MatchAnyLine) {
934  unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
935  if (LineNo1 != LineNo2)
936  continue;
937  }
938 
939  if (!D.DiagnosticLoc.isInvalid() &&
940  !IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
941  continue;
942 
943  const std::string &RightText = II->second;
944  if (D.match(RightText))
945  break;
946  }
947  if (II == IE) {
948  // Not found.
949  if (i >= D.Min) break;
950  LeftOnly.push_back(&D);
951  } else {
952  // Found. The same cannot be found twice.
953  Right.erase(II);
954  }
955  }
956  }
957  // Now all that's left in Right are those that were not matched.
958  unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label);
959  if (!IgnoreUnexpected)
960  num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);
961  return num;
962 }
963 
964 /// CheckResults - This compares the expected results to those that
965 /// were actually reported. It emits any discrepencies. Return "true" if there
966 /// were problems. Return "false" otherwise.
967 static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
968  const TextDiagnosticBuffer &Buffer,
969  ExpectedData &ED) {
970  // We want to capture the delta between what was expected and what was
971  // seen.
972  //
973  // Expected \ Seen - set expected but not seen
974  // Seen \ Expected - set seen but not expected
975  unsigned NumProblems = 0;
976 
977  const DiagnosticLevelMask DiagMask =
978  Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected();
979 
980  // See if there are error mismatches.
981  NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors,
982  Buffer.err_begin(), Buffer.err_end(),
983  bool(DiagnosticLevelMask::Error & DiagMask));
984 
985  // See if there are warning mismatches.
986  NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings,
987  Buffer.warn_begin(), Buffer.warn_end(),
988  bool(DiagnosticLevelMask::Warning & DiagMask));
989 
990  // See if there are remark mismatches.
991  NumProblems += CheckLists(Diags, SourceMgr, "remark", ED.Remarks,
992  Buffer.remark_begin(), Buffer.remark_end(),
993  bool(DiagnosticLevelMask::Remark & DiagMask));
994 
995  // See if there are note mismatches.
996  NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes,
997  Buffer.note_begin(), Buffer.note_end(),
998  bool(DiagnosticLevelMask::Note & DiagMask));
999 
1000  return NumProblems;
1001 }
1002 
1004  FileID FID,
1005  ParsedStatus PS) {
1006  // Check SourceManager hasn't changed.
1007  setSourceManager(SM);
1008 
1009 #ifndef NDEBUG
1010  if (FID.isInvalid())
1011  return;
1012 
1013  const FileEntry *FE = SM.getFileEntryForID(FID);
1014 
1015  if (PS == IsParsed) {
1016  // Move the FileID from the unparsed set to the parsed set.
1017  UnparsedFiles.erase(FID);
1018  ParsedFiles.insert(std::make_pair(FID, FE));
1019  } else if (!ParsedFiles.count(FID) && !UnparsedFiles.count(FID)) {
1020  // Add the FileID to the unparsed set if we haven't seen it before.
1021 
1022  // Check for directives.
1023  bool FoundDirectives;
1024  if (PS == IsUnparsedNoDirectives)
1025  FoundDirectives = false;
1026  else
1027  FoundDirectives = !LangOpts || findDirectives(SM, FID, *LangOpts);
1028 
1029  // Add the FileID to the unparsed set.
1030  UnparsedFiles.insert(std::make_pair(FID,
1031  UnparsedFileStatus(FE, FoundDirectives)));
1032  }
1033 #endif
1034 }
1035 
1036 void VerifyDiagnosticConsumer::CheckDiagnostics() {
1037  // Ensure any diagnostics go to the primary client.
1038  DiagnosticConsumer *CurClient = Diags.getClient();
1039  std::unique_ptr<DiagnosticConsumer> Owner = Diags.takeClient();
1040  Diags.setClient(PrimaryClient, false);
1041 
1042 #ifndef NDEBUG
1043  // In a debug build, scan through any files that may have been missed
1044  // during parsing and issue a fatal error if directives are contained
1045  // within these files. If a fatal error occurs, this suggests that
1046  // this file is being parsed separately from the main file, in which
1047  // case consider moving the directives to the correct place, if this
1048  // is applicable.
1049  if (!UnparsedFiles.empty()) {
1050  // Generate a cache of parsed FileEntry pointers for alias lookups.
1051  llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache;
1052  for (const auto &I : ParsedFiles)
1053  if (const FileEntry *FE = I.second)
1054  ParsedFileCache.insert(FE);
1055 
1056  // Iterate through list of unparsed files.
1057  for (const auto &I : UnparsedFiles) {
1058  const UnparsedFileStatus &Status = I.second;
1059  const FileEntry *FE = Status.getFile();
1060 
1061  // Skip files that have been parsed via an alias.
1062  if (FE && ParsedFileCache.count(FE))
1063  continue;
1064 
1065  // Report a fatal error if this file contained directives.
1066  if (Status.foundDirectives()) {
1067  llvm::report_fatal_error(Twine("-verify directives found after rather"
1068  " than during normal parsing of ",
1069  StringRef(FE ? FE->getName() : "(unknown)")));
1070  }
1071  }
1072 
1073  // UnparsedFiles has been processed now, so clear it.
1074  UnparsedFiles.clear();
1075  }
1076 #endif // !NDEBUG
1077 
1078  if (SrcManager) {
1079  // Produce an error if no expected-* directives could be found in the
1080  // source file(s) processed.
1081  if (Status == HasNoDirectives) {
1082  Diags.Report(diag::err_verify_no_directives).setForceEmit();
1083  ++NumErrors;
1084  Status = HasNoDirectivesReported;
1085  }
1086 
1087  // Check that the expected diagnostics occurred.
1088  NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
1089  } else {
1090  const DiagnosticLevelMask DiagMask =
1091  ~Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected();
1092  if (bool(DiagnosticLevelMask::Error & DiagMask))
1093  NumErrors += PrintUnexpected(Diags, nullptr, Buffer->err_begin(),
1094  Buffer->err_end(), "error");
1095  if (bool(DiagnosticLevelMask::Warning & DiagMask))
1096  NumErrors += PrintUnexpected(Diags, nullptr, Buffer->warn_begin(),
1097  Buffer->warn_end(), "warn");
1098  if (bool(DiagnosticLevelMask::Remark & DiagMask))
1099  NumErrors += PrintUnexpected(Diags, nullptr, Buffer->remark_begin(),
1100  Buffer->remark_end(), "remark");
1101  if (bool(DiagnosticLevelMask::Note & DiagMask))
1102  NumErrors += PrintUnexpected(Diags, nullptr, Buffer->note_begin(),
1103  Buffer->note_end(), "note");
1104  }
1105 
1106  Diags.setClient(CurClient, Owner.release() != nullptr);
1107 
1108  // Reset the buffer, we have processed all the diagnostics in it.
1109  Buffer.reset(new TextDiagnosticBuffer());
1110  ED.Reset();
1111 }
1112 
1113 std::unique_ptr<Directive> Directive::create(bool RegexKind,
1114  SourceLocation DirectiveLoc,
1115  SourceLocation DiagnosticLoc,
1116  bool MatchAnyLine, StringRef Text,
1117  unsigned Min, unsigned Max) {
1118  if (!RegexKind)
1119  return llvm::make_unique<StandardDirective>(DirectiveLoc, DiagnosticLoc,
1120  MatchAnyLine, Text, Min, Max);
1121 
1122  // Parse the directive into a regular expression.
1123  std::string RegexStr;
1124  StringRef S = Text;
1125  while (!S.empty()) {
1126  if (S.startswith("{{")) {
1127  S = S.drop_front(2);
1128  size_t RegexMatchLength = S.find("}}");
1129  assert(RegexMatchLength != StringRef::npos);
1130  // Append the regex, enclosed in parentheses.
1131  RegexStr += "(";
1132  RegexStr.append(S.data(), RegexMatchLength);
1133  RegexStr += ")";
1134  S = S.drop_front(RegexMatchLength + 2);
1135  } else {
1136  size_t VerbatimMatchLength = S.find("{{");
1137  if (VerbatimMatchLength == StringRef::npos)
1138  VerbatimMatchLength = S.size();
1139  // Escape and append the fixed string.
1140  RegexStr += llvm::Regex::escape(S.substr(0, VerbatimMatchLength));
1141  S = S.drop_front(VerbatimMatchLength);
1142  }
1143  }
1144 
1145  return llvm::make_unique<RegexDirective>(
1147 }
static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid=nullptr)
getSpelling - This method is used to get the spelling of a token into a preallocated buffer...
Definition: Lexer.cpp:388
bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const
Returns true if the spelling locations for both SourceLocations are part of the same file buffer...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
Definition: Lexer.h:76
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
DiagnosticConsumer * getClient()
Definition: Diagnostic.h:509
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
std::vector< std::unique_ptr< Directive > > DirectiveList
VerifyDiagnosticConsumer - Create a diagnostic client which will use markers in the input source to c...
Defines the clang::FileManager interface and associated types.
SourceManager & getSourceManager() const
Definition: Diagnostic.h:521
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
Definition: Lexer.h:194
unsigned NumErrors
Number of errors reported.
Definition: Diagnostic.h:1492
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
Definition: Token.h:94
Defines the SourceManager interface.
void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS)
Update lists of parsed and unparsed files.
const_iterator remark_end() const
static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const TextDiagnosticBuffer &Buffer, ExpectedData &ED)
CheckResults - This compares the expected results to those that were actually reported.
VerifyDiagnosticConsumer(DiagnosticsEngine &Diags)
Create a new verifying diagnostic client, which will issue errors to the currently-attached diagnosti...
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
StringRef P
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
File has been processed via HandleComment.
const DiagnosticBuilder & setForceEmit() const
Forces the diagnostic to be emitted.
Definition: Diagnostic.h:1135
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1296
std::unique_ptr< DiagnosticConsumer > takeClient()
Return the current diagnostic client along with ownership of that client.
Definition: Diagnostic.h:517
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
Definition: Diagnostic.h:1521
static std::unique_ptr< Directive > create(bool RegexKind, SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1489
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
Definition: SourceManager.h:77
bool hasSourceManager() const
Definition: Diagnostic.h:1329
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:35
void EndSourceFile() override
Callback to inform the diagnostic client that processing of a source file has ended.
static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, Preprocessor *PP, SourceLocation Pos, VerifyDiagnosticConsumer::DirectiveStatus &Status, VerifyDiagnosticConsumer::MarkerTracker &Markers)
ParseDirective - Go through the comment and see if it indicates expected diagnostics.
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient=true)
Set the diagnostic client associated with this diagnostic object.
Definition: Diagnostic.cpp:99
ExpectedData - owns directive objects and deletes on destructor.
LLVM_READONLY bool isLetter(unsigned char c)
Return true if this character is an ASCII letter: [a-zA-Z].
Definition: CharInfo.h:111
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
void setKind(tok::TokenKind K)
Definition: Token.h:90
const_iterator err_end() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
const_iterator note_begin() const
const_iterator note_end() const
bool isInvalid() const
FileID translateFile(const FileEntry *SourceFile) const
Get the FileID for the given file.
TextDiagnosticBuffer::DiagList DiagList
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: &#39; &#39;, &#39;\t&#39;, &#39;\f&#39;, &#39;\v&#39;, &#39;\n&#39;, &#39;\r&#39;.
Definition: CharInfo.h:87
HeaderSearch & getHeaderSearchInfo() const
Definition: Preprocessor.h:905
const SourceLocation & getLocation() const
Definition: Diagnostic.h:1328
const FormatToken & Tok
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:148
void addMarker(StringRef MarkerName, SourceLocation Pos)
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Defines the Diagnostic-related interfaces.
DiagnosticsEngine & getDiagnostics() const
const_iterator err_begin() const
DiagList::const_iterator const_iterator
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
Encapsulates the information needed to find the file referenced by a #include or #include_next, (sub-)framework lookup, etc.
Definition: HeaderSearch.h:158
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
File has diagnostics but guaranteed no directives.
StringRef Filename
Definition: Format.cpp:1707
std::vector< std::pair< SourceLocation, std::string > > DiagList
SourceLocation End
std::string Label
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
const AnnotatedLine * Line
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:123
Defines the clang::Preprocessor interface.
static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr, const_diag_iterator diag_begin, const_diag_iterator diag_end, const char *Kind)
Takes a list of diagnostics that have been generated but not matched by an expected-* directive and p...
#define bool
Definition: stdbool.h:15
bool isWrittenInMainFile(SourceLocation Loc) const
Returns true if the spelling location for the given location is in the main file buffer.
SourceLocation Begin
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
Definition: CharInfo.h:117
int Depth
Definition: ASTDiff.cpp:190
SourceLocation getEnd() const
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
const SourceManager & SM
Definition: Format.cpp:1568
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
bool HandleComment(Preprocessor &PP, SourceRange Comment) override
HandleComment - Hook into the preprocessor and extract comments containing expected errors and warnin...
SourceManager & getSourceManager() const
Definition: Preprocessor.h:904
ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File, bool AllowTextual=false) const
Retrieve the module that corresponds to the given file, if any.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc)
Determine whether two source locations come from the same file.
Kind
Encodes a location in the source.
static ICEDiag NoDiag()
StringRef getName() const
Definition: FileManager.h:83
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:59
void addDirective(StringRef MarkerName, const UnattachedDirective &UD)
const FileEntry * LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const FileEntry *FromFile, const DirectoryLookup *&CurDir, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache=false)
Given a "foo" or <foo> reference, look up the indicated file.
SourceManager & getSourceManager() const
Definition: Diagnostic.h:1330
virtual bool match(StringRef S)=0
File has diagnostics and may have directives.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool isNot(tok::TokenKind K) const
Definition: Token.h:95
virtual bool isValid(std::string &Error)=0
const llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
const_iterator warn_end() const
Dataflow Directional Tag Classes.
static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr, std::vector< Directive *> &DL, const char *Kind)
Takes a list of diagnostics that were expected to have been generated but were not and produces a dia...
bool isValid() const
Return true if this is a valid SourceLocation object.
static bool findDirectives(SourceManager &SM, FileID FID, const LangOptions &LangOpts)
Lex the specified source file to determine whether it contains any expected-* directives.
std::vector< std::string > VerifyPrefixes
The prefixes for comment directives sought by -verify ("expected" by default).
VerifyDiagnosticConsumer::DirectiveList DirectiveList
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
Definition: Diagnostic.h:499
VerifyDiagnosticConsumer::ExpectedData ExpectedData
SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const
Get the source location in FID for the given line:col.
bool isMacroID() const
TextDiagnosticBuffer::const_iterator const_diag_iterator
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
Definition: CharInfo.h:93
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
Defines the PPCallbacks interface.
Defines the clang::TokenKind enum and support functions.
const_iterator warn_begin() const
Defines the clang::SourceLocation class and associated facilities.
static const unsigned MaxCount
Constant representing n or more matches.
DiagnosticsEngine & getDiagnostics() const
Definition: Preprocessor.h:897
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:151
const_iterator remark_begin() const
bool hasSourceManager() const
Definition: Diagnostic.h:519
static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const char *Label, DirectiveList &Left, const_diag_iterator d2_begin, const_diag_iterator d2_end, bool IgnoreUnexpected)
CheckLists - Compare expected to seen diagnostic lists and return the the difference between them...
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode...
Definition: Lexer.h:227
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1317
DiagnosticLevelMask
A bitmask representing the diagnostic levels used by VerifyDiagnosticConsumer.
StringRef Text
Definition: Format.cpp:1708
A trivial tuple used to represent a source range.
Directive - Abstract class representing a parsed verify directive.
virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP=nullptr)
Callback to inform the diagnostic client that processing of a source file is beginning.
Definition: Diagnostic.h:1513
SourceLocation getBegin() const
VerifyDiagnosticConsumer::Directive Directive
This class handles loading and caching of source files into memory.
void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP) override
Callback to inform the diagnostic client that processing of a source file is beginning.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:123
bool ownsClient() const
Determine whether this DiagnosticsEngine object own its client.
Definition: Diagnostic.h:513