29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/StringExtras.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/ADT/StringSwitch.h"
33#include "llvm/Support/Compiler.h"
34#include "llvm/Support/ConvertUTF.h"
35#include "llvm/Support/MemoryBufferRef.h"
36#include "llvm/Support/NativeFormatting.h"
37#include "llvm/Support/SaveAndRestore.h"
38#include "llvm/Support/Unicode.h"
39#include "llvm/Support/UnicodeCharRanges.h"
65 return II->getObjCKeywordID() == objcKey;
72 return tok::objc_not_keyword;
78 if (AllowExport &&
is(tok::kw_export))
80 if (
isOneOf(tok::kw_import, tok::kw_module))
82 if (
isNot(tok::identifier))
85 return II->isImportKeyword() || II->isModuleKeyword();
91 case tok::annot_typename:
92 case tok::annot_decltype:
93 case tok::annot_pack_indexing_type:
99 case tok::kw___int128:
101 case tok::kw_unsigned:
109 case tok::kw__Float16:
110 case tok::kw___float128:
111 case tok::kw___ibm128:
112 case tok::kw_wchar_t:
118#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
119#include "clang/Basic/BuiltinTraits.inc"
120 case tok::kw___auto_type:
121 case tok::kw_char16_t:
122 case tok::kw_char32_t:
124 case tok::kw_decltype:
125 case tok::kw_char8_t:
137void Lexer::anchor() {}
139void Lexer::InitLexer(
const char *BufStart,
const char *BufPtr,
140 const char *BufEnd) {
141 BufferStart = BufStart;
145 assert(BufEnd[0] == 0 &&
146 "We assume that the input buffer has a null character at the end"
147 " to simplify lexing!");
152 if (BufferStart == BufferPtr) {
154 StringRef Buf(BufferStart, BufferEnd - BufferStart);
155 size_t BOMLength = llvm::StringSwitch<size_t>(Buf)
156 .StartsWith(
"\xEF\xBB\xBF", 3)
160 BufferPtr += BOMLength;
163 Is_PragmaLexer =
false;
164 CurrentConflictMarkerState =
CMK_None;
167 IsAtStartOfLine =
true;
168 IsAtPhysicalStartOfLine =
true;
170 HasLeadingSpace =
false;
171 HasLeadingEmptyMacro =
false;
186 ExtendedTokenMode = 0;
188 NewLinePtr =
nullptr;
198 FileLoc(
PP.getSourceManager().getLocForStartOfFile(
FID)),
199 LangOpts(
PP.getLangOpts()), LineComment(LangOpts.LineComment),
200 IsFirstTimeLexingFile(IsFirstIncludeOfFile) {
201 InitLexer(InputFile.getBufferStart(), InputFile.getBufferStart(),
202 InputFile.getBufferEnd());
211 const char *BufStart,
const char *BufPtr,
const char *BufEnd,
212 bool IsFirstIncludeOfFile)
213 : FileLoc(fileloc), LangOpts(langOpts), LineComment(LangOpts.LineComment),
214 IsFirstTimeLexingFile(IsFirstIncludeOfFile) {
215 InitLexer(BufStart, BufPtr, BufEnd);
226 bool IsFirstIncludeOfFile)
227 :
Lexer(SM.getLocForStartOfFile(
FID), langOpts, FromFile.getBufferStart(),
228 FromFile.getBufferStart(), FromFile.getBufferEnd(),
229 IsFirstIncludeOfFile) {}
232 assert(
PP &&
"Cannot reset token mode without a preprocessor");
233 if (LangOpts.TraditionalCPP)
262 auto L = std::make_unique<Lexer>(SpellingFID, InputFile,
PP);
269 L->BufferPtr = StrData;
270 L->BufferEnd = StrData+TokLen;
271 assert(L->BufferEnd[0] == 0 &&
"Buffer is not nul terminated!");
277 ExpansionLocEnd, TokLen);
281 L->ParsingPreprocessorDirective =
true;
284 L->Is_PragmaLexer =
true;
289 this->IsAtPhysicalStartOfLine = IsAtStartOfLine;
290 this->IsAtStartOfLine = IsAtStartOfLine;
291 assert((BufferStart + Offset) <= BufferEnd);
292 BufferPtr = BufferStart + Offset;
296 typename T::size_type i = 0, e = Str.size();
298 if (Str[i] ==
'\\' || Str[i] == Quote) {
299 Str.insert(Str.begin() + i,
'\\');
302 }
else if (Str[i] ==
'\n' || Str[i] ==
'\r') {
304 if ((i < e - 1) && (Str[i + 1] ==
'\n' || Str[i + 1] ==
'\r') &&
305 Str[i] != Str[i + 1]) {
311 Str.insert(Str.begin() + i + 1,
'n');
321 std::string
Result = std::string(Str);
322 char Quote = Charify ?
'\'' :
'"';
337 assert(
Tok.needsCleaning() &&
"getSpellingSlow called on simple token");
340 const char *BufEnd = BufPtr +
Tok.getLength();
344 while (BufPtr < BufEnd) {
346 Spelling[Length++] = CharAndSize.Char;
347 BufPtr += CharAndSize.Size;
349 if (Spelling[Length - 1] ==
'"')
357 Spelling[Length - 2] ==
'R' && Spelling[Length - 1] ==
'"') {
360 const char *RawEnd = BufEnd;
361 do --RawEnd;
while (*RawEnd !=
'"');
362 size_t RawLength = RawEnd - BufPtr + 1;
365 memcpy(Spelling + Length, BufPtr, RawLength);
373 while (BufPtr < BufEnd) {
375 Spelling[Length++] = CharAndSize.Char;
376 BufPtr += CharAndSize.Size;
379 assert(Length <
Tok.getLength() &&
380 "NeedsCleaning flag set on token that didn't need cleaning!");
398 bool invalidTemp =
false;
399 StringRef file = SM.
getBufferData(locInfo.first, &invalidTemp);
401 if (invalid) *invalid =
true;
405 const char *tokenBegin = file.data() + locInfo.second;
409 file.begin(), tokenBegin, file.end());
417 return StringRef(tokenBegin,
length);
422 return StringRef(buffer.data(), buffer.size());
432 assert((
int)
Tok.getLength() >= 0 &&
"Token character range is bogus!");
434 bool CharDataInvalid =
false;
435 const char *TokStart = SourceMgr.getCharacterData(
Tok.getLocation(),
443 if (!
Tok.needsCleaning())
444 return std::string(TokStart, TokStart +
Tok.getLength());
465 assert((
int)
Tok.getLength() >= 0 &&
"Token character range is bogus!");
467 const char *TokStart =
nullptr;
469 if (
Tok.is(tok::raw_identifier))
470 TokStart =
Tok.getRawIdentifier().data();
471 else if (!
Tok.hasUCN()) {
474 Buffer = II->getNameStart();
475 return II->getLength();
481 TokStart =
Tok.getLiteralData();
485 bool CharDataInvalid =
false;
486 TokStart = SourceMgr.getCharacterData(
Tok.getLocation(), &CharDataInvalid);
489 if (CharDataInvalid) {
496 if (!
Tok.needsCleaning()) {
498 return Tok.getLength();
527 const char *StrData = Buffer.data() + LocInfo.second;
528 if (StrData >= Buffer.end())
534 Buffer.begin(), StrData, Buffer.end());
537 TheLexer.LexIdentifierContinue(
Tok, StrData);
546 bool IgnoreWhiteSpace) {
562 const char *StrData = Buffer.data()+LocInfo.second;
564 if (!IgnoreWhiteSpace &&
isWhitespace(SkipEscapedNewLines(StrData)[0]))
569 Buffer.begin(), StrData, Buffer.end());
578 const char *BufStart = Buffer.data();
579 if (Offset >= Buffer.size())
582 const char *LexStart = BufStart + Offset;
583 for (; LexStart != BufStart; --LexStart) {
599 if (LocInfo.first.isInvalid())
609 const char *StrData = Buffer.data() + LocInfo.second;
611 if (!LexStart || LexStart == StrData)
616 Lexer TheLexer(LexerStartLoc, LangOpts, Buffer.data(), LexStart,
636 }
while (TheTok.
getKind() != tok::eof);
655 assert(FileLocInfo.first == BeginFileLocInfo.first &&
656 FileLocInfo.second >= BeginFileLocInfo.second);
662enum PreambleDirectiveKind {
677 Lexer TheLexer(FileLoc, LangOpts, Buffer.begin(), Buffer.begin(),
681 bool InPreprocessorDirective =
false;
685 unsigned MaxLineOffset = 0;
687 const char *CurPtr = Buffer.begin();
688 unsigned CurLine = 0;
689 while (CurPtr != Buffer.end()) {
693 if (CurLine == MaxLines)
697 if (CurPtr != Buffer.end())
698 MaxLineOffset = CurPtr - Buffer.begin();
704 if (InPreprocessorDirective) {
706 if (TheTok.
getKind() == tok::eof) {
717 InPreprocessorDirective =
false;
726 if (MaxLineOffset && TokOffset >= MaxLineOffset)
731 if (TheTok.
getKind() == tok::comment) {
739 Token HashTok = TheTok;
740 InPreprocessorDirective =
true;
749 PreambleDirectiveKind PDK
750 = llvm::StringSwitch<PreambleDirectiveKind>(
Keyword)
751 .Case(
"include", PDK_Skipped)
752 .Case(
"__include_macros", PDK_Skipped)
753 .Case(
"define", PDK_Skipped)
754 .Case(
"undef", PDK_Skipped)
755 .Case(
"line", PDK_Skipped)
756 .Case(
"error", PDK_Skipped)
757 .Case(
"pragma", PDK_Skipped)
758 .Case(
"import", PDK_Skipped)
759 .Case(
"include_next", PDK_Skipped)
760 .Case(
"warning", PDK_Skipped)
761 .Case(
"ident", PDK_Skipped)
762 .Case(
"sccs", PDK_Skipped)
763 .Case(
"assert", PDK_Skipped)
764 .Case(
"unassert", PDK_Skipped)
765 .Case(
"if", PDK_Skipped)
766 .Case(
"ifdef", PDK_Skipped)
767 .Case(
"ifndef", PDK_Skipped)
768 .Case(
"elif", PDK_Skipped)
769 .Case(
"elifdef", PDK_Skipped)
770 .Case(
"elifndef", PDK_Skipped)
771 .Case(
"else", PDK_Skipped)
772 .Case(
"endif", PDK_Skipped)
773 .Default(PDK_Unknown);
790 TheTok.
getKind() == tok::raw_identifier &&
792 LangOpts.CPlusPlusModules) {
795 Token ModuleTok = TheTok;
798 }
while (TheTok.
getKind() == tok::comment);
799 if (TheTok.
getKind() != tok::semi) {
814 if (ActiveCommentLoc.
isValid())
815 End = ActiveCommentLoc;
833 if (
Invalid || (CharNo == 0 && Lexer::isObviouslySimpleCharacter(*TokPtr)))
836 unsigned PhysOffset = 0;
841 while (Lexer::isObviouslySimpleCharacter(*TokPtr)) {
851 for (; CharNo; --CharNo) {
853 TokPtr += CharAndSize.Size;
854 PhysOffset += CharAndSize.Size;
861 if (!Lexer::isObviouslySimpleCharacter(*TokPtr))
862 PhysOffset += Lexer::SkipEscapedNewLines(TokPtr)-TokPtr;
925 *MacroBegin = expansionLoc;
959 assert(Entry.
isExpansion() &&
"Should be in an expansion");
966 *MacroEnd = expansionLoc;
979 if (Range.isTokenRange()) {
1020 Range.setBegin(Begin);
1025 if (Range.isTokenRange()) {
1043 Range.setBegin(MacroBegin);
1044 Range.setEnd(MacroEnd);
1046 if (Range.isTokenRange())
1080 if (Range.isInvalid()) {
1087 if (beginInfo.first.isInvalid()) {
1093 if (!SM.
isInFileID(Range.getEnd(), beginInfo.first, &EndOffs) ||
1094 beginInfo.second > EndOffs) {
1100 bool invalidTemp =
false;
1101 StringRef file = SM.
getBufferData(beginInfo.first, &invalidTemp);
1108 return file.substr(beginInfo.second, EndOffs - beginInfo.second);
1114 assert(Loc.
isMacroID() &&
"Only reasonable to call this on macros");
1154 StringRef ExpansionBuffer = SM.
getBufferData(ExpansionInfo.first);
1155 return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
1160 assert(Loc.
isMacroID() &&
"Only reasonable to call this on macros");
1181 StringRef ExpansionBuffer = SM.
getBufferData(ExpansionInfo.first);
1182 return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength);
1191 if (Str - 1 < BufferStart)
1194 if ((Str[0] ==
'\n' && Str[-1] ==
'\r') ||
1195 (Str[0] ==
'\r' && Str[-1] ==
'\n')) {
1196 if (Str - 2 < BufferStart)
1206 return *Str ==
'\\';
1214 if (LocInfo.first.isInvalid())
1223 StringRef Rest = Buffer.substr(
Line - Buffer.data());
1224 size_t NumWhitespaceChars = Rest.find_first_not_of(
" \t");
1225 return NumWhitespaceChars == StringRef::npos
1227 : Rest.take_front(NumWhitespaceChars);
1242 unsigned CharNo,
unsigned TokLen) {
1243 assert(FileLoc.
isMacroID() &&
"Must be a macro expansion");
1265 unsigned TokLen)
const {
1266 assert(Loc >= BufferStart && Loc <= BufferEnd &&
1267 "Location out of range for this buffer!");
1271 unsigned CharNo = Loc-BufferStart;
1272 if (FileLoc.isFileID())
1273 return FileLoc.getLocWithOffset(CharNo);
1277 assert(
PP &&
"This doesn't work on raw lexers");
1288 unsigned CompatDiagId)
const {
1301 case '=':
return '#';
1302 case ')':
return ']';
1303 case '(':
return '[';
1304 case '!':
return '|';
1305 case '\'':
return '^';
1306 case '>':
return '}';
1307 case '/':
return '\\';
1308 case '<':
return '{';
1309 case '-':
return '~';
1324 L->
Diag(CP-2, diag::trigraph_ignored);
1329 L->
Diag(CP-2, diag::trigraph_converted) << StringRef(&Res, 1);
1341 if (Ptr[Size-1] !=
'\n' && Ptr[Size-1] !=
'\r')
1345 if ((Ptr[Size] ==
'\r' || Ptr[Size] ==
'\n') &&
1346 Ptr[Size-1] != Ptr[Size])
1359const char *Lexer::SkipEscapedNewLines(
const char *P) {
1361 const char *AfterEscape;
1364 }
else if (*P ==
'?') {
1366 if (P[1] !=
'?' || P[2] !=
'/')
1376 if (NewLineSize == 0)
return P;
1377 P = AfterEscape+NewLineSize;
1384 bool IncludeComments) {
1387 return std::nullopt;
1395 bool InvalidTemp =
false;
1398 return std::nullopt;
1400 const char *TokenBegin =
File.data() + LocInfo.second;
1404 TokenBegin,
File.end());
1415 bool IncludeComments) {
1417 while (Loc != StartOfFile) {
1420 return std::nullopt;
1426 if (!
Tok.is(tok::comment) || IncludeComments) {
1430 return std::nullopt;
1439 const LangOptions &LangOpts,
bool SkipTrailingWhitespaceAndNewLine) {
1441 if (!
Tok ||
Tok->isNot(TKind))
1446 unsigned NumWhitespaceChars = 0;
1447 if (SkipTrailingWhitespaceAndNewLine) {
1449 unsigned char C = *TokenEnd;
1452 NumWhitespaceChars++;
1456 if (
C ==
'\n' ||
C ==
'\r') {
1459 NumWhitespaceChars++;
1460 if ((
C ==
'\n' ||
C ==
'\r') &&
C != PrevC)
1461 NumWhitespaceChars++;
1486 if (Ptr[0] ==
'\\') {
1492 return {
'\\', Size};
1502 Diag(Ptr, diag::backslash_newline_space);
1505 Size += EscapedNewLineSize;
1506 Ptr += EscapedNewLineSize;
1509 auto CharAndSize = getCharAndSizeSlow(Ptr,
Tok);
1510 CharAndSize.Size += Size;
1515 return {
'\\',
Size};
1519 if (Ptr[0] ==
'?' && Ptr[1] ==
'?') {
1523 LangOpts.Trigraphs)) {
1529 if (
C ==
'\\')
goto Slash;
1549 if (Ptr[0] ==
'\\') {
1555 return {
'\\',
Size};
1560 Size += EscapedNewLineSize;
1561 Ptr += EscapedNewLineSize;
1564 auto CharAndSize = getCharAndSizeSlowNoWarn(Ptr, LangOpts);
1565 CharAndSize.Size +=
Size;
1570 return {
'\\',
Size};
1574 if (LangOpts.Trigraphs && Ptr[0] ==
'?' && Ptr[1] ==
'?') {
1580 if (
C ==
'\\')
goto Slash;
1594void Lexer::SetByteOffset(
unsigned Offset,
bool StartOfLine) {
1595 BufferPtr = BufferStart + Offset;
1596 if (BufferPtr > BufferEnd)
1597 BufferPtr = BufferEnd;
1601 IsAtStartOfLine = StartOfLine;
1602 IsAtPhysicalStartOfLine = StartOfLine;
1606 static const llvm::sys::UnicodeCharSet UnicodeWhitespaceChars(
1608 return UnicodeWhitespaceChars.contains(Codepoint);
1615 bool IsStart,
bool &IsExtension) {
1616 static const llvm::sys::UnicodeCharSet MathStartChars(
1618 static const llvm::sys::UnicodeCharSet MathContinueChars(
1620 if (MathStartChars.contains(
C) ||
1621 (!IsStart && MathContinueChars.contains(
C))) {
1629 bool &IsExtension) {
1630 if (LangOpts.AsmPreprocessor) {
1632 }
else if (LangOpts.DollarIdents &&
'$' ==
C) {
1634 }
else if (LangOpts.CPlusPlus || LangOpts.C23) {
1639 static const llvm::sys::UnicodeCharSet XIDStartChars(
1641 static const llvm::sys::UnicodeCharSet XIDContinueChars(
1643 if (
C ==
'_' || XIDStartChars.contains(
C) || XIDContinueChars.contains(
C))
1647 }
else if (LangOpts.C11) {
1648 static const llvm::sys::UnicodeCharSet C11AllowedIDChars(
1650 return C11AllowedIDChars.contains(
C);
1652 static const llvm::sys::UnicodeCharSet C99AllowedIDChars(
1654 return C99AllowedIDChars.contains(
C);
1659 bool &IsExtension) {
1660 assert(
C > 0x7F &&
"isAllowedInitiallyIDChar called with an ASCII codepoint");
1661 IsExtension =
false;
1662 if (LangOpts.AsmPreprocessor) {
1665 if (LangOpts.CPlusPlus || LangOpts.C23) {
1666 static const llvm::sys::UnicodeCharSet XIDStartChars(
1668 if (XIDStartChars.contains(
C))
1676 static const llvm::sys::UnicodeCharSet C11DisallowedInitialIDChars(
1678 return !C11DisallowedInitialIDChars.contains(
C);
1680 static const llvm::sys::UnicodeCharSet C99DisallowedInitialIDChars(
1682 return !C99DisallowedInitialIDChars.contains(
C);
1690 static const llvm::sys::UnicodeCharSet MathStartChars(
1692 static const llvm::sys::UnicodeCharSet MathContinueChars(
1695 (void)MathStartChars;
1696 (void)MathContinueChars;
1697 assert((MathStartChars.contains(
C) || MathContinueChars.contains(
C)) &&
1698 "Unexpected mathematical notation codepoint");
1699 unsigned DiagID = LangOpts.CPlusPlus
1701 LangOpts, diag_compat::mathematical_notation)
1702 : diag::ext_mathematical_notation;
1703 Diags.
Report(Range.getBegin(), DiagID)
1716 if (!Diags.
isIgnored(diag::warn_c99_compat_unicode_id, Range.getBegin())) {
1718 CannotAppearInIdentifier = 0,
1719 CannotStartIdentifier
1722 static const llvm::sys::UnicodeCharSet C99AllowedIDChars(
1724 static const llvm::sys::UnicodeCharSet C99DisallowedInitialIDChars(
1726 if (!C99AllowedIDChars.contains(
C)) {
1727 Diags.
Report(Range.getBegin(), diag::warn_c99_compat_unicode_id)
1729 << CannotAppearInIdentifier;
1730 }
else if (
IsFirst && C99DisallowedInitialIDChars.contains(
C)) {
1731 Diags.
Report(Range.getBegin(), diag::warn_c99_compat_unicode_id)
1733 << CannotStartIdentifier;
1745 struct HomoglyphPair {
1748 bool operator<(HomoglyphPair R)
const {
return Character < R.Character; }
1750 static constexpr HomoglyphPair SortedHomoglyphs[] = {
1803 std::lower_bound(std::begin(SortedHomoglyphs),
1804 std::end(SortedHomoglyphs) - 1, HomoglyphPair{
C,
'\0'});
1805 if (Homoglyph->Character ==
C) {
1806 if (Homoglyph->LooksLike) {
1807 const char LooksLikeStr[] = {Homoglyph->LooksLike, 0};
1808 Diags.
Report(Range.getBegin(), diag::warn_utf8_symbol_homoglyph)
1811 Diags.
Report(Range.getBegin(), diag::warn_utf8_symbol_zero_width)
1836 bool InvalidOnlyAtStart =
IsFirst && !IsIDStart && IsIDContinue;
1838 if (!
IsFirst || InvalidOnlyAtStart) {
1839 PP->
Diag(Range.getBegin(), diag::err_character_not_allowed_identifier)
1843 PP->
Diag(Range.getBegin(), diag::err_character_not_allowed)
1850bool Lexer::tryConsumeIdentifierUCN(
const char *&CurPtr,
unsigned Size,
1852 const char *UCNPtr = CurPtr +
Size;
1853 uint32_t CodePoint = tryReadUCN(UCNPtr, CurPtr,
nullptr);
1854 if (CodePoint == 0) {
1857 bool IsExtension =
false;
1864 !
PP->isPreprocessedOutput();
1867 false, DiagnoseAndContinue) &&
1868 !DiagnoseAndContinue)
1876 PP->getDiagnostics(), LangOpts, CodePoint,
1885 if ((UCNPtr - CurPtr == 6 && CurPtr[1] ==
'u') ||
1886 (UCNPtr - CurPtr == 10 && CurPtr[1] ==
'U'))
1889 while (CurPtr != UCNPtr)
1890 (void)getAndAdvanceChar(CurPtr,
Result);
1894bool Lexer::tryConsumeIdentifierUTF8Char(
const char *&CurPtr,
Token &
Result) {
1895 llvm::UTF32 CodePoint;
1900 unsigned FirstCodeUnitSize;
1901 getCharAndSize(CurPtr, FirstCodeUnitSize);
1902 const char *CharStart = CurPtr + FirstCodeUnitSize - 1;
1903 const char *UnicodePtr = CharStart;
1905 llvm::ConversionResult ConvResult = llvm::convertUTF8Sequence(
1906 (
const llvm::UTF8 **)&UnicodePtr, (
const llvm::UTF8 *)BufferEnd,
1907 &CodePoint, llvm::strictConversion);
1908 if (ConvResult != llvm::conversionOK)
1911 bool IsExtension =
false;
1919 !
PP->isPreprocessedOutput();
1922 PP, LangOpts, CodePoint,
1924 DiagnoseAndContinue) &&
1925 !DiagnoseAndContinue)
1933 PP->getDiagnostics(), LangOpts, CodePoint,
1945 ConsumeChar(CurPtr, FirstCodeUnitSize,
Result);
1946 CurPtr = UnicodePtr;
1951 const char *CurPtr) {
1952 bool IsExtension =
false;
1955 !
PP->isPreprocessedOutput()) {
1958 PP->getDiagnostics(), LangOpts,
C,
1968 return LexIdentifierContinue(
Result, CurPtr);
1972 !
PP->isPreprocessedOutput() && !
isASCII(*BufferPtr) &&
1993 FormTokenWithChars(
Result, CurPtr, tok::unknown);
1998 unsigned char C = *CurPtr;
2006LLVM_TARGET_SSE42
static const char *
2007fastParseASCIIIdentifierSSE42(
const char *CurPtr,
const char *BufferEnd) {
2008 alignas(16)
static constexpr char AsciiIdentifierRange[16] = {
2009 '_',
'_',
'A',
'Z',
'a',
'z',
'0',
'9',
2011 constexpr ssize_t BytesPerRegister = 16;
2013 __m128i AsciiIdentifierRangeV =
2014 _mm_load_si128(
reinterpret_cast<const __m128i *
>(AsciiIdentifierRange));
2016 while (LLVM_LIKELY(BufferEnd - CurPtr >= BytesPerRegister)) {
2017 __m128i Cv =
_mm_loadu_si128(
reinterpret_cast<const __m128i *
>(CurPtr));
2019 const int Consumed =
2024 if (Consumed == BytesPerRegister)
2034 const char *BufferEnd) {
2036 if (LLVM_LIKELY(LLVM_CPU_SUPPORTS_SSE42))
2037 return fastParseASCIIIdentifierSSE42(CurPtr, BufferEnd);
2042bool Lexer::LexIdentifierContinue(
Token &
Result,
const char *CurPtr) {
2051 unsigned char C = getCharAndSize(CurPtr, Size);
2053 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2058 if (!LangOpts.DollarIdents)
2062 Diag(CurPtr, diag::ext_dollar_in_identifier);
2063 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2066 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2074 const char *IdStart = BufferPtr;
2075 FormTokenWithChars(
Result, CurPtr, tok::raw_identifier);
2076 Result.setRawIdentifierData(IdStart);
2085 const IdentifierInfo *II =
PP->LookUpIdentifierInfo(
Result);
2092 if (isCodeCompletionPoint(CurPtr)) {
2094 Result.setKind(tok::code_completion);
2100 assert(*CurPtr == 0 &&
"Completion character must be 0");
2105 if (CurPtr < BufferEnd) {
2117 return PP->HandleIdentifier(
Result);
2124bool Lexer::isHexaLiteral(
const char *Start,
const LangOptions &LangOpts) {
2126 char C1 = CharAndSize1.Char;
2132 char C2 = CharAndSize2.Char;
2133 return (C2 ==
'x' || C2 ==
'X');
2139bool Lexer::LexNumericConstant(
Token &
Result,
const char *CurPtr) {
2141 char C = getCharAndSize(CurPtr, Size);
2144 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2146 if (LangOpts.HLSL &&
C ==
'.' && (*CurPtr ==
'x' || *CurPtr ==
'r')) {
2150 C = getCharAndSize(CurPtr, Size);
2154 if ((
C ==
'-' ||
C ==
'+') && (PrevCh ==
'E' || PrevCh ==
'e')) {
2157 if (!LangOpts.MicrosoftExt || !isHexaLiteral(BufferPtr, LangOpts))
2158 return LexNumericConstant(
Result, ConsumeChar(CurPtr, Size,
Result));
2162 if ((
C ==
'-' ||
C ==
'+') && (PrevCh ==
'P' || PrevCh ==
'p')) {
2166 bool IsHexFloat =
true;
2167 if (!LangOpts.C99) {
2168 if (!isHexaLiteral(BufferPtr, LangOpts))
2170 else if (!LangOpts.CPlusPlus17 &&
2171 std::find(BufferPtr, CurPtr,
'_') != CurPtr)
2175 return LexNumericConstant(
Result, ConsumeChar(CurPtr, Size,
Result));
2179 if (
C ==
'\'' && LangOpts.AllowLiteralDigitSeparator) {
2184 Diag(CurPtr, LangOpts.CPlusPlus
2185 ? diag::warn_cxx11_compat_digit_separator
2186 : diag::warn_c23_compat_digit_separator);
2187 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2188 CurPtr = ConsumeChar(CurPtr, NextSize,
Result);
2189 return LexNumericConstant(
Result, CurPtr);
2193 if (
C ==
'$' && LangOpts.DollarIdents) {
2194 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2195 return LexNumericConstant(
Result, CurPtr);
2199 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2200 return LexNumericConstant(
Result, CurPtr);
2202 return LexNumericConstant(
Result, CurPtr);
2205 const char *TokStart = BufferPtr;
2206 FormTokenWithChars(
Result, CurPtr, tok::numeric_constant);
2207 Result.setLiteralData(TokStart);
2213const char *Lexer::LexUDSuffix(
Token &
Result,
const char *CurPtr,
2214 bool IsStringLiteral) {
2215 assert(LangOpts.CPlusPlus);
2219 char C = getCharAndSize(CurPtr, Size);
2220 bool Consumed =
false;
2223 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2225 else if (!
isASCII(
C) && tryConsumeIdentifierUTF8Char(CurPtr,
Result))
2231 if (!LangOpts.CPlusPlus11) {
2234 C ==
'_' ? diag::warn_cxx11_compat_user_defined_literal
2235 : diag::warn_cxx11_compat_reserved_user_defined_literal)
2246 bool IsUDSuffix =
false;
2249 else if (IsStringLiteral && LangOpts.CPlusPlus14) {
2253 const unsigned MaxStandardSuffixLength = 3;
2254 char Buffer[MaxStandardSuffixLength] = {
C };
2255 unsigned Consumed =
Size;
2258 auto [
Next, NextSize] =
2262 const StringRef CompleteSuffix(Buffer, Chars);
2268 if (Chars == MaxStandardSuffixLength)
2272 Buffer[Chars++] =
Next;
2273 Consumed += NextSize;
2279 Diag(CurPtr, LangOpts.MSVCCompat
2280 ? diag::ext_ms_reserved_user_defined_literal
2281 : diag::ext_reserved_user_defined_literal)
2286 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2291 C = getCharAndSize(CurPtr, Size);
2293 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2294 }
else if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result)) {
2295 }
else if (!
isASCII(
C) && tryConsumeIdentifierUTF8Char(CurPtr,
Result)) {
2305bool Lexer::LexStringLiteral(
Token &
Result,
const char *CurPtr,
2307 const char *AfterQuote = CurPtr;
2309 const char *NulCharacter =
nullptr;
2312 (Kind == tok::utf8_string_literal ||
2313 Kind == tok::utf16_string_literal ||
2314 Kind == tok::utf32_string_literal))
2315 Diag(BufferPtr, LangOpts.CPlusPlus ? diag::warn_cxx98_compat_unicode_literal
2316 : diag::warn_c99_compat_unicode_literal);
2318 char C = getAndAdvanceChar(CurPtr,
Result);
2323 const char *SavedCurPtr = CurPtr;
2324 C = getAndAdvanceChar(CurPtr,
Result);
2342 CurPtr = SavedCurPtr;
2345 if (
C ==
'\n' ||
C ==
'\r' ||
2346 (
C == 0 && CurPtr-1 == BufferEnd)) {
2348 Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 1;
2349 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2354 if (isCodeCompletionPoint(CurPtr-1)) {
2356 codeCompleteIncludedFile(AfterQuote, CurPtr - 1,
false);
2358 PP->CodeCompleteNaturalLanguage();
2359 FormTokenWithChars(
Result, CurPtr - 1, tok::unknown);
2364 NulCharacter = CurPtr-1;
2366 C = getAndAdvanceChar(CurPtr,
Result);
2370 if (LangOpts.CPlusPlus)
2371 CurPtr = LexUDSuffix(
Result, CurPtr,
true);
2375 Diag(NulCharacter, diag::null_in_char_or_string) << 1;
2378 const char *TokStart = BufferPtr;
2379 FormTokenWithChars(
Result, CurPtr, Kind);
2380 Result.setLiteralData(TokStart);
2386bool Lexer::LexRawStringLiteral(
Token &
Result,
const char *CurPtr,
2394 Diag(BufferPtr, diag::warn_cxx98_compat_raw_string_literal);
2396 unsigned PrefixLen = 0;
2400 llvm::is_contained({
'$',
'@',
'`'}, CurPtr[PrefixLen])) {
2401 const char *Pos = &CurPtr[PrefixLen];
2402 DiagCompat(Pos, diag_compat::raw_string_literal_character_set)
2403 << StringRef(Pos, 1);
2409 if (CurPtr[PrefixLen] !=
'(') {
2411 const char *PrefixEnd = &CurPtr[PrefixLen];
2412 if (PrefixLen == 16) {
2413 Diag(PrefixEnd, diag::err_raw_delim_too_long);
2414 }
else if (*PrefixEnd ==
'\n') {
2415 Diag(PrefixEnd, diag::err_invalid_newline_raw_delim);
2417 Diag(PrefixEnd, diag::err_invalid_char_raw_delim)
2418 << StringRef(PrefixEnd, 1);
2430 if (
C == 0 && CurPtr-1 == BufferEnd) {
2436 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2441 const char *Prefix = CurPtr;
2442 CurPtr += PrefixLen + 1;
2449 if (strncmp(CurPtr, Prefix, PrefixLen) == 0 && CurPtr[PrefixLen] ==
'"') {
2450 CurPtr += PrefixLen + 1;
2453 }
else if (
C == 0 && CurPtr-1 == BufferEnd) {
2455 Diag(BufferPtr, diag::err_unterminated_raw_string)
2456 << StringRef(Prefix, PrefixLen);
2457 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2463 if (LangOpts.CPlusPlus)
2464 CurPtr = LexUDSuffix(
Result, CurPtr,
true);
2467 const char *TokStart = BufferPtr;
2468 FormTokenWithChars(
Result, CurPtr, Kind);
2469 Result.setLiteralData(TokStart);
2477bool Lexer::LexAngledStringLiteral(
Token &
Result,
const char *CurPtr) {
2479 const char *NulCharacter =
nullptr;
2480 const char *AfterLessPos = CurPtr;
2481 char C = getAndAdvanceChar(CurPtr,
Result);
2486 C = getAndAdvanceChar(CurPtr,
Result);
2489 (
C == 0 && (CurPtr - 1 == BufferEnd))) {
2495 if (isCodeCompletionPoint(CurPtr - 1)) {
2496 codeCompleteIncludedFile(AfterLessPos, CurPtr - 1,
true);
2498 FormTokenWithChars(
Result, CurPtr - 1, tok::unknown);
2501 NulCharacter = CurPtr-1;
2503 C = getAndAdvanceChar(CurPtr,
Result);
2508 Diag(NulCharacter, diag::null_in_char_or_string) << 1;
2511 const char *TokStart = BufferPtr;
2512 FormTokenWithChars(
Result, CurPtr, tok::header_name);
2513 Result.setLiteralData(TokStart);
2517void Lexer::codeCompleteIncludedFile(
const char *PathStart,
2518 const char *CompletionPoint,
2521 StringRef PartialPath(PathStart, CompletionPoint - PathStart);
2522 llvm::StringRef SlashChars = LangOpts.MSVCCompat ?
"/\\" :
"/";
2523 auto Slash = PartialPath.find_last_of(SlashChars);
2525 (Slash == StringRef::npos) ?
"" : PartialPath.take_front(Slash);
2526 const char *StartOfFilename =
2527 (Slash == StringRef::npos) ? PathStart : PathStart + Slash + 1;
2529 PP->setCodeCompletionIdentifierInfo(&
PP->getIdentifierTable().get(
2530 StringRef(StartOfFilename, CompletionPoint - StartOfFilename)));
2533 while (CompletionPoint < BufferEnd) {
2534 char Next = *(CompletionPoint + 1);
2538 if (
Next == (IsAngled ?
'>' :
'"'))
2540 if (SlashChars.contains(
Next))
2544 PP->setCodeCompletionTokenRange(
2545 FileLoc.getLocWithOffset(StartOfFilename - BufferStart),
2546 FileLoc.getLocWithOffset(CompletionPoint - BufferStart));
2547 PP->CodeCompleteIncludedFile(Dir, IsAngled);
2552bool Lexer::LexCharConstant(
Token &
Result,
const char *CurPtr,
2555 const char *NulCharacter =
nullptr;
2558 if (Kind == tok::utf16_char_constant || Kind == tok::utf32_char_constant)
2559 Diag(BufferPtr, LangOpts.CPlusPlus
2560 ? diag::warn_cxx98_compat_unicode_literal
2561 : diag::warn_c99_compat_unicode_literal);
2562 else if (Kind == tok::utf8_char_constant)
2563 Diag(BufferPtr, LangOpts.CPlusPlus
2564 ? diag::warn_cxx14_compat_u8_character_literal
2565 : diag::warn_c17_compat_u8_character_literal);
2568 char C = getAndAdvanceChar(CurPtr,
Result);
2571 Diag(BufferPtr, diag::ext_empty_character);
2572 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2579 C = getAndAdvanceChar(CurPtr,
Result);
2581 if (
C ==
'\n' ||
C ==
'\r' ||
2582 (
C == 0 && CurPtr-1 == BufferEnd)) {
2584 Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 0;
2585 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2590 if (isCodeCompletionPoint(CurPtr-1)) {
2591 PP->CodeCompleteNaturalLanguage();
2592 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2597 NulCharacter = CurPtr-1;
2599 C = getAndAdvanceChar(CurPtr,
Result);
2603 if (LangOpts.CPlusPlus)
2604 CurPtr = LexUDSuffix(
Result, CurPtr,
false);
2608 Diag(NulCharacter, diag::null_in_char_or_string) << 0;
2611 const char *TokStart = BufferPtr;
2612 FormTokenWithChars(
Result, CurPtr, Kind);
2613 Result.setLiteralData(TokStart);
2621bool Lexer::SkipWhitespace(
Token &
Result,
const char *CurPtr) {
2625 unsigned char Char = *CurPtr;
2627 const char *lastNewLine =
nullptr;
2628 auto setLastNewLine = [&](
const char *
Ptr) {
2634 setLastNewLine(CurPtr - 1);
2653 if (*CurPtr ==
'\n')
2654 setLastNewLine(CurPtr);
2661 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2663 IsAtStartOfLine =
true;
2664 IsAtPhysicalStartOfLine =
true;
2671 char PrevChar = CurPtr[-1];
2679 if (NewLinePtr && lastNewLine && NewLinePtr != lastNewLine &&
PP) {
2680 if (
auto *Handler =
PP->getEmptylineHandler())
2696bool Lexer::SkipLineComment(
Token &
Result,
const char *CurPtr) {
2701 Diag(BufferPtr, diag::ext_line_comment);
2719 bool UnicodeDecodingAlreadyDiagnosed =
false;
2726 C !=
'\n' &&
C !=
'\r') {
2728 UnicodeDecodingAlreadyDiagnosed =
false;
2732 unsigned Length = llvm::getUTF8SequenceSize(
2733 (
const llvm::UTF8 *)CurPtr, (
const llvm::UTF8 *)BufferEnd);
2736 Diag(CurPtr, diag::warn_invalid_utf8_in_comment);
2737 UnicodeDecodingAlreadyDiagnosed =
true;
2740 UnicodeDecodingAlreadyDiagnosed =
false;
2746 const char *NextLine = CurPtr;
2749 const char *EscapePtr = CurPtr-1;
2750 bool HasSpace =
false;
2756 if (*EscapePtr ==
'\\')
2759 else if (EscapePtr[0] ==
'/' && EscapePtr[-1] ==
'?' &&
2760 EscapePtr[-2] ==
'?' && LangOpts.Trigraphs)
2762 CurPtr = EscapePtr-2;
2768 Diag(EscapePtr, diag::backslash_newline_space);
2775 const char *OldPtr = CurPtr;
2778 C = getAndAdvanceChar(CurPtr,
Result);
2783 if (
C != 0 && CurPtr == OldPtr+1) {
2791 if (CurPtr != OldPtr + 1 &&
C !=
'/' &&
2792 (CurPtr == BufferEnd + 1 || CurPtr[0] !=
'/')) {
2793 for (; OldPtr != CurPtr; ++OldPtr)
2794 if (OldPtr[0] ==
'\n' || OldPtr[0] ==
'\r') {
2798 const char *ForwardPtr = CurPtr;
2801 if (ForwardPtr[0] ==
'/' && ForwardPtr[1] ==
'/')
2806 Diag(OldPtr-1, diag::ext_multi_line_line_comment);
2811 if (
C ==
'\r' ||
C ==
'\n' || CurPtr == BufferEnd + 1) {
2816 if (
C ==
'\0' && isCodeCompletionPoint(CurPtr-1)) {
2817 PP->CodeCompleteNaturalLanguage();
2834 return SaveLineComment(
Result, CurPtr);
2848 NewLinePtr = CurPtr++;
2861bool Lexer::SaveLineComment(
Token &
Result,
const char *CurPtr) {
2864 FormTokenWithChars(
Result, CurPtr, tok::comment);
2876 assert(Spelling[0] ==
'/' && Spelling[1] ==
'/' &&
"Not line comment?");
2880 Result.setKind(tok::comment);
2891 assert(CurPtr[0] ==
'\n' || CurPtr[0] ==
'\r');
2894 const char *TrigraphPos =
nullptr;
2896 const char *SpacePos =
nullptr;
2903 if (CurPtr[0] ==
'\n' || CurPtr[0] ==
'\r') {
2905 if (CurPtr[0] == CurPtr[1])
2919 if (*CurPtr ==
'\\') {
2921 }
else if (CurPtr[0] ==
'/' && CurPtr[-1] ==
'?' && CurPtr[-2] ==
'?') {
2923 TrigraphPos = CurPtr - 2;
2934 if (*CurPtr !=
'\n' && *CurPtr !=
'\r')
2943 L->
Diag(TrigraphPos, diag::trigraph_ignored_block_comment);
2947 L->
Diag(TrigraphPos, diag::trigraph_ends_block_comment);
2952 L->
Diag(CurPtr + 1, diag::escaped_newline_block_comment_end);
2956 L->
Diag(SpacePos, diag::backslash_newline_space);
2962#include <emmintrin.h>
2977bool Lexer::SkipBlockComment(
Token &
Result,
const char *CurPtr) {
2987 unsigned char C = getCharAndSize(CurPtr, CharSize);
2989 if (
C == 0 && CurPtr == BufferEnd+1) {
2991 Diag(BufferPtr, diag::err_unterminated_block_comment);
2997 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3014 bool UnicodeDecodingAlreadyDiagnosed =
false;
3019 if (CurPtr + 24 < BufferEnd &&
3022 !(
PP &&
PP->getCodeCompletionFileLoc() == FileLoc)) {
3024 while (
C !=
'/' && (
intptr_t)CurPtr % 16 != 0) {
3029 if (
C ==
'/')
goto FoundSlash;
3033 while (CurPtr + 16 < BufferEnd) {
3035 if (LLVM_UNLIKELY(Mask != 0)) {
3045 CurPtr += llvm::countr_zero<unsigned>(cmp) + 1;
3051 __vector
unsigned char LongUTF = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
3052 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
3053 0x80, 0x80, 0x80, 0x80};
3054 __vector
unsigned char Slashes = {
3055 '/',
'/',
'/',
'/',
'/',
'/',
'/',
'/',
3056 '/',
'/',
'/',
'/',
'/',
'/',
'/',
'/'
3058 while (CurPtr + 16 < BufferEnd) {
3060 vec_any_ge(*(
const __vector
unsigned char *)CurPtr, LongUTF)))
3062 if (
vec_any_eq(*(
const __vector
unsigned char *)CurPtr, Slashes)) {
3069 while (CurPtr + 16 < BufferEnd) {
3070 bool HasNonASCII =
false;
3071 for (
unsigned I = 0; I < 16; ++I)
3072 HasNonASCII |= !
isASCII(CurPtr[I]);
3074 if (LLVM_UNLIKELY(HasNonASCII))
3077 bool HasSlash =
false;
3078 for (
unsigned I = 0; I < 16; ++I)
3079 HasSlash |= CurPtr[I] ==
'/';
3093 while (
C !=
'/' &&
C !=
'\0') {
3095 UnicodeDecodingAlreadyDiagnosed =
false;
3102 unsigned Length = llvm::getUTF8SequenceSize(
3103 (
const llvm::UTF8 *)CurPtr - 1, (
const llvm::UTF8 *)BufferEnd);
3106 Diag(CurPtr - 1, diag::warn_invalid_utf8_in_comment);
3107 UnicodeDecodingAlreadyDiagnosed =
true;
3109 UnicodeDecodingAlreadyDiagnosed =
false;
3110 CurPtr += Length - 1;
3117 if (CurPtr[-2] ==
'*')
3120 if ((CurPtr[-2] ==
'\n' || CurPtr[-2] ==
'\r')) {
3122 LangOpts.Trigraphs)) {
3128 if (CurPtr[0] ==
'*' && CurPtr[1] !=
'/') {
3133 Diag(CurPtr-1, diag::warn_nested_block_comment);
3135 }
else if (
C == 0 && CurPtr == BufferEnd+1) {
3137 Diag(BufferPtr, diag::err_unterminated_block_comment);
3146 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3152 }
else if (
C ==
'\0' && isCodeCompletionPoint(CurPtr-1)) {
3153 PP->CodeCompleteNaturalLanguage();
3171 FormTokenWithChars(
Result, CurPtr, tok::comment);
3172 IsAtPhysicalStartOfLine =
Result.isAtPhysicalStartOfLine();
3181 SkipWhitespace(
Result, CurPtr + 1);
3199 "Must be in a preprocessing directive!");
3204 const char *CurPtr = BufferPtr;
3206 char Char = getAndAdvanceChar(CurPtr, Tmp);
3214 if (CurPtr-1 != BufferEnd) {
3215 if (isCodeCompletionPoint(CurPtr-1)) {
3216 PP->CodeCompleteNaturalLanguage();
3231 assert(CurPtr[-1] == Char &&
"Trigraphs for newline?");
3232 BufferPtr = CurPtr-1;
3236 if (Tmp.
is(tok::code_completion)) {
3238 PP->CodeCompleteNaturalLanguage();
3241 assert(Tmp.
is(tok::eod) &&
"Unexpected token!");
3253bool Lexer::LexEndOfFile(
Token &
Result,
const char *CurPtr) {
3261 FormTokenWithChars(
Result, CurPtr, tok::eod);
3273 BufferPtr = BufferEnd;
3274 FormTokenWithChars(
Result, BufferEnd, tok::eof);
3278 if (
PP->isRecordingPreamble() &&
PP->isInPrimaryFile()) {
3284 MIOpt.ExitTopLevelConditional();
3292 if (
PP->getCodeCompletionFileLoc() != FileLoc)
3294 diag::err_pp_unterminated_conditional);
3301 if (CurPtr != BufferStart && (CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r'))
3302 Diag(BufferEnd, diag::warn_no_newline_eof)
3314std::optional<Token> Lexer::peekNextPPToken() {
3315 assert(!
LexingRawMode &&
"How can we expand a macro from a skipping buffer?");
3317 if (isDependencyDirectivesLexer()) {
3318 if (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size())
3319 return std::nullopt;
3321 (void)convertDependencyDirectiveToken(
3322 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex],
Result);
3332 const char *TmpBufferPtr = BufferPtr;
3334 bool atStartOfLine = IsAtStartOfLine;
3335 bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
3336 bool leadingSpace = HasLeadingSpace;
3337 MultipleIncludeOpt MIOptState =
MIOpt;
3343 BufferPtr = TmpBufferPtr;
3345 HasLeadingSpace = leadingSpace;
3346 IsAtStartOfLine = atStartOfLine;
3347 IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
3352 if (
Tok.
is(tok::eof))
3353 return std::nullopt;
3360 const char *Terminator = CMK ==
CMK_Perforce ?
"<<<<\n" :
">>>>>>>";
3362 auto RestOfBuffer = StringRef(CurPtr, BufferEnd - CurPtr).substr(TermLen);
3363 size_t Pos = RestOfBuffer.find(Terminator);
3364 while (Pos != StringRef::npos) {
3367 (RestOfBuffer[Pos - 1] !=
'\r' && RestOfBuffer[Pos - 1] !=
'\n')) {
3368 RestOfBuffer = RestOfBuffer.substr(Pos+TermLen);
3369 Pos = RestOfBuffer.find(Terminator);
3372 return RestOfBuffer.data()+Pos;
3381bool Lexer::IsStartOfConflictMarker(
const char *CurPtr) {
3383 if (CurPtr != BufferStart &&
3384 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3388 if (!StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
"<<<<<<<") &&
3389 !StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
">>>> "))
3404 Diag(CurPtr, diag::err_conflict_marker);
3405 CurrentConflictMarkerState =
Kind;
3409 while (*CurPtr !=
'\r' && *CurPtr !=
'\n') {
3410 assert(CurPtr != BufferEnd &&
"Didn't find end of line");
3425bool Lexer::HandleEndOfConflictMarker(
const char *CurPtr) {
3427 if (CurPtr != BufferStart &&
3428 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3437 for (
unsigned i = 1; i != 4; ++i)
3438 if (CurPtr[i] != CurPtr[0])
3445 CurrentConflictMarkerState)) {
3449 while (CurPtr != BufferEnd && *CurPtr !=
'\r' && *CurPtr !=
'\n')
3455 CurrentConflictMarkerState =
CMK_None;
3463 const char *BufferEnd) {
3464 if (CurPtr == BufferEnd)
3467 for (; CurPtr != BufferEnd; ++CurPtr) {
3468 if (CurPtr[0] ==
'#' && CurPtr[1] ==
'>')
3474bool Lexer::lexEditorPlaceholder(
Token &
Result,
const char *CurPtr) {
3475 assert(CurPtr[-1] ==
'<' && CurPtr[0] ==
'#' &&
"Not a placeholder!");
3481 const char *Start = CurPtr - 1;
3482 if (!LangOpts.AllowEditorPlaceholders)
3483 Diag(Start, diag::err_placeholder_in_source);
3485 FormTokenWithChars(
Result, End, tok::raw_identifier);
3486 Result.setRawIdentifierData(Start);
3493bool Lexer::isCodeCompletionPoint(
const char *CurPtr)
const {
3494 if (
PP &&
PP->isCodeCompletionEnabled()) {
3495 SourceLocation Loc = FileLoc.getLocWithOffset(CurPtr-BufferStart);
3496 return Loc ==
PP->getCodeCompletionLoc();
3507 if (Opts.CPlusPlus23)
3508 DiagId = diag::warn_cxx23_delimited_escape_sequence;
3509 else if (Opts.C2y && !Named)
3510 DiagId = diag::warn_c2y_delimited_escape_sequence;
3512 DiagId = diag::ext_delimited_escape_sequence;
3518 if (!Opts.CPlusPlus)
3519 Ext = Named ? 2 : 1 ;
3523 Diags.
Report(Loc, DiagId) << Named << Ext;
3526std::optional<uint32_t> Lexer::tryReadNumericUCN(
const char *&StartPtr,
3527 const char *SlashLoc,
3530 char Kind = getCharAndSize(StartPtr, CharSize);
3531 assert((Kind ==
'u' || Kind ==
'U') &&
"expected a UCN");
3533 unsigned NumHexDigits;
3536 else if (Kind ==
'U')
3539 bool Delimited =
false;
3540 bool FoundEndDelimiter =
false;
3544 if (!LangOpts.CPlusPlus && !LangOpts.C99) {
3546 Diag(SlashLoc, diag::warn_ucn_not_valid_in_c89);
3547 return std::nullopt;
3550 const char *CurPtr = StartPtr + CharSize;
3551 const char *KindLoc = &CurPtr[-1];
3554 while (Count != NumHexDigits || Delimited) {
3555 char C = getCharAndSize(CurPtr, CharSize);
3556 if (!Delimited && Count == 0 &&
C ==
'{') {
3562 if (Delimited &&
C ==
'}') {
3564 FoundEndDelimiter =
true;
3568 unsigned Value = llvm::hexDigitValue(
C);
3569 if (
Value == std::numeric_limits<unsigned>::max()) {
3573 Diag(SlashLoc, diag::warn_delimited_ucn_incomplete)
3574 << StringRef(KindLoc, 1);
3575 return std::nullopt;
3578 if (CodePoint & 0xF000'0000) {
3580 Diag(KindLoc, diag::err_escape_too_large) << 0;
3581 return std::nullopt;
3592 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3593 : diag::warn_ucn_escape_no_digits)
3594 << StringRef(KindLoc, 1);
3595 return std::nullopt;
3598 if (Delimited && Kind ==
'U') {
3600 Diag(SlashLoc, diag::err_hex_escape_no_digits) << StringRef(KindLoc, 1);
3601 return std::nullopt;
3604 if (!Delimited && Count != NumHexDigits) {
3606 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3608 if (Count == 4 && NumHexDigits == 8) {
3609 CharSourceRange URange =
makeCharRange(*
this, KindLoc, KindLoc + 1);
3610 Diag(KindLoc, diag::note_ucn_four_not_eight)
3614 return std::nullopt;
3617 if (Delimited &&
PP)
3620 PP->getDiagnostics());
3627 if (CurPtr - StartPtr == (
ptrdiff_t)(Count + 1 + (Delimited ? 2 : 0)))
3630 while (StartPtr != CurPtr)
3631 (void)getAndAdvanceChar(StartPtr, *
Result);
3638std::optional<uint32_t> Lexer::tryReadNamedUCN(
const char *&StartPtr,
3639 const char *SlashLoc,
3644 char C = getCharAndSize(StartPtr, CharSize);
3645 assert(
C ==
'N' &&
"expected \\N{...}");
3647 const char *CurPtr = StartPtr + CharSize;
3648 const char *KindLoc = &CurPtr[-1];
3650 C = getCharAndSize(CurPtr, CharSize);
3653 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3654 return std::nullopt;
3657 const char *StartName = CurPtr;
3658 bool FoundEndDelimiter =
false;
3659 llvm::SmallVector<char, 30> Buffer;
3661 C = getCharAndSize(CurPtr, CharSize);
3664 FoundEndDelimiter =
true;
3670 Buffer.push_back(
C);
3673 if (!FoundEndDelimiter || Buffer.empty()) {
3675 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3676 : diag::warn_delimited_ucn_incomplete)
3677 << StringRef(KindLoc, 1);
3678 return std::nullopt;
3681 StringRef Name(Buffer.data(), Buffer.size());
3682 std::optional<char32_t>
Match =
3683 llvm::sys::unicode::nameToCodepointStrict(Name);
3684 std::optional<llvm::sys::unicode::LooseMatchingResult> LooseMatch;
3686 LooseMatch = llvm::sys::unicode::nameToCodepointLooseMatching(Name);
3688 Diag(StartName, diag::err_invalid_ucn_name)
3689 << StringRef(Buffer.data(), Buffer.size())
3692 Diag(StartName, diag::note_invalid_ucn_name_loose_matching)
3703 if (Diagnose &&
Match)
3706 PP->getDiagnostics());
3712 if (LooseMatch && Diagnose)
3713 Match = LooseMatch->CodePoint;
3720 if (CurPtr - StartPtr == (
ptrdiff_t)(Buffer.size() + 3))
3723 while (StartPtr != CurPtr)
3724 (void)getAndAdvanceChar(StartPtr, *
Result);
3728 return Match ? std::optional<uint32_t>(*
Match) : std::nullopt;
3731uint32_t Lexer::tryReadUCN(
const char *&StartPtr,
const char *SlashLoc,
3735 std::optional<uint32_t> CodePointOpt;
3736 char Kind = getCharAndSize(StartPtr, CharSize);
3737 if (Kind ==
'u' || Kind ==
'U')
3738 CodePointOpt = tryReadNumericUCN(StartPtr, SlashLoc,
Result);
3739 else if (Kind ==
'N')
3740 CodePointOpt = tryReadNamedUCN(StartPtr, SlashLoc,
Result);
3745 uint32_t CodePoint = *CodePointOpt;
3748 if (LangOpts.AsmPreprocessor)
3767 if (CodePoint < 0xA0) {
3771 if (CodePoint < 0x20 || CodePoint >= 0x7F)
3772 Diag(BufferPtr, diag::err_ucn_control_character);
3774 char C =
static_cast<char>(CodePoint);
3775 Diag(BufferPtr, diag::err_ucn_escape_basic_scs) << StringRef(&
C, 1);
3780 }
else if (CodePoint >= 0xD800 && CodePoint <= 0xDFFF) {
3785 if (LangOpts.CPlusPlus && !LangOpts.CPlusPlus11)
3786 Diag(BufferPtr, diag::warn_ucn_escape_surrogate);
3788 Diag(BufferPtr, diag::err_ucn_escape_invalid);
3797 const char *CurPtr) {
3800 Diag(BufferPtr, diag::ext_unicode_whitespace)
3810void Lexer::PropagateLineStartLeadingSpaceInfo(
Token &
Result) {
3811 IsAtStartOfLine =
Result.isAtStartOfLine();
3812 HasLeadingSpace =
Result.hasLeadingSpace();
3813 HasLeadingEmptyMacro =
Result.hasLeadingEmptyMacro();
3818 assert(!isDependencyDirectivesLexer());
3824 if (IsAtStartOfLine) {
3826 IsAtStartOfLine =
false;
3829 if (IsAtPhysicalStartOfLine) {
3831 IsAtPhysicalStartOfLine =
false;
3834 if (HasLeadingSpace) {
3836 HasLeadingSpace =
false;
3839 if (HasLeadingEmptyMacro) {
3841 HasLeadingEmptyMacro =
false;
3846 bool returnedToken = LexTokenInternal(
Result);
3848 assert((returnedToken || !isRawLex) &&
"Raw lex must succeed");
3849 return returnedToken;
3859 assert(!
Result.needsCleaning() &&
"Result needs cleaning");
3860 assert(!
Result.hasPtrData() &&
"Result has not been reset");
3863 const char *CurPtr = BufferPtr;
3877 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3886 unsigned SizeTmp, SizeTmp2;
3889 char Char = getAndAdvanceChar(CurPtr,
Result);
3893 NewLinePtr =
nullptr;
3898 if (CurPtr-1 == BufferEnd)
3899 return LexEndOfFile(
Result, CurPtr-1);
3902 if (isCodeCompletionPoint(CurPtr-1)) {
3905 FormTokenWithChars(
Result, CurPtr, tok::code_completion);
3910 Diag(CurPtr-1, diag::null_in_file);
3912 if (SkipWhitespace(
Result, CurPtr))
3921 if (LangOpts.MicrosoftExt) {
3923 Diag(CurPtr-1, diag::ext_ctrl_z_eof_microsoft);
3924 return LexEndOfFile(
Result, CurPtr-1);
3928 Kind = tok::unknown;
3932 if (CurPtr[0] ==
'\n')
3933 (void)getAndAdvanceChar(CurPtr,
Result);
3947 IsAtStartOfLine =
true;
3948 IsAtPhysicalStartOfLine =
true;
3949 NewLinePtr = CurPtr - 1;
3958 if (SkipWhitespace(
Result, CurPtr))
3968 SkipHorizontalWhitespace:
3970 if (SkipWhitespace(
Result, CurPtr))
3979 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP)) {
3980 if (SkipLineComment(
Result, CurPtr + 2))
3982 goto SkipIgnoredUnits;
3984 if (SkipBlockComment(
Result, CurPtr + 2))
3986 goto SkipIgnoredUnits;
3988 goto SkipHorizontalWhitespace;
3996 case '0':
case '1':
case '2':
case '3':
case '4':
3997 case '5':
case '6':
case '7':
case '8':
case '9':
4000 return LexNumericConstant(
Result, CurPtr);
4009 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4010 Char = getCharAndSize(CurPtr, SizeTmp);
4014 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4015 tok::utf16_string_literal);
4019 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4020 tok::utf16_char_constant);
4023 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4024 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4025 return LexRawStringLiteral(
Result,
4026 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4028 tok::utf16_string_literal);
4031 char Char2 = getCharAndSize(CurPtr + SizeTmp, SizeTmp2);
4035 return LexStringLiteral(
Result,
4036 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4038 tok::utf8_string_literal);
4039 if (Char2 ==
'\'' && (LangOpts.CPlusPlus17 || LangOpts.C23))
4040 return LexCharConstant(
4041 Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4043 tok::utf8_char_constant);
4045 if (Char2 ==
'R' && LangOpts.RawStringLiterals) {
4047 char Char3 = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4050 return LexRawStringLiteral(
Result,
4051 ConsumeChar(ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4054 tok::utf8_string_literal);
4061 return LexIdentifierContinue(
Result, CurPtr);
4067 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4068 Char = getCharAndSize(CurPtr, SizeTmp);
4072 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4073 tok::utf32_string_literal);
4077 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4078 tok::utf32_char_constant);
4081 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4082 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4083 return LexRawStringLiteral(
Result,
4084 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4086 tok::utf32_string_literal);
4090 return LexIdentifierContinue(
Result, CurPtr);
4096 if (LangOpts.RawStringLiterals) {
4097 Char = getCharAndSize(CurPtr, SizeTmp);
4100 return LexRawStringLiteral(
Result,
4101 ConsumeChar(CurPtr, SizeTmp,
Result),
4102 tok::string_literal);
4106 return LexIdentifierContinue(
Result, CurPtr);
4111 Char = getCharAndSize(CurPtr, SizeTmp);
4115 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4116 tok::wide_string_literal);
4119 if (LangOpts.RawStringLiterals && Char ==
'R' &&
4120 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4121 return LexRawStringLiteral(
Result,
4122 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4124 tok::wide_string_literal);
4128 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4129 tok::wide_char_constant);
4134 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
4135 case 'H':
case 'I':
case 'J':
case 'K':
case 'M':
case 'N':
4136 case 'O':
case 'P':
case 'Q':
case 'S':
case 'T':
4137 case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
4138 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
4139 case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
4140 case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
4141 case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
4145 return LexIdentifierContinue(
Result, CurPtr);
4147 if (LangOpts.DollarIdents) {
4149 Diag(CurPtr-1, diag::ext_dollar_in_identifier);
4152 return LexIdentifierContinue(
Result, CurPtr);
4155 Kind = tok::unknown;
4162 return LexCharConstant(
Result, CurPtr, tok::char_constant);
4168 return LexStringLiteral(
Result, CurPtr,
4170 : tok::string_literal);
4174 Kind = tok::question;
4177 Kind = tok::l_square;
4180 Kind = tok::r_square;
4183 Kind = tok::l_paren;
4186 Kind = tok::r_paren;
4189 Kind = tok::l_brace;
4192 Kind = tok::r_brace;
4195 Char = getCharAndSize(CurPtr, SizeTmp);
4196 if (Char >=
'0' && Char <=
'9') {
4200 return LexNumericConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result));
4201 }
else if (LangOpts.CPlusPlus && Char ==
'*') {
4202 Kind = tok::periodstar;
4204 }
else if (Char ==
'.' &&
4205 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'.') {
4206 Kind = tok::ellipsis;
4207 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4214 Char = getCharAndSize(CurPtr, SizeTmp);
4217 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4218 }
else if (Char ==
'=') {
4219 Kind = tok::ampequal;
4220 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4226 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4227 Kind = tok::starequal;
4228 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4234 Char = getCharAndSize(CurPtr, SizeTmp);
4236 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4237 Kind = tok::plusplus;
4238 }
else if (Char ==
'=') {
4239 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4240 Kind = tok::plusequal;
4246 Char = getCharAndSize(CurPtr, SizeTmp);
4248 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4249 Kind = tok::minusminus;
4250 }
else if (Char ==
'>' && LangOpts.CPlusPlus &&
4251 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'*') {
4252 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4254 Kind = tok::arrowstar;
4255 }
else if (Char ==
'>') {
4256 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4258 }
else if (Char ==
'=') {
4259 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4260 Kind = tok::minusequal;
4269 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4270 Kind = tok::exclaimequal;
4271 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4273 Kind = tok::exclaim;
4278 Char = getCharAndSize(CurPtr, SizeTmp);
4288 bool TreatAsComment =
4289 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP);
4290 if (!TreatAsComment)
4291 if (!(
PP &&
PP->isPreprocessedOutput()))
4292 TreatAsComment = getCharAndSize(CurPtr+SizeTmp, SizeTmp2) !=
'*';
4294 if (TreatAsComment) {
4295 if (SkipLineComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4301 goto SkipIgnoredUnits;
4306 if (SkipBlockComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4315 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4316 Kind = tok::slashequal;
4322 Char = getCharAndSize(CurPtr, SizeTmp);
4324 Kind = tok::percentequal;
4325 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4326 }
else if (LangOpts.Digraphs && Char ==
'>') {
4327 Kind = tok::r_brace;
4328 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4329 }
else if (LangOpts.Digraphs && Char ==
':') {
4330 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4331 Char = getCharAndSize(CurPtr, SizeTmp);
4332 if (Char ==
'%' && getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
':') {
4333 Kind = tok::hashhash;
4334 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4336 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4337 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4339 Diag(BufferPtr, diag::ext_charize_microsoft);
4348 goto HandleDirective;
4353 Kind = tok::percent;
4357 Char = getCharAndSize(CurPtr, SizeTmp);
4362 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4364 Kind = tok::lesslessequal;
4365 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4367 }
else if (After ==
'<' && IsStartOfConflictMarker(CurPtr-1)) {
4371 }
else if (After ==
'<' && HandleEndOfConflictMarker(CurPtr-1)) {
4375 }
else if (LangOpts.CUDA && After ==
'<') {
4376 Kind = tok::lesslessless;
4377 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4380 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4381 Kind = tok::lessless;
4383 }
else if (Char ==
'=') {
4384 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4386 if (LangOpts.CPlusPlus20) {
4388 Diag(BufferPtr, diag::warn_cxx17_compat_spaceship);
4389 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4391 Kind = tok::spaceship;
4397 Diag(BufferPtr, diag::warn_cxx20_compat_spaceship)
4402 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4403 Kind = tok::lessequal;
4404 }
else if (LangOpts.Digraphs && Char ==
':') {
4405 if (LangOpts.CPlusPlus11 &&
4406 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
':') {
4413 char After = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4414 if (After !=
':' && After !=
'>') {
4417 Diag(BufferPtr, diag::warn_cxx98_compat_less_colon_colon);
4422 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4423 Kind = tok::l_square;
4424 }
else if (LangOpts.Digraphs && Char ==
'%') {
4425 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4426 Kind = tok::l_brace;
4427 }
else if (Char ==
'#' && SizeTmp == 1 &&
4428 lexEditorPlaceholder(
Result, CurPtr)) {
4435 Char = getCharAndSize(CurPtr, SizeTmp);
4437 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4438 Kind = tok::greaterequal;
4439 }
else if (Char ==
'>') {
4440 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4442 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4444 Kind = tok::greatergreaterequal;
4445 }
else if (After ==
'>' && IsStartOfConflictMarker(CurPtr-1)) {
4449 }
else if (After ==
'>' && HandleEndOfConflictMarker(CurPtr-1)) {
4452 }
else if (LangOpts.CUDA && After ==
'>') {
4453 Kind = tok::greatergreatergreater;
4454 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4457 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4458 Kind = tok::greatergreater;
4461 Kind = tok::greater;
4465 Char = getCharAndSize(CurPtr, SizeTmp);
4467 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4468 Kind = tok::caretequal;
4469 }
else if (LangOpts.Reflection && Char ==
'^') {
4470 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4471 Kind = tok::caretcaret;
4473 if (LangOpts.OpenCL && Char ==
'^')
4474 Diag(CurPtr, diag::err_opencl_logical_exclusive_or);
4479 Char = getCharAndSize(CurPtr, SizeTmp);
4481 Kind = tok::pipeequal;
4482 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4483 }
else if (Char ==
'|') {
4485 if (CurPtr[1] ==
'|' && HandleEndOfConflictMarker(CurPtr-1))
4487 Kind = tok::pipepipe;
4488 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4494 Char = getCharAndSize(CurPtr, SizeTmp);
4495 if (LangOpts.Digraphs && Char ==
'>') {
4496 Kind = tok::r_square;
4497 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4498 }
else if (Char ==
':') {
4499 Kind = tok::coloncolon;
4500 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4509 Char = getCharAndSize(CurPtr, SizeTmp);
4512 if (CurPtr[1] ==
'=' && HandleEndOfConflictMarker(CurPtr-1))
4515 Kind = tok::equalequal;
4516 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4525 Char = getCharAndSize(CurPtr, SizeTmp);
4527 Kind = tok::hashhash;
4528 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4529 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4532 Diag(BufferPtr, diag::ext_charize_microsoft);
4533 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4540 goto HandleDirective;
4548 if (CurPtr[-1] ==
'@' && LangOpts.ObjC) {
4549 FormTokenWithChars(
Result, CurPtr, tok::at);
4555 llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
4557 auto NextTokOr = peekNextPPToken();
4558 if (NextTokOr.has_value()) {
4559 NextPPTok = *NextTokOr;
4562 if (NextPPTok.
is(tok::raw_identifier) &&
4570 Kind = tok::unknown;
4575 if (!LangOpts.AsmPreprocessor) {
4576 if (
uint32_t CodePoint = tryReadUCN(CurPtr, BufferPtr, &
Result)) {
4577 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4578 if (SkipWhitespace(
Result, CurPtr))
4586 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4590 Kind = tok::unknown;
4595 Kind = tok::unknown;
4599 llvm::UTF32 CodePoint;
4604 llvm::ConversionResult Status =
4605 llvm::convertUTF8Sequence((
const llvm::UTF8 **)&CurPtr,
4606 (
const llvm::UTF8 *)BufferEnd,
4608 llvm::strictConversion);
4609 if (Status == llvm::conversionOK) {
4610 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4611 if (SkipWhitespace(
Result, CurPtr))
4618 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4622 PP->isPreprocessedOutput()) {
4624 Kind = tok::unknown;
4631 Diag(CurPtr, diag::err_invalid_utf8);
4633 BufferPtr = CurPtr+1;
4645 FormTokenWithChars(
Result, CurPtr, Kind);
4651 FormTokenWithChars(
Result, CurPtr, tok::hash);
4654 if (
PP->hadModuleLoaderFatalFailure())
4666const char *Lexer::convertDependencyDirectiveToken(
4668 const char *TokPtr = BufferStart + DDTok.
Offset;
4671 if (
Result.is(tok::raw_identifier))
4672 Result.setRawIdentifierData(TokPtr);
4673 else if (
Result.isLiteral())
4674 Result.setLiteralData(TokPtr);
4675 BufferPtr = TokPtr + DDTok.
Length;
4679bool Lexer::LexDependencyDirectiveToken(
Token &
Result) {
4680 assert(isDependencyDirectivesLexer());
4684 using namespace dependency_directives_scan;
4686 if (BufferPtr == BufferEnd)
4687 return LexEndOfFile(
Result, BufferPtr);
4689 while (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size()) {
4690 if (DepDirectives.front().Kind == pp_eof)
4691 return LexEndOfFile(
Result, BufferEnd);
4692 if (DepDirectives.front().Kind == tokens_present_before_eof)
4694 NextDepDirectiveTokenIndex = 0;
4695 DepDirectives = DepDirectives.drop_front();
4698 const dependency_directives_scan::Token &DDTok =
4699 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex++];
4700 if (NextDepDirectiveTokenIndex > 1 || DDTok.
Kind != tok::hash) {
4705 const char *DDTokPtr = BufferStart + DDTok.
Offset;
4709 BufferPtr = DDTokPtr;
4710 if (!LexAngledStringLiteral(
Result, BufferPtr + 1)) {
4711 convertDependencyDirectiveToken(DDTok,
Result);
4719 const dependency_directives_scan::Token &NextTok =
4720 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex];
4721 if (BufferStart + NextTok.
Offset >= BufferPtr)
4723 ++NextDepDirectiveTokenIndex;
4728 const char *TokPtr = convertDependencyDirectiveToken(DDTok,
Result);
4730 if (
Result.is(tok::hash) &&
Result.isAtStartOfLine()) {
4732 if (
PP->hadModuleLoaderFatalFailure())
4738 auto NextTok = peekNextPPToken();
4739 if (NextTok && NextTok->
is(tok::raw_identifier) &&
4740 NextTok->getRawIdentifier() ==
"import") {
4742 if (
PP->hadModuleLoaderFatalFailure())
4747 if (
Result.is(tok::raw_identifier)) {
4748 Result.setRawIdentifierData(TokPtr);
4750 const IdentifierInfo *II =
PP->LookUpIdentifierInfo(
Result);
4751 if (LangOpts.CPlusPlusModules &&
Result.isModuleContextualKeyword() &&
4752 PP->HandleModuleContextualKeyword(
Result)) {
4757 return PP->HandleIdentifier(
Result);
4763 if (
Result.is(tok::colon)) {
4765 if (*BufferPtr ==
':') {
4766 assert(DepDirectives.front().Tokens[NextDepDirectiveTokenIndex].is(
4768 ++NextDepDirectiveTokenIndex;
4769 Result.setKind(tok::coloncolon);
4779bool Lexer::LexDependencyDirectiveTokenWhileSkipping(
Token &
Result) {
4780 assert(isDependencyDirectivesLexer());
4782 using namespace dependency_directives_scan;
4785 unsigned NestedIfs = 0;
4787 DepDirectives = DepDirectives.drop_front();
4788 switch (DepDirectives.front().Kind) {
4790 llvm_unreachable(
"unexpected 'pp_none'");
4831 NextDepDirectiveTokenIndex = 0;
4832 return LexEndOfFile(
Result, BufferEnd);
4836 const dependency_directives_scan::Token &DDTok =
4837 DepDirectives.front().Tokens.front();
4838 assert(DDTok.
is(tok::hash));
4839 NextDepDirectiveTokenIndex = 1;
4841 convertDependencyDirectiveToken(DDTok,
Result);
Defines the Diagnostic-related interfaces.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Result
Implement __builtin_bit_cast and related operations.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
static bool isInExpansionTokenRange(const SourceLocation Loc, const SourceManager &SM)
static bool isMathematicalExtensionID(uint32_t C, const LangOptions &LangOpts, bool IsStart, bool &IsExtension)
static char DecodeTrigraphChar(const char *CP, Lexer *L, bool Trigraphs)
DecodeTrigraphChar - If the specified character is a legal trigraph when prefixed with ?
static size_t getSpellingSlow(const Token &Tok, const char *BufPtr, const LangOptions &LangOpts, char *Spelling)
Slow case of getSpelling.
static bool CheckCodepointValidInIdentifier(const Preprocessor *PP, const LangOptions &LangOpts, uint32_t CodePoint, CharSourceRange Range, bool IsFirst, bool Diagnose)
static const char * FindConflictEnd(const char *CurPtr, const char *BufferEnd, ConflictMarkerKind CMK)
Find the end of a version control conflict marker.
static void maybeDiagnoseUTF8Homoglyph(DiagnosticsEngine &Diags, uint32_t C, CharSourceRange Range)
After encountering UTF-8 character C and interpreting it as an identifier character,...
static SourceLocation getBeginningOfFileToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
static const char * fastParseASCIIIdentifierScalar(const char *CurPtr)
static void StringifyImpl(T &Str, char Quote)
static LLVM_ATTRIBUTE_NOINLINE SourceLocation GetMappedTokenLoc(Preprocessor &PP, SourceLocation FileLoc, unsigned CharNo, unsigned TokLen)
GetMappedTokenLoc - If lexing out of a 'mapped buffer', where we pretend the lexer buffer was all exp...
static bool isAllowedIDChar(uint32_t C, const LangOptions &LangOpts, bool &IsExtension)
static CharSourceRange makeCharRange(Lexer &L, const char *Begin, const char *End)
static bool isUnicodeWhitespace(uint32_t Codepoint)
static void diagnoseMathematicalNotationInIdentifier(DiagnosticsEngine &Diags, const LangOptions &LangOpts, uint32_t C, CharSourceRange Range)
static const char * findPlaceholderEnd(const char *CurPtr, const char *BufferEnd)
static CharSourceRange makeRangeFromFileLocs(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
static bool isEndOfBlockCommentWithEscapedNewLine(const char *CurPtr, Lexer *L, bool Trigraphs)
isBlockCommentEndOfEscapedNewLine - Return true if the specified newline character (either \n or \r) ...
static const char * fastParseASCIIIdentifier(const char *CurPtr, const char *BufferEnd)
static char GetTrigraphCharForLetter(char Letter)
GetTrigraphCharForLetter - Given a character that occurs after a ?
static bool isAllowedInitiallyIDChar(uint32_t C, const LangOptions &LangOpts, bool &IsExtension)
static void maybeDiagnoseIDCharCompat(DiagnosticsEngine &Diags, uint32_t C, CharSourceRange Range, bool IsFirst)
static const char * findBeginningOfLine(StringRef Buffer, unsigned Offset)
Returns the pointer that points to the beginning of line that contains the given offset,...
Defines the MultipleIncludeOpt interface.
Defines the clang::Preprocessor interface.
static constexpr bool isOneOf()
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
static const llvm::sys::UnicodeCharRange C11DisallowedInitialIDCharRanges[]
static const llvm::sys::UnicodeCharRange C99DisallowedInitialIDCharRanges[]
static const llvm::sys::UnicodeCharRange UnicodeWhitespaceCharRanges[]
static const llvm::sys::UnicodeCharRange C99AllowedIDCharRanges[]
static const llvm::sys::UnicodeCharRange C11AllowedIDCharRanges[]
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__PTRDIFF_TYPE__ ptrdiff_t
A signed integer type that is the result of subtracting two pointers.
static __inline__ int __ATTRS_o_ai vec_any_ge(vector signed char __a, vector signed char __b)
static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed char __a, vector signed char __b)
Represents a byte-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getEnd() const
SourceLocation getBegin() const
A little helper class used to produce diagnostics.
static unsigned getCompatDiagId(const LangOptions &LangOpts, unsigned CompatDiagId)
Get the appropriate diagnostic Id to use for issuing a compatibility diagnostic.
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 isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
One of these records is kept for each identifier that is lexed.
bool isHandleIdentifierCase() const
Return true if the Preprocessor::HandleIdentifier must be called on a token of this identifier.
bool isModuleKeyword() const
Determine whether this is the contextual keyword module.
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
bool isKeyword(const LangOptions &LangOpts) const
Return true if this token is a keyword in the specified language.
bool isImportKeyword() const
Determine whether this is the contextual keyword import.
tok::ObjCKeywordKind getObjCKeywordID() const
Return the Objective-C keyword ID for the this identifier.
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 StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
friend class Preprocessor
void SetKeepWhitespaceMode(bool Val)
SetKeepWhitespaceMode - This method lets clients enable or disable whitespace retention mode.
static SourceLocation findLocationAfterToken(SourceLocation loc, tok::TokenKind TKind, const SourceManager &SM, const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLine)
Checks that the given token is the first token that occurs after the given location (this excludes co...
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
static unsigned getEscapedNewLineSize(const char *P)
getEscapedNewLineSize - Return the size of the specified escaped newline, or 0 if it is not an escape...
bool inKeepCommentMode() const
inKeepCommentMode - Return true if the lexer should return comments as tokens.
void SetCommentRetentionState(bool Mode)
SetCommentRetentionMode - Change the comment retention mode of the lexer to the specified mode.
static std::optional< Token > findPreviousToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeComments)
Finds the token that comes before the given location.
void seek(unsigned Offset, bool IsAtStartOfLine)
Set the lexer's buffer pointer to Offset.
static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
void ReadToEndOfLine(SmallVectorImpl< char > *Result=nullptr)
ReadToEndOfLine - Read the rest of the current preprocessor line as an uninterpreted string.
static bool isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroBegin=nullptr)
Returns true if the given MacroID location points at the first token of the macro expansion.
DiagnosticBuilder Diag(const char *Loc, unsigned DiagID) const
Diag - Forwarding function for diagnostics.
DiagnosticBuilder DiagCompat(const char *Loc, unsigned CompatDiagId) const
static std::unique_ptr< Lexer > Create_PragmaLexer(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned TokLen, Preprocessor &PP)
Create_PragmaLexer: Lexer constructor - Create a new lexer object for _Pragma expansion.
const char * getBufferLocation() const
Return the current location in the buffer.
bool Lex(Token &Result)
Lex - Return the next token in the file.
bool isPragmaLexer() const
isPragmaLexer - Returns true if this Lexer is being used to lex a pragma.
static void DiagnoseDelimitedOrNamedEscapeSequence(SourceLocation Loc, bool Named, const LangOptions &Opts, DiagnosticsEngine &Diags)
Diagnose use of a delimited or named escape sequence.
static unsigned getTokenPrefixLength(SourceLocation TokStart, unsigned CharNo, const SourceManager &SM, const LangOptions &LangOpts)
Get the physical length (including trigraphs and escaped newlines) of the first CharNo characters of ...
Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile, Preprocessor &PP, bool IsFirstIncludeOfFile=true)
Lexer constructor - Create a new lexer object for the specified buffer with the specified preprocesso...
static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)
Returns true if the given MacroID location points at the last token of the macro expansion.
SourceLocation getSourceLocation() override
getSourceLocation - Return a source location for the next character in the current file.
static CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Accepts a range and returns a character range with file locations.
static bool isNewLineEscaped(const char *BufferStart, const char *Str)
Checks whether new line pointed by Str is preceded by escape sequence.
SourceLocation getSourceLocation(const char *Loc, unsigned TokLen=1) const
getSourceLocation - Return a source location identifier for the specified offset in the current file.
static StringRef getIndentationForLine(SourceLocation Loc, const SourceManager &SM)
Returns the leading whitespace for line that corresponds to the given location Loc.
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,...
bool isKeepWhitespaceMode() const
isKeepWhitespaceMode - Return true if the lexer should return tokens for every character in the file,...
static bool isAsciiIdentifierContinueChar(char c, const LangOptions &LangOpts)
Returns true if the given character could appear in an identifier.
static SourceLocation findEndOfIdentifierContinuation(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Finds the end of an identifier-continuation sequence starting at Loc.
static std::optional< Token > findNextToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeComments=false)
Finds the token that comes right after the given location.
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
static SourceLocation GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Given a location any where in a source buffer, find the location that corresponds to the beginning of...
void resetExtendedTokenMode()
Sets the extended token mode back to its initial value, according to the language options and preproc...
static StringRef getImmediateMacroNameForDiagnostics(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
Retrieve the name of the immediate macro expansion.
static PreambleBounds ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines=0)
Compute the preamble of the given file.
static bool getRawToken(SourceLocation Loc, Token &Result, const SourceManager &SM, const LangOptions &LangOpts, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
static std::string Stringify(StringRef Str, bool Charify=false)
Stringify - Convert the specified string into a C string by i) escaping '\' and " characters and ii) ...
static SizedChar getCharAndSizeNoWarn(const char *Ptr, const LangOptions &LangOpts)
getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever emit a warning.
bool LexingRawMode
True if in raw mode.
SmallVector< PPConditionalInfo, 4 > ConditionalStack
Information about the set of #if/#ifdef/#ifndef blocks we are currently in.
bool ParsingPreprocessorDirective
True when parsing #XXX; turns '\n' into a tok::eod token.
MultipleIncludeOpt MIOpt
A state machine that detects the #ifndef-wrapping a file idiom for the multiple-include optimization.
bool ParsingFilename
True after #include; turns <xx> or "xxx" into a tok::header_name token.
bool isLexingRawMode() const
Return true if this lexer is in raw mode or not.
const FileID FID
The SourceManager FileID corresponding to the file being lexed.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
SourceManager & getSourceManager() const
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
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.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isAtEndOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroEnd=nullptr) const
Returns true if the given MacroID location points at the character end of the immediate macro expansi...
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
bool isWrittenInScratchSpace(SourceLocation Loc) const
Returns whether Loc is located in a <scratch space> file.
bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const
Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin=nullptr) const
Returns true if the given MacroID location points at the beginning of the immediate macro expansion.
SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Creates an expansion SLocEntry for a macro use.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() const
bool isExpansionTokenRange() const
SourceLocation getSpellingLoc() const
bool isMacroArgExpansion() const
SourceLocation getExpansionLocEnd() const
This is a discriminated union of FileInfo and ExpansionInfo.
const ExpansionInfo & getExpansion() const
static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix)
Determine whether a suffix is a valid ud-suffix.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
static Token create(tok::TokenKind Kind, SourceLocation Loc, unsigned Length=0)
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
tok::ObjCKeywordKind getObjCKeywordID() const
Return the ObjC keyword kind.
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)) {....
tok::TokenKind getKind() const
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool isModuleContextualKeyword(bool AllowExport=true) const
Return true if we have a C++20 modules contextual keyword(export, importor module).
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const
Return true if we have an ObjC keyword identifier.
bool isSimpleTypeSpecifier(const LangOptions &LangOpts) const
Determine whether the token kind starts a simple-type-specifier.
void startToken()
Reset all flags to cleared.
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode),...
void setFlag(TokenFlags Flag)
Set the specified flag.
static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR _mm_movemask_epi8(__m128i __a)
Copies the values of the most significant bits from each 8-bit element in a 128-bit integer vector of...
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR _mm_cmpeq_epi8(__m128i __a, __m128i __b)
Compares each of the corresponding 8-bit values of the 128-bit integer vectors for equality.
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_loadu_si128(__m128i_u const *__p)
Moves packed integer values from an unaligned 128-bit memory location to elements in a 128-bit intege...
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_load_si128(__m128i const *__p)
Moves packed integer values from an aligned 128-bit memory location to elements in a 128-bit integer ...
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR _mm_set1_epi8(char __b)
Initializes all values in a 128-bit vector of [16 x i8] with the specified 8-bit value.
@ 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
@ After
Like System, but searched after the system directories.
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
ObjCKeywordKind
Provides a namespace for Objective-C keywords which start with an '@'.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Top level wrappers for InstallAPI frontend operations.
LLVM_READNONE bool isASCII(char c)
Returns true if a byte is an ASCII character.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
LLVM_READONLY bool isVerticalWhitespace(unsigned char c)
Returns true if this character is vertical ASCII whitespace: '\n', '\r'.
ConflictMarkerKind
ConflictMarkerKind - Kinds of conflict marker which the lexer might be recovering from.
@ CMK_Perforce
A Perforce-style conflict marker, initiated by 4 ">"s, separated by 4 "="s, and terminated by 4 "<"s.
@ CMK_None
Not within a conflict marker.
@ CMK_Normal
A normal or diff3 conflict marker, initiated by at least 7 "<"s, separated by at least 7 "="s or "|"s...
LLVM_READONLY bool isAsciiIdentifierContinue(unsigned char c)
std::pair< FileID, unsigned > FileIDAndOffset
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)
Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.
const llvm::sys::UnicodeCharSet::CharRanges GeneratedXIDStartRanges
@ Result
The result type of a method or function.
const llvm::sys::UnicodeCharSet::CharRanges GeneratedXIDContinueRanges
const FunctionProtoType * T
LLVM_READONLY bool isRawStringDelimBody(unsigned char c)
Return true if this is the body character of a C++ raw string delimiter.
const llvm::sys::UnicodeCharSet::CharRanges GeneratedMathematicalNotationProfileIDContinueRanges
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_.
@ Keyword
The name has been typo-corrected to a keyword.
SmallString< 16 > EscapeSingleCodepointForDiagnostic(StringRef Str)
Displays a single Unicode codepoint in U+NNNN notation, optionally prepending the quoted codepoint it...
const llvm::sys::UnicodeCharSet::CharRanges GeneratedMathematicalNotationProfileIDStartRanges
LLVM_READONLY bool isAsciiIdentifierStart(unsigned char c, bool AllowDollar=false)
Returns true if this is a valid first character of a C identifier, which is [a-zA-Z_].
__INTPTR_TYPE__ intptr_t
A signed integer type with the property that any valid pointer to void can be converted to this type,...
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
#define _mm_cmpistri(A, B, M)
Uses the immediate operand M to perform a comparison of string data with implicitly defined lengths t...
#define _SIDD_LEAST_SIGNIFICANT
#define _SIDD_NEGATIVE_POLARITY
Represents a char and the number of bytes parsed to produce it.
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Token lexed as part of dependency directive scanning.
unsigned Offset
Offset into the original source input.
bool is(tok::TokenKind K) const