;
35structDirectiveWithTokens {
40:
Kind(
Kind), NumTokens(NumTokens) {}
63Scanner(StringRef Input,
66: Input(Input), Tokens(Tokens), Diags(Diags),
67InputSourceLoc(InputSourceLoc), LangOpts(getLangOptsForDepScanning()),
68TheLexer(InputSourceLoc, LangOpts, Input.begin(), Input.begin(),
74LangOpts.ObjC =
true;
75LangOpts.LineComment =
true;
76LangOpts.RawStringLiterals =
true;
89lexToken(
const char*&
First,
const char*
constEnd);
92lexIncludeFilename(
const char*&
First,
const char*
constEnd);
94 voidskipLine(
const char*&
First,
const char*
constEnd);
95 voidskipDirective(StringRef Name,
const char*&
First,
const char*
constEnd);
106[[nodiscard]] std::optional<StringRef>
107tryLexIdentifierOrSkipLine(
const char*&
First,
const char*
constEnd);
110[[nodiscard]] StringRef lexIdentifier(
const char*&
First,
111 const char*
constEnd);
118[[nodiscard]]
boolisNextIdentifierOrSkipLine(StringRef
Id,
119 const char*&
First,
120 const char*
constEnd);
128 const char*
constEnd);
135[[nodiscard]] std::optional<StringRef>
136tryLexStringLiteralOrSkipLine(
const char*&
First,
const char*
constEnd);
138[[nodiscard]]
boolscanImpl(
const char*
First,
const char*
constEnd);
139[[nodiscard]]
boollexPPLine(
const char*&
First,
const char*
constEnd);
140[[nodiscard]]
boollexAt(
const char*&
First,
const char*
constEnd);
141[[nodiscard]]
boollexModule(
const char*&
First,
const char*
constEnd);
142[[nodiscard]]
boollexDefine(
const char*HashLoc,
const char*&
First,
143 const char*
constEnd);
144[[nodiscard]]
boollexPragma(
const char*&
First,
const char*
constEnd);
145[[nodiscard]]
boollex_Pragma(
const char*&
First,
const char*
constEnd);
146[[nodiscard]]
boollexEndif(
const char*&
First,
const char*
constEnd);
148 const char*
constEnd);
149[[nodiscard]]
boollexModuleDirectiveBody(
DirectiveKindKind,
150 const char*&
First,
151 const char*
constEnd);
152 voidlexPPDirectiveBody(
const char*&
First,
const char*
constEnd);
155Tokens.append(CurDirToks);
156DirsWithToks.emplace_back(Kind, CurDirToks.size());
158 returnDirsWithToks.back();
160 voidpopDirective() {
161Tokens.pop_back_n(DirsWithToks.pop_back_val().NumTokens);
164 returnDirsWithToks.empty() ?
pp_none: DirsWithToks.back().Kind;
167 unsignedgetOffsetAt(
const char*CurPtr)
const{
168 returnCurPtr - Input.data();
173 boolreportError(
const char*CurPtr,
unsignedErr);
175StringMap<char> SplitIds;
181 const char*LastTokenPtr =
nullptr;
196boolScanner::reportError(
const char*CurPtr,
unsignedErr) {
199assert(CurPtr >= Input.data() &&
"invalid buffer ptr");
200Diags->Report(InputSourceLoc.getLocWithOffset(getOffsetAt(CurPtr)), Err);
210 const char*Current) {
211assert(
First<= Current);
214 if(*Current !=
'"'||
First== Current)
219 if(*Current !=
'R')
225 if(*Current ==
'u'|| *Current ==
'U'|| *Current ==
'L')
229 if(*Current !=
'8'||
First== Current || *Current-- !=
'u')
235assert(
First[0] ==
'"');
236assert(
First[-1] ==
'R');
239 while(
Last!= End && *
Last!=
'(')
258 while(
Last!= End &&
size_t(
Last-
First) < Terminator.size() &&
267 if(
size_t(
Last-
First) < Terminator.size())
277static unsigned isEOL(
const char*
First,
const char*
constEnd) {
288 const charTerminator = *
First==
'<'?
'>': *
First;
293 if(*
First!=
'\\')
303 const char*FirstAfterBackslashPastSpace =
First;
305 if(
unsignedNLSize =
isEOL(FirstAfterBackslashPastSpace, End)) {
308 First= FirstAfterBackslashPastSpace + NLSize - 1;
321assert(Len &&
"expected newline");
327 return*(
First- (
int)EOLLen - 1) ==
'\\';
345 if(
First[-1] !=
'\\')
354assert(
First[0] ==
'/'&&
First[1] ==
'/');
360assert(
First[0] ==
'/'&&
First[1] ==
'*');
361 if(End -
First< 4) {
366 if(
First[-1] ==
'*'&&
First[0] ==
'/') {
375 const char*
constCur,
376 const char*
constEnd) {
377assert(*Cur ==
'\''&&
"expected quotation character");
385 charPrev = *(Cur - 1);
386 if(Prev ==
'L'|| Prev ==
'U'|| Prev ==
'u')
388 if(Prev ==
'8'&& (Cur - 1 != Start) && *(Cur - 2) ==
'u')
396voidScanner::skipLine(
const char*&
First,
const char*
constEnd) {
398assert(
First<= End);
406 const char*Start =
First;
409 if(*
First==
'"'||
411LastTokenPtr =
First;
421LastTokenPtr =
First;
426 if(
First[1] ==
'/') {
432 if(
First[1] !=
'*') {
433LastTokenPtr =
First;
451voidScanner::skipDirective(StringRef Name,
const char*&
First,
452 const char*
constEnd) {
453 if(llvm::StringSwitch<bool>(Name)
454.Case(
"warning",
true)
455.Case(
"error",
true)
460skipLine(
First, End);
465assert(
First<= End);
477 if(
First[0] !=
'/')
481 if(
First[1] ==
'/') {
487 if(
First[1] !=
'*')
496 const char*
constEnd) {
497 const char*DirectiveLoc = Input.data() + CurDirToks.front().Offset;
500 if(Tok.
is(tok::eof))
503diag::err_dep_source_scanner_missing_semi_after_at_import);
504 if(Tok.
is(tok::semi))
513DirectiveLoc, diag::err_dep_source_scanner_unexpected_tokens_at_import);
519 const char*
constEnd) {
521TheLexer.LexFromRawLexer(Tok);
522 First= Input.data() + TheLexer.getCurrentBufferOffset();
523assert(
First<= End);
525 unsignedOffset = TheLexer.getCurrentBufferOffset() - Tok.
getLength();
528 returnCurDirToks.back();
532Scanner::lexIncludeFilename(
const char*&
First,
const char*
constEnd) {
534TheLexer.LexIncludeFilename(Tok);
535 First= Input.data() + TheLexer.getCurrentBufferOffset();
536assert(
First<= End);
538 unsignedOffset = TheLexer.getCurrentBufferOffset() - Tok.
getLength();
541 returnCurDirToks.back();
544voidScanner::lexPPDirectiveBody(
const char*&
First,
const char*
constEnd) {
547 if(Tok.
is(tok::eod) || Tok.
is(tok::eof))
555 if(LLVM_LIKELY(!NeedsCleaning))
559Spelling.resize(Tok.
Length);
564 unsignedSpellingLength = 0;
565 const char*BufPtr = Input.begin() + Tok.
Offset;
566 const char*AfterIdent = Input.begin() + Tok.
getEnd();
567 while(BufPtr < AfterIdent) {
569Spelling[SpellingLength++] = Char;
573 returnSplitIds.try_emplace(StringRef(Spelling.begin(), SpellingLength), 0)
577std::optional<StringRef>
578Scanner::tryLexIdentifierOrSkipLine(
const char*&
First,
const char*
constEnd) {
580 if(Tok.
isNot(tok::raw_identifier)) {
581 if(!Tok.
is(tok::eod))
582skipLine(
First, End);
586 returncleanStringIfNeeded(Tok);
589StringRef Scanner::lexIdentifier(
const char*&
First,
const char*
constEnd) {
590std::optional<StringRef>
Id= tryLexIdentifierOrSkipLine(
First, End);
591assert(
Id&&
"expected identifier token");
595boolScanner::isNextIdentifierOrSkipLine(StringRef
Id,
const char*&
First,
596 const char*
constEnd) {
597 if(std::optional<StringRef> FoundId =
598tryLexIdentifierOrSkipLine(
First, End)) {
601skipLine(
First, End);
607 const char*
constEnd) {
611skipLine(
First, End);
615std::optional<StringRef>
616Scanner::tryLexStringLiteralOrSkipLine(
const char*&
First,
617 const char*
constEnd) {
620 if(!Tok.
is(tok::eod))
621skipLine(
First, End);
625 returncleanStringIfNeeded(Tok);
628boolScanner::lexAt(
const char*&
First,
const char*
constEnd) {
633assert(AtTok.
is(tok::at));
636 if(!isNextIdentifierOrSkipLine(
"import",
First, End))
641boolScanner::lexModule(
const char*&
First,
const char*
constEnd) {
642StringRef
Id= lexIdentifier(
First, End);
643 boolExport =
false;
644 if(
Id==
"export") {
646std::optional<StringRef> NextId = tryLexIdentifierOrSkipLine(
First, End);
652 if(
Id!=
"module"&&
Id!=
"import") {
653skipLine(
First, End);
665 if(
Id==
"module") {
666skipLine(
First, End);
670(void)lexToken(
First, End);
671 if(!tryLexIdentifierOrSkipLine(
First, End))
680skipLine(
First, End);
685TheLexer.seek(getOffsetAt(
First),
false);
688 if(
Id==
"module")
693 returnlexModuleDirectiveBody(Kind,
First, End);
696boolScanner::lex_Pragma(
const char*&
First,
const char*
constEnd) {
697 if(!isNextTokenOrSkipLine(tok::l_paren,
First, End))
700std::optional<StringRef> Str = tryLexStringLiteralOrSkipLine(
First, End);
702 if(!Str || !isNextTokenOrSkipLine(tok::r_paren,
First, End))
712 const char*
Begin= Buffer.c_str();
713Scanner PragmaScanner{StringRef(
Begin, Buffer.size()), DiscardTokens, Diags,
716PragmaScanner.TheLexer.setParsingPreprocessorDirective(
true);
717 if(PragmaScanner.lexPragma(
Begin, Buffer.end()))
722skipLine(
First, End);
726assert(
Begin== Buffer.end());
731boolScanner::lexPragma(
const char*&
First,
const char*
constEnd) {
732std::optional<StringRef> FoundId = tryLexIdentifierOrSkipLine(
First, End);
736StringRef
Id= *FoundId;
737 auto Kind= llvm::StringSwitch<DirectiveKind>(
Id)
744lexPPDirectiveBody(
First, End);
749 if(
Id!=
"clang") {
750skipLine(
First, End);
754FoundId = tryLexIdentifierOrSkipLine(
First, End);
760 if(
Id==
"system_header") {
761lexPPDirectiveBody(
First, End);
766 if(
Id!=
"module") {
767skipLine(
First, End);
772 if(!isNextIdentifierOrSkipLine(
"import",
First, End))
776lexPPDirectiveBody(
First, End);
781boolScanner::lexEndif(
const char*&
First,
const char*
constEnd) {
783 if(topDirective() ==
pp_else)
794skipLine(
First, End);
802 const char*
constEnd) {
803lexPPDirectiveBody(
First, End);
821boolScanner::lexPPLine(
const char*&
First,
const char*
constEnd) {
822assert(
First!= End);
825assert(
First<= End);
830skipLine(
First, End);
831assert(
First<= End);
835LastTokenPtr =
First;
837TheLexer.seek(getOffsetAt(
First),
true);
839 autoScEx1 = make_scope_exit([&]() {
847 returnlexAt(
First, End);
850 returnlexModule(
First, End);
852 if(*
First==
'_') {
853 if(isNextIdentifierOrSkipLine(
"_Pragma",
First, End))
854 returnlex_Pragma(
First, End);
860TheLexer.setParsingPreprocessorDirective(
true);
861 autoScEx2 = make_scope_exit(
862[&]() { TheLexer.setParsingPreprocessorDirective(
false); });
866 if(HashTok.is(tok::hashhash)) {
870skipLine(
First, End);
871assert(
First<= End);
874assert(HashTok.is(tok::hash));
877std::optional<StringRef> FoundId = tryLexIdentifierOrSkipLine(
First, End);
881StringRef
Id= *FoundId;
883 if(
Id==
"pragma")
884 returnlexPragma(
First, End);
886 auto Kind= llvm::StringSwitch<DirectiveKind>(
Id)
893.Case(
"if",
pp_if)
903skipDirective(
Id,
First, End);
908 returnlexEndif(
First, End);
916 if(lexIncludeFilename(
First, End).is(tok::eod)) {
925 returnlexDefault(Kind,
First, End);
929 if((End -
First) >= 3 &&
First[0] ==
'\xef'&&
First[1] ==
'\xbb'&&
930 First[2] ==
'\xbf')
934boolScanner::scanImpl(
const char*
First,
const char*
constEnd) {
936 while(
First!= End)
937 if(lexPPLine(
First, End))
943 bool Error= scanImpl(Input.begin(), Input.end());
948(Tokens.empty() || LastTokenPtr > Input.begin() + Tokens.back().Offset))
954 for(
constDirectiveWithTokens &DirWithToks : DirsWithToks) {
955assert(RemainingTokens.size() >= DirWithToks.NumTokens);
956Directives.emplace_back(DirWithToks.Kind,
957RemainingTokens.take_front(DirWithToks.NumTokens));
958RemainingTokens = RemainingTokens.drop_front(DirWithToks.NumTokens);
960assert(RemainingTokens.empty());
969 returnScanner(Input, Tokens, Diags, InputSourceLoc).scan(Directives);
975llvm::raw_ostream &OS) {
977 autoneedsSpaceSeparator =
980 if(Prev == Tok.
Kind)
981 return!Tok.
isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
983 if(Prev == tok::raw_identifier &&
984Tok.
isOneOf(tok::hash, tok::numeric_constant, tok::string_literal,
985tok::char_constant, tok::header_name))
987 if(Prev == tok::r_paren &&
988Tok.
isOneOf(tok::raw_identifier, tok::hash, tok::string_literal,
989tok::char_constant, tok::unknown))
991 if(Prev == tok::comma &&
992Tok.
isOneOf(tok::l_paren, tok::string_literal, tok::less))
999OS <<
"<TokBeforeEOF>";
1000std::optional<tok::TokenKind> PrevTokenKind;
1002 if(PrevTokenKind && needsSpaceSeparator(*PrevTokenKind, Tok))
1004PrevTokenKind = Tok.
Kind;
Defines the Diagnostic-related interfaces.
static void skipBlockComment(const char *&First, const char *const End)
static void skipRawString(const char *&First, const char *const End)
static void skipString(const char *&First, const char *const End)
static bool isStartOfRelevantLine(char First)
static void skipWhitespace(const char *&First, const char *const End)
static bool isRawStringLiteral(const char *First, const char *Current)
static void skipOverSpaces(const char *&First, const char *const End)
static unsigned isEOL(const char *First, const char *const End)
static void skipToNewlineRaw(const char *&First, const char *const End)
static unsigned skipNewline(const char *&First, const char *End)
static void skipUTF8ByteOrderMark(const char *&First, const char *const End)
static void skipLineComment(const char *&First, const char *const End)
static bool isQuoteCppDigitSeparator(const char *const Start, const char *const Cur, const char *const End)
static bool wasLineContinuation(const char *First, unsigned EOLLen)
This is the interface for scanning header and source files to get the minimum necessary preprocessor ...
Concrete class used by the front-end to report problems and issues.
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.
static SizedChar getCharAndSizeNoWarn(const char *Ptr, const LangOptions &LangOpts)
getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever emit a warning.
Encodes a location in the source.
Token - This structure provides full information about a lexed token.
unsigned getFlags() const
Return the internal represtation of the flags.
unsigned getLength() const
tok::TokenKind getKind() const
DirectiveKind
Represents the kind of preprocessor directive or a module declaration that is tracked by the scanner ...
@ tokens_present_before_eof
Indicates that there are tokens present between the last scanned directive and eof.
@ pp_pragma_system_header
@ pp_pragma_include_alias
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
The JSON file list parser is used to communicate input to InstallAPI.
LLVM_READONLY bool isVerticalWhitespace(unsigned char c)
Returns true if this character is vertical ASCII whitespace: '\n', '\r'.
LLVM_READONLY bool isAsciiIdentifierContinue(unsigned char c)
void printDependencyDirectivesAsSource(StringRef Source, ArrayRef< dependency_directives_scan::Directive > Directives, llvm::raw_ostream &OS)
Print the previously scanned dependency directives as minimized source text.
LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)
Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.
bool scanSourceForDependencyDirectives(StringRef Input, SmallVectorImpl< dependency_directives_scan::Token > &Tokens, SmallVectorImpl< dependency_directives_scan::Directive > &Directives, DiagnosticsEngine *Diags=nullptr, SourceLocation InputSourceLoc=SourceLocation())
Scan the input for the preprocessor directives that might have an effect on the dependencies for a co...
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...
LLVM_READONLY bool isPreprocessingNumberBody(unsigned char c)
Return true if this is the body character of a C preprocessing number, which is [a-zA-Z0-9_.
void prepare_PragmaString(SmallVectorImpl< char > &StrVal)
Destringize a _Pragma("") string according to C11 6.10.9.1: "The string literal is destringized by de...
Diagnostic wrappers for TextAPI types for error reporting.
Represents a directive that's lexed as part of the dependency directives scanning.
DirectiveKind Kind
The kind of token.
Token lexed as part of dependency directive scanning.
bool isNot(tok::TokenKind K) const
unsigned Offset
Offset into the original source input.
bool is(tok::TokenKind K) const
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4