diff options
Diffstat (limited to 'lib/Frontend/VerifyDiagnosticConsumer.cpp')
| -rw-r--r-- | lib/Frontend/VerifyDiagnosticConsumer.cpp | 471 | 
1 files changed, 293 insertions, 178 deletions
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index 552282dafb34d..a9378a117d6bd 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -11,58 +11,108 @@  //  //===----------------------------------------------------------------------===// +#include "clang/Basic/FileManager.h"  #include "clang/Frontend/VerifyDiagnosticConsumer.h"  #include "clang/Frontend/FrontendDiagnostic.h"  #include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Lex/HeaderSearch.h"  #include "clang/Lex/Preprocessor.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/Support/Regex.h"  #include "llvm/Support/raw_ostream.h" -#include <climits> +#include <cctype>  using namespace clang; +typedef VerifyDiagnosticConsumer::Directive Directive; +typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList; +typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData;  VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags) -  : Diags(_Diags), PrimaryClient(Diags.getClient()), -    OwnsPrimaryClient(Diags.ownsClient()), -    Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0)  +  : Diags(_Diags), +    PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()), +    Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0), +    ActiveSourceFiles(0)  {    Diags.takeClient();  }  VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() { +  assert(!ActiveSourceFiles && "Incomplete parsing of source files!"); +  assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");    CheckDiagnostics();      Diags.takeClient();    if (OwnsPrimaryClient)      delete PrimaryClient;  } +#ifndef NDEBUG +namespace { +class VerifyFileTracker : public PPCallbacks { +  typedef VerifyDiagnosticConsumer::FilesParsedForDirectivesSet ListType; +  ListType &FilesList; +  SourceManager &SM; + +public: +  VerifyFileTracker(ListType &FilesList, SourceManager &SM) +    : FilesList(FilesList), SM(SM) { } + +  /// \brief Hook into the preprocessor and update the list of parsed +  /// files when the preprocessor indicates a new file is entered. +  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, +                           SrcMgr::CharacteristicKind FileType, +                           FileID PrevFID) { +    if (const FileEntry *E = SM.getFileEntryForID(SM.getFileID(Loc))) +      FilesList.insert(E); +  } +}; +} // End anonymous namespace. +#endif +  // DiagnosticConsumer interface.  void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,                                                 const Preprocessor *PP) { -  // FIXME: Const hack, we screw up the preprocessor but in practice its ok -  // because it doesn't get reused. It would be better if we could make a copy -  // though. -  CurrentPreprocessor = const_cast<Preprocessor*>(PP); +  // Attach comment handler on first invocation. +  if (++ActiveSourceFiles == 1) { +    if (PP) { +      CurrentPreprocessor = PP; +      const_cast<Preprocessor*>(PP)->addCommentHandler(this); +#ifndef NDEBUG +      VerifyFileTracker *V = new VerifyFileTracker(FilesParsedForDirectives, +                                                   PP->getSourceManager()); +      const_cast<Preprocessor*>(PP)->addPPCallbacks(V); +#endif +    } +  } +  assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!");    PrimaryClient->BeginSourceFile(LangOpts, PP);  }  void VerifyDiagnosticConsumer::EndSourceFile() { -  CheckDiagnostics(); - +  assert(ActiveSourceFiles && "No active source files!");    PrimaryClient->EndSourceFile(); -  CurrentPreprocessor = 0; +  // Detach comment handler once last active source file completed. +  if (--ActiveSourceFiles == 0) { +    if (CurrentPreprocessor) +      const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this); + +    // Check diagnostics once last file completed. +    CheckDiagnostics(); +    CurrentPreprocessor = 0; +  }  }  void VerifyDiagnosticConsumer::HandleDiagnostic(        DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { -  if (FirstErrorFID.isInvalid() && Info.hasSourceManager()) { -    const SourceManager &SM = Info.getSourceManager(); -    FirstErrorFID = SM.getFileID(Info.getLocation()); +#ifndef NDEBUG +  if (Info.hasSourceManager()) { +    FileID FID = Info.getSourceManager().getFileID(Info.getLocation()); +    if (!FID.isInvalid()) +      FilesWithDiagnostics.insert(FID);    } +#endif    // Send the diagnostic to the buffer, we will check it once we reach the end    // of the source file (or are destructed).    Buffer->HandleDiagnostic(DiagLevel, Info); @@ -77,54 +127,21 @@ typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;  namespace { -/// Directive - Abstract class representing a parsed verify directive. -/// -class Directive { -public: -  static Directive* Create(bool RegexKind, const SourceLocation &Location, -                           const std::string &Text, unsigned Count); -public: -  /// Constant representing one or more matches aka regex "+". -  static const unsigned OneOrMoreCount =  UINT_MAX; - -  SourceLocation Location; -  const std::string Text; -  unsigned Count; - -  virtual ~Directive() { } - -  // Returns true if directive text is valid. -  // Otherwise returns false and populates E. -  virtual bool isValid(std::string &Error) = 0; - -  // Returns true on match. -  virtual bool Match(const std::string &S) = 0; - -protected: -  Directive(const SourceLocation &Location, const std::string &Text, -            unsigned Count) -    : Location(Location), Text(Text), Count(Count) { } - -private: -  Directive(const Directive&); // DO NOT IMPLEMENT -  void operator=(const Directive&); // DO NOT IMPLEMENT -}; -  /// StandardDirective - Directive with string matching.  ///  class StandardDirective : public Directive {  public: -  StandardDirective(const SourceLocation &Location, const std::string &Text, -                    unsigned Count) -    : Directive(Location, Text, Count) { } +  StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, +                    StringRef Text, unsigned Min, unsigned Max) +    : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max) { }    virtual bool isValid(std::string &Error) {      // all strings are considered valid; even empty ones      return true;    } -  virtual bool Match(const std::string &S) { -    return S.find(Text) != std::string::npos; +  virtual bool match(StringRef S) { +    return S.find(Text) != StringRef::npos;    }  }; @@ -132,9 +149,9 @@ public:  ///  class RegexDirective : public Directive {  public: -  RegexDirective(const SourceLocation &Location, const std::string &Text, -                 unsigned Count) -    : Directive(Location, Text, Count), Regex(Text) { } +  RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, +                 StringRef Text, unsigned Min, unsigned Max) +    : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max), Regex(Text) { }    virtual bool isValid(std::string &Error) {      if (Regex.isValid(Error)) @@ -142,7 +159,7 @@ public:      return false;    } -  virtual bool Match(const std::string &S) { +  virtual bool match(StringRef S) {      return Regex.match(S);    } @@ -150,30 +167,11 @@ private:    llvm::Regex Regex;  }; -typedef std::vector<Directive*> DirectiveList; - -/// ExpectedData - owns directive objects and deletes on destructor. -/// -struct ExpectedData { -  DirectiveList Errors; -  DirectiveList Warnings; -  DirectiveList Notes; - -  ~ExpectedData() { -    DirectiveList* Lists[] = { &Errors, &Warnings, &Notes, 0 }; -    for (DirectiveList **PL = Lists; *PL; ++PL) { -      DirectiveList * const L = *PL; -      for (DirectiveList::iterator I = L->begin(), E = L->end(); I != E; ++I) -        delete *I; -    } -  } -};   -  class ParseHelper  {  public: -  ParseHelper(const char *Begin, const char *End) -    : Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { } +  ParseHelper(StringRef S) +    : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(NULL) { }    // Return true if string literal is next.    bool Next(StringRef S) { @@ -240,78 +238,134 @@ private:  /// ParseDirective - Go through the comment and see if it indicates expected  /// diagnostics. If so, then put them in the appropriate directive list.  /// -static void ParseDirective(const char *CommentStart, unsigned CommentLen, -                           ExpectedData &ED, Preprocessor &PP, -                           SourceLocation Pos) { +/// Returns true if any valid directives were found. +static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, +                           SourceLocation Pos, DiagnosticsEngine &Diags) {    // A single comment may contain multiple directives. -  for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) { -    // search for token: expected +  bool FoundDirective = false; +  for (ParseHelper PH(S); !PH.Done();) { +    // Search for token: expected      if (!PH.Search("expected"))        break;      PH.Advance(); -    // next token: - +    // Next token: -      if (!PH.Next("-"))        continue;      PH.Advance(); -    // next token: { error | warning | note } +    // Next token: { error | warning | note }      DirectiveList* DL = NULL;      if (PH.Next("error")) -      DL = &ED.Errors; +      DL = ED ? &ED->Errors : NULL;      else if (PH.Next("warning")) -      DL = &ED.Warnings; +      DL = ED ? &ED->Warnings : NULL;      else if (PH.Next("note")) -      DL = &ED.Notes; +      DL = ED ? &ED->Notes : NULL;      else        continue;      PH.Advance(); -    // default directive kind +    // If a directive has been found but we're not interested +    // in storing the directive information, return now. +    if (!DL) +      return true; + +    // Default directive kind.      bool RegexKind = false;      const char* KindStr = "string"; -    // next optional token: - +    // Next optional token: -      if (PH.Next("-re")) {        PH.Advance();        RegexKind = true;        KindStr = "regex";      } -    // skip optional whitespace +    // Next optional token: @ +    SourceLocation ExpectedLoc; +    if (!PH.Next("@")) { +      ExpectedLoc = Pos; +    } else { +      PH.Advance(); +      unsigned Line = 0; +      bool FoundPlus = PH.Next("+"); +      if (FoundPlus || PH.Next("-")) { +        // Relative to current line. +        PH.Advance(); +        bool Invalid = false; +        unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid); +        if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) { +          if (FoundPlus) ExpectedLine += Line; +          else ExpectedLine -= Line; +          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1); +        } +      } else { +        // Absolute line number. +        if (PH.Next(Line) && Line > 0) +          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1); +      } + +      if (ExpectedLoc.isInvalid()) { +        Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), +                     diag::err_verify_missing_line) << KindStr; +        continue; +      } +      PH.Advance(); +    } + +    // Skip optional whitespace.      PH.SkipWhitespace(); -    // next optional token: positive integer or a '+'. -    unsigned Count = 1; -    if (PH.Next(Count)) +    // Next optional token: positive integer or a '+'. +    unsigned Min = 1; +    unsigned Max = 1; +    if (PH.Next(Min)) {        PH.Advance(); -    else if (PH.Next("+")) { -      Count = Directive::OneOrMoreCount; +      // A positive integer can be followed by a '+' meaning min +      // or more, or by a '-' meaning a range from min to max. +      if (PH.Next("+")) { +        Max = Directive::MaxCount; +        PH.Advance(); +      } else if (PH.Next("-")) { +        PH.Advance(); +        if (!PH.Next(Max) || Max < Min) { +          Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), +                       diag::err_verify_invalid_range) << KindStr; +          continue; +        } +        PH.Advance(); +      } else { +        Max = Min; +      } +    } else if (PH.Next("+")) { +      // '+' on its own means "1 or more". +      Max = Directive::MaxCount;        PH.Advance();      } -    // skip optional whitespace +    // Skip optional whitespace.      PH.SkipWhitespace(); -    // next token: {{ +    // Next token: {{      if (!PH.Next("{{")) { -      PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin), -              diag::err_verify_missing_start) << KindStr; +      Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), +                   diag::err_verify_missing_start) << KindStr;        continue;      }      PH.Advance();      const char* const ContentBegin = PH.C; // mark content begin -    // search for token: }} +    // Search for token: }}      if (!PH.Search("}}")) { -      PP.Diag(Pos.getLocWithOffset(PH.C-PH.Begin), -              diag::err_verify_missing_end) << KindStr; +      Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), +                   diag::err_verify_missing_end) << KindStr;        continue;      }      const char* const ContentEnd = PH.P; // mark content end      PH.Advance(); -    // build directive text; convert \n to newlines +    // Build directive text; convert \n to newlines.      std::string Text;      StringRef NewlineStr = "\\n";      StringRef Content(ContentBegin, ContentEnd-ContentBegin); @@ -325,25 +379,83 @@ static void ParseDirective(const char *CommentStart, unsigned CommentLen,      if (Text.empty())        Text.assign(ContentBegin, ContentEnd); -    // construct new directive -    Directive *D = Directive::Create(RegexKind, Pos, Text, Count); +    // Construct new directive. +    Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, +                                     Min, Max);      std::string Error; -    if (D->isValid(Error)) +    if (D->isValid(Error)) {        DL->push_back(D); -    else { -      PP.Diag(Pos.getLocWithOffset(ContentBegin-PH.Begin), -              diag::err_verify_invalid_content) +      FoundDirective = true; +    } else { +      Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin), +                   diag::err_verify_invalid_content)          << KindStr << Error;      }    } + +  return FoundDirective;  } -/// FindExpectedDiags - Lex the main source file to find all of the -//   expected errors and warnings. -static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) { +/// HandleComment - Hook into the preprocessor and extract comments containing +///  expected errors and warnings. +bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP, +                                             SourceRange Comment) { +  SourceManager &SM = PP.getSourceManager(); +  SourceLocation CommentBegin = Comment.getBegin(); + +  const char *CommentRaw = SM.getCharacterData(CommentBegin); +  StringRef C(CommentRaw, SM.getCharacterData(Comment.getEnd()) - CommentRaw); + +  if (C.empty()) +    return false; + +  // Fold any "\<EOL>" sequences +  size_t loc = C.find('\\'); +  if (loc == StringRef::npos) { +    ParseDirective(C, &ED, SM, CommentBegin, PP.getDiagnostics()); +    return false; +  } + +  std::string C2; +  C2.reserve(C.size()); + +  for (size_t last = 0;; loc = C.find('\\', last)) { +    if (loc == StringRef::npos || loc == C.size()) { +      C2 += C.substr(last); +      break; +    } +    C2 += C.substr(last, loc-last); +    last = loc + 1; + +    if (C[last] == '\n' || C[last] == '\r') { +      ++last; + +      // Escape \r\n  or \n\r, but not \n\n. +      if (last < C.size()) +        if (C[last] == '\n' || C[last] == '\r') +          if (C[last] != C[last-1]) +            ++last; +    } else { +      // This was just a normal backslash. +      C2 += '\\'; +    } +  } + +  if (!C2.empty()) +    ParseDirective(C2, &ED, SM, CommentBegin, PP.getDiagnostics()); +  return false; +} + +#ifndef NDEBUG +/// \brief Lex the specified source file to determine whether it contains +/// any expected-* directives.  As a Lexer is used rather than a full-blown +/// Preprocessor, directives inside skipped #if blocks will still be found. +/// +/// \return true if any directives were found. +static bool findDirectives(const Preprocessor &PP, FileID FID) {    // Create a raw lexer to pull all the comments out of FID.    if (FID.isInvalid()) -    return; +    return false;    SourceManager& SM = PP.getSourceManager();    // Create a lexer to lex all the tokens of the main file in raw mode. @@ -355,6 +467,7 @@ static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) {    Token Tok;    Tok.setKind(tok::comment); +  bool Found = false;    while (Tok.isNot(tok::eof)) {      RawLex.Lex(Tok);      if (!Tok.is(tok::comment)) continue; @@ -363,19 +476,19 @@ static void FindExpectedDiags(Preprocessor &PP, ExpectedData &ED, FileID FID) {      if (Comment.empty()) continue;      // Find all expected errors/warnings/notes. -    ParseDirective(&Comment[0], Comment.size(), ED, PP, Tok.getLocation()); -  }; +    Found |= ParseDirective(Comment, 0, SM, Tok.getLocation(), +                            PP.getDiagnostics()); +  } +  return Found;  } - -/// PrintProblem - This takes a diagnostic map of the delta between expected and -/// seen diagnostics. If there's anything in it, then something unexpected -/// happened. Print the map out in a nice format and return "true". If the map -/// is empty and we're not going to print things, then return "false". -/// -static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr, -                             const_diag_iterator diag_begin, -                             const_diag_iterator diag_end, -                             const char *Kind, bool Expected) { +#endif // !NDEBUG + +/// \brief Takes a list of diagnostics that have been generated but not matched +/// by an expected-* directive and produces a diagnostic to the user from this. +static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr, +                                const_diag_iterator diag_begin, +                                const_diag_iterator diag_end, +                                const char *Kind) {    if (diag_begin == diag_end) return 0;    SmallString<256> Fmt; @@ -388,30 +501,32 @@ static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr,      OS << ": " << I->second;    } -  Diags.Report(diag::err_verify_inconsistent_diags) -    << Kind << !Expected << OS.str(); +  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit() +    << Kind << /*Unexpected=*/true << OS.str();    return std::distance(diag_begin, diag_end);  } -static unsigned PrintProblem(DiagnosticsEngine &Diags, SourceManager *SourceMgr, -                             DirectiveList &DL, const char *Kind, -                             bool Expected) { +/// \brief Takes a list of diagnostics that were expected to have been generated +/// but were not and produces a diagnostic to the user from this. +static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr, +                              DirectiveList &DL, const char *Kind) {    if (DL.empty())      return 0;    SmallString<256> Fmt;    llvm::raw_svector_ostream OS(Fmt);    for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) { -    Directive& D = **I; -    if (D.Location.isInvalid() || !SourceMgr) -      OS << "\n  (frontend)"; -    else -      OS << "\n  Line " << SourceMgr->getPresumedLineNumber(D.Location); +    Directive &D = **I; +    OS << "\n  Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc); +    if (D.DirectiveLoc != D.DiagnosticLoc) +      OS << " (directive at " +         << SourceMgr.getFilename(D.DirectiveLoc) << ":" +         << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ")";      OS << ": " << D.Text;    } -  Diags.Report(diag::err_verify_inconsistent_diags) -    << Kind << !Expected << OS.str(); +  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit() +    << Kind << /*Unexpected=*/false << OS.str();    return DL.size();  } @@ -428,10 +543,9 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,    for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {      Directive& D = **I; -    unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location); -    bool FoundOnce = false; +    unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc); -    for (unsigned i = 0; i < D.Count; ++i) { +    for (unsigned i = 0; i < D.Max; ++i) {        DiagList::iterator II, IE;        for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {          unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first); @@ -439,29 +553,22 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,            continue;          const std::string &RightText = II->second; -        if (D.Match(RightText)) +        if (D.match(RightText))            break;        }        if (II == IE) { -        if (D.Count == D.OneOrMoreCount) { -          if (!FoundOnce) -            LeftOnly.push_back(*I); -          // We are only interested in at least one match, so exit the loop. -          break; -        }          // Not found. +        if (i >= D.Min) break;          LeftOnly.push_back(*I);        } else {          // Found. The same cannot be found twice.          Right.erase(II); -        FoundOnce = true;        }      }    }    // Now all that's left in Right are those that were not matched. -  unsigned num = PrintProblem(Diags, &SourceMgr, LeftOnly, Label, true); -  num += PrintProblem(Diags, &SourceMgr, Right.begin(), Right.end(), -                      Label, false); +  unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label); +  num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);    return num;  } @@ -495,8 +602,6 @@ static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,  }  void VerifyDiagnosticConsumer::CheckDiagnostics() { -  ExpectedData ED; -    // Ensure any diagnostics go to the primary client.    bool OwnsCurClient = Diags.ownsClient();    DiagnosticConsumer *CurClient = Diags.takeClient(); @@ -506,32 +611,38 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {    // markers. If not then any diagnostics are unexpected.    if (CurrentPreprocessor) {      SourceManager &SM = CurrentPreprocessor->getSourceManager(); -    // Extract expected-error strings from main file. -    FindExpectedDiags(*CurrentPreprocessor, ED, SM.getMainFileID()); -    // Only check for expectations in other diagnostic locations -    // if they are not the main file (via ID or FileEntry) - the main -    // file has already been looked at, and its expectations must not -    // be added twice. -    if (!FirstErrorFID.isInvalid() && FirstErrorFID != SM.getMainFileID() -        && (!SM.getFileEntryForID(FirstErrorFID) -            || (SM.getFileEntryForID(FirstErrorFID) != -                SM.getFileEntryForID(SM.getMainFileID())))) { -      FindExpectedDiags(*CurrentPreprocessor, ED, FirstErrorFID); -      FirstErrorFID = FileID(); + +#ifndef NDEBUG +    // In a debug build, scan through any files that may have been missed +    // during parsing and issue a fatal error if directives are contained +    // within these files.  If a fatal error occurs, this suggests that +    // this file is being parsed separately from the main file. +    HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo(); +    for (FilesWithDiagnosticsSet::iterator I = FilesWithDiagnostics.begin(), +                                         End = FilesWithDiagnostics.end(); +            I != End; ++I) { +      const FileEntry *E = SM.getFileEntryForID(*I); +      // Don't check files already parsed or those handled as modules. +      if (E && (FilesParsedForDirectives.count(E) +                  || HS.findModuleForHeader(E))) +        continue; + +      if (findDirectives(*CurrentPreprocessor, *I)) +        llvm::report_fatal_error(Twine("-verify directives found after rather" +                                       " than during normal parsing of ", +                                 StringRef(E ? E->getName() : "(unknown)")));      } +#endif      // Check that the expected diagnostics occurred.      NumErrors += CheckResults(Diags, SM, *Buffer, ED);    } else { -    NumErrors += (PrintProblem(Diags, 0, -                               Buffer->err_begin(), Buffer->err_end(), -                               "error", false) + -                  PrintProblem(Diags, 0, -                               Buffer->warn_begin(), Buffer->warn_end(), -                               "warn", false) + -                  PrintProblem(Diags, 0, -                               Buffer->note_begin(), Buffer->note_end(), -                               "note", false)); +    NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(), +                                  Buffer->err_end(), "error") + +                  PrintUnexpected(Diags, 0, Buffer->warn_begin(), +                                  Buffer->warn_end(), "warn") + +                  PrintUnexpected(Diags, 0, Buffer->note_begin(), +                                  Buffer->note_end(), "note"));    }    Diags.takeClient(); @@ -539,6 +650,9 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {    // Reset the buffer, we have processed all the diagnostics in it.    Buffer.reset(new TextDiagnosticBuffer()); +  ED.Errors.clear(); +  ED.Warnings.clear(); +  ED.Notes.clear();  }  DiagnosticConsumer * @@ -549,9 +663,10 @@ VerifyDiagnosticConsumer::clone(DiagnosticsEngine &Diags) const {    return new VerifyDiagnosticConsumer(Diags);  } -Directive* Directive::Create(bool RegexKind, const SourceLocation &Location, -                             const std::string &Text, unsigned Count) { +Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc, +                             SourceLocation DiagnosticLoc, StringRef Text, +                             unsigned Min, unsigned Max) {    if (RegexKind) -    return new RegexDirective(Location, Text, Count); -  return new StandardDirective(Location, Text, Count); +    return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max); +  return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);  }  | 
