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()),
337c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(0),
34266dba3661928d26f043560b169bea87578aa917Andy Gibbs    LangOpts(0), SrcManager(0), ActiveSourceFiles(0), Status(HasNoDirectives)
3578243658c533168d51fd076fba328437932ba6f1Douglas Gregor{
3678243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.takeClient();
377eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (Diags.hasSourceManager())
387eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    setSourceManager(Diags.getSourceManager());
3981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
4081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
41621bc69624599da62abd9bc9e5edd8a63ac99fe6David BlaikieVerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
427c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert(!ActiveSourceFiles && "Incomplete parsing of source files!");
437c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
447eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  SrcManager = 0;
4578243658c533168d51fd076fba328437932ba6f1Douglas Gregor  CheckDiagnostics();
4678243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.takeClient();
4778243658c533168d51fd076fba328437932ba6f1Douglas Gregor  if (OwnsPrimaryClient)
4878243658c533168d51fd076fba328437932ba6f1Douglas Gregor    delete PrimaryClient;
4981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
5081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
517c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
527c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rosenamespace {
537c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Roseclass VerifyFileTracker : public PPCallbacks {
547eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  VerifyDiagnosticConsumer &Verify;
557c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  SourceManager &SM;
567c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
577c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rosepublic:
587eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM)
597eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    : Verify(Verify), SM(SM) { }
607c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
617c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  /// \brief Hook into the preprocessor and update the list of parsed
627c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  /// files when the preprocessor indicates a new file is entered.
637c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
647c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose                           SrcMgr::CharacteristicKind FileType,
657c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose                           FileID PrevFID) {
667eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    Verify.UpdateParsedFileStatus(SM, SM.getFileID(Loc),
677eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                  VerifyDiagnosticConsumer::IsParsed);
687c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
697c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose};
707c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose} // End anonymous namespace.
717c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif
727c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
7378ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie// DiagnosticConsumer interface.
7481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
75621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
761f6b2b5c82b2d2d3935b0db76352a04e9877b73fDouglas Gregor                                               const Preprocessor *PP) {
777c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  // Attach comment handler on first invocation.
787c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  if (++ActiveSourceFiles == 1) {
797c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    if (PP) {
807c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      CurrentPreprocessor = PP;
817eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      this->LangOpts = &LangOpts;
827eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      setSourceManager(PP->getSourceManager());
837c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      const_cast<Preprocessor*>(PP)->addCommentHandler(this);
847c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
857eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      // Debug build tracks parsed files.
867eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      VerifyFileTracker *V = new VerifyFileTracker(*this, *SrcManager);
877c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      const_cast<Preprocessor*>(PP)->addPPCallbacks(V);
887c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif
897c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    }
907c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
9181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
927c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!");
9381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  PrimaryClient->BeginSourceFile(LangOpts, PP);
9481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
9581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
96621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::EndSourceFile() {
977c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  assert(ActiveSourceFiles && "No active source files!");
9881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  PrimaryClient->EndSourceFile();
9981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
1007c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  // Detach comment handler once last active source file completed.
1017c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  if (--ActiveSourceFiles == 0) {
1027c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    if (CurrentPreprocessor)
1037c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this);
1047c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
1057c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    // Check diagnostics once last file completed.
1067c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    CheckDiagnostics();
1077c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    CurrentPreprocessor = 0;
1087eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    LangOpts = 0;
1097c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
11081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
111221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar
112621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::HandleDiagnostic(
11340847cfb58acc3cac7d68727df9455ac45f2e118David Blaikie      DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) {
114a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  if (Info.hasSourceManager()) {
115a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor    // If this diagnostic is for a different source manager, ignore it.
116a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor    if (SrcManager && &Info.getSourceManager() != SrcManager)
117a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor      return;
118a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor
1197eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    setSourceManager(Info.getSourceManager());
120a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  }
1217eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1227c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
1237eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // Debug build tracks unparsed files for possible
1247eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // unparsed expected-* directives.
1257eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (SrcManager) {
1267eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    SourceLocation Loc = Info.getLocation();
1277eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    if (Loc.isValid()) {
1287eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      ParsedStatus PS = IsUnparsed;
1297eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1307eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      Loc = SrcManager->getExpansionLoc(Loc);
1317eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      FileID FID = SrcManager->getFileID(Loc);
1327eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1337eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      const FileEntry *FE = SrcManager->getFileEntryForID(FID);
1347eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (FE && CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) {
1357eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        // If the file is a modules header file it shall not be parsed
1367eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        // for expected-* directives.
1377eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo();
1387eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        if (HS.findModuleForHeader(FE))
1397eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose          PS = IsUnparsedNoDirectives;
1407eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      }
1417eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
1427eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      UpdateParsedFileStatus(*SrcManager, FID, PS);
1437eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    }
14401231610bc89a8d3ae1bdfee0063af9386fd82a4Axel Naumann  }
1457c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif
1467eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
14781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Send the diagnostic to the buffer, we will check it once we reach the end
14881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // of the source file (or are destructed).
14981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Buffer->HandleDiagnostic(DiagLevel, Info);
15081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
15181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
15281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//===----------------------------------------------------------------------===//
15381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar// Checking diagnostics implementation.
15481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar//===----------------------------------------------------------------------===//
15581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
15681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbartypedef TextDiagnosticBuffer::DiagList DiagList;
15781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbartypedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
15881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
15960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnernamespace {
16060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
16160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// StandardDirective - Directive with string matching.
16260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
16360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerclass StandardDirective : public Directive {
16460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerpublic:
165aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
1663b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose                    StringRef Text, unsigned Min, unsigned Max)
1673b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max) { }
16860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
16960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  virtual bool isValid(std::string &Error) {
17060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    // all strings are considered valid; even empty ones
17160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return true;
17260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
17360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
1744313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  virtual bool match(StringRef S) {
1754313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose    return S.find(Text) != StringRef::npos;
17660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
17760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner};
17860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
17960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// RegexDirective - Directive with regular-expression matching.
18060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
18160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerclass RegexDirective : public Directive {
18260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerpublic:
183aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
1843b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose                 StringRef Text, unsigned Min, unsigned Max)
1853b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    : Directive(DirectiveLoc, DiagnosticLoc, Text, Min, Max), Regex(Text) { }
18660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
18760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  virtual bool isValid(std::string &Error) {
18860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (Regex.isValid(Error))
18960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      return true;
19060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return false;
19160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
19260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
1934313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose  virtual bool match(StringRef S) {
19460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return Regex.match(S);
19560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
19681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
19760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerprivate:
19860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  llvm::Regex Regex;
19960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner};
20060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
20160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerclass ParseHelper
20260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner{
20360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerpublic:
20478541c433049322b27b4f437973076ba29cff709Jordan Rose  ParseHelper(StringRef S)
20578541c433049322b27b4f437973076ba29cff709Jordan Rose    : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(NULL) { }
20660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
20760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if string literal is next.
2085f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  bool Next(StringRef S) {
20960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    P = C;
2100080f0ca30cd35e59347d632a261951f01a8129eBenjamin Kramer    PEnd = C + S.size();
21160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (PEnd > End)
21260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      return false;
2130080f0ca30cd35e59347d632a261951f01a8129eBenjamin Kramer    return !memcmp(P, S.data(), S.size());
21460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
21560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
21660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if number is next.
21760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Output N only if number is next.
21860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  bool Next(unsigned &N) {
21960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    unsigned TMP = 0;
22060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    P = C;
22160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    for (; P < End && P[0] >= '0' && P[0] <= '9'; ++P) {
22260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      TMP *= 10;
22360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      TMP += P[0] - '0';
22481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    }
22560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (P == C)
22660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      return false;
22760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PEnd = P;
22860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    N = TMP;
22960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return true;
23060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
23160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
23260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if string literal is found.
23360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // When true, P marks begin-position of S in content.
2344a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs  bool Search(StringRef S, bool EnsureStartOfWord = false) {
2354a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    do {
2364a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      P = std::search(C, End, S.begin(), S.end());
2374a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      PEnd = P + S.size();
2384a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      if (P == End)
2394a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs        break;
2404a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      if (!EnsureStartOfWord
2414a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs            // Check if string literal starts a new word.
2423f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose            || P == Begin || isWhitespace(P[-1])
2434a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs            // Or it could be preceeded by the start of a comment.
2444a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs            || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
2454a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs                                &&  P[-2] == '/'))
2464a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs        return true;
2474a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs      // Otherwise, skip and search again.
2484a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    } while (Advance());
2494a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    return false;
25060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
25160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
25260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Advance 1-past previous next/search.
25360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Behavior is undefined if previous next/search failed.
25460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  bool Advance() {
25560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    C = PEnd;
25660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return C < End;
25760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
25860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
25960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Skip zero or more whitespace.
26060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  void SkipWhitespace() {
2613f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose    for (; C < End && isWhitespace(*C); ++C)
26260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      ;
26360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
26460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
26560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // Return true if EOF reached.
26660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  bool Done() {
26760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return !(C < End);
26860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
26960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
27060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char * const Begin; // beginning of expected content
27160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char * const End;   // end of expected content (1-past)
27260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char *C;            // position of next char in content
27360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char *P;
27460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
27560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattnerprivate:
27660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  const char *PEnd; // previous next/search subject end (1-past)
27760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner};
27860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
27960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner} // namespace anonymous
28060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
28160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// ParseDirective - Go through the comment and see if it indicates expected
28260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// diagnostics. If so, then put them in the appropriate directive list.
28360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner///
28478541c433049322b27b4f437973076ba29cff709Jordan Rose/// Returns true if any valid directives were found.
2857c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rosestatic bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
286b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                           Preprocessor *PP, SourceLocation Pos,
287266dba3661928d26f043560b169bea87578aa917Andy Gibbs                           VerifyDiagnosticConsumer::DirectiveStatus &Status) {
288b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  DiagnosticsEngine &Diags = PP ? PP->getDiagnostics() : SM.getDiagnostics();
289b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
29060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  // A single comment may contain multiple directives.
29178541c433049322b27b4f437973076ba29cff709Jordan Rose  bool FoundDirective = false;
29278541c433049322b27b4f437973076ba29cff709Jordan Rose  for (ParseHelper PH(S); !PH.Done();) {
293aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Search for token: expected
2944a529d26d6ccfc9b3d11031f1256f4f87055c562Andy Gibbs    if (!PH.Search("expected", true))
29560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      break;
29660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
29760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
298aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next token: -
29960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (!PH.Next("-"))
30060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
30160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
30260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
303aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next token: { error | warning | note }
30460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    DirectiveList* DL = NULL;
30560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (PH.Next("error"))
3067c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      DL = ED ? &ED->Errors : NULL;
30760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    else if (PH.Next("warning"))
3087c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      DL = ED ? &ED->Warnings : NULL;
30960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    else if (PH.Next("note"))
3107c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      DL = ED ? &ED->Notes : NULL;
311266dba3661928d26f043560b169bea87578aa917Andy Gibbs    else if (PH.Next("no-diagnostics")) {
312266dba3661928d26f043560b169bea87578aa917Andy Gibbs      if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
313266dba3661928d26f043560b169bea87578aa917Andy Gibbs        Diags.Report(Pos, diag::err_verify_invalid_no_diags)
314266dba3661928d26f043560b169bea87578aa917Andy Gibbs          << /*IsExpectedNoDiagnostics=*/true;
315266dba3661928d26f043560b169bea87578aa917Andy Gibbs      else
316266dba3661928d26f043560b169bea87578aa917Andy Gibbs        Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics;
317266dba3661928d26f043560b169bea87578aa917Andy Gibbs      continue;
318266dba3661928d26f043560b169bea87578aa917Andy Gibbs    } else
31960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
32060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
32181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
322266dba3661928d26f043560b169bea87578aa917Andy Gibbs    if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) {
323266dba3661928d26f043560b169bea87578aa917Andy Gibbs      Diags.Report(Pos, diag::err_verify_invalid_no_diags)
324266dba3661928d26f043560b169bea87578aa917Andy Gibbs        << /*IsExpectedNoDiagnostics=*/false;
325266dba3661928d26f043560b169bea87578aa917Andy Gibbs      continue;
326266dba3661928d26f043560b169bea87578aa917Andy Gibbs    }
327266dba3661928d26f043560b169bea87578aa917Andy Gibbs    Status = VerifyDiagnosticConsumer::HasOtherExpectedDirectives;
328266dba3661928d26f043560b169bea87578aa917Andy Gibbs
3297c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    // If a directive has been found but we're not interested
3307c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    // in storing the directive information, return now.
3317c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    if (!DL)
3327c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose      return true;
3337c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
334aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Default directive kind.
33560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    bool RegexKind = false;
33660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    const char* KindStr = "string";
33781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
338aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next optional token: -
33960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (PH.Next("-re")) {
34060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      PH.Advance();
34160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      RegexKind = true;
34260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      KindStr = "regex";
34381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    }
34481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
345aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next optional token: @
346aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    SourceLocation ExpectedLoc;
347aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    if (!PH.Next("@")) {
348aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      ExpectedLoc = Pos;
349aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    } else {
350aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      PH.Advance();
351aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      unsigned Line = 0;
352aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      bool FoundPlus = PH.Next("+");
353aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      if (FoundPlus || PH.Next("-")) {
354aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        // Relative to current line.
355aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        PH.Advance();
356aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        bool Invalid = false;
357aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid);
358aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
359aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          if (FoundPlus) ExpectedLine += Line;
360aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          else ExpectedLine -= Line;
361aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1);
362aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        }
363b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      } else if (PH.Next(Line)) {
364aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        // Absolute line number.
365b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (Line > 0)
366aa48fe80a1b2000809900a437f0819d929793002Jordan Rose          ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1);
367b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      } else if (PP && PH.Search(":")) {
368b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        // Specific source file.
369b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        StringRef Filename(PH.C, PH.P-PH.C);
370b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        PH.Advance();
371b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
372b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        // Lookup file via Preprocessor, like a #include.
373b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        const DirectoryLookup *CurDir;
374bc3f628815b3841dc99109e7f67f9afa7793bc94Lawrence Crowl        const FileEntry *FE = PP->LookupFile(Pos, Filename, false, NULL, CurDir,
375b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                                             NULL, NULL, 0);
376b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (!FE) {
377b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
378b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                       diag::err_verify_missing_file) << Filename << KindStr;
379b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          continue;
380b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        }
381b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
382b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (SM.translateFile(FE).isInvalid())
383b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          SM.createFileID(FE, Pos, SrcMgr::C_User);
384b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
385b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (PH.Next(Line) && Line > 0)
386b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          ExpectedLoc = SM.translateFileLineCol(FE, Line, 1);
387aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      }
388aa48fe80a1b2000809900a437f0819d929793002Jordan Rose
389aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      if (ExpectedLoc.isInvalid()) {
390aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
391aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                     diag::err_verify_missing_line) << KindStr;
392aa48fe80a1b2000809900a437f0819d929793002Jordan Rose        continue;
393aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      }
394aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      PH.Advance();
395aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    }
396aa48fe80a1b2000809900a437f0819d929793002Jordan Rose
397aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Skip optional whitespace.
39860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.SkipWhitespace();
39960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
400aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next optional token: positive integer or a '+'.
4013b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    unsigned Min = 1;
4023b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    unsigned Max = 1;
4033b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    if (PH.Next(Min)) {
40460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      PH.Advance();
4053b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      // A positive integer can be followed by a '+' meaning min
4063b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      // or more, or by a '-' meaning a range from min to max.
4073b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      if (PH.Next("+")) {
4083b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        Max = Directive::MaxCount;
4093b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        PH.Advance();
4103b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      } else if (PH.Next("-")) {
4113b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        PH.Advance();
4123b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        if (!PH.Next(Max) || Max < Min) {
4133b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose          Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
4143b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose                       diag::err_verify_invalid_range) << KindStr;
4153b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose          continue;
4163b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        }
4173b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        PH.Advance();
4183b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      } else {
4193b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        Max = Min;
4203b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      }
4213b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    } else if (PH.Next("+")) {
4223b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      // '+' on its own means "1 or more".
4233b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose      Max = Directive::MaxCount;
4242135ebb83179ee87910afdebc1bc091e17a7d1ebAnna Zaks      PH.Advance();
4252135ebb83179ee87910afdebc1bc091e17a7d1ebAnna Zaks    }
42660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
427aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Skip optional whitespace.
42860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.SkipWhitespace();
42960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
430aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Next token: {{
43160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (!PH.Next("{{")) {
4324313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
4334313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose                   diag::err_verify_missing_start) << KindStr;
43460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
43560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
43660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
43760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    const char* const ContentBegin = PH.C; // mark content begin
43881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
439aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Search for token: }}
44060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (!PH.Search("}}")) {
4414313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
4424313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose                   diag::err_verify_missing_end) << KindStr;
44360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      continue;
44460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
44560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    const char* const ContentEnd = PH.P; // mark content end
44660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    PH.Advance();
44760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
448aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Build directive text; convert \n to newlines.
44960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    std::string Text;
4505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef NewlineStr = "\\n";
4515f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    StringRef Content(ContentBegin, ContentEnd-ContentBegin);
45260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    size_t CPos = 0;
45360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    size_t FPos;
4545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) {
45560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      Text += Content.substr(CPos, FPos-CPos);
45660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      Text += '\n';
45760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      CPos = FPos + NewlineStr.size();
45860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
45960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    if (Text.empty())
46060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      Text.assign(ContentBegin, ContentEnd);
46160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
462aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    // Construct new directive.
4633b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text,
4643b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose                                     Min, Max);
46560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    std::string Error;
46678541c433049322b27b4f437973076ba29cff709Jordan Rose    if (D->isValid(Error)) {
46760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      DL->push_back(D);
46878541c433049322b27b4f437973076ba29cff709Jordan Rose      FoundDirective = true;
46978541c433049322b27b4f437973076ba29cff709Jordan Rose    } else {
4704313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose      Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin),
4714313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose                   diag::err_verify_invalid_content)
47260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        << KindStr << Error;
47360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    }
47481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  }
47578541c433049322b27b4f437973076ba29cff709Jordan Rose
47678541c433049322b27b4f437973076ba29cff709Jordan Rose  return FoundDirective;
47778541c433049322b27b4f437973076ba29cff709Jordan Rose}
47878541c433049322b27b4f437973076ba29cff709Jordan Rose
47978541c433049322b27b4f437973076ba29cff709Jordan Rose/// HandleComment - Hook into the preprocessor and extract comments containing
48078541c433049322b27b4f437973076ba29cff709Jordan Rose///  expected errors and warnings.
48178541c433049322b27b4f437973076ba29cff709Jordan Rosebool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP,
48278541c433049322b27b4f437973076ba29cff709Jordan Rose                                             SourceRange Comment) {
48378541c433049322b27b4f437973076ba29cff709Jordan Rose  SourceManager &SM = PP.getSourceManager();
484a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor
485a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  // If this comment is for a different source manager, ignore it.
486a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor  if (SrcManager && &SM != SrcManager)
487a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor    return false;
488a4a90cabfa15c900016a7cfaea51a6d4e8ebf4dbDouglas Gregor
48978541c433049322b27b4f437973076ba29cff709Jordan Rose  SourceLocation CommentBegin = Comment.getBegin();
49078541c433049322b27b4f437973076ba29cff709Jordan Rose
49178541c433049322b27b4f437973076ba29cff709Jordan Rose  const char *CommentRaw = SM.getCharacterData(CommentBegin);
49278541c433049322b27b4f437973076ba29cff709Jordan Rose  StringRef C(CommentRaw, SM.getCharacterData(Comment.getEnd()) - CommentRaw);
49378541c433049322b27b4f437973076ba29cff709Jordan Rose
49478541c433049322b27b4f437973076ba29cff709Jordan Rose  if (C.empty())
49578541c433049322b27b4f437973076ba29cff709Jordan Rose    return false;
49678541c433049322b27b4f437973076ba29cff709Jordan Rose
49778541c433049322b27b4f437973076ba29cff709Jordan Rose  // Fold any "\<EOL>" sequences
49878541c433049322b27b4f437973076ba29cff709Jordan Rose  size_t loc = C.find('\\');
49978541c433049322b27b4f437973076ba29cff709Jordan Rose  if (loc == StringRef::npos) {
500b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    ParseDirective(C, &ED, SM, &PP, CommentBegin, Status);
50178541c433049322b27b4f437973076ba29cff709Jordan Rose    return false;
50278541c433049322b27b4f437973076ba29cff709Jordan Rose  }
50378541c433049322b27b4f437973076ba29cff709Jordan Rose
50478541c433049322b27b4f437973076ba29cff709Jordan Rose  std::string C2;
50578541c433049322b27b4f437973076ba29cff709Jordan Rose  C2.reserve(C.size());
50678541c433049322b27b4f437973076ba29cff709Jordan Rose
50778541c433049322b27b4f437973076ba29cff709Jordan Rose  for (size_t last = 0;; loc = C.find('\\', last)) {
50878541c433049322b27b4f437973076ba29cff709Jordan Rose    if (loc == StringRef::npos || loc == C.size()) {
50978541c433049322b27b4f437973076ba29cff709Jordan Rose      C2 += C.substr(last);
51078541c433049322b27b4f437973076ba29cff709Jordan Rose      break;
51178541c433049322b27b4f437973076ba29cff709Jordan Rose    }
51278541c433049322b27b4f437973076ba29cff709Jordan Rose    C2 += C.substr(last, loc-last);
51378541c433049322b27b4f437973076ba29cff709Jordan Rose    last = loc + 1;
51478541c433049322b27b4f437973076ba29cff709Jordan Rose
51578541c433049322b27b4f437973076ba29cff709Jordan Rose    if (C[last] == '\n' || C[last] == '\r') {
51678541c433049322b27b4f437973076ba29cff709Jordan Rose      ++last;
51778541c433049322b27b4f437973076ba29cff709Jordan Rose
51878541c433049322b27b4f437973076ba29cff709Jordan Rose      // Escape \r\n  or \n\r, but not \n\n.
51978541c433049322b27b4f437973076ba29cff709Jordan Rose      if (last < C.size())
52078541c433049322b27b4f437973076ba29cff709Jordan Rose        if (C[last] == '\n' || C[last] == '\r')
52178541c433049322b27b4f437973076ba29cff709Jordan Rose          if (C[last] != C[last-1])
52278541c433049322b27b4f437973076ba29cff709Jordan Rose            ++last;
52378541c433049322b27b4f437973076ba29cff709Jordan Rose    } else {
52478541c433049322b27b4f437973076ba29cff709Jordan Rose      // This was just a normal backslash.
52578541c433049322b27b4f437973076ba29cff709Jordan Rose      C2 += '\\';
52678541c433049322b27b4f437973076ba29cff709Jordan Rose    }
52778541c433049322b27b4f437973076ba29cff709Jordan Rose  }
52878541c433049322b27b4f437973076ba29cff709Jordan Rose
52978541c433049322b27b4f437973076ba29cff709Jordan Rose  if (!C2.empty())
530b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status);
53178541c433049322b27b4f437973076ba29cff709Jordan Rose  return false;
53281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
53381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
5347c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
5357c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// \brief Lex the specified source file to determine whether it contains
5367c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// any expected-* directives.  As a Lexer is used rather than a full-blown
5377c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// Preprocessor, directives inside skipped #if blocks will still be found.
5387c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose///
5397c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose/// \return true if any directives were found.
5407eaaa186d1e9797f424136f565403f7a8b6672faJordan Rosestatic bool findDirectives(SourceManager &SM, FileID FID,
5417eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                           const LangOptions &LangOpts) {
54201231610bc89a8d3ae1bdfee0063af9386fd82a4Axel Naumann  // Create a raw lexer to pull all the comments out of FID.
54301231610bc89a8d3ae1bdfee0063af9386fd82a4Axel Naumann  if (FID.isInvalid())
5447c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose    return false;
54581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
54681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Create a lexer to lex all the tokens of the main file in raw mode.
5476e2901407bff59aeb4cc301cc58b034723d0eb49Chris Lattner  const llvm::MemoryBuffer *FromFile = SM.getBuffer(FID);
5487eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  Lexer RawLex(FID, FromFile, SM, LangOpts);
54981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
55081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Return comments as tokens, this is how we find expected diagnostics.
55181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  RawLex.SetCommentRetentionState(true);
55281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
55381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Token Tok;
55481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Tok.setKind(tok::comment);
555266dba3661928d26f043560b169bea87578aa917Andy Gibbs  VerifyDiagnosticConsumer::DirectiveStatus Status =
556266dba3661928d26f043560b169bea87578aa917Andy Gibbs    VerifyDiagnosticConsumer::HasNoDirectives;
55781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  while (Tok.isNot(tok::eof)) {
55881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    RawLex.Lex(Tok);
55981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    if (!Tok.is(tok::comment)) continue;
56081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
5617eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    std::string Comment = RawLex.getSpelling(Tok, SM, LangOpts);
56281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    if (Comment.empty()) continue;
56381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
5647eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Find first directive.
565b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    if (ParseDirective(Comment, 0, SM, 0, Tok.getLocation(), Status))
5667eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      return true;
5677c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose  }
5687eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  return false;
56981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
5707c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#endif // !NDEBUG
57181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
572aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// \brief Takes a list of diagnostics that have been generated but not matched
573aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// by an expected-* directive and produces a diagnostic to the user from this.
574aa48fe80a1b2000809900a437f0819d929793002Jordan Rosestatic unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr,
575aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                const_diag_iterator diag_begin,
576aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                const_diag_iterator diag_end,
577aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                const char *Kind) {
57881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  if (diag_begin == diag_end) return 0;
57981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
580f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<256> Fmt;
58181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  llvm::raw_svector_ostream OS(Fmt);
58281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I) {
583221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar    if (I->first.isInvalid() || !SourceMgr)
58481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar      OS << "\n  (frontend)";
585b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    else {
586b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      OS << "\n ";
587b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      if (const FileEntry *File = SourceMgr->getFileEntryForID(
588b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                                                SourceMgr->getFileID(I->first)))
589b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        OS << " File " << File->getName();
590b42f200777a66b98989160bf3987ce431540a584Andy Gibbs      OS << " Line " << SourceMgr->getPresumedLineNumber(I->first);
591b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    }
59281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    OS << ": " << I->second;
59381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  }
59481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
595c6d64a26c28bbeee50e06c94c4f4c08e610327b7Jordan Rose  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
596aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    << Kind << /*Unexpected=*/true << OS.str();
59781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  return std::distance(diag_begin, diag_end);
59881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
59981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
600aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// \brief Takes a list of diagnostics that were expected to have been generated
601aa48fe80a1b2000809900a437f0819d929793002Jordan Rose/// but were not and produces a diagnostic to the user from this.
602aa48fe80a1b2000809900a437f0819d929793002Jordan Rosestatic unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
603aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                              DirectiveList &DL, const char *Kind) {
60460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  if (DL.empty())
60560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    return 0;
60660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
607f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<256> Fmt;
60860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  llvm::raw_svector_ostream OS(Fmt);
60960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
610aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    Directive &D = **I;
611b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    OS << "\n  File " << SourceMgr.getFilename(D.DiagnosticLoc)
612b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
613aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    if (D.DirectiveLoc != D.DiagnosticLoc)
614aa48fe80a1b2000809900a437f0819d929793002Jordan Rose      OS << " (directive at "
615b42f200777a66b98989160bf3987ce431540a584Andy Gibbs         << SourceMgr.getFilename(D.DirectiveLoc) << ':'
616b42f200777a66b98989160bf3987ce431540a584Andy Gibbs         << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ')';
61760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    OS << ": " << D.Text;
61860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  }
61960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
620c6d64a26c28bbeee50e06c94c4f4c08e610327b7Jordan Rose  Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit()
621aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    << Kind << /*Unexpected=*/false << OS.str();
62260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  return DL.size();
62360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner}
62460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
625b42f200777a66b98989160bf3987ce431540a584Andy Gibbs/// \brief Determine whether two source locations come from the same file.
626b42f200777a66b98989160bf3987ce431540a584Andy Gibbsstatic bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc,
627b42f200777a66b98989160bf3987ce431540a584Andy Gibbs                           SourceLocation DiagnosticLoc) {
628b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  while (DiagnosticLoc.isMacroID())
629b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    DiagnosticLoc = SM.getImmediateMacroCallerLoc(DiagnosticLoc);
630b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
631b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  if (SM.isFromSameFile(DirectiveLoc, DiagnosticLoc))
632b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    return true;
633b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
634b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  const FileEntry *DiagFile = SM.getFileEntryForID(SM.getFileID(DiagnosticLoc));
635b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  if (!DiagFile && SM.isFromMainFile(DirectiveLoc))
636b42f200777a66b98989160bf3987ce431540a584Andy Gibbs    return true;
637b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
638b42f200777a66b98989160bf3987ce431540a584Andy Gibbs  return (DiagFile == SM.getFileEntryForID(SM.getFileID(DirectiveLoc)));
639b42f200777a66b98989160bf3987ce431540a584Andy Gibbs}
640b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
64160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// CheckLists - Compare expected to seen diagnostic lists and return the
64260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner/// the difference between them.
64381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
644d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiestatic unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
64560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           const char *Label,
64660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           DirectiveList &Left,
64760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           const_diag_iterator d2_begin,
64860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                           const_diag_iterator d2_end) {
64960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  DirectiveList LeftOnly;
65081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  DiagList Right(d2_begin, d2_end);
65181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
65260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
65360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner    Directive& D = **I;
654aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
65581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
6563b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    for (unsigned i = 0; i < D.Max; ++i) {
65760909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      DiagList::iterator II, IE;
65860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
6595ef04ee40c3332d31b6d1439f50d0ddb45812929Chandler Carruth        unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first);
66060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        if (LineNo1 != LineNo2)
66160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner          continue;
66281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
663b42f200777a66b98989160bf3987ce431540a584Andy Gibbs        if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first))
664b42f200777a66b98989160bf3987ce431540a584Andy Gibbs          continue;
665b42f200777a66b98989160bf3987ce431540a584Andy Gibbs
66660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        const std::string &RightText = II->second;
6674313c013c658f6c97e6460e7780c26faa6b78d9aJordan Rose        if (D.match(RightText))
66860909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner          break;
66960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      }
67060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      if (II == IE) {
67160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        // Not found.
6723b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose        if (i >= D.Min) break;
67360909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        LeftOnly.push_back(*I);
67460909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner      } else {
67560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        // Found. The same cannot be found twice.
67660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner        Right.erase(II);
67781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar      }
67881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar    }
67981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  }
68081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Now all that's left in Right are those that were not matched.
681aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  unsigned num = PrintExpected(Diags, SourceMgr, LeftOnly, Label);
682aa48fe80a1b2000809900a437f0819d929793002Jordan Rose  num += PrintUnexpected(Diags, &SourceMgr, Right.begin(), Right.end(), Label);
683ad646846f7033d3ee813998bb0bc028aee51e65eNAKAMURA Takumi  return num;
68481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
68581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
68681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// CheckResults - This compares the expected results to those that
68781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// were actually reported. It emits any discrepencies. Return "true" if there
68881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar/// were problems. Return "false" otherwise.
68981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar///
690d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikiestatic unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
69181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar                             const TextDiagnosticBuffer &Buffer,
69260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                             ExpectedData &ED) {
69381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // We want to capture the delta between what was expected and what was
69481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // seen.
69581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  //
69681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  //   Expected \ Seen - set expected but not seen
69781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  //   Seen \ Expected - set seen but not expected
69881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  unsigned NumProblems = 0;
69981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
70081f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // See if there are error mismatches.
70160909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  NumProblems += CheckLists(Diags, SourceMgr, "error", ED.Errors,
70260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                            Buffer.err_begin(), Buffer.err_end());
703221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar
70481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // See if there are warning mismatches.
70560909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  NumProblems += CheckLists(Diags, SourceMgr, "warning", ED.Warnings,
70660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                            Buffer.warn_begin(), Buffer.warn_end());
70781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
70881f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // See if there are note mismatches.
70960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  NumProblems += CheckLists(Diags, SourceMgr, "note", ED.Notes,
71060909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner                            Buffer.note_begin(), Buffer.note_end());
71181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
71281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  return NumProblems;
71381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
71481f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
7157eaaa186d1e9797f424136f565403f7a8b6672faJordan Rosevoid VerifyDiagnosticConsumer::UpdateParsedFileStatus(SourceManager &SM,
7167eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                                      FileID FID,
7177eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                                      ParsedStatus PS) {
7187eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // Check SourceManager hasn't changed.
7197eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  setSourceManager(SM);
7207eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7217eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose#ifndef NDEBUG
7227eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (FID.isInvalid())
7237eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    return;
7247eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7257eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  const FileEntry *FE = SM.getFileEntryForID(FID);
7267eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7277eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (PS == IsParsed) {
7287eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Move the FileID from the unparsed set to the parsed set.
7297eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    UnparsedFiles.erase(FID);
7307eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    ParsedFiles.insert(std::make_pair(FID, FE));
7317eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  } else if (!ParsedFiles.count(FID) && !UnparsedFiles.count(FID)) {
7327eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Add the FileID to the unparsed set if we haven't seen it before.
7337eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7347eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Check for directives.
7357eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    bool FoundDirectives;
7367eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    if (PS == IsUnparsedNoDirectives)
7377eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      FoundDirectives = false;
7387eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    else
7397eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      FoundDirectives = !LangOpts || findDirectives(SM, FID, *LangOpts);
7407eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7417eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Add the FileID to the unparsed set.
7427eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    UnparsedFiles.insert(std::make_pair(FID,
7437eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                      UnparsedFileStatus(FE, FoundDirectives)));
7447eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  }
7457eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose#endif
7467eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose}
7477eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
748621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikievoid VerifyDiagnosticConsumer::CheckDiagnostics() {
74981f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Ensure any diagnostics go to the primary client.
75078243658c533168d51fd076fba328437932ba6f1Douglas Gregor  bool OwnsCurClient = Diags.ownsClient();
75178ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie  DiagnosticConsumer *CurClient = Diags.takeClient();
75278243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.setClient(PrimaryClient, false);
75381f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
7547c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose#ifndef NDEBUG
7557eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // In a debug build, scan through any files that may have been missed
7567eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // during parsing and issue a fatal error if directives are contained
7577eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // within these files.  If a fatal error occurs, this suggests that
7587eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // this file is being parsed separately from the main file, in which
7597eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // case consider moving the directives to the correct place, if this
7607eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  // is applicable.
7617eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (UnparsedFiles.size() > 0) {
7627eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Generate a cache of parsed FileEntry pointers for alias lookups.
7637eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache;
7647eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    for (ParsedFilesMap::iterator I = ParsedFiles.begin(),
7657eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                End = ParsedFiles.end(); I != End; ++I) {
7667eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (const FileEntry *FE = I->second)
7677eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose        ParsedFileCache.insert(FE);
7687eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    }
7697eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7707eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // Iterate through list of unparsed files.
7717eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    for (UnparsedFilesMap::iterator I = UnparsedFiles.begin(),
7727eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                  End = UnparsedFiles.end(); I != End; ++I) {
7737eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      const UnparsedFileStatus &Status = I->second;
7747eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      const FileEntry *FE = Status.getFile();
7757eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7767eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      // Skip files that have been parsed via an alias.
7777eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (FE && ParsedFileCache.count(FE))
7787c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose        continue;
7797c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose
7807eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      // Report a fatal error if this file contained directives.
7817eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      if (Status.foundDirectives()) {
7827c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose        llvm::report_fatal_error(Twine("-verify directives found after rather"
7837c304f56eecbd03db7d222a05dfcd593750d50d3Jordan Rose                                       " than during normal parsing of ",
7847eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose                                 StringRef(FE ? FE->getName() : "(unknown)")));
7857eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose      }
78684c05e3b873a95c8c8d64fa8083407bcf395383fAxel Naumann    }
78781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
7887eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    // UnparsedFiles has been processed now, so clear it.
7897eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    UnparsedFiles.clear();
7907eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  }
7917eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose#endif // !NDEBUG
7927eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose
7937eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose  if (SrcManager) {
794266dba3661928d26f043560b169bea87578aa917Andy Gibbs    // Produce an error if no expected-* directives could be found in the
795266dba3661928d26f043560b169bea87578aa917Andy Gibbs    // source file(s) processed.
796266dba3661928d26f043560b169bea87578aa917Andy Gibbs    if (Status == HasNoDirectives) {
797266dba3661928d26f043560b169bea87578aa917Andy Gibbs      Diags.Report(diag::err_verify_no_directives).setForceEmit();
798266dba3661928d26f043560b169bea87578aa917Andy Gibbs      ++NumErrors;
799266dba3661928d26f043560b169bea87578aa917Andy Gibbs      Status = HasNoDirectivesReported;
800266dba3661928d26f043560b169bea87578aa917Andy Gibbs    }
801266dba3661928d26f043560b169bea87578aa917Andy Gibbs
802221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar    // Check that the expected diagnostics occurred.
8037eaaa186d1e9797f424136f565403f7a8b6672faJordan Rose    NumErrors += CheckResults(Diags, *SrcManager, *Buffer, ED);
804221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar  } else {
805aa48fe80a1b2000809900a437f0819d929793002Jordan Rose    NumErrors += (PrintUnexpected(Diags, 0, Buffer->err_begin(),
806aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                  Buffer->err_end(), "error") +
807aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                  PrintUnexpected(Diags, 0, Buffer->warn_begin(),
808aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                  Buffer->warn_end(), "warn") +
809aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                  PrintUnexpected(Diags, 0, Buffer->note_begin(),
810aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                                  Buffer->note_end(), "note"));
811221c7211c507482a91e97ede1bf6cf65a456ff67Daniel Dunbar  }
81281f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
813bdbb004f38978da0c4a75af3294d1c7b5ff84af1Douglas Gregor  Diags.takeClient();
81478243658c533168d51fd076fba328437932ba6f1Douglas Gregor  Diags.setClient(CurClient, OwnsCurClient);
81581f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar
81681f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  // Reset the buffer, we have processed all the diagnostics in it.
81781f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar  Buffer.reset(new TextDiagnosticBuffer());
818e445e5d6377827f222f0d15e18fbd1f86114d2ccAxel Naumann  ED.Errors.clear();
819e445e5d6377827f222f0d15e18fbd1f86114d2ccAxel Naumann  ED.Warnings.clear();
820e445e5d6377827f222f0d15e18fbd1f86114d2ccAxel Naumann  ED.Notes.clear();
82181f5a1e699b2eefa4a5e50b5dfc06df600748f59Daniel Dunbar}
82260909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner
823aa48fe80a1b2000809900a437f0819d929793002Jordan RoseDirective *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
824aa48fe80a1b2000809900a437f0819d929793002Jordan Rose                             SourceLocation DiagnosticLoc, StringRef Text,
8253b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose                             unsigned Min, unsigned Max) {
82660909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner  if (RegexKind)
8273b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose    return new RegexDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
8283b81b7d604e851498243ee732dee3babc1cf20d4Jordan Rose  return new StandardDirective(DirectiveLoc, DiagnosticLoc, Text, Min, Max);
82960909e1242f19aa8b1b87110aaa8e394f329ae96Chris Lattner}
830