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(
XIDStartRanges);
1641 if (
C ==
'_' || XIDStartChars.contains(
C) || XIDContinueChars.contains(
C))
1645 }
else if (LangOpts.C11) {
1646 static const llvm::sys::UnicodeCharSet C11AllowedIDChars(
1648 return C11AllowedIDChars.contains(
C);
1650 static const llvm::sys::UnicodeCharSet C99AllowedIDChars(
1652 return C99AllowedIDChars.contains(
C);
1657 bool &IsExtension) {
1658 assert(
C > 0x7F &&
"isAllowedInitiallyIDChar called with an ASCII codepoint");
1659 IsExtension =
false;
1660 if (LangOpts.AsmPreprocessor) {
1663 if (LangOpts.CPlusPlus || LangOpts.C23) {
1664 static const llvm::sys::UnicodeCharSet XIDStartChars(
XIDStartRanges);
1665 if (XIDStartChars.contains(
C))
1673 static const llvm::sys::UnicodeCharSet C11DisallowedInitialIDChars(
1675 return !C11DisallowedInitialIDChars.contains(
C);
1677 static const llvm::sys::UnicodeCharSet C99DisallowedInitialIDChars(
1679 return !C99DisallowedInitialIDChars.contains(
C);
1687 static const llvm::sys::UnicodeCharSet MathStartChars(
1689 static const llvm::sys::UnicodeCharSet MathContinueChars(
1692 (void)MathStartChars;
1693 (void)MathContinueChars;
1694 assert((MathStartChars.contains(
C) || MathContinueChars.contains(
C)) &&
1695 "Unexpected mathematical notation codepoint");
1696 unsigned DiagID = LangOpts.CPlusPlus
1698 LangOpts, diag_compat::mathematical_notation)
1699 : diag::ext_mathematical_notation;
1700 Diags.
Report(Range.getBegin(), DiagID)
1713 if (!Diags.
isIgnored(diag::warn_c99_compat_unicode_id, Range.getBegin())) {
1715 CannotAppearInIdentifier = 0,
1716 CannotStartIdentifier
1719 static const llvm::sys::UnicodeCharSet C99AllowedIDChars(
1721 static const llvm::sys::UnicodeCharSet C99DisallowedInitialIDChars(
1723 if (!C99AllowedIDChars.contains(
C)) {
1724 Diags.
Report(Range.getBegin(), diag::warn_c99_compat_unicode_id)
1726 << CannotAppearInIdentifier;
1727 }
else if (
IsFirst && C99DisallowedInitialIDChars.contains(
C)) {
1728 Diags.
Report(Range.getBegin(), diag::warn_c99_compat_unicode_id)
1730 << CannotStartIdentifier;
1742 struct HomoglyphPair {
1745 bool operator<(HomoglyphPair R)
const {
return Character < R.Character; }
1747 static constexpr HomoglyphPair SortedHomoglyphs[] = {
1800 std::lower_bound(std::begin(SortedHomoglyphs),
1801 std::end(SortedHomoglyphs) - 1, HomoglyphPair{
C,
'\0'});
1802 if (Homoglyph->Character ==
C) {
1803 if (Homoglyph->LooksLike) {
1804 const char LooksLikeStr[] = {Homoglyph->LooksLike, 0};
1805 Diags.
Report(Range.getBegin(), diag::warn_utf8_symbol_homoglyph)
1808 Diags.
Report(Range.getBegin(), diag::warn_utf8_symbol_zero_width)
1833 bool InvalidOnlyAtStart =
IsFirst && !IsIDStart && IsIDContinue;
1835 if (!
IsFirst || InvalidOnlyAtStart) {
1836 PP->
Diag(Range.getBegin(), diag::err_character_not_allowed_identifier)
1840 PP->
Diag(Range.getBegin(), diag::err_character_not_allowed)
1847bool Lexer::tryConsumeIdentifierUCN(
const char *&CurPtr,
unsigned Size,
1849 const char *UCNPtr = CurPtr +
Size;
1850 uint32_t CodePoint = tryReadUCN(UCNPtr, CurPtr,
nullptr);
1851 if (CodePoint == 0) {
1854 bool IsExtension =
false;
1861 !
PP->isPreprocessedOutput();
1864 false, DiagnoseAndContinue) &&
1865 !DiagnoseAndContinue)
1873 PP->getDiagnostics(), LangOpts, CodePoint,
1882 if ((UCNPtr - CurPtr == 6 && CurPtr[1] ==
'u') ||
1883 (UCNPtr - CurPtr == 10 && CurPtr[1] ==
'U'))
1886 while (CurPtr != UCNPtr)
1887 (void)getAndAdvanceChar(CurPtr,
Result);
1891bool Lexer::tryConsumeIdentifierUTF8Char(
const char *&CurPtr,
Token &
Result) {
1892 llvm::UTF32 CodePoint;
1897 unsigned FirstCodeUnitSize;
1898 getCharAndSize(CurPtr, FirstCodeUnitSize);
1899 const char *CharStart = CurPtr + FirstCodeUnitSize - 1;
1900 const char *UnicodePtr = CharStart;
1902 llvm::ConversionResult ConvResult = llvm::convertUTF8Sequence(
1903 (
const llvm::UTF8 **)&UnicodePtr, (
const llvm::UTF8 *)BufferEnd,
1904 &CodePoint, llvm::strictConversion);
1905 if (ConvResult != llvm::conversionOK)
1908 bool IsExtension =
false;
1916 !
PP->isPreprocessedOutput();
1919 PP, LangOpts, CodePoint,
1921 DiagnoseAndContinue) &&
1922 !DiagnoseAndContinue)
1930 PP->getDiagnostics(), LangOpts, CodePoint,
1942 ConsumeChar(CurPtr, FirstCodeUnitSize,
Result);
1943 CurPtr = UnicodePtr;
1948 const char *CurPtr) {
1949 bool IsExtension =
false;
1952 !
PP->isPreprocessedOutput()) {
1955 PP->getDiagnostics(), LangOpts,
C,
1965 return LexIdentifierContinue(
Result, CurPtr);
1969 !
PP->isPreprocessedOutput() && !
isASCII(*BufferPtr) &&
1990 FormTokenWithChars(
Result, CurPtr, tok::unknown);
1995 unsigned char C = *CurPtr;
2003LLVM_TARGET_SSE42
static const char *
2004fastParseASCIIIdentifierSSE42(
const char *CurPtr,
const char *BufferEnd) {
2005 alignas(16)
static constexpr char AsciiIdentifierRange[16] = {
2006 '_',
'_',
'A',
'Z',
'a',
'z',
'0',
'9',
2008 constexpr ssize_t BytesPerRegister = 16;
2010 __m128i AsciiIdentifierRangeV =
2011 _mm_load_si128(
reinterpret_cast<const __m128i *
>(AsciiIdentifierRange));
2013 while (LLVM_LIKELY(BufferEnd - CurPtr >= BytesPerRegister)) {
2014 __m128i Cv =
_mm_loadu_si128(
reinterpret_cast<const __m128i *
>(CurPtr));
2016 const int Consumed =
2021 if (Consumed == BytesPerRegister)
2031 const char *BufferEnd) {
2033 if (LLVM_LIKELY(LLVM_CPU_SUPPORTS_SSE42))
2034 return fastParseASCIIIdentifierSSE42(CurPtr, BufferEnd);
2039bool Lexer::LexIdentifierContinue(
Token &
Result,
const char *CurPtr) {
2048 unsigned char C = getCharAndSize(CurPtr, Size);
2050 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2055 if (!LangOpts.DollarIdents)
2059 Diag(CurPtr, diag::ext_dollar_in_identifier);
2060 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2063 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2071 const char *IdStart = BufferPtr;
2072 FormTokenWithChars(
Result, CurPtr, tok::raw_identifier);
2073 Result.setRawIdentifierData(IdStart);
2082 const IdentifierInfo *II =
PP->LookUpIdentifierInfo(
Result);
2089 if (isCodeCompletionPoint(CurPtr)) {
2091 Result.setKind(tok::code_completion);
2097 assert(*CurPtr == 0 &&
"Completion character must be 0");
2102 if (CurPtr < BufferEnd) {
2114 return PP->HandleIdentifier(
Result);
2121bool Lexer::isHexaLiteral(
const char *Start,
const LangOptions &LangOpts) {
2123 char C1 = CharAndSize1.Char;
2129 char C2 = CharAndSize2.Char;
2130 return (C2 ==
'x' || C2 ==
'X');
2136bool Lexer::LexNumericConstant(
Token &
Result,
const char *CurPtr) {
2138 char C = getCharAndSize(CurPtr, Size);
2141 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2143 if (LangOpts.HLSL &&
C ==
'.' && (*CurPtr ==
'x' || *CurPtr ==
'r')) {
2147 C = getCharAndSize(CurPtr, Size);
2151 if ((
C ==
'-' ||
C ==
'+') && (PrevCh ==
'E' || PrevCh ==
'e')) {
2154 if (!LangOpts.MicrosoftExt || !isHexaLiteral(BufferPtr, LangOpts))
2155 return LexNumericConstant(
Result, ConsumeChar(CurPtr, Size,
Result));
2159 if ((
C ==
'-' ||
C ==
'+') && (PrevCh ==
'P' || PrevCh ==
'p')) {
2163 bool IsHexFloat =
true;
2164 if (!LangOpts.C99) {
2165 if (!isHexaLiteral(BufferPtr, LangOpts))
2167 else if (!LangOpts.CPlusPlus17 &&
2168 std::find(BufferPtr, CurPtr,
'_') != CurPtr)
2172 return LexNumericConstant(
Result, ConsumeChar(CurPtr, Size,
Result));
2176 if (
C ==
'\'' && LangOpts.AllowLiteralDigitSeparator) {
2181 Diag(CurPtr, LangOpts.CPlusPlus
2182 ? diag::warn_cxx11_compat_digit_separator
2183 : diag::warn_c23_compat_digit_separator);
2184 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2185 CurPtr = ConsumeChar(CurPtr, NextSize,
Result);
2186 return LexNumericConstant(
Result, CurPtr);
2190 if (
C ==
'$' && LangOpts.DollarIdents) {
2191 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2192 return LexNumericConstant(
Result, CurPtr);
2196 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2197 return LexNumericConstant(
Result, CurPtr);
2199 return LexNumericConstant(
Result, CurPtr);
2202 const char *TokStart = BufferPtr;
2203 FormTokenWithChars(
Result, CurPtr, tok::numeric_constant);
2204 Result.setLiteralData(TokStart);
2210const char *Lexer::LexUDSuffix(
Token &
Result,
const char *CurPtr,
2211 bool IsStringLiteral) {
2212 assert(LangOpts.CPlusPlus);
2216 char C = getCharAndSize(CurPtr, Size);
2217 bool Consumed =
false;
2220 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2222 else if (!
isASCII(
C) && tryConsumeIdentifierUTF8Char(CurPtr,
Result))
2228 if (!LangOpts.CPlusPlus11) {
2231 C ==
'_' ? diag::warn_cxx11_compat_user_defined_literal
2232 : diag::warn_cxx11_compat_reserved_user_defined_literal)
2243 bool IsUDSuffix =
false;
2246 else if (IsStringLiteral && LangOpts.CPlusPlus14) {
2250 const unsigned MaxStandardSuffixLength = 3;
2251 char Buffer[MaxStandardSuffixLength] = {
C };
2252 unsigned Consumed =
Size;
2255 auto [
Next, NextSize] =
2259 const StringRef CompleteSuffix(Buffer, Chars);
2265 if (Chars == MaxStandardSuffixLength)
2269 Buffer[Chars++] =
Next;
2270 Consumed += NextSize;
2276 Diag(CurPtr, LangOpts.MSVCCompat
2277 ? diag::ext_ms_reserved_user_defined_literal
2278 : diag::ext_reserved_user_defined_literal)
2283 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2288 C = getCharAndSize(CurPtr, Size);
2290 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2291 }
else if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result)) {
2292 }
else if (!
isASCII(
C) && tryConsumeIdentifierUTF8Char(CurPtr,
Result)) {
2302bool Lexer::LexStringLiteral(
Token &
Result,
const char *CurPtr,
2304 const char *AfterQuote = CurPtr;
2306 const char *NulCharacter =
nullptr;
2309 (Kind == tok::utf8_string_literal ||
2310 Kind == tok::utf16_string_literal ||
2311 Kind == tok::utf32_string_literal))
2312 Diag(BufferPtr, LangOpts.CPlusPlus ? diag::warn_cxx98_compat_unicode_literal
2313 : diag::warn_c99_compat_unicode_literal);
2315 char C = getAndAdvanceChar(CurPtr,
Result);
2320 const char *SavedCurPtr = CurPtr;
2321 C = getAndAdvanceChar(CurPtr,
Result);
2339 CurPtr = SavedCurPtr;
2342 if (
C ==
'\n' ||
C ==
'\r' ||
2343 (
C == 0 && CurPtr-1 == BufferEnd)) {
2345 Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 1;
2346 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2351 if (isCodeCompletionPoint(CurPtr-1)) {
2353 codeCompleteIncludedFile(AfterQuote, CurPtr - 1,
false);
2355 PP->CodeCompleteNaturalLanguage();
2356 FormTokenWithChars(
Result, CurPtr - 1, tok::unknown);
2361 NulCharacter = CurPtr-1;
2363 C = getAndAdvanceChar(CurPtr,
Result);
2367 if (LangOpts.CPlusPlus)
2368 CurPtr = LexUDSuffix(
Result, CurPtr,
true);
2372 Diag(NulCharacter, diag::null_in_char_or_string) << 1;
2375 const char *TokStart = BufferPtr;
2376 FormTokenWithChars(
Result, CurPtr, Kind);
2377 Result.setLiteralData(TokStart);
2383bool Lexer::LexRawStringLiteral(
Token &
Result,
const char *CurPtr,
2391 Diag(BufferPtr, diag::warn_cxx98_compat_raw_string_literal);
2393 unsigned PrefixLen = 0;
2397 llvm::is_contained({
'$',
'@',
'`'}, CurPtr[PrefixLen])) {
2398 const char *Pos = &CurPtr[PrefixLen];
2399 DiagCompat(Pos, diag_compat::raw_string_literal_character_set)
2400 << StringRef(Pos, 1);
2406 if (CurPtr[PrefixLen] !=
'(') {
2408 const char *PrefixEnd = &CurPtr[PrefixLen];
2409 if (PrefixLen == 16) {
2410 Diag(PrefixEnd, diag::err_raw_delim_too_long);
2411 }
else if (*PrefixEnd ==
'\n') {
2412 Diag(PrefixEnd, diag::err_invalid_newline_raw_delim);
2414 Diag(PrefixEnd, diag::err_invalid_char_raw_delim)
2415 << StringRef(PrefixEnd, 1);
2427 if (
C == 0 && CurPtr-1 == BufferEnd) {
2433 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2438 const char *Prefix = CurPtr;
2439 CurPtr += PrefixLen + 1;
2446 if (strncmp(CurPtr, Prefix, PrefixLen) == 0 && CurPtr[PrefixLen] ==
'"') {
2447 CurPtr += PrefixLen + 1;
2450 }
else if (
C == 0 && CurPtr-1 == BufferEnd) {
2452 Diag(BufferPtr, diag::err_unterminated_raw_string)
2453 << StringRef(Prefix, PrefixLen);
2454 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2460 if (LangOpts.CPlusPlus)
2461 CurPtr = LexUDSuffix(
Result, CurPtr,
true);
2464 const char *TokStart = BufferPtr;
2465 FormTokenWithChars(
Result, CurPtr, Kind);
2466 Result.setLiteralData(TokStart);
2474bool Lexer::LexAngledStringLiteral(
Token &
Result,
const char *CurPtr) {
2476 const char *NulCharacter =
nullptr;
2477 const char *AfterLessPos = CurPtr;
2478 char C = getAndAdvanceChar(CurPtr,
Result);
2483 C = getAndAdvanceChar(CurPtr,
Result);
2486 (
C == 0 && (CurPtr - 1 == BufferEnd))) {
2492 if (isCodeCompletionPoint(CurPtr - 1)) {
2493 codeCompleteIncludedFile(AfterLessPos, CurPtr - 1,
true);
2495 FormTokenWithChars(
Result, CurPtr - 1, tok::unknown);
2498 NulCharacter = CurPtr-1;
2500 C = getAndAdvanceChar(CurPtr,
Result);
2505 Diag(NulCharacter, diag::null_in_char_or_string) << 1;
2508 const char *TokStart = BufferPtr;
2509 FormTokenWithChars(
Result, CurPtr, tok::header_name);
2510 Result.setLiteralData(TokStart);
2514void Lexer::codeCompleteIncludedFile(
const char *PathStart,
2515 const char *CompletionPoint,
2518 StringRef PartialPath(PathStart, CompletionPoint - PathStart);
2519 llvm::StringRef SlashChars = LangOpts.MSVCCompat ?
"/\\" :
"/";
2520 auto Slash = PartialPath.find_last_of(SlashChars);
2522 (Slash == StringRef::npos) ?
"" : PartialPath.take_front(Slash);
2523 const char *StartOfFilename =
2524 (Slash == StringRef::npos) ? PathStart : PathStart + Slash + 1;
2526 PP->setCodeCompletionIdentifierInfo(&
PP->getIdentifierTable().get(
2527 StringRef(StartOfFilename, CompletionPoint - StartOfFilename)));
2530 while (CompletionPoint < BufferEnd) {
2531 char Next = *(CompletionPoint + 1);
2535 if (
Next == (IsAngled ?
'>' :
'"'))
2537 if (SlashChars.contains(
Next))
2541 PP->setCodeCompletionTokenRange(
2542 FileLoc.getLocWithOffset(StartOfFilename - BufferStart),
2543 FileLoc.getLocWithOffset(CompletionPoint - BufferStart));
2544 PP->CodeCompleteIncludedFile(Dir, IsAngled);
2549bool Lexer::LexCharConstant(
Token &
Result,
const char *CurPtr,
2552 const char *NulCharacter =
nullptr;
2555 if (Kind == tok::utf16_char_constant || Kind == tok::utf32_char_constant)
2556 Diag(BufferPtr, LangOpts.CPlusPlus
2557 ? diag::warn_cxx98_compat_unicode_literal
2558 : diag::warn_c99_compat_unicode_literal);
2559 else if (Kind == tok::utf8_char_constant)
2560 Diag(BufferPtr, LangOpts.CPlusPlus
2561 ? diag::warn_cxx14_compat_u8_character_literal
2562 : diag::warn_c17_compat_u8_character_literal);
2565 char C = getAndAdvanceChar(CurPtr,
Result);
2568 Diag(BufferPtr, diag::ext_empty_character);
2569 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2576 C = getAndAdvanceChar(CurPtr,
Result);
2578 if (
C ==
'\n' ||
C ==
'\r' ||
2579 (
C == 0 && CurPtr-1 == BufferEnd)) {
2581 Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 0;
2582 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2587 if (isCodeCompletionPoint(CurPtr-1)) {
2588 PP->CodeCompleteNaturalLanguage();
2589 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2594 NulCharacter = CurPtr-1;
2596 C = getAndAdvanceChar(CurPtr,
Result);
2600 if (LangOpts.CPlusPlus)
2601 CurPtr = LexUDSuffix(
Result, CurPtr,
false);
2605 Diag(NulCharacter, diag::null_in_char_or_string) << 0;
2608 const char *TokStart = BufferPtr;
2609 FormTokenWithChars(
Result, CurPtr, Kind);
2610 Result.setLiteralData(TokStart);
2618bool Lexer::SkipWhitespace(
Token &
Result,
const char *CurPtr) {
2622 unsigned char Char = *CurPtr;
2624 const char *lastNewLine =
nullptr;
2625 auto setLastNewLine = [&](
const char *
Ptr) {
2631 setLastNewLine(CurPtr - 1);
2650 if (*CurPtr ==
'\n')
2651 setLastNewLine(CurPtr);
2658 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2660 IsAtStartOfLine =
true;
2661 IsAtPhysicalStartOfLine =
true;
2668 char PrevChar = CurPtr[-1];
2676 if (NewLinePtr && lastNewLine && NewLinePtr != lastNewLine &&
PP) {
2677 if (
auto *Handler =
PP->getEmptylineHandler())
2693bool Lexer::SkipLineComment(
Token &
Result,
const char *CurPtr) {
2698 Diag(BufferPtr, diag::ext_line_comment);
2716 bool UnicodeDecodingAlreadyDiagnosed =
false;
2723 C !=
'\n' &&
C !=
'\r') {
2725 UnicodeDecodingAlreadyDiagnosed =
false;
2729 unsigned Length = llvm::getUTF8SequenceSize(
2730 (
const llvm::UTF8 *)CurPtr, (
const llvm::UTF8 *)BufferEnd);
2733 Diag(CurPtr, diag::warn_invalid_utf8_in_comment);
2734 UnicodeDecodingAlreadyDiagnosed =
true;
2737 UnicodeDecodingAlreadyDiagnosed =
false;
2743 const char *NextLine = CurPtr;
2746 const char *EscapePtr = CurPtr-1;
2747 bool HasSpace =
false;
2753 if (*EscapePtr ==
'\\')
2756 else if (EscapePtr[0] ==
'/' && EscapePtr[-1] ==
'?' &&
2757 EscapePtr[-2] ==
'?' && LangOpts.Trigraphs)
2759 CurPtr = EscapePtr-2;
2765 Diag(EscapePtr, diag::backslash_newline_space);
2772 const char *OldPtr = CurPtr;
2775 C = getAndAdvanceChar(CurPtr,
Result);
2780 if (
C != 0 && CurPtr == OldPtr+1) {
2788 if (CurPtr != OldPtr + 1 &&
C !=
'/' &&
2789 (CurPtr == BufferEnd + 1 || CurPtr[0] !=
'/')) {
2790 for (; OldPtr != CurPtr; ++OldPtr)
2791 if (OldPtr[0] ==
'\n' || OldPtr[0] ==
'\r') {
2795 const char *ForwardPtr = CurPtr;
2798 if (ForwardPtr[0] ==
'/' && ForwardPtr[1] ==
'/')
2803 Diag(OldPtr-1, diag::ext_multi_line_line_comment);
2808 if (
C ==
'\r' ||
C ==
'\n' || CurPtr == BufferEnd + 1) {
2813 if (
C ==
'\0' && isCodeCompletionPoint(CurPtr-1)) {
2814 PP->CodeCompleteNaturalLanguage();
2831 return SaveLineComment(
Result, CurPtr);
2845 NewLinePtr = CurPtr++;
2858bool Lexer::SaveLineComment(
Token &
Result,
const char *CurPtr) {
2861 FormTokenWithChars(
Result, CurPtr, tok::comment);
2873 assert(Spelling[0] ==
'/' && Spelling[1] ==
'/' &&
"Not line comment?");
2877 Result.setKind(tok::comment);
2888 assert(CurPtr[0] ==
'\n' || CurPtr[0] ==
'\r');
2891 const char *TrigraphPos =
nullptr;
2893 const char *SpacePos =
nullptr;
2900 if (CurPtr[0] ==
'\n' || CurPtr[0] ==
'\r') {
2902 if (CurPtr[0] == CurPtr[1])
2916 if (*CurPtr ==
'\\') {
2918 }
else if (CurPtr[0] ==
'/' && CurPtr[-1] ==
'?' && CurPtr[-2] ==
'?') {
2920 TrigraphPos = CurPtr - 2;
2931 if (*CurPtr !=
'\n' && *CurPtr !=
'\r')
2940 L->
Diag(TrigraphPos, diag::trigraph_ignored_block_comment);
2944 L->
Diag(TrigraphPos, diag::trigraph_ends_block_comment);
2949 L->
Diag(CurPtr + 1, diag::escaped_newline_block_comment_end);
2953 L->
Diag(SpacePos, diag::backslash_newline_space);
2959#include <emmintrin.h>
2974bool Lexer::SkipBlockComment(
Token &
Result,
const char *CurPtr) {
2984 unsigned char C = getCharAndSize(CurPtr, CharSize);
2986 if (
C == 0 && CurPtr == BufferEnd+1) {
2988 Diag(BufferPtr, diag::err_unterminated_block_comment);
2994 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3011 bool UnicodeDecodingAlreadyDiagnosed =
false;
3016 if (CurPtr + 24 < BufferEnd &&
3019 !(
PP &&
PP->getCodeCompletionFileLoc() == FileLoc)) {
3021 while (
C !=
'/' && (
intptr_t)CurPtr % 16 != 0) {
3026 if (
C ==
'/')
goto FoundSlash;
3030 while (CurPtr + 16 < BufferEnd) {
3032 if (LLVM_UNLIKELY(Mask != 0)) {
3042 CurPtr += llvm::countr_zero<unsigned>(cmp) + 1;
3048 __vector
unsigned char LongUTF = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
3049 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
3050 0x80, 0x80, 0x80, 0x80};
3051 __vector
unsigned char Slashes = {
3052 '/',
'/',
'/',
'/',
'/',
'/',
'/',
'/',
3053 '/',
'/',
'/',
'/',
'/',
'/',
'/',
'/'
3055 while (CurPtr + 16 < BufferEnd) {
3057 vec_any_ge(*(
const __vector
unsigned char *)CurPtr, LongUTF)))
3059 if (
vec_any_eq(*(
const __vector
unsigned char *)CurPtr, Slashes)) {
3066 while (CurPtr + 16 < BufferEnd) {
3067 bool HasNonASCII =
false;
3068 for (
unsigned I = 0; I < 16; ++I)
3069 HasNonASCII |= !
isASCII(CurPtr[I]);
3071 if (LLVM_UNLIKELY(HasNonASCII))
3074 bool HasSlash =
false;
3075 for (
unsigned I = 0; I < 16; ++I)
3076 HasSlash |= CurPtr[I] ==
'/';
3090 while (
C !=
'/' &&
C !=
'\0') {
3092 UnicodeDecodingAlreadyDiagnosed =
false;
3099 unsigned Length = llvm::getUTF8SequenceSize(
3100 (
const llvm::UTF8 *)CurPtr - 1, (
const llvm::UTF8 *)BufferEnd);
3103 Diag(CurPtr - 1, diag::warn_invalid_utf8_in_comment);
3104 UnicodeDecodingAlreadyDiagnosed =
true;
3106 UnicodeDecodingAlreadyDiagnosed =
false;
3107 CurPtr += Length - 1;
3114 if (CurPtr[-2] ==
'*')
3117 if ((CurPtr[-2] ==
'\n' || CurPtr[-2] ==
'\r')) {
3119 LangOpts.Trigraphs)) {
3125 if (CurPtr[0] ==
'*' && CurPtr[1] !=
'/') {
3130 Diag(CurPtr-1, diag::warn_nested_block_comment);
3132 }
else if (
C == 0 && CurPtr == BufferEnd+1) {
3134 Diag(BufferPtr, diag::err_unterminated_block_comment);
3143 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3149 }
else if (
C ==
'\0' && isCodeCompletionPoint(CurPtr-1)) {
3150 PP->CodeCompleteNaturalLanguage();
3168 FormTokenWithChars(
Result, CurPtr, tok::comment);
3169 IsAtPhysicalStartOfLine =
Result.isAtPhysicalStartOfLine();
3178 SkipWhitespace(
Result, CurPtr + 1);
3196 "Must be in a preprocessing directive!");
3201 const char *CurPtr = BufferPtr;
3203 char Char = getAndAdvanceChar(CurPtr, Tmp);
3211 if (CurPtr-1 != BufferEnd) {
3212 if (isCodeCompletionPoint(CurPtr-1)) {
3213 PP->CodeCompleteNaturalLanguage();
3228 assert(CurPtr[-1] == Char &&
"Trigraphs for newline?");
3229 BufferPtr = CurPtr-1;
3233 if (Tmp.
is(tok::code_completion)) {
3235 PP->CodeCompleteNaturalLanguage();
3238 assert(Tmp.
is(tok::eod) &&
"Unexpected token!");
3250bool Lexer::LexEndOfFile(
Token &
Result,
const char *CurPtr) {
3258 FormTokenWithChars(
Result, CurPtr, tok::eod);
3270 BufferPtr = BufferEnd;
3271 FormTokenWithChars(
Result, BufferEnd, tok::eof);
3275 if (
PP->isRecordingPreamble() &&
PP->isInPrimaryFile()) {
3281 MIOpt.ExitTopLevelConditional();
3289 if (
PP->getCodeCompletionFileLoc() != FileLoc)
3291 diag::err_pp_unterminated_conditional);
3298 if (CurPtr != BufferStart && (CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r'))
3299 Diag(BufferEnd, diag::warn_no_newline_eof)
3311std::optional<Token> Lexer::peekNextPPToken() {
3312 assert(!
LexingRawMode &&
"How can we expand a macro from a skipping buffer?");
3314 if (isDependencyDirectivesLexer()) {
3315 if (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size())
3316 return std::nullopt;
3318 (void)convertDependencyDirectiveToken(
3319 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex],
Result);
3329 const char *TmpBufferPtr = BufferPtr;
3331 bool atStartOfLine = IsAtStartOfLine;
3332 bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
3333 bool leadingSpace = HasLeadingSpace;
3334 MultipleIncludeOpt MIOptState =
MIOpt;
3340 BufferPtr = TmpBufferPtr;
3342 HasLeadingSpace = leadingSpace;
3343 IsAtStartOfLine = atStartOfLine;
3344 IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
3349 if (
Tok.
is(tok::eof))
3350 return std::nullopt;
3357 const char *Terminator = CMK ==
CMK_Perforce ?
"<<<<\n" :
">>>>>>>";
3359 auto RestOfBuffer = StringRef(CurPtr, BufferEnd - CurPtr).substr(TermLen);
3360 size_t Pos = RestOfBuffer.find(Terminator);
3361 while (Pos != StringRef::npos) {
3364 (RestOfBuffer[Pos - 1] !=
'\r' && RestOfBuffer[Pos - 1] !=
'\n')) {
3365 RestOfBuffer = RestOfBuffer.substr(Pos+TermLen);
3366 Pos = RestOfBuffer.find(Terminator);
3369 return RestOfBuffer.data()+Pos;
3378bool Lexer::IsStartOfConflictMarker(
const char *CurPtr) {
3380 if (CurPtr != BufferStart &&
3381 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3385 if (!StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
"<<<<<<<") &&
3386 !StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
">>>> "))
3401 Diag(CurPtr, diag::err_conflict_marker);
3402 CurrentConflictMarkerState =
Kind;
3406 while (*CurPtr !=
'\r' && *CurPtr !=
'\n') {
3407 assert(CurPtr != BufferEnd &&
"Didn't find end of line");
3422bool Lexer::HandleEndOfConflictMarker(
const char *CurPtr) {
3424 if (CurPtr != BufferStart &&
3425 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3434 for (
unsigned i = 1; i != 4; ++i)
3435 if (CurPtr[i] != CurPtr[0])
3442 CurrentConflictMarkerState)) {
3446 while (CurPtr != BufferEnd && *CurPtr !=
'\r' && *CurPtr !=
'\n')
3452 CurrentConflictMarkerState =
CMK_None;
3460 const char *BufferEnd) {
3461 if (CurPtr == BufferEnd)
3464 for (; CurPtr != BufferEnd; ++CurPtr) {
3465 if (CurPtr[0] ==
'#' && CurPtr[1] ==
'>')
3471bool Lexer::lexEditorPlaceholder(
Token &
Result,
const char *CurPtr) {
3472 assert(CurPtr[-1] ==
'<' && CurPtr[0] ==
'#' &&
"Not a placeholder!");
3478 const char *Start = CurPtr - 1;
3479 if (!LangOpts.AllowEditorPlaceholders)
3480 Diag(Start, diag::err_placeholder_in_source);
3482 FormTokenWithChars(
Result, End, tok::raw_identifier);
3483 Result.setRawIdentifierData(Start);
3490bool Lexer::isCodeCompletionPoint(
const char *CurPtr)
const {
3491 if (
PP &&
PP->isCodeCompletionEnabled()) {
3492 SourceLocation Loc = FileLoc.getLocWithOffset(CurPtr-BufferStart);
3493 return Loc ==
PP->getCodeCompletionLoc();
3504 if (Opts.CPlusPlus23)
3505 DiagId = diag::warn_cxx23_delimited_escape_sequence;
3506 else if (Opts.C2y && !Named)
3507 DiagId = diag::warn_c2y_delimited_escape_sequence;
3509 DiagId = diag::ext_delimited_escape_sequence;
3515 if (!Opts.CPlusPlus)
3516 Ext = Named ? 2 : 1 ;
3520 Diags.
Report(Loc, DiagId) << Named << Ext;
3523std::optional<uint32_t> Lexer::tryReadNumericUCN(
const char *&StartPtr,
3524 const char *SlashLoc,
3527 char Kind = getCharAndSize(StartPtr, CharSize);
3528 assert((Kind ==
'u' || Kind ==
'U') &&
"expected a UCN");
3530 unsigned NumHexDigits;
3533 else if (Kind ==
'U')
3536 bool Delimited =
false;
3537 bool FoundEndDelimiter =
false;
3541 if (!LangOpts.CPlusPlus && !LangOpts.C99) {
3543 Diag(SlashLoc, diag::warn_ucn_not_valid_in_c89);
3544 return std::nullopt;
3547 const char *CurPtr = StartPtr + CharSize;
3548 const char *KindLoc = &CurPtr[-1];
3551 while (Count != NumHexDigits || Delimited) {
3552 char C = getCharAndSize(CurPtr, CharSize);
3553 if (!Delimited && Count == 0 &&
C ==
'{') {
3559 if (Delimited &&
C ==
'}') {
3561 FoundEndDelimiter =
true;
3565 unsigned Value = llvm::hexDigitValue(
C);
3566 if (
Value == std::numeric_limits<unsigned>::max()) {
3570 Diag(SlashLoc, diag::warn_delimited_ucn_incomplete)
3571 << StringRef(KindLoc, 1);
3572 return std::nullopt;
3575 if (CodePoint & 0xF000'0000) {
3577 Diag(KindLoc, diag::err_escape_too_large) << 0;
3578 return std::nullopt;
3589 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3590 : diag::warn_ucn_escape_no_digits)
3591 << StringRef(KindLoc, 1);
3592 return std::nullopt;
3595 if (Delimited && Kind ==
'U') {
3597 Diag(SlashLoc, diag::err_hex_escape_no_digits) << StringRef(KindLoc, 1);
3598 return std::nullopt;
3601 if (!Delimited && Count != NumHexDigits) {
3603 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3605 if (Count == 4 && NumHexDigits == 8) {
3606 CharSourceRange URange =
makeCharRange(*
this, KindLoc, KindLoc + 1);
3607 Diag(KindLoc, diag::note_ucn_four_not_eight)
3611 return std::nullopt;
3614 if (Delimited &&
PP)
3617 PP->getDiagnostics());
3624 if (CurPtr - StartPtr == (
ptrdiff_t)(Count + 1 + (Delimited ? 2 : 0)))
3627 while (StartPtr != CurPtr)
3628 (void)getAndAdvanceChar(StartPtr, *
Result);
3635std::optional<uint32_t> Lexer::tryReadNamedUCN(
const char *&StartPtr,
3636 const char *SlashLoc,
3641 char C = getCharAndSize(StartPtr, CharSize);
3642 assert(
C ==
'N' &&
"expected \\N{...}");
3644 const char *CurPtr = StartPtr + CharSize;
3645 const char *KindLoc = &CurPtr[-1];
3647 C = getCharAndSize(CurPtr, CharSize);
3650 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3651 return std::nullopt;
3654 const char *StartName = CurPtr;
3655 bool FoundEndDelimiter =
false;
3656 llvm::SmallVector<char, 30> Buffer;
3658 C = getCharAndSize(CurPtr, CharSize);
3661 FoundEndDelimiter =
true;
3667 Buffer.push_back(
C);
3670 if (!FoundEndDelimiter || Buffer.empty()) {
3672 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3673 : diag::warn_delimited_ucn_incomplete)
3674 << StringRef(KindLoc, 1);
3675 return std::nullopt;
3678 StringRef Name(Buffer.data(), Buffer.size());
3679 std::optional<char32_t>
Match =
3680 llvm::sys::unicode::nameToCodepointStrict(Name);
3681 std::optional<llvm::sys::unicode::LooseMatchingResult> LooseMatch;
3683 LooseMatch = llvm::sys::unicode::nameToCodepointLooseMatching(Name);
3685 Diag(StartName, diag::err_invalid_ucn_name)
3686 << StringRef(Buffer.data(), Buffer.size())
3689 Diag(StartName, diag::note_invalid_ucn_name_loose_matching)
3700 if (Diagnose &&
Match)
3703 PP->getDiagnostics());
3709 if (LooseMatch && Diagnose)
3710 Match = LooseMatch->CodePoint;
3717 if (CurPtr - StartPtr == (
ptrdiff_t)(Buffer.size() + 3))
3720 while (StartPtr != CurPtr)
3721 (void)getAndAdvanceChar(StartPtr, *
Result);
3725 return Match ? std::optional<uint32_t>(*
Match) : std::nullopt;
3728uint32_t Lexer::tryReadUCN(
const char *&StartPtr,
const char *SlashLoc,
3732 std::optional<uint32_t> CodePointOpt;
3733 char Kind = getCharAndSize(StartPtr, CharSize);
3734 if (Kind ==
'u' || Kind ==
'U')
3735 CodePointOpt = tryReadNumericUCN(StartPtr, SlashLoc,
Result);
3736 else if (Kind ==
'N')
3737 CodePointOpt = tryReadNamedUCN(StartPtr, SlashLoc,
Result);
3742 uint32_t CodePoint = *CodePointOpt;
3745 if (LangOpts.AsmPreprocessor)
3764 if (CodePoint < 0xA0) {
3768 if (CodePoint < 0x20 || CodePoint >= 0x7F)
3769 Diag(BufferPtr, diag::err_ucn_control_character);
3771 char C =
static_cast<char>(CodePoint);
3772 Diag(BufferPtr, diag::err_ucn_escape_basic_scs) << StringRef(&
C, 1);
3777 }
else if (CodePoint >= 0xD800 && CodePoint <= 0xDFFF) {
3782 if (LangOpts.CPlusPlus && !LangOpts.CPlusPlus11)
3783 Diag(BufferPtr, diag::warn_ucn_escape_surrogate);
3785 Diag(BufferPtr, diag::err_ucn_escape_invalid);
3794 const char *CurPtr) {
3797 Diag(BufferPtr, diag::ext_unicode_whitespace)
3807void Lexer::PropagateLineStartLeadingSpaceInfo(
Token &
Result) {
3808 IsAtStartOfLine =
Result.isAtStartOfLine();
3809 HasLeadingSpace =
Result.hasLeadingSpace();
3810 HasLeadingEmptyMacro =
Result.hasLeadingEmptyMacro();
3815 assert(!isDependencyDirectivesLexer());
3821 if (IsAtStartOfLine) {
3823 IsAtStartOfLine =
false;
3826 if (IsAtPhysicalStartOfLine) {
3828 IsAtPhysicalStartOfLine =
false;
3831 if (HasLeadingSpace) {
3833 HasLeadingSpace =
false;
3836 if (HasLeadingEmptyMacro) {
3838 HasLeadingEmptyMacro =
false;
3843 bool returnedToken = LexTokenInternal(
Result);
3845 assert((returnedToken || !isRawLex) &&
"Raw lex must succeed");
3846 return returnedToken;
3856 assert(!
Result.needsCleaning() &&
"Result needs cleaning");
3857 assert(!
Result.hasPtrData() &&
"Result has not been reset");
3860 const char *CurPtr = BufferPtr;
3874 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3883 unsigned SizeTmp, SizeTmp2;
3886 char Char = getAndAdvanceChar(CurPtr,
Result);
3890 NewLinePtr =
nullptr;
3895 if (CurPtr-1 == BufferEnd)
3896 return LexEndOfFile(
Result, CurPtr-1);
3899 if (isCodeCompletionPoint(CurPtr-1)) {
3902 FormTokenWithChars(
Result, CurPtr, tok::code_completion);
3907 Diag(CurPtr-1, diag::null_in_file);
3909 if (SkipWhitespace(
Result, CurPtr))
3918 if (LangOpts.MicrosoftExt) {
3920 Diag(CurPtr-1, diag::ext_ctrl_z_eof_microsoft);
3921 return LexEndOfFile(
Result, CurPtr-1);
3925 Kind = tok::unknown;
3929 if (CurPtr[0] ==
'\n')
3930 (void)getAndAdvanceChar(CurPtr,
Result);
3944 IsAtStartOfLine =
true;
3945 IsAtPhysicalStartOfLine =
true;
3946 NewLinePtr = CurPtr - 1;
3955 if (SkipWhitespace(
Result, CurPtr))
3965 SkipHorizontalWhitespace:
3967 if (SkipWhitespace(
Result, CurPtr))
3976 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP)) {
3977 if (SkipLineComment(
Result, CurPtr + 2))
3979 goto SkipIgnoredUnits;
3981 if (SkipBlockComment(
Result, CurPtr + 2))
3983 goto SkipIgnoredUnits;
3985 goto SkipHorizontalWhitespace;
3993 case '0':
case '1':
case '2':
case '3':
case '4':
3994 case '5':
case '6':
case '7':
case '8':
case '9':
3997 return LexNumericConstant(
Result, CurPtr);
4006 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4007 Char = getCharAndSize(CurPtr, SizeTmp);
4011 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4012 tok::utf16_string_literal);
4016 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4017 tok::utf16_char_constant);
4020 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4021 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4022 return LexRawStringLiteral(
Result,
4023 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4025 tok::utf16_string_literal);
4028 char Char2 = getCharAndSize(CurPtr + SizeTmp, SizeTmp2);
4032 return LexStringLiteral(
Result,
4033 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4035 tok::utf8_string_literal);
4036 if (Char2 ==
'\'' && (LangOpts.CPlusPlus17 || LangOpts.C23))
4037 return LexCharConstant(
4038 Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4040 tok::utf8_char_constant);
4042 if (Char2 ==
'R' && LangOpts.RawStringLiterals) {
4044 char Char3 = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4047 return LexRawStringLiteral(
Result,
4048 ConsumeChar(ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4051 tok::utf8_string_literal);
4058 return LexIdentifierContinue(
Result, CurPtr);
4064 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4065 Char = getCharAndSize(CurPtr, SizeTmp);
4069 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4070 tok::utf32_string_literal);
4074 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4075 tok::utf32_char_constant);
4078 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4079 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4080 return LexRawStringLiteral(
Result,
4081 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4083 tok::utf32_string_literal);
4087 return LexIdentifierContinue(
Result, CurPtr);
4093 if (LangOpts.RawStringLiterals) {
4094 Char = getCharAndSize(CurPtr, SizeTmp);
4097 return LexRawStringLiteral(
Result,
4098 ConsumeChar(CurPtr, SizeTmp,
Result),
4099 tok::string_literal);
4103 return LexIdentifierContinue(
Result, CurPtr);
4108 Char = getCharAndSize(CurPtr, SizeTmp);
4112 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4113 tok::wide_string_literal);
4116 if (LangOpts.RawStringLiterals && Char ==
'R' &&
4117 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4118 return LexRawStringLiteral(
Result,
4119 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4121 tok::wide_string_literal);
4125 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4126 tok::wide_char_constant);
4131 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
4132 case 'H':
case 'I':
case 'J':
case 'K':
case 'M':
case 'N':
4133 case 'O':
case 'P':
case 'Q':
case 'S':
case 'T':
4134 case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
4135 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
4136 case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
4137 case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
4138 case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
4142 return LexIdentifierContinue(
Result, CurPtr);
4144 if (LangOpts.DollarIdents) {
4146 Diag(CurPtr-1, diag::ext_dollar_in_identifier);
4149 return LexIdentifierContinue(
Result, CurPtr);
4152 Kind = tok::unknown;
4159 return LexCharConstant(
Result, CurPtr, tok::char_constant);
4165 return LexStringLiteral(
Result, CurPtr,
4167 : tok::string_literal);
4171 Kind = tok::question;
4174 Kind = tok::l_square;
4177 Kind = tok::r_square;
4180 Kind = tok::l_paren;
4183 Kind = tok::r_paren;
4186 Kind = tok::l_brace;
4189 Kind = tok::r_brace;
4192 Char = getCharAndSize(CurPtr, SizeTmp);
4193 if (Char >=
'0' && Char <=
'9') {
4197 return LexNumericConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result));
4198 }
else if (LangOpts.CPlusPlus && Char ==
'*') {
4199 Kind = tok::periodstar;
4201 }
else if (Char ==
'.' &&
4202 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'.') {
4203 Kind = tok::ellipsis;
4204 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4211 Char = getCharAndSize(CurPtr, SizeTmp);
4214 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4215 }
else if (Char ==
'=') {
4216 Kind = tok::ampequal;
4217 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4223 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4224 Kind = tok::starequal;
4225 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4231 Char = getCharAndSize(CurPtr, SizeTmp);
4233 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4234 Kind = tok::plusplus;
4235 }
else if (Char ==
'=') {
4236 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4237 Kind = tok::plusequal;
4243 Char = getCharAndSize(CurPtr, SizeTmp);
4245 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4246 Kind = tok::minusminus;
4247 }
else if (Char ==
'>' && LangOpts.CPlusPlus &&
4248 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'*') {
4249 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4251 Kind = tok::arrowstar;
4252 }
else if (Char ==
'>') {
4253 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4255 }
else if (Char ==
'=') {
4256 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4257 Kind = tok::minusequal;
4266 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4267 Kind = tok::exclaimequal;
4268 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4270 Kind = tok::exclaim;
4275 Char = getCharAndSize(CurPtr, SizeTmp);
4285 bool TreatAsComment =
4286 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP);
4287 if (!TreatAsComment)
4288 if (!(
PP &&
PP->isPreprocessedOutput()))
4289 TreatAsComment = getCharAndSize(CurPtr+SizeTmp, SizeTmp2) !=
'*';
4291 if (TreatAsComment) {
4292 if (SkipLineComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4298 goto SkipIgnoredUnits;
4303 if (SkipBlockComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4312 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4313 Kind = tok::slashequal;
4319 Char = getCharAndSize(CurPtr, SizeTmp);
4321 Kind = tok::percentequal;
4322 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4323 }
else if (LangOpts.Digraphs && Char ==
'>') {
4324 Kind = tok::r_brace;
4325 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4326 }
else if (LangOpts.Digraphs && Char ==
':') {
4327 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4328 Char = getCharAndSize(CurPtr, SizeTmp);
4329 if (Char ==
'%' && getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
':') {
4330 Kind = tok::hashhash;
4331 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4333 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4334 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4336 Diag(BufferPtr, diag::ext_charize_microsoft);
4345 goto HandleDirective;
4350 Kind = tok::percent;
4354 Char = getCharAndSize(CurPtr, SizeTmp);
4359 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4361 Kind = tok::lesslessequal;
4362 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4364 }
else if (After ==
'<' && IsStartOfConflictMarker(CurPtr-1)) {
4368 }
else if (After ==
'<' && HandleEndOfConflictMarker(CurPtr-1)) {
4372 }
else if (LangOpts.CUDA && After ==
'<') {
4373 Kind = tok::lesslessless;
4374 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4377 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4378 Kind = tok::lessless;
4380 }
else if (Char ==
'=') {
4381 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4383 if (LangOpts.CPlusPlus20) {
4385 Diag(BufferPtr, diag::warn_cxx17_compat_spaceship);
4386 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4388 Kind = tok::spaceship;
4394 Diag(BufferPtr, diag::warn_cxx20_compat_spaceship)
4399 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4400 Kind = tok::lessequal;
4401 }
else if (LangOpts.Digraphs && Char ==
':') {
4402 if (LangOpts.CPlusPlus11 &&
4403 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
':') {
4410 char After = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4411 if (After !=
':' && After !=
'>') {
4414 Diag(BufferPtr, diag::warn_cxx98_compat_less_colon_colon);
4419 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4420 Kind = tok::l_square;
4421 }
else if (LangOpts.Digraphs && Char ==
'%') {
4422 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4423 Kind = tok::l_brace;
4424 }
else if (Char ==
'#' && SizeTmp == 1 &&
4425 lexEditorPlaceholder(
Result, CurPtr)) {
4432 Char = getCharAndSize(CurPtr, SizeTmp);
4434 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4435 Kind = tok::greaterequal;
4436 }
else if (Char ==
'>') {
4437 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4439 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4441 Kind = tok::greatergreaterequal;
4442 }
else if (After ==
'>' && IsStartOfConflictMarker(CurPtr-1)) {
4446 }
else if (After ==
'>' && HandleEndOfConflictMarker(CurPtr-1)) {
4449 }
else if (LangOpts.CUDA && After ==
'>') {
4450 Kind = tok::greatergreatergreater;
4451 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4454 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4455 Kind = tok::greatergreater;
4458 Kind = tok::greater;
4462 Char = getCharAndSize(CurPtr, SizeTmp);
4464 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4465 Kind = tok::caretequal;
4466 }
else if (LangOpts.Reflection && Char ==
'^') {
4467 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4468 Kind = tok::caretcaret;
4470 if (LangOpts.OpenCL && Char ==
'^')
4471 Diag(CurPtr, diag::err_opencl_logical_exclusive_or);
4476 Char = getCharAndSize(CurPtr, SizeTmp);
4478 Kind = tok::pipeequal;
4479 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4480 }
else if (Char ==
'|') {
4482 if (CurPtr[1] ==
'|' && HandleEndOfConflictMarker(CurPtr-1))
4484 Kind = tok::pipepipe;
4485 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4491 Char = getCharAndSize(CurPtr, SizeTmp);
4492 if (LangOpts.Digraphs && Char ==
'>') {
4493 Kind = tok::r_square;
4494 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4495 }
else if (Char ==
':') {
4496 Kind = tok::coloncolon;
4497 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4506 Char = getCharAndSize(CurPtr, SizeTmp);
4509 if (CurPtr[1] ==
'=' && HandleEndOfConflictMarker(CurPtr-1))
4512 Kind = tok::equalequal;
4513 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4522 Char = getCharAndSize(CurPtr, SizeTmp);
4524 Kind = tok::hashhash;
4525 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4526 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4529 Diag(BufferPtr, diag::ext_charize_microsoft);
4530 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4537 goto HandleDirective;
4545 if (CurPtr[-1] ==
'@' && LangOpts.ObjC) {
4546 FormTokenWithChars(
Result, CurPtr, tok::at);
4552 llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
4554 auto NextTokOr = peekNextPPToken();
4555 if (NextTokOr.has_value()) {
4556 NextPPTok = *NextTokOr;
4559 if (NextPPTok.
is(tok::raw_identifier) &&
4567 Kind = tok::unknown;
4572 if (!LangOpts.AsmPreprocessor) {
4573 if (
uint32_t CodePoint = tryReadUCN(CurPtr, BufferPtr, &
Result)) {
4574 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4575 if (SkipWhitespace(
Result, CurPtr))
4583 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4587 Kind = tok::unknown;
4592 Kind = tok::unknown;
4596 llvm::UTF32 CodePoint;
4601 llvm::ConversionResult Status =
4602 llvm::convertUTF8Sequence((
const llvm::UTF8 **)&CurPtr,
4603 (
const llvm::UTF8 *)BufferEnd,
4605 llvm::strictConversion);
4606 if (Status == llvm::conversionOK) {
4607 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4608 if (SkipWhitespace(
Result, CurPtr))
4615 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4619 PP->isPreprocessedOutput()) {
4621 Kind = tok::unknown;
4628 Diag(CurPtr, diag::err_invalid_utf8);
4630 BufferPtr = CurPtr+1;
4642 FormTokenWithChars(
Result, CurPtr, Kind);
4648 FormTokenWithChars(
Result, CurPtr, tok::hash);
4651 if (
PP->hadModuleLoaderFatalFailure())
4663const char *Lexer::convertDependencyDirectiveToken(
4665 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());
4682 using namespace dependency_directives_scan;
4684 if (BufferPtr == BufferEnd)
4685 return LexEndOfFile(
Result, BufferPtr);
4687 while (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size()) {
4688 if (DepDirectives.front().Kind == pp_eof)
4689 return LexEndOfFile(
Result, BufferEnd);
4690 if (DepDirectives.front().Kind == tokens_present_before_eof)
4692 NextDepDirectiveTokenIndex = 0;
4693 DepDirectives = DepDirectives.drop_front();
4696 const dependency_directives_scan::Token &DDTok =
4697 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex++];
4698 if (NextDepDirectiveTokenIndex > 1 || DDTok.
Kind != tok::hash) {
4703 const char *DDTokPtr = BufferStart + DDTok.
Offset;
4708 BufferPtr = DDTokPtr;
4709 if (!LexAngledStringLiteral(
Result, BufferPtr + 1)) {
4710 convertDependencyDirectiveToken(DDTok,
Result);
4718 const dependency_directives_scan::Token &NextTok =
4719 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex];
4720 if (BufferStart + NextTok.
Offset >= BufferPtr)
4722 ++NextDepDirectiveTokenIndex;
4727 const char *TokPtr = convertDependencyDirectiveToken(DDTok,
Result);
4729 if (
Result.is(tok::hash) &&
Result.isAtStartOfLine()) {
4731 if (
PP->hadModuleLoaderFatalFailure())
4737 auto NextTok = peekNextPPToken();
4738 if (NextTok && NextTok->
is(tok::raw_identifier) &&
4739 NextTok->getRawIdentifier() ==
"import") {
4741 if (
PP->hadModuleLoaderFatalFailure())
4746 if (
Result.is(tok::raw_identifier)) {
4747 Result.setRawIdentifierData(TokPtr);
4749 const IdentifierInfo *II =
PP->LookUpIdentifierInfo(
Result);
4750 if (LangOpts.CPlusPlusModules &&
Result.isModuleContextualKeyword() &&
4751 PP->HandleModuleContextualKeyword(
Result)) {
4756 return PP->HandleIdentifier(
Result);
4762 if (
Result.is(tok::colon)) {
4764 if (*BufferPtr ==
':') {
4765 assert(DepDirectives.front().Tokens[NextDepDirectiveTokenIndex].is(
4767 ++NextDepDirectiveTokenIndex;
4768 Result.setKind(tok::coloncolon);
4778bool Lexer::LexDependencyDirectiveTokenWhileSkipping(
Token &
Result) {
4779 assert(isDependencyDirectivesLexer());
4781 using namespace dependency_directives_scan;
4784 unsigned NestedIfs = 0;
4786 DepDirectives = DepDirectives.drop_front();
4787 switch (DepDirectives.front().Kind) {
4789 llvm_unreachable(
"unexpected 'pp_none'");
4830 NextDepDirectiveTokenIndex = 0;
4831 return LexEndOfFile(
Result, BufferEnd);
4835 const dependency_directives_scan::Token &DDTok =
4836 DepDirectives.front().Tokens.front();
4837 assert(DDTok.
is(tok::hash));
4838 NextDepDirectiveTokenIndex = 1;
4840 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[]
static const llvm::sys::UnicodeCharRange MathematicalNotationProfileIDStartRanges[]
static const llvm::sys::UnicodeCharRange MathematicalNotationProfileIDContinueRanges[]
static const llvm::sys::UnicodeCharRange XIDStartRanges[]
static const llvm::sys::UnicodeCharRange XIDContinueRanges[]
__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 Characters characters...
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
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'.
@ Result
The result type of a method or function.
const FunctionProtoType * T
LLVM_READONLY bool isRawStringDelimBody(unsigned char c)
Return true if this is the body character of a C++ raw string delimiter.
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...
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 + ...)
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
#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