VerifyDiagnosticConsumer.cpp revision 234353
118334Speter//===---- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ------===//
250506Sobrien//
318334Speter//                     The LLVM Compiler Infrastructure
418334Speter//
518334Speter// This file is distributed under the University of Illinois Open Source
618334Speter// License. See LICENSE.TXT for details.
718334Speter//
818334Speter//===----------------------------------------------------------------------===//
918334Speter//
1018334Speter// This is a concrete diagnostic client, which buffers the diagnostic messages.
1118334Speter//
1218334Speter//===----------------------------------------------------------------------===//
1318334Speter
1418334Speter#include "clang/Frontend/VerifyDiagnosticConsumer.h"
1518334Speter#include "clang/Frontend/FrontendDiagnostic.h"
1618334Speter#include "clang/Frontend/TextDiagnosticBuffer.h"
1718334Speter#include "clang/Lex/Preprocessor.h"
1818334Speter#include "llvm/ADT/SmallString.h"
1918334Speter#include "llvm/Support/Regex.h"
2018334Speter#include "llvm/Support/raw_ostream.h"
2118334Speter#include <climits>
2218334Speter
2318334Speterusing namespace clang;
2418334Speter
2518334SpeterVerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
2618334Speter  : Diags(_Diags), PrimaryClient(Diags.getClient()),
2718334Speter    OwnsPrimaryClient(Diags.ownsClient()),
2818334Speter    Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0)
2918334Speter{
3050506Sobrien  Diags.takeClient();
3118334Speter}
3218334Speter
3318334SpeterVerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
3418334Speter  CheckDiagnostics();
3518334Speter  Diags.takeClient();
3618334Speter  if (OwnsPrimaryClient)
3718334Speter    delete PrimaryClient;
3818334Speter}
3918334Speter
4018334Speter// DiagnosticConsumer interface.
4118334Speter
4218334Spetervoid VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
4318334Speter                                               const Preprocessor *PP) {
4418334Speter  // FIXME: Const hack, we screw up the preprocessor but in practice its ok
4518334Speter  // because it doesn't get reused. It would be better if we could make a copy
4618334Speter  // though.
4718334Speter  CurrentPreprocessor = const_cast<Preprocessor*>(PP);
4818334Speter
4918334Speter  PrimaryClient->BeginSourceFile(LangOpts, PP);
5018334Speter}
5118334Speter
5218334Spetervoid VerifyDiagnosticConsumer::EndSourceFile() {
5318334Speter  CheckDiagnostics();
5418334Speter
5518334Speter  PrimaryClient->EndSourceFile();
5650506Sobrien
5750506Sobrien  CurrentPreprocessor = 0;
5850506Sobrien}
5950506Sobrien
6018334Spetervoid VerifyDiagnosticConsumer::HandleDiagnostic(
6118334Speter      DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
6218334Speter  if (FirstErrorFID.isInvalid() && Info.hasSourceManager()) {
6318334Speter    const SourceManager &SM = Info.getSourceManager();
6418334Speter    FirstErrorFID = SM.getFileID(Info.getLocation());
6518334Speter  }
6618334Speter  // Send the diagnostic to the buffer, we will check it once we reach the end
6718334Speter  // of the source file (or are destructed).
6818334Speter  Buffer->HandleDiagnostic(DiagLevel, Info);
6918334Speter}
7018334Speter
7118334Speter//===----------------------------------------------------------------------===//
7218334Speter// Checking diagnostics implementation.
7318334Speter//===----------------------------------------------------------------------===//
7418334Speter
7518334Spetertypedef TextDiagnosticBuffer::DiagList DiagList;
7618334Spetertypedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
7718334Speter
7818334Speternamespace {
7918334Speter
8018334Speter/// Directive - Abstract class representing a parsed verify directive.
8118334Speter///
8218334Speterclass Directive {
8318334Speterpublic:
8418334Speter  static Directive* Create(bool RegexKind, const SourceLocation &Location,
8518334Speter                           const std::string &Text, unsigned Count);
8618334Speterpublic:
8718334Speter  /// Constant representing one or more matches aka regex "+".
8818334Speter  static const unsigned OneOrMoreCount =  UINT_MAX;
8918334Speter
9050506Sobrien  SourceLocation Location;
9150506Sobrien  const std::string Text;
9250506Sobrien  unsigned Count;
9350506Sobrien
9450506Sobrien  virtual ~Directive() { }
9550506Sobrien
9650506Sobrien  // Returns true if directive text is valid.
9750506Sobrien  // Otherwise returns false and populates E.
9818334Speter  virtual bool isValid(std::string &Error) = 0;
9918334Speter
10018334Speter  // Returns true on match.
10118334Speter  virtual bool Match(const std::string &S) = 0;
10218334Speter
10318334Speterprotected:
10418334Speter  Directive(const SourceLocation &Location, const std::string &Text,
10518334Speter            unsigned Count)
10618334Speter    : Location(Location), Text(Text), Count(Count) { }
10718334Speter
10818334Speterprivate:
10918334Speter  Directive(const Directive&); // DO NOT IMPLEMENT
11018334Speter  void operator=(const Directive&); // DO NOT IMPLEMENT
11118334Speter};
11218334Speter
11318334Speter/// StandardDirective - Directive with string matching.
11418334Speter///
11518334Speterclass StandardDirective : public Directive {
11618334Speterpublic:
11718334Speter  StandardDirective(const SourceLocation &Location, const std::string &Text,
11818334Speter                    unsigned Count)
11918334Speter    : Directive(Location, Text, Count) { }
12018334Speter
12118334Speter  virtual bool isValid(std::string &Error) {
12218334Speter    // all strings are considered valid; even empty ones
12318334Speter    return true;
12418334Speter  }
12518334Speter
12618334Speter  virtual bool Match(const std::string &S) {
12718334Speter    return S.find(Text) != std::string::npos;
12818334Speter  }
12918334Speter};
13018334Speter
13118334Speter/// RegexDirective - Directive with regular-expression matching.
13218334Speter///
13318334Speterclass RegexDirective : public Directive {
13418334Speterpublic:
13518334Speter  RegexDirective(const SourceLocation &Location, const std::string &Text,
13618334Speter                 unsigned Count)
13718334Speter    : Directive(Location, Text, Count), Regex(Text) { }
13818334Speter
13918334Speter  virtual bool isValid(std::string &Error) {
14050506Sobrien    if (Regex.isValid(Error))
14150506Sobrien      return true;
14250506Sobrien    return false;
14350506Sobrien  }
14418334Speter
14518334Speter  virtual bool Match(const std::string &S) {
14618334Speter    return Regex.match(S);
14718334Speter  }
14818334Speter
14918334Speterprivate:
15018334Speter  llvm::Regex Regex;
15118334Speter};
15250506Sobrien
15350506Sobrientypedef std::vector<Directive*> DirectiveList;
15450506Sobrien
15550506Sobrien/// ExpectedData - owns directive objects and deletes on destructor.
15650506Sobrien///
15750506Sobrienstruct ExpectedData {
15850506Sobrien  DirectiveList Errors;
15950506Sobrien  DirectiveList Warnings;
16050506Sobrien  DirectiveList Notes;
16150506Sobrien
16250506Sobrien  ~ExpectedData() {
16350506Sobrien    DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 };
16418334Speter    for (DirectiveList **PL = Lists; *PL; ++PL) {
16518334Speter      DirectiveList * const L = *PL;
16618334Speter      for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I)
16718334Speter        delete *I;
16818334Speter    }
16918334Speter  }
17018334Speter};
17118334Speter
17218334Speterclass ParseHelper
17318334Speter{
17418334Speterpublic:
17518334Speter  ParseHelper(const char *Begin, const char *End)
17618334Speter    : Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { }
17718334Speter
17818334Speter  // Return true if string literal is next.
17918334Speter  bool Next(StringRef S) {
18018334Speter    P = C;
18118334Speter    PEnd = C + S.size();
18218334Speter    if (PEnd > End)
18318334Speter      return false;
18418334Speter    return !memcmp(P, S.data(), S.size());
18518334Speter  }
18618334Speter
18718334Speter  // Return true if number is next.
18818334Speter  // Output N only if number is next.
18918334Speter  bool Next(unsigned &N) {
19018334Speter    unsigned TMP = 0;
19118334Speter    P = C;
19218334Speter    for (; P < End && P[0] >= '0' && P[0] <= '9'; ++P) {
19318334Speter      TMP *= 10;
19418334Speter      TMP += P[0] - '0';
19518334Speter    }
19618334Speter    if (P == C)
19718334Speter      return false;
19818334Speter    PEnd = P;
19918334Speter    N = TMP;
20018334Speter    return true;
20118334Speter  }
20218334Speter
20318334Speter  // Return true if string literal is found.
20418334Speter  // When true, P marks begin-position of S in content.
20518334Speter  bool Search(StringRef S) {
20618334Speter    P = std::search(C, End, S.begin(), S.end());
20718334Speter    PEnd = P + S.size();
20818334Speter    return P != End;
20918334Speter  }
21018334Speter
21118334Speter  // Advance 1-past previous next/search.
21218334Speter  // Behavior is undefined if previous next/search failed.
21318334Speter  bool Advance() {
21418334Speter    C = PEnd;
21518334Speter    return C < End;
21618334Speter  }
21718334Speter
21818334Speter  // Skip zero or more whitespace.
21918334Speter  void SkipWhitespace() {
22018334Speter    for (; C < End && isspace(*C); ++C)
22118334Speter      ;
22218334Speter  }
22318334Speter
22418334Speter  // Return true if EOF reached.
22518334Speter  bool Done() {
22618334Speter    return !(C < End);
22718334Speter  }
22818334Speter
22918334Speter  const char * const Begin; // beginning of expected content
23018334Speter  const char * const End;   // end of expected content (1-past)
23118334Speter  const char *C;            // position of next char in content
23218334Speter  const char *P;
23318334Speter
23418334Speterprivate:
23550506Sobrien  const char *PEnd; // previous next/search subject end (1-past)
23650506Sobrien};
23750506Sobrien
23850506Sobrien} // namespace anonymous
23950506Sobrien
24050506Sobrien/// ParseDirective - Go through the comment and see if it indicates expected
24150506Sobrien/// diagnostics. If so, then put them in the appropriate directive list.
24250506Sobrien///
24350506Sobrienstatic void ParseDirective(const char *CommentStart, unsigned CommentLen,
24450506Sobrien                           ExpectedData &ED, Preprocessor &PP,
24518334Speter                           SourceLocation Pos) {
24618334Speter  // A single comment may contain multiple directives.
24718334Speter  for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) {
24818334Speter    // search for token: expected
24918334Speter    if (!PH.Search("expected"))
25018334Speter      break;
25118334Speter    PH.Advance();
25218334Speter
25318334Speter    // next token: -
25418334Speter    if (!PH.Next("-"))
25518334Speter      continue;
25618334Speter    PH.Advance();
25718334Speter
25818334Speter    // next token: { error | warning | note }
25918334Speter    DirectiveList* DL = NULL;
26018334Speter    if (PH.Next("error"))
26118334Speter      DL = &ED.Errors;
26218334Speter    else if (PH.Next("warning"))
26318334Speter      DL = &ED.Warnings;
26418334Speter    else if (PH.Next("note"))
26518334Speter      DL = &ED.Notes;
26618334Speter    else
26718334Speter      continue;
26818334Speter    PH.Advance();
26918334Speter
27018334Speter    // default directive kind
27118334Speter    bool RegexKind = false;
27218334Speter    const char* KindStr = "string";
27318334Speter
27418334Speter    // next optional token: -
27518334Speter    if (PH.Next("-re")) {
27618334Speter      PH.Advance();
27718334Speter      RegexKind = true;
27818334Speter      KindStr = "regex";
27918334Speter    }
28018334Speter
28118334Speter    // skip optional whitespace
28218334Speter    PH.SkipWhitespace();
28318334Speter
28418334Speter    // next optional token: positive integer or a '+'.
28518334Speter    unsigned Count = 1;
28618334Speter    if (PH.Next(Count))
28718334Speter      PH.Advance();
28818334Speter    else if (PH.Next("+")) {
28918334Speter      Count = Directive::OneOrMoreCount;
29018334Speter      PH.Advance();
29118334Speter    }
29218334Speter
29318334Speter    // skip optional whitespace
29450506Sobrien    PH.SkipWhitespace();
29550506Sobrien
29650506Sobrien    // next token: {{
29750506Sobrien    if (!PH.Next("{{")) {
29850506Sobrien      PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin),
29950506Sobrien              diag::err_verify_missing_start) << KindStr;
30050506Sobrien      continue;
30150506Sobrien    }
30250506Sobrien    PH.Advance();
30318334Speter    const char* const ContentBegin = PH.C; // mark content begin
30418334Speter
30518334Speter    // search for token: }}
30618334Speter    if (!PH.Search("}}")) {
30718334Speter      PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin),
30818334Speter              diag::err_verify_missing_end) << KindStr;
30918334Speter      continue;
31018334Speter    }
31118334Speter    const char* const ContentEnd = PH.P; // mark content end
31218334Speter    PH.Advance();
31318334Speter
31418334Speter    // build directive text; convert \n to newlines
31518334Speter    std::string Text;
31618334Speter    StringRef NewlineStr = "\\n";
31718334Speter    StringRef Content(ContentBegin, ContentEnd-ContentBegin);
31818334Speter    size_t CPos = 0;
31918334Speter    size_t FPos;
32018334Speter    while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) {
32118334Speter      Text += Content.substr(CPos, FPos-CPos);
32218334Speter      Text += '\n';
32318334Speter      CPos = FPos + NewlineStr.size();
32418334Speter    }
32518334Speter    if (Text.empty())
32618334Speter      Text.assign(ContentBegin, ContentEnd);
32718334Speter
32818334Speter    // construct new directive
32918334Speter    Directive *D = Directive::Create(RegexKind, Pos, Text, Count);
33018334Speter    std::string Error;
33118334Speter    if (D->isValid(Error))
33218334Speter      DL->push_back(D);
33318334Speter    else {
33418334Speter      PP.Diag(Pos.getLocWithOffset(ContentBegin-PH.Begin),
33518334Speter              diag::err_verify_invalid_content)
33618334Speter        << KindStr << Error;
33718334Speter    }
33818334Speter  }
33918334Speter}
34018334Speter
34118334Speter/// FindExpectedDiags - Lex the main source file to find all of the
34250506Sobrien//   expected errors and warnings.
34350506Sobrienstatic void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) {
34450506Sobrien  // Create a raw lexer to pull all the comments out of FID.
34550506Sobrien  if (FID.isInvalid())
34650506Sobrien    return;
34750506Sobrien
34850506Sobrien  SourceManager& SM = PP.getSourceManager();
34950506Sobrien  // Create a lexer to lex all the tokens of the main file in raw mode.
35050506Sobrien  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
35150506Sobrien  Lexer RawLex(FID, FromFile, SM, PP.getLangOpts());
35250506Sobrien
35350506Sobrien  // Return comments as tokens, this is how we find expected diagnostics.
35450506Sobrien  RawLex.SetCommentRetentionState(true);
35550506Sobrien
35650506Sobrien  Token Tok;
35750506Sobrien  Tok.setKind(tok::comment);
35850506Sobrien  while (Tok.isNot(tok::eof)) {
35950506Sobrien    RawLex.Lex(Tok);
36050506Sobrien    if (!Tok.is(tok::comment)) continue;
36150506Sobrien
36250506Sobrien    std::string Comment = PP.getSpelling(Tok);
36350506Sobrien    if (Comment.empty()) continue;
36418334Speter
36518334Speter    // Find all expected errors/warnings/notes.
36618334Speter    ParseDirective(&Comment[0], Comment.size(), ED, PP, Tok.getLocation());
36718334Speter  };
36818334Speter}
36918334Speter
37018334Speter/// PrintProblem - This takes a diagnostic map of the delta between expected and
37118334Speter/// seen diagnostics. If there's anything in it, then something unexpected
37218334Speter/// happened. Print the map out in a nice format and return "true". If the map
37318334Speter/// is empty and we're not going to print things, then return "false".
37418334Speter///
37518334Speterstatic unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
37618334Speter                             const_diag_iterator diag_begin,
37718334Speter                             const_diag_iterator diag_end,
37818334Speter                             const char *Kind, bool Expected) {
37918334Speter  if (diag_begin == diag_end) return 0;
38018334Speter
38118334Speter  SmallString<256> Fmt;
38218334Speter  llvm::raw_svector_ostream OS(Fmt);
38318334Speter  for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
38450506Sobrien    if (I->first.isInvalid() || !SourceMgr)
38550506Sobrien      OS << "\n  (frontend)";
38618334Speter    else
38750506Sobrien      OS << "\n  Line " << SourceMgr->getPresumedLineNumber(I->first);
38850506Sobrien    OS << ": " << I->second;
38950506Sobrien  }
39050506Sobrien
39150506Sobrien  Diags.Report(diag::err_verify_inconsistent_diags)
39250506Sobrien    << Kind << !Expected << OS.str();
39350506Sobrien  return std::distance(diag_begin, diag_end);
39450506Sobrien}
39550506Sobrien
39650506Sobrienstatic unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
39718334Speter                             DirectiveList &DL, const char *Kind,
39818334Speter                             bool Expected) {
39918334Speter  if (DL.empty())
40018334Speter    return 0;
40118334Speter
40218334Speter  SmallString<256> Fmt;
40318334Speter  llvm::raw_svector_ostream OS(Fmt);
40418334Speter  for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
40550506Sobrien    Directive& D = **I;
40650506Sobrien    if (D.Location.isInvalid() || !SourceMgr)
40750506Sobrien      OS << "\n  (frontend)";
40850506Sobrien    else
40950506Sobrien      OS << "\n  Line " << SourceMgr->getPresumedLineNumber(D.Location);
41018334Speter    OS << ": " << D.Text;
41118334Speter  }
41218334Speter
41350506Sobrien  Diags.Report(diag::err_verify_inconsistent_diags)
41450506Sobrien    << Kind << !Expected << OS.str();
41550506Sobrien  return DL.size();
41618334Speter}
41718334Speter
41818334Speter/// CheckLists - Compare expected to seen diagnostic lists and return the
41950506Sobrien/// the difference between them.
42050506Sobrien///
42150506Sobrienstatic unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
42250506Sobrien                           const char *Label,
42350506Sobrien                           DirectiveList &Left,
42450506Sobrien                           const_diag_iterator d2_begin,
42550506Sobrien                           const_diag_iterator d2_end) {
42650506Sobrien  DirectiveList LeftOnly;
42750506Sobrien  DiagList Right(d2_begin, d2_end);
42818334Speter
42918334Speter  for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
43018334Speter    Directive& D = **I;
43118334Speter    unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location);
43218334Speter    bool FoundOnce = false;
43318334Speter
43438510Sbde    for (unsigned i = 0; i < D.Count; ++i) {
43550506Sobrien      DiagList::iterator II, IE;
43650506Sobrien      for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
43750506Sobrien        unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
43850506Sobrien        if (LineNo1 != LineNo2)
43950506Sobrien          continue;
44050506Sobrien
44150506Sobrien        const std::string &RightText = II->second;
44250506Sobrien        if (D.Match(RightText))
44338510Sbde          break;
44450506Sobrien      }
44550506Sobrien      if (II == IE) {
44650506Sobrien        if (D.Count == D.OneOrMoreCount) {
44750506Sobrien          if (!FoundOnce)
44850506Sobrien            LeftOnly.push_back(*I);
44950506Sobrien          // We are only interested in at least one match, so exit the loop.
45050506Sobrien          break;
45150506Sobrien        }
45250506Sobrien        // Not found.
45350506Sobrien        LeftOnly.push_back(*I);
45450506Sobrien      } else {
45550506Sobrien        // Found. The same cannot be found twice.
45618334Speter        Right.erase(II);
45718334Speter        FoundOnce = true;
45818334Speter      }
45918334Speter    }
46018334Speter  }
46118334Speter  // Now all that's left in Right are those that were not matched.
46218334Speter  unsigned num = PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true);
46318334Speter  num += PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(),
46418334Speter                      Label, false);
46518334Speter  return num;
46618334Speter}
46718334Speter
46818334Speter/// CheckResults - This compares the expected results to those that
46918334Speter/// were actually reported. It emits any discrepencies. Return "true" if there
47018334Speter/// were problems. Return "false" otherwise.
47118334Speter///
47218334Speterstatic unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
47318334Speter                             const TextDiagnosticBuffer &Buffer,
47418334Speter                             ExpectedData &ED) {
47518334Speter  // We want to capture the delta between what was expected and what was
47618334Speter  // seen.
47718334Speter  //
47818334Speter  //   Expected \ Seen - set expected but not seen
47950506Sobrien  //   Seen \ Expected - set seen but not expected
48050506Sobrien  unsigned NumProblems = 0;
48150506Sobrien
48250506Sobrien  // See if there are error mismatches.
48350506Sobrien  NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors,
48450506Sobrien                            Buffer.err_begin(), Buffer.err_end());
48550506Sobrien
48650506Sobrien  // See if there are warning mismatches.
48750506Sobrien  NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings,
48850506Sobrien                            Buffer.warn_begin(), Buffer.warn_end());
48950506Sobrien
49050506Sobrien  // See if there are note mismatches.
49150506Sobrien  NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes,
49250506Sobrien                            Buffer.note_begin(), Buffer.note_end());
49350506Sobrien
49450506Sobrien  return NumProblems;
49550506Sobrien}
49650506Sobrien
49750506Sobrienvoid VerifyDiagnosticConsumer::CheckDiagnostics() {
49850506Sobrien  ExpectedData ED;
49950506Sobrien
50050506Sobrien  // Ensure any diagnostics go to the primary client.
50150506Sobrien  bool OwnsCurClient = Diags.ownsClient();
502  DiagnosticConsumer *CurClient = Diags.takeClient();
503  Diags.setClient(PrimaryClient, false);
504
505  // If we have a preprocessor, scan the source for expected diagnostic
506  // markers. If not then any diagnostics are unexpected.
507  if (CurrentPreprocessor) {
508    SourceManager &SM = CurrentPreprocessor->getSourceManager();
509    // Extract expected-error strings from main file.
510    FindExpectedDiags(*CurrentPreprocessor, ED, SM.getMainFileID());
511    // Only check for expectations in other diagnostic locations
512    // if they are not the main file (via ID or FileEntry) - the main
513    // file has already been looked at, and its expectations must not
514    // be added twice.
515    if (!FirstErrorFID.isInvalid() && FirstErrorFID != SM.getMainFileID()
516        && (!SM.getFileEntryForID(FirstErrorFID)
517            || (SM.getFileEntryForID(FirstErrorFID) !=
518                SM.getFileEntryForID(SM.getMainFileID())))) {
519      FindExpectedDiags(*CurrentPreprocessor, ED, FirstErrorFID);
520      FirstErrorFID = FileID();
521    }
522
523    // Check that the expected diagnostics occurred.
524    NumErrors += CheckResults(Diags, SM, *Buffer, ED);
525  } else {
526    NumErrors += (PrintProblem(Diags, 0,
527                               Buffer->err_begin(), Buffer->err_end(),
528                               "error", false) +
529                  PrintProblem(Diags, 0,
530                               Buffer->warn_begin(), Buffer->warn_end(),
531                               "warn", false) +
532                  PrintProblem(Diags, 0,
533                               Buffer->note_begin(), Buffer->note_end(),
534                               "note", false));
535  }
536
537  Diags.takeClient();
538  Diags.setClient(CurClient, OwnsCurClient);
539
540  // Reset the buffer, we have processed all the diagnostics in it.
541  Buffer.reset(new TextDiagnosticBuffer());
542}
543
544DiagnosticConsumer *
545VerifyDiagnosticConsumer::clone(DiagnosticsEngine &Diags) const {
546  if (!Diags.getClient())
547    Diags.setClient(PrimaryClient->clone(Diags));
548
549  return new VerifyDiagnosticConsumer(Diags);
550}
551
552Directive* Directive::Create(bool RegexKind, const SourceLocation &Location,
553                             const std::string &Text, unsigned Count) {
554  if (RegexKind)
555    return new RegexDirective(Location, Text, Count);
556  return new StandardDirective(Location, Text, Count);
557}
558