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