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