29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/SmallPtrSet.h"
31#include "llvm/ADT/SmallString.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/ADT/Twine.h"
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/Regex.h"
36#include "llvm/Support/raw_ostream.h"
63 : Verify(Verify),
SM(
SM) {}
89class StandardDirective :
public Directive {
92 bool MatchAnyFileAndLine,
bool MatchAnyLine, StringRef
Text,
93 unsigned Min,
unsigned Max)
94 :
Directive(DirectiveLoc, DiagnosticLoc, MatchAnyFileAndLine,
97 bool isValid(std::string &Error)
override {
102 bool match(StringRef S)
override {
return S.contains(
Text); }
109 bool MatchAnyFileAndLine,
bool MatchAnyLine, StringRef
Text,
110 unsigned Min,
unsigned Max, StringRef RegexStr)
111 :
Directive(DirectiveLoc, DiagnosticLoc, MatchAnyFileAndLine,
115 bool isValid(std::string &Error)
override {
116 return Regex.isValid(Error);
119 bool match(StringRef S)
override {
120 return Regex.match(S);
130 ParseHelper(StringRef S)
134 bool Next(StringRef S) {
139 return memcmp(
P, S.data(), S.size()) == 0;
144 bool Next(
unsigned &N) {
148 for (; PEnd < End && *PEnd >=
'0' && *PEnd <=
'9'; ++PEnd) {
162 if (
P == End || *
P !=
'#')
181 bool Search(StringRef S,
bool EnsureStartOfWord =
false,
182 bool FinishDirectiveToken =
false) {
185 P = std::search(C, End, S.begin(), S.end());
197 if (EnsureStartOfWord
201 || (
P > (
Begin + 1) && (
P[-1] ==
'/' ||
P[-1] ==
'*')
204 if (FinishDirectiveToken) {
206 || *PEnd ==
'-' || *PEnd ==
'_'))
213 assert(
isLetter(*
P) &&
"-verify prefix must start with a letter");
214 while (
isDigit(PEnd[-1]) || PEnd[-1] ==
'-')
224 bool SearchClosingBrace(StringRef OpenBrace, StringRef CloseBrace) {
228 StringRef S(
P, End -
P);
229 if (S.starts_with(OpenBrace)) {
231 P += OpenBrace.size();
232 }
else if (S.starts_with(CloseBrace)) {
235 PEnd =
P + CloseBrace.size();
238 P += CloseBrace.size();
255 StringRef Match() {
return StringRef(
P, PEnd -
P); }
258 void SkipWhitespace() {
269 const char *
const Begin;
272 const char *
const End;
282 const char *PEnd =
nullptr;
286struct UnattachedDirective {
288 bool RegexKind =
false;
291 unsigned Min = 1,
Max = 1;
298 bool MatchAnyFileAndLine =
false,
299 bool MatchAnyLine =
false) {
302 UD.RegexKind, UD.DirectivePos, ExpectedLoc, MatchAnyFileAndLine,
303 MatchAnyLine, UD.Text, UD.Min, UD.Max);
306 if (!
D->isValid(Error)) {
307 Diags.
Report(UD.ContentBegin, diag::err_verify_invalid_content)
308 << (UD.RegexKind ?
"regex" :
"string") << Error;
311 UD.DL->push_back(std::move(
D));
334 llvm::StringMap<Marker> Markers;
338 llvm::StringMap<llvm::SmallVector<UnattachedDirective, 2>> DeferredDirectives;
345 auto InsertResult = Markers.insert(
348 Marker &M = InsertResult.first->second;
349 if (!InsertResult.second) {
354 auto Deferred = DeferredDirectives.find(MarkerName);
355 if (Deferred != DeferredDirectives.end()) {
356 for (
auto &UD : Deferred->second) {
357 if (M.UseLoc.isInvalid())
358 M.UseLoc = UD.DirectivePos;
359 attachDirective(Diags, UD, Pos);
361 DeferredDirectives.erase(Deferred);
367 void addDirective(StringRef MarkerName,
const UnattachedDirective &UD) {
368 auto MarkerIt = Markers.find(MarkerName);
369 if (MarkerIt != Markers.end()) {
370 Marker &M = MarkerIt->second;
371 if (M.UseLoc.isInvalid())
372 M.UseLoc = UD.DirectivePos;
373 return attachDirective(Diags, UD, M.DefLoc);
375 DeferredDirectives[MarkerName].push_back(UD);
381 for (
auto &MarkerInfo : Markers) {
382 StringRef Name = MarkerInfo.first();
383 Marker &M = MarkerInfo.second;
384 if (M.RedefLoc.isValid() && M.UseLoc.isValid()) {
385 Diags.
Report(M.UseLoc, diag::err_verify_ambiguous_marker) << Name;
386 Diags.
Report(M.DefLoc, diag::note_verify_ambiguous_marker) << Name;
387 Diags.
Report(M.RedefLoc, diag::note_verify_ambiguous_marker) << Name;
391 for (
auto &DeferredPair : DeferredDirectives) {
392 Diags.
Report(DeferredPair.second.front().DirectivePos,
393 diag::err_verify_no_such_marker)
394 << DeferredPair.first();
416 for (ParseHelper PH(S); !PH.Done();) {
417 if (!PH.Search(
"#",
true))
420 if (!PH.NextMarker()) {
430 bool FoundDirective =
false;
431 for (ParseHelper PH(S); !PH.Done();) {
436 if (!(Prefixes.size() == 1 ? PH.Search(*Prefixes.begin(),
true,
true)
437 : PH.Search(
"",
true,
true)))
440 StringRef DToken = PH.Match();
444 UnattachedDirective
D;
445 const char *KindStr =
"string";
454 if (DToken.consume_back(
"-re")) {
462 if (DToken.ends_with(
DType =
"-error"))
463 D.DL = ED ? &ED->
Errors :
nullptr;
464 else if (DToken.ends_with(
DType =
"-warning"))
466 else if (DToken.ends_with(
DType =
"-remark"))
468 else if (DToken.ends_with(
DType =
"-note"))
469 D.DL = ED ? &ED->
Notes :
nullptr;
470 else if (DToken.ends_with(
DType =
"-no-diagnostics")) {
476 DToken = DToken.substr(0, DToken.size()-
DType.size());
481 if (!std::binary_search(Prefixes.begin(), Prefixes.end(), DToken))
486 Diags.
Report(Pos, diag::err_verify_invalid_no_diags)
493 Diags.
Report(Pos, diag::err_verify_invalid_no_diags)
507 bool MatchAnyFileAndLine =
false;
508 bool MatchAnyLine =
false;
514 bool FoundPlus = PH.Next(
"+");
515 if (FoundPlus || PH.Next(
"-")) {
519 unsigned ExpectedLine =
SM.getSpellingLineNumber(Pos, &
Invalid);
520 if (!
Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
521 if (FoundPlus) ExpectedLine += Line;
522 else ExpectedLine -= Line;
523 ExpectedLoc =
SM.translateLineCol(
SM.getFileID(Pos), ExpectedLine, 1);
525 }
else if (PH.Next(Line)) {
528 ExpectedLoc =
SM.translateLineCol(
SM.getFileID(Pos), Line, 1);
529 }
else if (PH.NextMarker()) {
531 }
else if (PP && PH.Search(
":")) {
533 StringRef
Filename(PH.C, PH.P-PH.C);
537 MatchAnyFileAndLine =
true;
540 diag::err_verify_missing_line)
550 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
553 diag::err_verify_missing_file)
562 if (PH.Next(Line) && Line > 0)
563 ExpectedLoc =
SM.translateLineCol(FID, Line, 1);
564 else if (PH.Next(
"*")) {
566 ExpectedLoc =
SM.translateLineCol(FID, 1, 1);
569 }
else if (PH.Next(
"*")) {
574 if (ExpectedLoc.
isInvalid() && !MatchAnyLine && Marker.empty()) {
576 diag::err_verify_missing_line) << KindStr;
586 if (PH.Next(
D.Min)) {
593 }
else if (PH.Next(
"-")) {
595 if (!PH.Next(
D.Max) ||
D.Max <
D.Min) {
597 diag::err_verify_invalid_range) << KindStr;
604 }
else if (PH.Next(
"+")) {
614 if (!PH.Next(
"{{")) {
616 diag::err_verify_missing_start) << KindStr;
620 const char *
const DelimBegin = PH.C;
623 for (; !
D.RegexKind && PH.Next(
"{"); PH.Advance())
625 const char*
const ContentBegin = PH.C;
627 StringRef OpenBrace(DelimBegin, ContentBegin - DelimBegin);
628 if (!PH.SearchClosingBrace(OpenBrace, CloseBrace)) {
630 diag::err_verify_missing_end)
631 << KindStr << CloseBrace;
634 const char*
const ContentEnd = PH.P;
637 D.DirectivePos = Pos;
641 StringRef NewlineStr =
"\\n";
642 StringRef Content(ContentBegin, ContentEnd-ContentBegin);
645 while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) {
646 D.Text += Content.substr(CPos, FPos-CPos);
648 CPos = FPos + NewlineStr.size();
651 D.Text.assign(ContentBegin, ContentEnd);
654 if (
D.RegexKind &&
D.Text.find(
"{{") == StringRef::npos) {
655 Diags.
Report(
D.ContentBegin, diag::err_verify_missing_regex) <<
D.Text;
660 attachDirective(Diags,
D, ExpectedLoc, MatchAnyFileAndLine, MatchAnyLine);
663 FoundDirective =
true;
666 return FoundDirective;
670 : Diags(Diags_), PrimaryClient(Diags.getClient()),
671 PrimaryClientOwner(Diags.takeClient()),
673 Status(HasNoDirectives) {
679 assert(!ActiveSourceFiles &&
"Incomplete parsing of source files!");
680 assert(!CurrentPreprocessor &&
"CurrentPreprocessor should be invalid!");
681 SrcManager =
nullptr;
684 "The VerifyDiagnosticConsumer takes over ownership of the client!");
692 if (++ActiveSourceFiles == 1) {
694 CurrentPreprocessor = PP;
695 this->LangOpts = &LangOpts;
697 const_cast<Preprocessor *
>(PP)->addCommentHandler(
this);
701 std::make_unique<VerifyFileTracker>(*
this, *SrcManager));
706 assert((!PP || CurrentPreprocessor == PP) &&
"Preprocessor changed!");
711 assert(ActiveSourceFiles &&
"No active source files!");
715 if (--ActiveSourceFiles == 0) {
716 if (CurrentPreprocessor)
718 removeCommentHandler(
this);
725 CurrentPreprocessor =
nullptr;
752 if (FE && CurrentPreprocessor && SrcManager->
isLoadedFileID(FID)) {
767 Buffer->HandleDiagnostic(DiagLevel, Info);
777 if (SrcManager && &
SM != SrcManager)
782 const char *CommentRaw =
SM.getCharacterData(CommentBegin);
783 StringRef
C(CommentRaw,
SM.getCharacterData(Comment.
getEnd()) - CommentRaw);
789 size_t loc =
C.find(
'\\');
790 if (loc == StringRef::npos) {
796 C2.reserve(
C.size());
798 for (
size_t last = 0;; loc =
C.find(
'\\', last)) {
799 if (loc == StringRef::npos || loc ==
C.size()) {
800 C2 +=
C.substr(last);
803 C2 +=
C.substr(last, loc-last);
806 if (
C[last] ==
'\n' ||
C[last] ==
'\r') {
811 if (
C[last] ==
'\n' ||
C[last] ==
'\r')
812 if (
C[last] !=
C[last-1])
838 llvm::MemoryBufferRef FromFile =
SM.getBufferOrFake(FID);
839 Lexer RawLex(FID, FromFile,
SM, LangOpts);
848 while (Tok.
isNot(tok::eof)) {
850 if (!Tok.
is(tok::comment))
continue;
853 if (Comment.empty())
continue;
873 if (diag_begin == diag_end)
return 0;
876 llvm::raw_svector_ostream OS(Fmt);
878 if (I->first.isInvalid() || !SourceMgr)
879 OS <<
"\n (frontend)";
884 OS <<
" File " <<
File->getName();
887 OS <<
": " << I->second;
891 std::string KindStr = Prefix +
"-" + Kind;
893 << KindStr <<
true << OS.str();
894 return std::distance(diag_begin, diag_end);
901 std::vector<Directive *> &DL,
const char *Kind) {
906 llvm::raw_svector_ostream OS(Fmt);
907 for (
const auto *
D : DL) {
908 if (
D->DiagnosticLoc.isInvalid() ||
D->MatchAnyFileAndLine)
911 OS <<
"\n File " << SourceMgr.
getFilename(
D->DiagnosticLoc);
916 if (
D->DirectiveLoc !=
D->DiagnosticLoc)
917 OS <<
" (directive at "
920 OS <<
": " <<
D->Text;
924 std::string KindStr = Prefix +
"-" + Kind;
926 << KindStr <<
false << OS.str();
934 DiagnosticLoc =
SM.getImmediateMacroCallerLoc(DiagnosticLoc);
936 if (
SM.isWrittenInSameFile(DirectiveLoc, DiagnosticLoc))
939 const FileEntry *DiagFile =
SM.getFileEntryForID(
SM.getFileID(DiagnosticLoc));
940 if (!DiagFile &&
SM.isWrittenInMainFile(DirectiveLoc))
943 return (DiagFile ==
SM.getFileEntryForID(
SM.getFileID(DirectiveLoc)));
953 bool IgnoreUnexpected) {
954 std::vector<Directive *> LeftOnly;
957 for (
auto &Owner : Left) {
961 for (
unsigned i = 0; i <
D.Max; ++i) {
962 DiagList::iterator II, IE;
963 for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
964 if (!
D.MatchAnyLine) {
966 if (LineNo1 != LineNo2)
970 if (!
D.DiagnosticLoc.isInvalid() && !
D.MatchAnyFileAndLine &&
974 const std::string &RightText = II->second;
975 if (
D.match(RightText))
980 if (i >=
D.Min)
break;
981 LeftOnly.push_back(&
D);
990 if (!IgnoreUnexpected)
1006 unsigned NumProblems = 0;
1038 setSourceManager(
SM);
1048 UnparsedFiles.erase(FID);
1049 ParsedFiles.insert(std::make_pair(FID, FE ? &FE->
getFileEntry() :
nullptr));
1050 }
else if (!ParsedFiles.count(FID) && !UnparsedFiles.count(FID)) {
1054 bool FoundDirectives;
1056 FoundDirectives =
false;
1061 UnparsedFiles.insert(std::make_pair(FID,
1062 UnparsedFileStatus(FE, FoundDirectives)));
1067void VerifyDiagnosticConsumer::CheckDiagnostics() {
1070 std::unique_ptr<DiagnosticConsumer> Owner = Diags.
takeClient();
1080 if (!UnparsedFiles.empty()) {
1083 for (
const auto &I : ParsedFiles)
1085 ParsedFileCache.insert(FE);
1088 for (
const auto &I : UnparsedFiles) {
1089 const UnparsedFileStatus &Status = I.second;
1093 if (FE && ParsedFileCache.count(*FE))
1097 if (Status.foundDirectives()) {
1098 llvm::report_fatal_error(
"-verify directives found after rather"
1099 " than during normal parsing of " +
1100 (FE ? FE->
getName() :
"(unknown)"));
1105 UnparsedFiles.clear();
1123 ~Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected();
1126 Buffer->err_end(),
"error");
1129 Buffer->warn_end(),
"warn");
1132 Buffer->remark_end(),
"remark");
1135 Buffer->note_end(),
"note");
1138 Diags.
setClient(CurClient, Owner.release() !=
nullptr);
1148 bool MatchAnyFileAndLine,
1149 bool MatchAnyLine, StringRef
Text,
1150 unsigned Min,
unsigned Max) {
1152 return std::make_unique<StandardDirective>(DirectiveLoc, DiagnosticLoc,
1153 MatchAnyFileAndLine,
1157 std::string RegexStr;
1159 while (!S.empty()) {
1160 if (S.consume_front(
"{{")) {
1161 size_t RegexMatchLength = S.find(
"}}");
1162 assert(RegexMatchLength != StringRef::npos);
1165 RegexStr.append(S.data(), RegexMatchLength);
1167 S = S.drop_front(RegexMatchLength + 2);
1169 size_t VerbatimMatchLength = S.find(
"{{");
1170 if (VerbatimMatchLength == StringRef::npos)
1171 VerbatimMatchLength = S.size();
1173 RegexStr += llvm::Regex::escape(S.substr(0, VerbatimMatchLength));
1174 S = S.drop_front(VerbatimMatchLength);
1178 return std::make_unique<RegexDirective>(DirectiveLoc, DiagnosticLoc,
1179 MatchAnyFileAndLine, MatchAnyLine,
Defines the Diagnostic-related interfaces.
Defines the clang::FileManager interface and associated types.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::FileType FileType
Defines the PPCallbacks interface.
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const char *Label, DirectiveList &Left, const_diag_iterator d2_begin, const_diag_iterator d2_end, bool IgnoreUnexpected)
CheckLists - Compare expected to seen diagnostic lists and return the the difference between them.
static bool findDirectives(SourceManager &SM, FileID FID, const LangOptions &LangOpts)
Lex the specified source file to determine whether it contains any expected-* directives.
TextDiagnosticBuffer::const_iterator const_diag_iterator
TextDiagnosticBuffer::DiagList DiagList
static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc)
Determine whether two source locations come from the same file.
VerifyDiagnosticConsumer::DirectiveList DirectiveList
static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const TextDiagnosticBuffer &Buffer, ExpectedData &ED)
CheckResults - This compares the expected results to those that were actually reported.
static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr, const_diag_iterator diag_begin, const_diag_iterator diag_end, const char *Kind)
Takes a list of diagnostics that have been generated but not matched by an expected-* directive and p...
VerifyDiagnosticConsumer::Directive Directive
static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, Preprocessor *PP, SourceLocation Pos, VerifyDiagnosticConsumer::DirectiveStatus &Status, VerifyDiagnosticConsumer::MarkerTracker &Markers)
ParseDirective - Go through the comment and see if it indicates expected diagnostics.
static std::string DetailedErrorString(const DiagnosticsEngine &Diags)
static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr, std::vector< Directive * > &DL, const char *Kind)
Takes a list of diagnostics that were expected to have been generated but were not and produces a dia...
void addDirective(StringRef MarkerName, const UnattachedDirective &UD)
MarkerTracker(DiagnosticsEngine &Diags)
void addMarker(StringRef MarkerName, SourceLocation Pos)
const DiagnosticBuilder & setForceEmit() const
Forces the diagnostic to be emitted.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
unsigned NumErrors
Number of errors reported.
virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP=nullptr)
Callback to inform the diagnostic client that processing of a source file is beginning.
std::vector< std::string > VerifyPrefixes
The prefixes for comment directives sought by -verify ("expected" by default).
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
const SourceLocation & getLocation() const
SourceManager & getSourceManager() const
bool hasSourceManager() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool hasSourceManager() const
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
void setClient(DiagnosticConsumer *client, bool ShouldOwnClient=true)
Set the diagnostic client associated with this diagnostic object.
std::unique_ptr< DiagnosticConsumer > takeClient()
Return the current diagnostic client along with ownership of that client.
SourceManager & getSourceManager() const
Level
The level of the diagnostic, after it has been through mapping.
DiagnosticConsumer * getClient()
bool ownsClient() const
Determine whether this DiagnosticsEngine object own its client.
const FileEntry & getFileEntry() const
StringRef getName() const
The name of this FileEntry.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode.
static unsigned getSpelling(const Token &Tok, const char *&Buffer, const SourceManager &SourceMgr, const LangOptions &LangOpts, bool *Invalid=nullptr)
getSpelling - This method is used to get the spelling of a token into a preallocated buffer,...
This interface provides a way to observe the actions of the preprocessor as it does its thing.
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID=FileID())
Callback invoked whenever a source file is entered or exited.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
SourceManager & getSourceManager() const
HeaderSearch & getHeaderSearchInfo() const
OptionalFileEntryRef LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, ConstSearchDirIterator FromDir, const FileEntry *FromFile, ConstSearchDirIterator *CurDir, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache=false, bool OpenFile=true, bool CacheFailures=true)
Given a "foo" or <foo> reference, look up the indicated file.
DiagnosticsEngine & getDiagnostics() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
StringRef getFilename(SourceLocation SpellingLoc) const
Return the filename of the file containing a SourceLocation.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
DiagList::const_iterator const_iterator
std::vector< std::pair< SourceLocation, std::string > > DiagList
const_iterator warn_end() const
const_iterator note_begin() const
const_iterator err_begin() const
const_iterator note_end() const
const_iterator warn_begin() const
const_iterator remark_begin() const
const_iterator remark_end() const
const_iterator err_end() const
Token - This structure provides full information about a lexed token.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
void setKind(tok::TokenKind K)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
bool isNot(tok::TokenKind K) const
Directive - Abstract class representing a parsed verify directive.
virtual bool isValid(std::string &Error)=0
static std::unique_ptr< Directive > create(bool RegexKind, SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, bool MatchAnyFileAndLine, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
static const unsigned MaxCount
Constant representing n or more matches.
virtual bool match(StringRef S)=0
VerifyDiagnosticConsumer - Create a diagnostic client which will use markers in the input source to c...
void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS)
Update lists of parsed and unparsed files.
VerifyDiagnosticConsumer(DiagnosticsEngine &Diags)
Create a new verifying diagnostic client, which will issue errors to the currently-attached diagnosti...
@ IsUnparsed
File has diagnostics and may have directives.
@ IsUnparsedNoDirectives
File has diagnostics but guaranteed no directives.
@ IsParsed
File has been processed via HandleComment.
void EndSourceFile() override
Callback to inform the diagnostic client that processing of a source file has ended.
void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP) override
Callback to inform the diagnostic client that processing of a source file is beginning.
std::vector< std::unique_ptr< Directive > > DirectiveList
~VerifyDiagnosticConsumer() override
@ HasExpectedNoDiagnostics
@ HasNoDirectivesReported
@ HasOtherExpectedDirectives
bool HandleComment(Preprocessor &PP, SourceRange Comment) override
HandleComment - Hook into the preprocessor and extract comments containing expected errors and warnin...
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
The JSON file list parser is used to communicate input to InstallAPI.
@ DType
'dtype' clause, an alias for 'device_type', stored separately for diagnostic purposes.
DiagnosticLevelMask
A bitmask representing the diagnostic levels used by VerifyDiagnosticConsumer.
LLVM_READONLY bool isLetter(unsigned char c)
Return true if this character is an ASCII letter: [a-zA-Z].
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...
ExpectedData - owns directive objects and deletes on destructor.