1621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie//===---- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ------===//
281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//                     The LLVM Compiler Infrastructure
481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar// This file is distributed under the University of Illinois Open Source
681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar// License. See LICENSE.TXT for details.
781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//===----------------------------------------------------------------------===//
981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
1081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar// This is a concrete diagnostic client, which buffers the diagnostic messages.
1181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//
1281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//===----------------------------------------------------------------------===//
1381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
14621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie#include "clang/Frontend/VerifyDiagnosticConsumer.h"
153f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose#include "clang/Basic/CharInfo.h"
1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h"
1781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#include "clang/Frontend/FrontendDiagnostic.h"
1881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#include "clang/Frontend/TextDiagnosticBuffer.h"
197c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#include "clang/Lex/HeaderSearch.h"
2081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#include "clang/Lex/Preprocessor.h"
2181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#include "llvm/ADT/SmallString.h"
2260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner#include "llvm/Support/Regex.h"
2381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar#include "llvm/Support/raw_ostream.h"
24c035e09b6f4ed51a21e7983e504fe5380d5f2723Anna Zaks
2581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbarusing namespace clang;
264313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rosetypedef VerifyDiagnosticConsumer::Directive Directive;
274313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rosetypedef VerifyDiagnosticConsumer::DirectiveList DirectiveList;
284313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rosetypedef VerifyDiagnosticConsumer::ExpectedData ExpectedData;
2981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
30621bc69624599da62abd9bc9e5edd8a63ac99fe6David BlaikieVerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
317c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  : Diags(_Diags),
327c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()),
336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(nullptr),
346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    LangOpts(nullptr), SrcManager(nullptr), ActiveSourceFiles(0),
356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Status(HasNoDirectives)
3678243658c533168d51fd076fba328437932ba6f1Douglas Gregor{
3778243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.takeClient();
387eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (Diags.hasSourceManager())
397eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    setSourceManager(Diags.getSourceManager());
4081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
4181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
42621bc69624599da62abd9bc9e5edd8a63ac99fe6David BlaikieVerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
437c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert(!ActiveSourceFiles && "Incomplete parsing of source files!");
447c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  SrcManager = nullptr;
4678243658c533168d51fd076fba328437932ba6f1Douglas Gregor  CheckDiagnostics();
4778243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.takeClient();
4878243658c533168d51fd076fba328437932ba6f1Douglas Gregor  if (OwnsPrimaryClient)
4978243658c533168d51fd076fba328437932ba6f1Douglas Gregor    delete PrimaryClient;
5081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
5181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
527c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
537c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rosenamespace {
547c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Roseclass VerifyFileTracker : public PPCallbacks {
557eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  VerifyDiagnosticConsumer &Verify;
567c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  SourceManager &SM;
577c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
587c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rosepublic:
597eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM)
607eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    : Verify(Verify), SM(SM) { }
617c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
627c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  /// \brief Hook into the preprocessor and update the list of parsed
637c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  /// files when the preprocessor indicates a new file is entered.
647c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
657c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose                           SrcMgr::CharacteristicKind FileType,
667c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose                           FileID PrevFID) {
677eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    Verify.UpdateParsedFileStatus(SM, SM.getFileID(Loc),
687eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                  VerifyDiagnosticConsumer::IsParsed);
697c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
707c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose};
717c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose} // End anonymous namespace.
727c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif
737c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
7478ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie// DiagnosticConsumer interface.
7581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
76621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
771f6b2b5c82b2d2d3935b0db76352a04e9877b73fDouglas Gregor                                               const Preprocessor *PP) {
787c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  // Attach comment handler on first invocation.
797c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  if (++ActiveSourceFiles == 1) {
807c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    if (PP) {
817c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      CurrentPreprocessor = PP;
827eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      this->LangOpts = &LangOpts;
837eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      setSourceManager(PP->getSourceManager());
847c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      const_cast<Preprocessor*>(PP)->addCommentHandler(this);
857c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
867eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      // Debug build tracks parsed files.
877eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      VerifyFileTracker *V = new VerifyFileTracker(*this, *SrcManager);
887c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      const_cast<Preprocessor*>(PP)->addPPCallbacks(V);
897c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif
907c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    }
917c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
9281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
937c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!");
9481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  PrimaryClient->BeginSourceFile(LangOpts, PP);
9581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
9681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
97621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::EndSourceFile() {
987c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert(ActiveSourceFiles && "No active source files!");
9981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  PrimaryClient->EndSourceFile();
10081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
1017c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  // Detach comment handler once last active source file completed.
1027c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  if (--ActiveSourceFiles == 0) {
1037c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    if (CurrentPreprocessor)
1047c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this);
1057c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
1067c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    // Check diagnostics once last file completed.
1077c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    CheckDiagnostics();
1086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    CurrentPreprocessor = nullptr;
1096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    LangOpts = nullptr;
1107c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
11181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
112221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar
113621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::HandleDiagnostic(
11440847cfb58acc3cac7d68727df9455ac45f2e118David Blaikie      DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
115a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  if (Info.hasSourceManager()) {
116a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor    // If this diagnostic is for a different source manager, ignore it.
117a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor    if (SrcManager && &Info.getSourceManager() != SrcManager)
118a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor      return;
119a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor
1207eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    setSourceManager(Info.getSourceManager());
121a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  }
1227eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1237c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
1247eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // Debug build tracks unparsed files for possible
1257eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // unparsed expected-* directives.
1267eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (SrcManager) {
1277eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    SourceLocation Loc = Info.getLocation();
1287eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    if (Loc.isValid()) {
1297eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      ParsedStatus PS = IsUnparsed;
1307eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1317eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      Loc = SrcManager->getExpansionLoc(Loc);
1327eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      FileID FID = SrcManager->getFileID(Loc);
1337eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1347eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      const FileEntry *FE = SrcManager->getFileEntryForID(FID);
1357eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (FE && CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) {
1367eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        // If the file is a modules header file it shall not be parsed
1377eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        // for expected-* directives.
1387eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
1397eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        if (HS.findModuleForHeader(FE))
1407eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose          PS = IsUnparsedNoDirectives;
1417eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      }
1427eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1437eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      UpdateParsedFileStatus(*SrcManager, FID, PS);
1447eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    }
14501231610bc89a8d3ae1bdfee0063af9386fd82a4Axel Naumann  }
1467c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif
1477eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
14881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Send the diagnostic to the buffer, we will check it once we reach the end
14981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // of the source file (or are destructed).
15081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Buffer->HandleDiagnostic(DiagLevel, Info);
15181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
15281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
15381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//===----------------------------------------------------------------------===//
15481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar// Checking diagnostics implementation.
15581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//===----------------------------------------------------------------------===//
15681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
15781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbartypedef TextDiagnosticBuffer::DiagList DiagList;
15881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbartypedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
15981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
16060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnernamespace {
16160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
16260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// StandardDirective - Directive with string matching.
16360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
16460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerclass StandardDirective : public Directive {
16560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerpublic:
166aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
167ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                    bool MatchAnyLine, StringRef Text, unsigned Min,
168ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                    unsigned Max)
169ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) { }
17060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isValid(std::string &Error) override {
17260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    // all strings are considered valid; even empty ones
17360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return true;
17460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
17560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool match(StringRef S) override {
1774313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    return S.find(Text) != StringRef::npos;
17860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
17960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner};
18060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
18160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// RegexDirective - Directive with regular-expression matching.
18260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
18360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerclass RegexDirective : public Directive {
18460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerpublic:
185aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
186ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                 bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max,
187ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                 StringRef RegexStr)
188ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max),
189ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      Regex(RegexStr) { }
19060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool isValid(std::string &Error) override {
19260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (Regex.isValid(Error))
19360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      return true;
19460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return false;
19560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
19660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool match(StringRef S) override {
19860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return Regex.match(S);
19960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
20081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
20160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerprivate:
20260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  llvm::Regex Regex;
20360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner};
20460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
20560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerclass ParseHelper
20660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner{
20760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerpublic:
20878541c433049322b27b4f437973076ba29cff709Jordan Rose  ParseHelper(StringRef S)
2096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(nullptr) {}
21060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
21160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if string literal is next.
2125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool Next(StringRef S) {
21360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    P = C;
2140080f0ca30cd35e59347d632a261951f01a8129eBenjamin Kramer    PEnd = C + S.size();
21560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (PEnd > End)
21660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      return false;
2170080f0ca30cd35e59347d632a261951f01a8129eBenjamin Kramer    return !memcmp(P, S.data(), S.size());
21860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
21960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
22060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if number is next.
22160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Output N only if number is next.
22260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  bool Next(unsigned &N) {
22360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    unsigned TMP = 0;
22460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    P = C;
22560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    for (; P < End && P[0] >= '0' && P[0] <= '9'; ++P) {
22660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      TMP *= 10;
22760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      TMP += P[0] - '0';
22881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    }
22960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (P == C)
23060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      return false;
23160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PEnd = P;
23260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    N = TMP;
23360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return true;
23460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
23560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
23660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if string literal is found.
23760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // When true, P marks begin-position of S in content.
2384a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs  bool Search(StringRef S, bool EnsureStartOfWord = false) {
2394a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    do {
2404a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      P = std::search(C, End, S.begin(), S.end());
2414a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      PEnd = P + S.size();
2424a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      if (P == End)
2434a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs        break;
2444a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      if (!EnsureStartOfWord
2454a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs            // Check if string literal starts a new word.
2463f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose            || P == Begin || isWhitespace(P[-1])
247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            // Or it could be preceded by the start of a comment.
2484a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs            || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
2494a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs                                &&  P[-2] == '/'))
2504a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs        return true;
2514a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      // Otherwise, skip and search again.
2524a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    } while (Advance());
2534a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    return false;
25460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
25560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Return true if a CloseBrace that closes the OpenBrace at the current nest
257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // level is found. When true, P marks begin-position of CloseBrace.
258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool SearchClosingBrace(StringRef OpenBrace, StringRef CloseBrace) {
259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    unsigned Depth = 1;
260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    P = C;
261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    while (P < End) {
262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      StringRef S(P, End - P);
263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (S.startswith(OpenBrace)) {
264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ++Depth;
265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P += OpenBrace.size();
266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      } else if (S.startswith(CloseBrace)) {
267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        --Depth;
268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        if (Depth == 0) {
269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          PEnd = P + CloseBrace.size();
270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          return true;
271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        }
272651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        P += CloseBrace.size();
273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      } else {
274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ++P;
275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
276651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return false;
278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
279651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
28060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Advance 1-past previous next/search.
28160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Behavior is undefined if previous next/search failed.
28260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  bool Advance() {
28360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    C = PEnd;
28460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return C < End;
28560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
28660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
28760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Skip zero or more whitespace.
28860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  void SkipWhitespace() {
2893f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose    for (; C < End && isWhitespace(*C); ++C)
29060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      ;
29160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
29260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
29360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if EOF reached.
29460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  bool Done() {
29560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return !(C < End);
29660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
29760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
29860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char * const Begin; // beginning of expected content
29960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char * const End;   // end of expected content (1-past)
30060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char *C;            // position of next char in content
30160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char *P;
30260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
30360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerprivate:
30460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char *PEnd; // previous next/search subject end (1-past)
30560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner};
30660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
30760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner} // namespace anonymous
30860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
30960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// ParseDirective - Go through the comment and see if it indicates expected
31060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// diagnostics. If so, then put them in the appropriate directive list.
31160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
31278541c433049322b27b4f437973076ba29cff709Jordan Rose/// Returns true if any valid directives were found.
3137c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rosestatic bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
314b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                           Preprocessor *PP, SourceLocation Pos,
315266dba3661928d26f043560b169bea87578aa917Andy Gibbs                           VerifyDiagnosticConsumer::DirectiveStatus &Status) {
316b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  DiagnosticsEngine &Diags = PP ? PP->getDiagnostics() : SM.getDiagnostics();
317b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
31860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // A single comment may contain multiple directives.
31978541c433049322b27b4f437973076ba29cff709Jordan Rose  bool FoundDirective = false;
32078541c433049322b27b4f437973076ba29cff709Jordan Rose  for (ParseHelper PH(S); !PH.Done();) {
321aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Search for token: expected
3224a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    if (!PH.Search("expected", true))
32360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      break;
32460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
32560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
326aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next token: -
32760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (!PH.Next("-"))
32860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
32960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
33060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
331aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next token: { error | warning | note }
3326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    DirectiveList *DL = nullptr;
33360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (PH.Next("error"))
3346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      DL = ED ? &ED->Errors : nullptr;
33560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    else if (PH.Next("warning"))
3366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      DL = ED ? &ED->Warnings : nullptr;
3376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    else if (PH.Next("remark"))
3386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      DL = ED ? &ED->Remarks : nullptr;
33960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    else if (PH.Next("note"))
3406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      DL = ED ? &ED->Notes : nullptr;
341266dba3661928d26f043560b169bea87578aa917Andy Gibbs    else if (PH.Next("no-diagnostics")) {
342266dba3661928d26f043560b169bea87578aa917Andy Gibbs      if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
343266dba3661928d26f043560b169bea87578aa917Andy Gibbs        Diags.Report(Pos, diag::err_verify_invalid_no_diags)
344266dba3661928d26f043560b169bea87578aa917Andy Gibbs          << /*IsExpectedNoDiagnostics=*/true;
345266dba3661928d26f043560b169bea87578aa917Andy Gibbs      else
346266dba3661928d26f043560b169bea87578aa917Andy Gibbs        Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics;
347266dba3661928d26f043560b169bea87578aa917Andy Gibbs      continue;
348266dba3661928d26f043560b169bea87578aa917Andy Gibbs    } else
34960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
35060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
35181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
352266dba3661928d26f043560b169bea87578aa917Andy Gibbs    if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) {
353266dba3661928d26f043560b169bea87578aa917Andy Gibbs      Diags.Report(Pos, diag::err_verify_invalid_no_diags)
354266dba3661928d26f043560b169bea87578aa917Andy Gibbs        << /*IsExpectedNoDiagnostics=*/false;
355266dba3661928d26f043560b169bea87578aa917Andy Gibbs      continue;
356266dba3661928d26f043560b169bea87578aa917Andy Gibbs    }
357266dba3661928d26f043560b169bea87578aa917Andy Gibbs    Status = VerifyDiagnosticConsumer::HasOtherExpectedDirectives;
358266dba3661928d26f043560b169bea87578aa917Andy Gibbs
3597c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    // If a directive has been found but we're not interested
3607c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    // in storing the directive information, return now.
3617c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    if (!DL)
3627c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      return true;
3637c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
364aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Default directive kind.
36560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    bool RegexKind = false;
36660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    const char* KindStr = "string";
36781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
368aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next optional token: -
36960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (PH.Next("-re")) {
37060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      PH.Advance();
37160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      RegexKind = true;
37260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      KindStr = "regex";
37381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    }
37481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
375aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next optional token: @
376aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    SourceLocation ExpectedLoc;
377ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    bool MatchAnyLine = false;
378aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    if (!PH.Next("@")) {
379aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      ExpectedLoc = Pos;
380aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    } else {
381aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      PH.Advance();
382aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      unsigned Line = 0;
383aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      bool FoundPlus = PH.Next("+");
384aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      if (FoundPlus || PH.Next("-")) {
385aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        // Relative to current line.
386aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        PH.Advance();
387aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        bool Invalid = false;
388aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid);
389aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
390aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          if (FoundPlus) ExpectedLine += Line;
391aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          else ExpectedLine -= Line;
392aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);
393aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        }
394b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      } else if (PH.Next(Line)) {
395aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        // Absolute line number.
396b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (Line > 0)
397aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);
398b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      } else if (PP && PH.Search(":")) {
399b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        // Specific source file.
400b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        StringRef Filename(PH.C, PH.P-PH.C);
401b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        PH.Advance();
402b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
403b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        // Lookup file via Preprocessor, like a #include.
404b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        const DirectoryLookup *CurDir;
4056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        const FileEntry *FE = PP->LookupFile(Pos, Filename, false, nullptr,
4066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                             CurDir, nullptr, nullptr, nullptr);
407b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (!FE) {
408b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
409b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                       diag::err_verify_missing_file) << Filename << KindStr;
410b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          continue;
411b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        }
412b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
413b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (SM.translateFile(FE).isInvalid())
414b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          SM.createFileID(FE, Pos, SrcMgr::C_User);
415b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
416b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (PH.Next(Line) && Line > 0)
417b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
418ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        else if (PH.Next("*")) {
419ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          MatchAnyLine = true;
420ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          ExpectedLoc = SM.translateFileLineCol(FE, 1, 1);
421ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        }
422aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      }
423aa48fe80a1b2000809900a437f0819d929793002Jordan Rose
424aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      if (ExpectedLoc.isInvalid()) {
425aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
426aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                     diag::err_verify_missing_line) << KindStr;
427aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        continue;
428aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      }
429aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      PH.Advance();
430aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    }
431aa48fe80a1b2000809900a437f0819d929793002Jordan Rose
432aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Skip optional whitespace.
43360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.SkipWhitespace();
43460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
435aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next optional token: positive integer or a '+'.
4363b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    unsigned Min = 1;
4373b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    unsigned Max = 1;
4383b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    if (PH.Next(Min)) {
43960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      PH.Advance();
4403b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      // A positive integer can be followed by a '+' meaning min
4413b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      // or more, or by a '-' meaning a range from min to max.
4423b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      if (PH.Next("+")) {
4433b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        Max = Directive::MaxCount;
4443b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        PH.Advance();
4453b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      } else if (PH.Next("-")) {
4463b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        PH.Advance();
4473b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        if (!PH.Next(Max) || Max < Min) {
4483b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose          Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
4493b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose                       diag::err_verify_invalid_range) << KindStr;
4503b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose          continue;
4513b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        }
4523b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        PH.Advance();
4533b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      } else {
4543b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        Max = Min;
4553b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      }
4563b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    } else if (PH.Next("+")) {
4573b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      // '+' on its own means "1 or more".
4583b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      Max = Directive::MaxCount;
4592135ebb83179ee87910afdebc1bc091e17a7d1ebAnna Zaks      PH.Advance();
4602135ebb83179ee87910afdebc1bc091e17a7d1ebAnna Zaks    }
46160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
462aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Skip optional whitespace.
46360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.SkipWhitespace();
46460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
465aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next token: {{
46660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (!PH.Next("{{")) {
4674313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
4684313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose                   diag::err_verify_missing_start) << KindStr;
46960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
47060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
47160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
47260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    const char* const ContentBegin = PH.C; // mark content begin
47381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
474aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Search for token: }}
475651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!PH.SearchClosingBrace("{{", "}}")) {
4764313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
4774313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose                   diag::err_verify_missing_end) << KindStr;
47860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
47960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
48060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    const char* const ContentEnd = PH.P; // mark content end
48160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
48260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
483aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Build directive text; convert \n to newlines.
48460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    std::string Text;
4855f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef NewlineStr = "\\n";
4865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef Content(ContentBegin, ContentEnd-ContentBegin);
48760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    size_t CPos = 0;
48860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    size_t FPos;
4895f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) {
49060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      Text += Content.substr(CPos, FPos-CPos);
49160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      Text += '\n';
49260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      CPos = FPos + NewlineStr.size();
49360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
49460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (Text.empty())
49560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      Text.assign(ContentBegin, ContentEnd);
49660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
497651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Check that regex directives contain at least one regex.
498651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (RegexKind && Text.find("{{") == StringRef::npos) {
499651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin),
500651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                   diag::err_verify_missing_regex) << Text;
501651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
502651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
503651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
504aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Construct new directive.
5056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    std::unique_ptr<Directive> D(
506ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        Directive::create(RegexKind, Pos, ExpectedLoc, MatchAnyLine, Text,
507ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                          Min, Max));
5086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
50960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    std::string Error;
51078541c433049322b27b4f437973076ba29cff709Jordan Rose    if (D->isValid(Error)) {
5116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      DL->push_back(D.release());
51278541c433049322b27b4f437973076ba29cff709Jordan Rose      FoundDirective = true;
51378541c433049322b27b4f437973076ba29cff709Jordan Rose    } else {
5144313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin),
5154313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose                   diag::err_verify_invalid_content)
51660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        << KindStr << Error;
51760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
51881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  }
51978541c433049322b27b4f437973076ba29cff709Jordan Rose
52078541c433049322b27b4f437973076ba29cff709Jordan Rose  return FoundDirective;
52178541c433049322b27b4f437973076ba29cff709Jordan Rose}
52278541c433049322b27b4f437973076ba29cff709Jordan Rose
52378541c433049322b27b4f437973076ba29cff709Jordan Rose/// HandleComment - Hook into the preprocessor and extract comments containing
52478541c433049322b27b4f437973076ba29cff709Jordan Rose///  expected errors and warnings.
52578541c433049322b27b4f437973076ba29cff709Jordan Rosebool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
52678541c433049322b27b4f437973076ba29cff709Jordan Rose                                             SourceRange Comment) {
52778541c433049322b27b4f437973076ba29cff709Jordan Rose  SourceManager &SM = PP.getSourceManager();
528a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor
529a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  // If this comment is for a different source manager, ignore it.
530a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  if (SrcManager && &SM != SrcManager)
531a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor    return false;
532a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor
53378541c433049322b27b4f437973076ba29cff709Jordan Rose  SourceLocation CommentBegin = Comment.getBegin();
53478541c433049322b27b4f437973076ba29cff709Jordan Rose
53578541c433049322b27b4f437973076ba29cff709Jordan Rose  const char *CommentRaw = SM.getCharacterData(CommentBegin);
53678541c433049322b27b4f437973076ba29cff709Jordan Rose  StringRef C(CommentRaw, SM.getCharacterData(Comment.getEnd()) - CommentRaw);
53778541c433049322b27b4f437973076ba29cff709Jordan Rose
53878541c433049322b27b4f437973076ba29cff709Jordan Rose  if (C.empty())
53978541c433049322b27b4f437973076ba29cff709Jordan Rose    return false;
54078541c433049322b27b4f437973076ba29cff709Jordan Rose
54178541c433049322b27b4f437973076ba29cff709Jordan Rose  // Fold any "\<EOL>" sequences
54278541c433049322b27b4f437973076ba29cff709Jordan Rose  size_t loc = C.find('\\');
54378541c433049322b27b4f437973076ba29cff709Jordan Rose  if (loc == StringRef::npos) {
544b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    ParseDirective(C, &ED, SM, &PP, CommentBegin, Status);
54578541c433049322b27b4f437973076ba29cff709Jordan Rose    return false;
54678541c433049322b27b4f437973076ba29cff709Jordan Rose  }
54778541c433049322b27b4f437973076ba29cff709Jordan Rose
54878541c433049322b27b4f437973076ba29cff709Jordan Rose  std::string C2;
54978541c433049322b27b4f437973076ba29cff709Jordan Rose  C2.reserve(C.size());
55078541c433049322b27b4f437973076ba29cff709Jordan Rose
55178541c433049322b27b4f437973076ba29cff709Jordan Rose  for (size_t last = 0;; loc = C.find('\\', last)) {
55278541c433049322b27b4f437973076ba29cff709Jordan Rose    if (loc == StringRef::npos || loc == C.size()) {
55378541c433049322b27b4f437973076ba29cff709Jordan Rose      C2 += C.substr(last);
55478541c433049322b27b4f437973076ba29cff709Jordan Rose      break;
55578541c433049322b27b4f437973076ba29cff709Jordan Rose    }
55678541c433049322b27b4f437973076ba29cff709Jordan Rose    C2 += C.substr(last, loc-last);
55778541c433049322b27b4f437973076ba29cff709Jordan Rose    last = loc + 1;
55878541c433049322b27b4f437973076ba29cff709Jordan Rose
55978541c433049322b27b4f437973076ba29cff709Jordan Rose    if (C[last] == '\n' || C[last] == '\r') {
56078541c433049322b27b4f437973076ba29cff709Jordan Rose      ++last;
56178541c433049322b27b4f437973076ba29cff709Jordan Rose
56278541c433049322b27b4f437973076ba29cff709Jordan Rose      // Escape \r\n  or \n\r, but not \n\n.
56378541c433049322b27b4f437973076ba29cff709Jordan Rose      if (last < C.size())
56478541c433049322b27b4f437973076ba29cff709Jordan Rose        if (C[last] == '\n' || C[last] == '\r')
56578541c433049322b27b4f437973076ba29cff709Jordan Rose          if (C[last] != C[last-1])
56678541c433049322b27b4f437973076ba29cff709Jordan Rose            ++last;
56778541c433049322b27b4f437973076ba29cff709Jordan Rose    } else {
56878541c433049322b27b4f437973076ba29cff709Jordan Rose      // This was just a normal backslash.
56978541c433049322b27b4f437973076ba29cff709Jordan Rose      C2 += '\\';
57078541c433049322b27b4f437973076ba29cff709Jordan Rose    }
57178541c433049322b27b4f437973076ba29cff709Jordan Rose  }
57278541c433049322b27b4f437973076ba29cff709Jordan Rose
57378541c433049322b27b4f437973076ba29cff709Jordan Rose  if (!C2.empty())
574b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status);
57578541c433049322b27b4f437973076ba29cff709Jordan Rose  return false;
57681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
57781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
5787c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
5797c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// \brief Lex the specified source file to determine whether it contains
5807c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// any expected-* directives.  As a Lexer is used rather than a full-blown
5817c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// Preprocessor, directives inside skipped #if blocks will still be found.
5827c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose///
5837c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// \return true if any directives were found.
5847eaaa186d1e9797f424136f565403f7a8b6672faJordan Rosestatic bool findDirectives(SourceManager &SM, FileID FID,
5857eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                           const LangOptions &LangOpts) {
58601231610bc89a8d3ae1bdfee0063af9386fd82a4Axel Naumann  // Create a raw lexer to pull all the comments out of FID.
58701231610bc89a8d3ae1bdfee0063af9386fd82a4Axel Naumann  if (FID.isInvalid())
5887c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    return false;
58981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
59081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Create a lexer to lex all the tokens of the main file in raw mode.
5916e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
5927eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  Lexer RawLex(FID, FromFile, SM, LangOpts);
59381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
59481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Return comments as tokens, this is how we find expected diagnostics.
59581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  RawLex.SetCommentRetentionState(true);
59681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
59781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Token Tok;
59881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Tok.setKind(tok::comment);
599266dba3661928d26f043560b169bea87578aa917Andy Gibbs  VerifyDiagnosticConsumer::DirectiveStatus Status =
600266dba3661928d26f043560b169bea87578aa917Andy Gibbs    VerifyDiagnosticConsumer::HasNoDirectives;
60181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  while (Tok.isNot(tok::eof)) {
602d2f9308220af22bfc1bcd3bc2cad118dbd8be013Eli Friedman    RawLex.LexFromRawLexer(Tok);
60381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    if (!Tok.is(tok::comment)) continue;
60481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
6057eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    std::string Comment = RawLex.getSpelling(Tok, SM, LangOpts);
60681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    if (Comment.empty()) continue;
60781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
6087eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Find first directive.
6096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (ParseDirective(Comment, nullptr, SM, nullptr, Tok.getLocation(),
6106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       Status))
6117eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      return true;
6127c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
6137eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  return false;
61481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
6157c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif // !NDEBUG
61681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
617aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// \brief Takes a list of diagnostics that have been generated but not matched
618aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// by an expected-* directive and produces a diagnostic to the user from this.
619aa48fe80a1b2000809900a437f0819d929793002Jordan Rosestatic unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
620aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                const_diag_iterator diag_begin,
621aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                const_diag_iterator diag_end,
622aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                const char *Kind) {
62381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  if (diag_begin == diag_end) return 0;
62481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
625f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<256> Fmt;
62681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  llvm::raw_svector_ostream OS(Fmt);
62781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
628221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar    if (I->first.isInvalid() || !SourceMgr)
62981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar      OS << "\n  (frontend)";
630b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    else {
631b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      OS << "\n ";
632b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      if (const FileEntry *File = SourceMgr->getFileEntryForID(
633b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                                                SourceMgr->getFileID(I->first)))
634b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        OS << " File " << File->getName();
635b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      OS << " Line " << SourceMgr->getPresumedLineNumber(I->first);
636b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    }
63781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    OS << ": " << I->second;
63881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  }
63981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
640c6d64a26c28bbeee50e06c94c4f4c08e610327b7Jordan Rose  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
641aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    << Kind << /*Unexpected=*/true << OS.str();
64281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  return std::distance(diag_begin, diag_end);
64381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
64481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
645aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// \brief Takes a list of diagnostics that were expected to have been generated
646aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// but were not and produces a diagnostic to the user from this.
647aa48fe80a1b2000809900a437f0819d929793002Jordan Rosestatic unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
648aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                              DirectiveList &DL, const char *Kind) {
64960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  if (DL.empty())
65060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return 0;
65160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
652f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<256> Fmt;
65360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  llvm::raw_svector_ostream OS(Fmt);
65460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
655aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    Directive &D = **I;
656ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    OS << "\n  File " << SourceMgr.getFilename(D.DiagnosticLoc);
657ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (D.MatchAnyLine)
658ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      OS << " Line *";
659ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    else
660ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      OS << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
661aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    if (D.DirectiveLoc != D.DiagnosticLoc)
662aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      OS << " (directive at "
663b42f200777a66b98989160bf3987ce431540a584Andy Gibbs         << SourceMgr.getFilename(D.DirectiveLoc) << ':'
664b42f200777a66b98989160bf3987ce431540a584Andy Gibbs         << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ')';
66560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    OS << ": " << D.Text;
66660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
66760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
668c6d64a26c28bbeee50e06c94c4f4c08e610327b7Jordan Rose  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
669aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    << Kind << /*Unexpected=*/false << OS.str();
67060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  return DL.size();
67160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner}
67260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
673b42f200777a66b98989160bf3987ce431540a584Andy Gibbs/// \brief Determine whether two source locations come from the same file.
674b42f200777a66b98989160bf3987ce431540a584Andy Gibbsstatic bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc,
675b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                           SourceLocation DiagnosticLoc) {
676b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  while (DiagnosticLoc.isMacroID())
677b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    DiagnosticLoc = SM.getImmediateMacroCallerLoc(DiagnosticLoc);
678b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
67924146975f1af8c1b4b14e8545f218129d0e7dfebEli Friedman  if (SM.isWrittenInSameFile(DirectiveLoc, DiagnosticLoc))
680b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    return true;
681b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
682b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  const FileEntry *DiagFile = SM.getFileEntryForID(SM.getFileID(DiagnosticLoc));
68324146975f1af8c1b4b14e8545f218129d0e7dfebEli Friedman  if (!DiagFile && SM.isWrittenInMainFile(DirectiveLoc))
684b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    return true;
685b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
686b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  return (DiagFile == SM.getFileEntryForID(SM.getFileID(DirectiveLoc)));
687b42f200777a66b98989160bf3987ce431540a584Andy Gibbs}
688b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
68960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// CheckLists - Compare expected to seen diagnostic lists and return the
69060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// the difference between them.
69181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
692d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiestatic unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
69360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           const char *Label,
69460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           DirectiveList &Left,
69560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           const_diag_iterator d2_begin,
69660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           const_diag_iterator d2_end) {
69760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  DirectiveList LeftOnly;
69881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  DiagList Right(d2_begin, d2_end);
69981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
70060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
70160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    Directive& D = **I;
702aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
70381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
7043b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    for (unsigned i = 0; i < D.Max; ++i) {
70560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      DiagList::iterator II, IE;
70660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
707ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        if (!D.MatchAnyLine) {
708ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
709ef8225444452a1486bd721f3285301fe84643b00Stephen Hines          if (LineNo1 != LineNo2)
710ef8225444452a1486bd721f3285301fe84643b00Stephen Hines            continue;
711ef8225444452a1486bd721f3285301fe84643b00Stephen Hines        }
71281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
713b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
714b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          continue;
715b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
71660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        const std::string &RightText = II->second;
7174313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose        if (D.match(RightText))
71860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner          break;
71960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      }
72060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      if (II == IE) {
72160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        // Not found.
7223b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        if (i >= D.Min) break;
72360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        LeftOnly.push_back(*I);
72460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      } else {
72560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        // Found. The same cannot be found twice.
72660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        Right.erase(II);
72781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar      }
72881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    }
72981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  }
73081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Now all that's left in Right are those that were not matched.
731aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label);
732aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);
733ad646846f7033d3ee813998bb0bc028aee51e65eNAKAMURA Takumi  return num;
73481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
73581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
73681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// CheckResults - This compares the expected results to those that
73781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// were actually reported. It emits any discrepencies. Return "true" if there
73881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// were problems. Return "false" otherwise.
73981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
740d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiestatic unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
74181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar                             const TextDiagnosticBuffer &Buffer,
74260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                             ExpectedData &ED) {
74381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // We want to capture the delta between what was expected and what was
74481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // seen.
74581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  //
74681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  //   Expected \ Seen - set expected but not seen
74781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  //   Seen \ Expected - set seen but not expected
74881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  unsigned NumProblems = 0;
74981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
75081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // See if there are error mismatches.
75160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors,
75260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                            Buffer.err_begin(), Buffer.err_end());
753221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar
75481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // See if there are warning mismatches.
75560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings,
75660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                            Buffer.warn_begin(), Buffer.warn_end());
75781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
7586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // See if there are remark mismatches.
7596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  NumProblems += CheckLists(Diags, SourceMgr, "remark", ED.Remarks,
7606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                            Buffer.remark_begin(), Buffer.remark_end());
7616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
76281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // See if there are note mismatches.
76360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes,
76460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                            Buffer.note_begin(), Buffer.note_end());
76581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
76681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  return NumProblems;
76781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
76881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
7697eaaa186d1e9797f424136f565403f7a8b6672faJordan Rosevoid VerifyDiagnosticConsumer::UpdateParsedFileStatus(SourceManager &SM,
7707eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                                      FileID FID,
7717eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                                      ParsedStatus PS) {
7727eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // Check SourceManager hasn't changed.
7737eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  setSourceManager(SM);
7747eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7757eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose#ifndef NDEBUG
7767eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (FID.isInvalid())
7777eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    return;
7787eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7797eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  const FileEntry *FE = SM.getFileEntryForID(FID);
7807eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7817eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (PS == IsParsed) {
7827eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Move the FileID from the unparsed set to the parsed set.
7837eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    UnparsedFiles.erase(FID);
7847eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    ParsedFiles.insert(std::make_pair(FID, FE));
7857eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  } else if (!ParsedFiles.count(FID) && !UnparsedFiles.count(FID)) {
7867eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Add the FileID to the unparsed set if we haven't seen it before.
7877eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7887eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Check for directives.
7897eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    bool FoundDirectives;
7907eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    if (PS == IsUnparsedNoDirectives)
7917eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      FoundDirectives = false;
7927eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    else
7937eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      FoundDirectives = !LangOpts || findDirectives(SM, FID, *LangOpts);
7947eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7957eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Add the FileID to the unparsed set.
7967eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    UnparsedFiles.insert(std::make_pair(FID,
7977eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                      UnparsedFileStatus(FE, FoundDirectives)));
7987eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  }
7997eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose#endif
8007eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose}
8017eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
802621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::CheckDiagnostics() {
80381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Ensure any diagnostics go to the primary client.
80478243658c533168d51fd076fba328437932ba6f1Douglas Gregor  bool OwnsCurClient = Diags.ownsClient();
80578ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie  DiagnosticConsumer *CurClient = Diags.takeClient();
80678243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.setClient(PrimaryClient, false);
80781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
8087c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
8097eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // In a debug build, scan through any files that may have been missed
8107eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // during parsing and issue a fatal error if directives are contained
8117eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // within these files.  If a fatal error occurs, this suggests that
8127eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // this file is being parsed separately from the main file, in which
8137eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // case consider moving the directives to the correct place, if this
8147eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // is applicable.
8157eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (UnparsedFiles.size() > 0) {
8167eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Generate a cache of parsed FileEntry pointers for alias lookups.
8177eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache;
8187eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    for (ParsedFilesMap::iterator I = ParsedFiles.begin(),
8197eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                End = ParsedFiles.end(); I != End; ++I) {
8207eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (const FileEntry *FE = I->second)
8217eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        ParsedFileCache.insert(FE);
8227eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    }
8237eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
8247eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Iterate through list of unparsed files.
8257eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    for (UnparsedFilesMap::iterator I = UnparsedFiles.begin(),
8267eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                  End = UnparsedFiles.end(); I != End; ++I) {
8277eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      const UnparsedFileStatus &Status = I->second;
8287eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      const FileEntry *FE = Status.getFile();
8297eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
8307eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      // Skip files that have been parsed via an alias.
8317eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (FE && ParsedFileCache.count(FE))
8327c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose        continue;
8337c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
8347eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      // Report a fatal error if this file contained directives.
8357eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (Status.foundDirectives()) {
8367c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose        llvm::report_fatal_error(Twine("-verify directives found after rather"
8377c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose                                       " than during normal parsing of ",
8387eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                 StringRef(FE ? FE->getName() : "(unknown)")));
8397eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      }
84084c05e3b873a95c8c8d64fa8083407bcf395383fAxel Naumann    }
84181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
8427eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // UnparsedFiles has been processed now, so clear it.
8437eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    UnparsedFiles.clear();
8447eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  }
8457eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose#endif // !NDEBUG
8467eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
8477eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (SrcManager) {
848266dba3661928d26f043560b169bea87578aa917Andy Gibbs    // Produce an error if no expected-* directives could be found in the
849266dba3661928d26f043560b169bea87578aa917Andy Gibbs    // source file(s) processed.
850266dba3661928d26f043560b169bea87578aa917Andy Gibbs    if (Status == HasNoDirectives) {
851266dba3661928d26f043560b169bea87578aa917Andy Gibbs      Diags.Report(diag::err_verify_no_directives).setForceEmit();
852266dba3661928d26f043560b169bea87578aa917Andy Gibbs      ++NumErrors;
853266dba3661928d26f043560b169bea87578aa917Andy Gibbs      Status = HasNoDirectivesReported;
854266dba3661928d26f043560b169bea87578aa917Andy Gibbs    }
855266dba3661928d26f043560b169bea87578aa917Andy Gibbs
856221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar    // Check that the expected diagnostics occurred.
8577eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
858221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar  } else {
8596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    NumErrors += (PrintUnexpected(Diags, nullptr, Buffer->err_begin(),
860aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                  Buffer->err_end(), "error") +
8616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                  PrintUnexpected(Diags, nullptr, Buffer->warn_begin(),
862aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                  Buffer->warn_end(), "warn") +
8636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                  PrintUnexpected(Diags, nullptr, Buffer->note_begin(),
864aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                  Buffer->note_end(), "note"));
865221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar  }
86681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
867bdbb004f38978da0c4a75af3294d1c7b5ff84af1Douglas Gregor  Diags.takeClient();
86878243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.setClient(CurClient, OwnsCurClient);
86981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
87081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Reset the buffer, we have processed all the diagnostics in it.
87181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Buffer.reset(new TextDiagnosticBuffer());
8726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  ED.Reset();
87381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
87460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
875aa48fe80a1b2000809900a437f0819d929793002Jordan RoseDirective *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
876ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                             SourceLocation DiagnosticLoc, bool MatchAnyLine,
877ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                             StringRef Text, unsigned Min, unsigned Max) {
878651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!RegexKind)
879ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    return new StandardDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine,
880ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                                 Text, Min, Max);
881651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
882651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Parse the directive into a regular expression.
883651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::string RegexStr;
884651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StringRef S = Text;
885651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  while (!S.empty()) {
886651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (S.startswith("{{")) {
887651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      S = S.drop_front(2);
888651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      size_t RegexMatchLength = S.find("}}");
889651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      assert(RegexMatchLength != StringRef::npos);
890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Append the regex, enclosed in parentheses.
891651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RegexStr += "(";
892651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RegexStr.append(S.data(), RegexMatchLength);
893651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RegexStr += ")";
894651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      S = S.drop_front(RegexMatchLength + 2);
895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    } else {
896651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      size_t VerbatimMatchLength = S.find("{{");
897651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (VerbatimMatchLength == StringRef::npos)
898651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        VerbatimMatchLength = S.size();
899651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Escape and append the fixed string.
900651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      RegexStr += llvm::Regex::escape(S.substr(0, VerbatimMatchLength));
901651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      S = S.drop_front(VerbatimMatchLength);
902651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
903651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
904651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
905ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  return new RegexDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text,
906ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                            Min, Max, RegexStr);
90760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner}
908