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,
95 MatchAnyLine,
Text, Min, Max) {}
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,
112 MatchAnyLine,
Text, Min, Max),
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.startswith(OpenBrace)) {
231 P += OpenBrace.size();
232 }
else if (S.startswith(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();
410 for (ParseHelper PH(S); !PH.Done();) {
411 if (!PH.Search(
"#",
true))
414 if (!PH.NextMarker()) {
424 bool FoundDirective =
false;
425 for (ParseHelper PH(S); !PH.Done();) {
430 if (!(Prefixes.size() == 1 ? PH.Search(*Prefixes.begin(),
true,
true)
431 : PH.Search(
"",
true,
true)))
434 StringRef DToken = PH.Match();
438 UnattachedDirective D;
439 const char *KindStr =
"string";
448 if (DToken.endswith(
"-re")) {
451 DToken = DToken.substr(0, DToken.size()-3);
457 if (DToken.endswith(DType=
"-error"))
458 D.DL = ED ? &ED->
Errors :
nullptr;
459 else if (DToken.endswith(DType=
"-warning"))
460 D.DL = ED ? &ED->
Warnings :
nullptr;
461 else if (DToken.endswith(DType=
"-remark"))
462 D.DL = ED ? &ED->
Remarks :
nullptr;
463 else if (DToken.endswith(DType=
"-note"))
464 D.DL = ED ? &ED->
Notes :
nullptr;
465 else if (DToken.endswith(DType=
"-no-diagnostics")) {
472 DToken = DToken.substr(0, DToken.size()-DType.size());
477 if (!std::binary_search(Prefixes.begin(), Prefixes.end(), DToken))
482 Diags.
Report(Pos, diag::err_verify_invalid_no_diags)
489 Diags.
Report(Pos, diag::err_verify_invalid_no_diags)
503 bool MatchAnyFileAndLine =
false;
504 bool MatchAnyLine =
false;
510 bool FoundPlus = PH.Next(
"+");
511 if (FoundPlus || PH.Next(
"-")) {
515 unsigned ExpectedLine =
SM.getSpellingLineNumber(Pos, &
Invalid);
516 if (!
Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) {
517 if (FoundPlus) ExpectedLine += Line;
518 else ExpectedLine -= Line;
519 ExpectedLoc =
SM.translateLineCol(
SM.getFileID(Pos), ExpectedLine, 1);
521 }
else if (PH.Next(Line)) {
524 ExpectedLoc =
SM.translateLineCol(
SM.getFileID(Pos), Line, 1);
525 }
else if (PH.NextMarker()) {
527 }
else if (PP && PH.Search(
":")) {
529 StringRef
Filename(PH.C, PH.P-PH.C);
533 MatchAnyFileAndLine =
true;
536 diag::err_verify_missing_line)
546 nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
549 diag::err_verify_missing_file)
558 if (PH.Next(Line) && Line > 0)
559 ExpectedLoc =
SM.translateLineCol(FID, Line, 1);
560 else if (PH.Next(
"*")) {
562 ExpectedLoc =
SM.translateLineCol(FID, 1, 1);
565 }
else if (PH.Next(
"*")) {
570 if (ExpectedLoc.
isInvalid() && !MatchAnyLine && Marker.empty()) {
572 diag::err_verify_missing_line) << KindStr;
582 if (PH.Next(D.Min)) {
589 }
else if (PH.Next(
"-")) {
591 if (!PH.Next(D.Max) || D.Max < D.Min) {
593 diag::err_verify_invalid_range) << KindStr;
600 }
else if (PH.Next(
"+")) {
610 if (!PH.Next(
"{{")) {
612 diag::err_verify_missing_start) << KindStr;
616 const char*
const ContentBegin = PH.C;
618 if (!PH.SearchClosingBrace(
"{{",
"}}")) {
620 diag::err_verify_missing_end) << KindStr;
623 const char*
const ContentEnd = PH.P;
626 D.DirectivePos = Pos;
630 StringRef NewlineStr =
"\\n";
631 StringRef Content(ContentBegin, ContentEnd-ContentBegin);
634 while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) {
635 D.Text += Content.substr(CPos, FPos-CPos);
637 CPos = FPos + NewlineStr.size();
640 D.Text.assign(ContentBegin, ContentEnd);
643 if (D.RegexKind && D.Text.find(
"{{") == StringRef::npos) {
644 Diags.
Report(D.ContentBegin, diag::err_verify_missing_regex) << D.Text;
649 attachDirective(Diags, D, ExpectedLoc, MatchAnyFileAndLine, MatchAnyLine);
652 FoundDirective =
true;
655 return FoundDirective;
659 : Diags(Diags_), PrimaryClient(Diags.getClient()),
660 PrimaryClientOwner(Diags.takeClient()),
662 Status(HasNoDirectives) {
668 assert(!ActiveSourceFiles &&
"Incomplete parsing of source files!");
669 assert(!CurrentPreprocessor &&
"CurrentPreprocessor should be invalid!");
670 SrcManager =
nullptr;
673 "The VerifyDiagnosticConsumer takes over ownership of the client!");
681 if (++ActiveSourceFiles == 1) {
683 CurrentPreprocessor = PP;
684 this->LangOpts = &LangOpts;
686 const_cast<Preprocessor *
>(PP)->addCommentHandler(
this);
690 std::make_unique<VerifyFileTracker>(*
this, *SrcManager));
695 assert((!PP || CurrentPreprocessor == PP) &&
"Preprocessor changed!");
700 assert(ActiveSourceFiles &&
"No active source files!");
704 if (--ActiveSourceFiles == 0) {
705 if (CurrentPreprocessor)
707 removeCommentHandler(
this);
714 CurrentPreprocessor =
nullptr;
741 if (FE && CurrentPreprocessor && SrcManager->
isLoadedFileID(FID)) {
756 Buffer->HandleDiagnostic(DiagLevel, Info);
766 if (SrcManager && &
SM != SrcManager)
771 const char *CommentRaw =
SM.getCharacterData(CommentBegin);
772 StringRef
C(CommentRaw,
SM.getCharacterData(Comment.
getEnd()) - CommentRaw);
778 size_t loc =
C.find(
'\\');
779 if (loc == StringRef::npos) {
785 C2.reserve(
C.size());
787 for (
size_t last = 0;; loc =
C.find(
'\\', last)) {
788 if (loc == StringRef::npos || loc ==
C.size()) {
789 C2 +=
C.substr(last);
792 C2 +=
C.substr(last, loc-last);
795 if (
C[last] ==
'\n' ||
C[last] ==
'\r') {
800 if (
C[last] ==
'\n' ||
C[last] ==
'\r')
801 if (
C[last] !=
C[last-1])
827 llvm::MemoryBufferRef FromFile =
SM.getBufferOrFake(FID);
828 Lexer RawLex(FID, FromFile,
SM, LangOpts);
837 while (Tok.
isNot(tok::eof)) {
839 if (!Tok.
is(tok::comment))
continue;
842 if (Comment.empty())
continue;
862 if (diag_begin == diag_end)
return 0;
865 llvm::raw_svector_ostream OS(Fmt);
867 if (I->first.isInvalid() || !SourceMgr)
868 OS <<
"\n (frontend)";
873 OS <<
" File " <<
File->getName();
876 OS <<
": " << I->second;
880 << Kind <<
true << OS.str();
881 return std::distance(diag_begin, diag_end);
888 std::vector<Directive *> &DL,
const char *Kind) {
893 llvm::raw_svector_ostream OS(Fmt);
894 for (
const auto *D : DL) {
895 if (D->DiagnosticLoc.isInvalid() || D->MatchAnyFileAndLine)
898 OS <<
"\n File " << SourceMgr.
getFilename(D->DiagnosticLoc);
903 if (D->DirectiveLoc != D->DiagnosticLoc)
904 OS <<
" (directive at "
907 OS <<
": " << D->Text;
911 << Kind <<
false << OS.str();
919 DiagnosticLoc =
SM.getImmediateMacroCallerLoc(DiagnosticLoc);
921 if (
SM.isWrittenInSameFile(DirectiveLoc, DiagnosticLoc))
924 const FileEntry *DiagFile =
SM.getFileEntryForID(
SM.getFileID(DiagnosticLoc));
925 if (!DiagFile &&
SM.isWrittenInMainFile(DirectiveLoc))
928 return (DiagFile ==
SM.getFileEntryForID(
SM.getFileID(DirectiveLoc)));
938 bool IgnoreUnexpected) {
939 std::vector<Directive *> LeftOnly;
942 for (
auto &Owner : Left) {
946 for (
unsigned i = 0; i < D.
Max; ++i) {
947 DiagList::iterator II, IE;
948 for (II = Right.begin(), IE = Right.end(); II != IE; ++II) {
951 if (LineNo1 != LineNo2)
959 const std::string &RightText = II->second;
960 if (D.
match(RightText))
965 if (i >= D.
Min)
break;
966 LeftOnly.push_back(&D);
975 if (!IgnoreUnexpected)
991 unsigned NumProblems = 0;
1023 setSourceManager(
SM);
1033 UnparsedFiles.erase(FID);
1034 ParsedFiles.insert(std::make_pair(FID, FE));
1035 }
else if (!ParsedFiles.count(FID) && !UnparsedFiles.count(FID)) {
1039 bool FoundDirectives;
1041 FoundDirectives =
false;
1046 UnparsedFiles.insert(std::make_pair(FID,
1047 UnparsedFileStatus(FE, FoundDirectives)));
1052void VerifyDiagnosticConsumer::CheckDiagnostics() {
1055 std::unique_ptr<DiagnosticConsumer> Owner = Diags.
takeClient();
1065 if (!UnparsedFiles.empty()) {
1068 for (
const auto &I : ParsedFiles)
1070 ParsedFileCache.insert(FE);
1073 for (
const auto &I : UnparsedFiles) {
1074 const UnparsedFileStatus &Status = I.second;
1078 if (FE && ParsedFileCache.count(FE))
1082 if (Status.foundDirectives()) {
1083 llvm::report_fatal_error(Twine(
"-verify directives found after rather"
1084 " than during normal parsing of ",
1085 StringRef(FE ? FE->
getName() :
"(unknown)")));
1090 UnparsedFiles.clear();
1107 ~Diags.getDiagnosticOptions().getVerifyIgnoreUnexpected();
1110 Buffer->err_end(),
"error");
1113 Buffer->warn_end(),
"warn");
1116 Buffer->remark_end(),
"remark");
1119 Buffer->note_end(),
"note");
1122 Diags.
setClient(CurClient, Owner.release() !=
nullptr);
1132 bool MatchAnyFileAndLine,
1133 bool MatchAnyLine, StringRef
Text,
1134 unsigned Min,
unsigned Max) {
1136 return std::make_unique<StandardDirective>(DirectiveLoc, DiagnosticLoc,
1137 MatchAnyFileAndLine,
1138 MatchAnyLine,
Text, Min, Max);
1141 std::string RegexStr;
1143 while (!S.empty()) {
1144 if (S.startswith(
"{{")) {
1145 S = S.drop_front(2);
1146 size_t RegexMatchLength = S.find(
"}}");
1147 assert(RegexMatchLength != StringRef::npos);
1150 RegexStr.append(S.data(), RegexMatchLength);
1152 S = S.drop_front(RegexMatchLength + 2);
1154 size_t VerbatimMatchLength = S.find(
"{{");
1155 if (VerbatimMatchLength == StringRef::npos)
1156 VerbatimMatchLength = S.size();
1158 RegexStr += llvm::Regex::escape(S.substr(0, VerbatimMatchLength));
1159 S = S.drop_front(VerbatimMatchLength);
1163 return std::make_unique<RegexDirective>(DirectiveLoc, DiagnosticLoc,
1164 MatchAnyFileAndLine, MatchAnyLine,
1165 Text, Min, Max, RegexStr);
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.
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 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.
Cached information about one file (either on disk or in the virtual file system).
StringRef getName() const
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.
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
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
SourceLocation DiagnosticLoc
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...
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].
@ C
Languages that the frontend can parse and compile.
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.