28#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/SmallPtrSet.h"
30#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/ADT/Twine.h"
33#include "llvm/Support/ErrorHandling.h"
34#include "llvm/Support/Regex.h"
35#include "llvm/Support/raw_ostream.h"
62 : Verify(Verify),
SM(
SM) {}
88class StandardDirective :
public Directive {
91 StringRef Spelling,
bool MatchAnyFileAndLine,
92 bool MatchAnyLine, StringRef
Text,
unsigned Min,
94 :
Directive(DirectiveLoc, DiagnosticLoc, Spelling, MatchAnyFileAndLine,
97 bool isValid(std::string &Error)
override {
102 bool match(StringRef S)
override {
return S.contains(
Text); }
109 StringRef Spelling,
bool MatchAnyFileAndLine,
110 bool MatchAnyLine, StringRef
Text,
unsigned Min,
unsigned Max,
112 :
Directive(DirectiveLoc, DiagnosticLoc, Spelling, MatchAnyFileAndLine,
116 bool isValid(std::string &Error)
override {
117 return Regex.isValid(Error);
120 bool match(StringRef S)
override {
121 return Regex.match(S);
131 ParseHelper(StringRef S)
135 bool Next(StringRef S) {
140 return memcmp(
P, S.data(), S.size()) == 0;
145 bool Next(
unsigned &N) {
149 for (; PEnd < End && *PEnd >=
'0' && *PEnd <=
'9'; ++PEnd) {
163 if (
P == End || *
P !=
'#')
182 bool Search(StringRef S,
bool EnsureStartOfWord =
false,
183 bool FinishDirectiveToken =
false) {
186 P = std::search(C, End, S.begin(), S.end());
198 if (EnsureStartOfWord
202 || (
P > (
Begin + 1) && (
P[-1] ==
'/' ||
P[-1] ==
'*')
205 if (FinishDirectiveToken) {
207 || *PEnd ==
'-' || *PEnd ==
'_'))
214 assert(
isLetter(*
P) &&
"-verify prefix must start with a letter");
215 while (
isDigit(PEnd[-1]) || PEnd[-1] ==
'-')
225 bool SearchClosingBrace(StringRef OpenBrace, StringRef CloseBrace) {
229 StringRef S(
P, End -
P);
230 if (S.starts_with(OpenBrace)) {
232 P += OpenBrace.size();
233 }
else if (S.starts_with(CloseBrace)) {
236 PEnd =
P + CloseBrace.size();
239 P += CloseBrace.size();
256 StringRef
Match() {
return StringRef(
P, PEnd -
P); }
259 void SkipWhitespace() {
270 const char *
const Begin;
273 const char *
const End;
283 const char *PEnd =
nullptr;
287struct UnattachedDirective {
289 std::string Spelling;
290 bool RegexKind =
false;
293 unsigned Min = 1,
Max = 1;
300 bool MatchAnyFileAndLine =
false,
301 bool MatchAnyLine =
false) {
304 UD.RegexKind, UD.DirectivePos, ExpectedLoc, UD.Spelling,
305 MatchAnyFileAndLine, MatchAnyLine, UD.Text, UD.Min, UD.Max);
308 if (!
D->isValid(Error)) {
309 Diags.
Report(UD.ContentBegin, diag::err_verify_invalid_content)
310 << (UD.RegexKind ?
"regex" :
"string") << Error;
313 UD.DL->push_back(std::move(
D));
336 llvm::StringMap<Marker> Markers;
340 llvm::StringMap<llvm::SmallVector<UnattachedDirective, 2>> DeferredDirectives;
347 auto InsertResult = Markers.insert(
350 Marker &M = InsertResult.first->second;
351 if (!InsertResult.second) {
356 auto Deferred = DeferredDirectives.find(MarkerName);
357 if (Deferred != DeferredDirectives.end()) {
358 for (
auto &UD : Deferred->second) {
359 if (M.UseLoc.isInvalid())
360 M.UseLoc = UD.DirectivePos;
361 attachDirective(Diags, UD, Pos);
363 DeferredDirectives.erase(Deferred);
369 void addDirective(StringRef MarkerName,
const UnattachedDirective &UD) {
370 auto MarkerIt = Markers.find(MarkerName);
371 if (MarkerIt != Markers.end()) {
372 Marker &M = MarkerIt->second;
373 if (M.UseLoc.isInvalid())
374 M.UseLoc = UD.DirectivePos;
375 return attachDirective(Diags, UD, M.DefLoc);
377 DeferredDirectives[MarkerName].push_back(UD);
383 for (
auto &MarkerInfo : Markers) {
384 StringRef Name = MarkerInfo.first();
385 Marker &M = MarkerInfo.second;
386 if (M.RedefLoc.isValid() && M.UseLoc.isValid()) {
387 Diags.
Report(M.UseLoc, diag::err_verify_ambiguous_marker) << Name;
388 Diags.
Report(M.DefLoc, diag::note_verify_ambiguous_marker) << Name;
389 Diags.
Report(M.RedefLoc, diag::note_verify_ambiguous_marker) << Name;
393 for (
auto &DeferredPair : DeferredDirectives) {
394 Diags.
Report(DeferredPair.second.front().DirectivePos,
395 diag::err_verify_no_such_marker)
396 << DeferredPair.first();
418 for (ParseHelper PH(S); !PH.Done();) {
419 if (!PH.Search(
"#",
true))
422 if (!PH.NextMarker()) {
432 bool FoundDirective =
false;
433 for (ParseHelper PH(S); !PH.Done();) {
438 if (!(Prefixes.size() == 1 ? PH.Search(*Prefixes.begin(),
true,
true)
439 : PH.Search(
"",
true,
true)))
442 StringRef DToken = PH.Match();
445 UnattachedDirective
D;
448 const char *KindStr =
"string";
457 if (DToken.consume_back(
"-re")) {
465 if (DToken.ends_with(
DType =
"-error"))
466 D.DL = ED ? &ED->
Errors :
nullptr;
467 else if (DToken.ends_with(
DType =
"-warning"))
469 else if (DToken.ends_with(
DType =
"-remark"))
471 else if (DToken.ends_with(
DType =
"-note"))
472 D.DL = ED ? &ED->
Notes :
nullptr;
473 else if (DToken.ends_with(
DType =
"-no-diagnostics")) {
479 DToken = DToken.substr(0, DToken.size()-
DType.size());
484 if (!llvm::binary_search(Prefixes, DToken))
490 Diags.
Report(Pos, diag::err_verify_invalid_no_diags)
491 <<
D.Spelling <<
true;
492 }
else if (State.Status !=
495 State.FirstNoDiagnosticsDirective =
D.Spelling;
500 Diags.
Report(Pos, diag::err_verify_invalid_no_diags)
501 <<
D.Spelling <<
false
502 << State.FirstNoDiagnosticsDirective;
515 bool MatchAnyFileAndLine =
false;
516 bool MatchAnyLine =
false;
522 bool FoundPlus = PH.Next(
"+");
523 if (FoundPlus || PH.Next(
"-")) {
527 unsigned ExpectedLine =
SM.getSpellingLineNumber(Pos, &
Invalid);
528 if (!
Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
529 if (FoundPlus) ExpectedLine += Line;
530 else ExpectedLine -= Line;
531 ExpectedLoc =
SM.translateLineCol(
SM.getFileID(Pos), ExpectedLine, 1);
533 }
else if (PH.Next(Line)) {
536 ExpectedLoc =
SM.translateLineCol(
SM.getFileID(Pos), Line, 1);
537 }
else if (PH.NextMarker()) {
539 }
else if (PP && PH.Search(
":")) {
541 StringRef
Filename(PH.C, PH.P-PH.C);
545 MatchAnyFileAndLine =
true;
548 diag::err_verify_missing_line)
558 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
561 diag::err_verify_missing_file)
570 if (PH.Next(Line) && Line > 0)
571 ExpectedLoc =
SM.translateLineCol(FID, Line, 1);
572 else if (PH.Next(
"*")) {
574 ExpectedLoc =
SM.translateLineCol(FID, 1, 1);
577 }
else if (PH.Next(
"*")) {
582 if (ExpectedLoc.
isInvalid() && !MatchAnyLine && Marker.empty()) {
584 diag::err_verify_missing_line) << KindStr;
594 if (PH.Next(
D.Min)) {
601 }
else if (PH.Next(
"-")) {
603 if (!PH.Next(
D.Max) ||
D.Max <
D.Min) {
605 diag::err_verify_invalid_range) << KindStr;
612 }
else if (PH.Next(
"+")) {
622 if (!PH.Next(
"{{")) {
624 diag::err_verify_missing_start) << KindStr;
628 const char *
const DelimBegin = PH.C;
631 for (; !
D.RegexKind && PH.Next(
"{"); PH.Advance())
633 const char*
const ContentBegin = PH.C;
635 StringRef OpenBrace(DelimBegin, ContentBegin - DelimBegin);
636 if (!PH.SearchClosingBrace(OpenBrace, CloseBrace)) {
638 diag::err_verify_missing_end)
639 << KindStr << CloseBrace;
642 const char*
const ContentEnd = PH.P;
645 D.DirectivePos = Pos;
649 StringRef NewlineStr =
"\\n";
650 StringRef Content(ContentBegin, ContentEnd-ContentBegin);
653 while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) {
654 D.Text += Content.substr(CPos, FPos-CPos);
656 CPos = FPos + NewlineStr.size();
659 D.Text.assign(ContentBegin, ContentEnd);
662 if (
D.RegexKind &&
D.Text.find(
"{{") == StringRef::npos) {
663 Diags.
Report(
D.ContentBegin, diag::err_verify_missing_regex) <<
D.Text;
668 attachDirective(Diags,
D, ExpectedLoc, MatchAnyFileAndLine, MatchAnyLine);
671 FoundDirective =
true;
674 return FoundDirective;
678 : Diags(Diags_), PrimaryClient(Diags.getClient()),
679 PrimaryClientOwner(Diags.takeClient()),
681 State{HasNoDirectives, {}} {
682 if (Diags.hasSourceManager())
683 setSourceManager(Diags.getSourceManager());
687 assert(!ActiveSourceFiles &&
"Incomplete parsing of source files!");
688 assert(!CurrentPreprocessor &&
"CurrentPreprocessor should be invalid!");
689 SrcManager =
nullptr;
692 "The VerifyDiagnosticConsumer takes over ownership of the client!");
700 if (++ActiveSourceFiles == 1) {
702 CurrentPreprocessor = PP;
703 this->LangOpts = &LangOpts;
705 const_cast<Preprocessor *
>(PP)->addCommentHandler(
this);
709 std::make_unique<VerifyFileTracker>(*
this, *SrcManager));
714 assert((!PP || CurrentPreprocessor == PP) &&
"Preprocessor changed!");
719 assert(ActiveSourceFiles &&
"No active source files!");
723 if (--ActiveSourceFiles == 0) {
724 if (CurrentPreprocessor)
726 removeCommentHandler(
this);
733 CurrentPreprocessor =
nullptr;
760 if (FE && CurrentPreprocessor && SrcManager->
isLoadedFileID(FID)) {
775 Buffer->HandleDiagnostic(DiagLevel, Info);
785 if (SrcManager && &
SM != SrcManager)
790 const char *CommentRaw =
SM.getCharacterData(CommentBegin);
791 StringRef
C(CommentRaw,
SM.getCharacterData(Comment.
getEnd()) - CommentRaw);
797 size_t loc =
C.find(
'\\');
798 if (loc == StringRef::npos) {
804 C2.reserve(
C.size());
806 for (
size_t last = 0;; loc =
C.find(
'\\', last)) {
807 if (loc == StringRef::npos || loc ==
C.size()) {
808 C2 +=
C.substr(last);
811 C2 +=
C.substr(last, loc-last);
814 if (last <
C.size() && (
C[last] ==
'\n' ||
C[last] ==
'\r')) {
819 if (
C[last] ==
'\n' ||
C[last] ==
'\r')
820 if (
C[last] !=
C[last-1])
846 llvm::MemoryBufferRef FromFile =
SM.getBufferOrFake(FID);
847 Lexer RawLex(FID, FromFile,
SM, LangOpts);
856 while (Tok.
isNot(tok::eof)) {
858 if (!Tok.
is(tok::comment))
continue;
861 if (Comment.empty())
continue;
881 if (diag_begin == diag_end)
return 0;
884 llvm::raw_svector_ostream OS(Fmt);
886 if (I->first.isInvalid() || !SourceMgr)
887 OS <<
"\n (frontend)";
892 OS <<
" File " <<
File->getName();
895 OS <<
": " << I->second;
898 const bool IsSinglePrefix =
902 << IsSinglePrefix << Prefix << Kind <<
true << OS.str();
903 return std::distance(diag_begin, diag_end);
910 std::vector<Directive *> &DL,
const char *Kind) {
914 const bool IsSinglePrefix =
918 llvm::raw_svector_ostream OS(Fmt);
919 for (
const auto *
D : DL) {
920 if (
D->DiagnosticLoc.isInvalid() ||
D->MatchAnyFileAndLine)
923 OS <<
"\n File " << SourceMgr.
getFilename(
D->DiagnosticLoc);
928 if (
D->DirectiveLoc !=
D->DiagnosticLoc)
929 OS <<
" (directive at "
933 OS <<
" \'" <<
D->Spelling <<
'\'';
934 OS <<
": " <<
D->Text;
939 << IsSinglePrefix << Prefix << Kind <<
false << OS.str();
947 DiagnosticLoc =
SM.getImmediateMacroCallerLoc(DiagnosticLoc);
949 if (
SM.isWrittenInSameFile(DirectiveLoc, DiagnosticLoc))
952 const FileEntry *DiagFile =
SM.getFileEntryForID(
SM.getFileID(DiagnosticLoc));
953 if (!DiagFile &&
SM.isWrittenInMainFile(DirectiveLoc))
956 return (DiagFile ==
SM.getFileEntryForID(
SM.getFileID(DirectiveLoc)));
966 bool IgnoreUnexpected) {
967 std::vector<Directive *> LeftOnly;
970 for (
auto &Owner : Left) {
974 for (
unsigned i = 0; i <
D.Max; ++i) {
975 DiagList::iterator II, IE;
976 for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
977 if (!
D.MatchAnyLine) {
979 if (LineNo1 != LineNo2)
983 if (!
D.DiagnosticLoc.isInvalid() && !
D.MatchAnyFileAndLine &&
987 const std::string &RightText = II->second;
988 if (
D.match(RightText))
993 if (i >=
D.Min)
break;
994 LeftOnly.push_back(&
D);
1003 if (!IgnoreUnexpected)
1019 unsigned NumProblems = 0;
1051 setSourceManager(
SM);
1061 UnparsedFiles.erase(FID);
1062 ParsedFiles.insert(std::make_pair(FID, FE ? &FE->
getFileEntry() :
nullptr));
1063 }
else if (!ParsedFiles.count(FID) && !UnparsedFiles.count(FID)) {
1067 bool FoundDirectives;
1069 FoundDirectives =
false;
1074 UnparsedFiles.insert(std::make_pair(FID,
1075 UnparsedFileStatus(FE, FoundDirectives)));
1080void VerifyDiagnosticConsumer::CheckDiagnostics() {
1083 std::unique_ptr<DiagnosticConsumer> Owner = Diags.
takeClient();
1093 if (!UnparsedFiles.empty()) {
1096 for (
const auto &I : ParsedFiles)
1098 ParsedFileCache.insert(FE);
1101 for (
const auto &I : UnparsedFiles) {
1102 const UnparsedFileStatus &Status = I.second;
1106 if (FE && ParsedFileCache.count(*FE))
1110 if (Status.foundDirectives()) {
1111 llvm::report_fatal_error(
"-verify directives found after rather"
1112 " than during normal parsing of " +
1113 (FE ? FE->
getName() :
"(unknown)"));
1118 UnparsedFiles.clear();
1136 ~Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected();
1139 Buffer->err_end(),
"error");
1142 Buffer->warn_end(),
"warn");
1145 Buffer->remark_end(),
"remark");
1148 Buffer->note_end(),
"note");
1151 Diags.
setClient(CurClient, Owner.release() !=
nullptr);
1158std::unique_ptr<Directive>
1161 bool MatchAnyFileAndLine,
bool MatchAnyLine, StringRef
Text,
1162 unsigned Min,
unsigned Max) {
1164 return std::make_unique<StandardDirective>(DirectiveLoc, DiagnosticLoc,
1165 Spelling, MatchAnyFileAndLine,
1169 std::string RegexStr;
1171 while (!S.empty()) {
1172 if (S.consume_front(
"{{")) {
1173 size_t RegexMatchLength = S.find(
"}}");
1174 assert(RegexMatchLength != StringRef::npos);
1177 RegexStr.append(S.data(), RegexMatchLength);
1179 S = S.drop_front(RegexMatchLength + 2);
1181 size_t VerbatimMatchLength = S.find(
"{{");
1182 if (VerbatimMatchLength == StringRef::npos)
1183 VerbatimMatchLength = S.size();
1185 RegexStr += llvm::Regex::escape(S.substr(0, VerbatimMatchLength));
1186 S = S.drop_front(VerbatimMatchLength);
1190 return std::make_unique<RegexDirective>(DirectiveLoc, DiagnosticLoc, Spelling,
1191 MatchAnyFileAndLine, MatchAnyLine,
Defines the Diagnostic-related interfaces.
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...
static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, Preprocessor *PP, SourceLocation Pos, VerifyDiagnosticConsumer::ParsingState &State, VerifyDiagnosticConsumer::MarkerTracker &Markers)
ParseDirective - Go through the comment and see if it indicates expected diagnostics.
VerifyDiagnosticConsumer::Directive Directive
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 a...
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.
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.
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, StringRef Spelling, 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.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
DiagnosticLevelMask
A bitmask representing the diagnostic levels used by VerifyDiagnosticConsumer.
@ DType
'dtype' clause, an alias for 'device_type', stored separately for diagnostic purposes.
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.