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");
1296 case '=':
return '#';
1297 case ')':
return ']';
1298 case '(':
return '[';
1299 case '!':
return '|';
1300 case '\'':
return '^';
1301 case '>':
return '}';
1302 case '/':
return '\\';
1303 case '<':
return '{';
1304 case '-':
return '~';
1319 L->
Diag(CP-2, diag::trigraph_ignored);
1324 L->
Diag(CP-2, diag::trigraph_converted) << StringRef(&Res, 1);
1336 if (Ptr[Size-1] !=
'\n' && Ptr[Size-1] !=
'\r')
1340 if ((Ptr[Size] ==
'\r' || Ptr[Size] ==
'\n') &&
1341 Ptr[Size-1] != Ptr[Size])
1354const char *Lexer::SkipEscapedNewLines(
const char *P) {
1356 const char *AfterEscape;
1359 }
else if (*P ==
'?') {
1361 if (P[1] !=
'?' || P[2] !=
'/')
1371 if (NewLineSize == 0)
return P;
1372 P = AfterEscape+NewLineSize;
1379 bool IncludeComments) {
1382 return std::nullopt;
1390 bool InvalidTemp =
false;
1393 return std::nullopt;
1395 const char *TokenBegin =
File.data() + LocInfo.second;
1399 TokenBegin,
File.end());
1410 bool IncludeComments) {
1412 while (Loc != StartOfFile) {
1415 return std::nullopt;
1421 if (!
Tok.is(tok::comment) || IncludeComments) {
1425 return std::nullopt;
1434 const LangOptions &LangOpts,
bool SkipTrailingWhitespaceAndNewLine) {
1436 if (!
Tok ||
Tok->isNot(TKind))
1441 unsigned NumWhitespaceChars = 0;
1442 if (SkipTrailingWhitespaceAndNewLine) {
1444 unsigned char C = *TokenEnd;
1447 NumWhitespaceChars++;
1451 if (
C ==
'\n' ||
C ==
'\r') {
1454 NumWhitespaceChars++;
1455 if ((
C ==
'\n' ||
C ==
'\r') &&
C != PrevC)
1456 NumWhitespaceChars++;
1481 if (Ptr[0] ==
'\\') {
1487 return {
'\\', Size};
1497 Diag(Ptr, diag::backslash_newline_space);
1500 Size += EscapedNewLineSize;
1501 Ptr += EscapedNewLineSize;
1504 auto CharAndSize = getCharAndSizeSlow(Ptr,
Tok);
1505 CharAndSize.Size += Size;
1510 return {
'\\',
Size};
1514 if (Ptr[0] ==
'?' && Ptr[1] ==
'?') {
1518 LangOpts.Trigraphs)) {
1524 if (
C ==
'\\')
goto Slash;
1530 return {*Ptr,
Size + 1u};
1544 if (Ptr[0] ==
'\\') {
1550 return {
'\\',
Size};
1555 Size += EscapedNewLineSize;
1556 Ptr += EscapedNewLineSize;
1559 auto CharAndSize = getCharAndSizeSlowNoWarn(Ptr, LangOpts);
1560 CharAndSize.Size +=
Size;
1565 return {
'\\',
Size};
1569 if (LangOpts.Trigraphs && Ptr[0] ==
'?' && Ptr[1] ==
'?') {
1575 if (
C ==
'\\')
goto Slash;
1581 return {*Ptr,
Size + 1u};
1589void Lexer::SetByteOffset(
unsigned Offset,
bool StartOfLine) {
1590 BufferPtr = BufferStart + Offset;
1591 if (BufferPtr > BufferEnd)
1592 BufferPtr = BufferEnd;
1596 IsAtStartOfLine = StartOfLine;
1597 IsAtPhysicalStartOfLine = StartOfLine;
1601 static const llvm::sys::UnicodeCharSet UnicodeWhitespaceChars(
1603 return UnicodeWhitespaceChars.contains(Codepoint);
1610 bool IsStart,
bool &IsExtension) {
1611 static const llvm::sys::UnicodeCharSet MathStartChars(
1613 static const llvm::sys::UnicodeCharSet MathContinueChars(
1615 if (MathStartChars.contains(
C) ||
1616 (!IsStart && MathContinueChars.contains(
C))) {
1624 bool &IsExtension) {
1625 if (LangOpts.AsmPreprocessor) {
1627 }
else if (LangOpts.DollarIdents &&
'$' ==
C) {
1629 }
else if (LangOpts.CPlusPlus || LangOpts.C23) {
1634 static const llvm::sys::UnicodeCharSet XIDStartChars(
XIDStartRanges);
1636 if (
C ==
'_' || XIDStartChars.contains(
C) || XIDContinueChars.contains(
C))
1640 }
else if (LangOpts.C11) {
1641 static const llvm::sys::UnicodeCharSet C11AllowedIDChars(
1643 return C11AllowedIDChars.contains(
C);
1645 static const llvm::sys::UnicodeCharSet C99AllowedIDChars(
1647 return C99AllowedIDChars.contains(
C);
1652 bool &IsExtension) {
1653 assert(
C > 0x7F &&
"isAllowedInitiallyIDChar called with an ASCII codepoint");
1654 IsExtension =
false;
1655 if (LangOpts.AsmPreprocessor) {
1658 if (LangOpts.CPlusPlus || LangOpts.C23) {
1659 static const llvm::sys::UnicodeCharSet XIDStartChars(
XIDStartRanges);
1660 if (XIDStartChars.contains(
C))
1668 static const llvm::sys::UnicodeCharSet C11DisallowedInitialIDChars(
1670 return !C11DisallowedInitialIDChars.contains(
C);
1672 static const llvm::sys::UnicodeCharSet C99DisallowedInitialIDChars(
1674 return !C99DisallowedInitialIDChars.contains(
C);
1682 static const llvm::sys::UnicodeCharSet MathStartChars(
1684 static const llvm::sys::UnicodeCharSet MathContinueChars(
1687 (void)MathStartChars;
1688 (void)MathContinueChars;
1689 assert((MathStartChars.contains(
C) || MathContinueChars.contains(
C)) &&
1690 "Unexpected mathematical notation codepoint");
1691 unsigned DiagID = LangOpts.CPlusPlus
1693 LangOpts, diag_compat::mathematical_notation)
1694 : diag::ext_mathematical_notation;
1695 Diags.
Report(Range.getBegin(), DiagID)
1708 if (!Diags.
isIgnored(diag::warn_c99_compat_unicode_id, Range.getBegin())) {
1710 CannotAppearInIdentifier = 0,
1711 CannotStartIdentifier
1714 static const llvm::sys::UnicodeCharSet C99AllowedIDChars(
1716 static const llvm::sys::UnicodeCharSet C99DisallowedInitialIDChars(
1718 if (!C99AllowedIDChars.contains(
C)) {
1719 Diags.
Report(Range.getBegin(), diag::warn_c99_compat_unicode_id)
1721 << CannotAppearInIdentifier;
1722 }
else if (
IsFirst && C99DisallowedInitialIDChars.contains(
C)) {
1723 Diags.
Report(Range.getBegin(), diag::warn_c99_compat_unicode_id)
1725 << CannotStartIdentifier;
1737 struct HomoglyphPair {
1740 bool operator<(HomoglyphPair R)
const {
return Character < R.Character; }
1742 static constexpr HomoglyphPair SortedHomoglyphs[] = {
1795 std::lower_bound(std::begin(SortedHomoglyphs),
1796 std::end(SortedHomoglyphs) - 1, HomoglyphPair{
C,
'\0'});
1797 if (Homoglyph->Character ==
C) {
1798 if (Homoglyph->LooksLike) {
1799 const char LooksLikeStr[] = {Homoglyph->LooksLike, 0};
1800 Diags.
Report(Range.getBegin(), diag::warn_utf8_symbol_homoglyph)
1803 Diags.
Report(Range.getBegin(), diag::warn_utf8_symbol_zero_width)
1828 bool InvalidOnlyAtStart =
IsFirst && !IsIDStart && IsIDContinue;
1830 if (!
IsFirst || InvalidOnlyAtStart) {
1831 PP->
Diag(Range.getBegin(), diag::err_character_not_allowed_identifier)
1835 PP->
Diag(Range.getBegin(), diag::err_character_not_allowed)
1842bool Lexer::tryConsumeIdentifierUCN(
const char *&CurPtr,
unsigned Size,
1844 const char *UCNPtr = CurPtr +
Size;
1845 uint32_t CodePoint = tryReadUCN(UCNPtr, CurPtr,
nullptr);
1846 if (CodePoint == 0) {
1849 bool IsExtension =
false;
1856 !
PP->isPreprocessedOutput();
1859 false, DiagnoseAndContinue) &&
1860 !DiagnoseAndContinue)
1868 PP->getDiagnostics(), LangOpts, CodePoint,
1877 if ((UCNPtr - CurPtr == 6 && CurPtr[1] ==
'u') ||
1878 (UCNPtr - CurPtr == 10 && CurPtr[1] ==
'U'))
1881 while (CurPtr != UCNPtr)
1882 (void)getAndAdvanceChar(CurPtr,
Result);
1886bool Lexer::tryConsumeIdentifierUTF8Char(
const char *&CurPtr,
Token &
Result) {
1887 llvm::UTF32 CodePoint;
1892 unsigned FirstCodeUnitSize;
1893 getCharAndSize(CurPtr, FirstCodeUnitSize);
1894 const char *CharStart = CurPtr + FirstCodeUnitSize - 1;
1895 const char *UnicodePtr = CharStart;
1897 llvm::ConversionResult ConvResult = llvm::convertUTF8Sequence(
1898 (
const llvm::UTF8 **)&UnicodePtr, (
const llvm::UTF8 *)BufferEnd,
1899 &CodePoint, llvm::strictConversion);
1900 if (ConvResult != llvm::conversionOK)
1903 bool IsExtension =
false;
1911 !
PP->isPreprocessedOutput();
1914 PP, LangOpts, CodePoint,
1916 DiagnoseAndContinue) &&
1917 !DiagnoseAndContinue)
1925 PP->getDiagnostics(), LangOpts, CodePoint,
1937 ConsumeChar(CurPtr, FirstCodeUnitSize,
Result);
1938 CurPtr = UnicodePtr;
1943 const char *CurPtr) {
1944 bool IsExtension =
false;
1947 !
PP->isPreprocessedOutput()) {
1950 PP->getDiagnostics(), LangOpts,
C,
1960 return LexIdentifierContinue(
Result, CurPtr);
1964 !
PP->isPreprocessedOutput() && !
isASCII(*BufferPtr) &&
1985 FormTokenWithChars(
Result, CurPtr, tok::unknown);
1990 unsigned char C = *CurPtr;
1998LLVM_TARGET_SSE42
static const char *
1999fastParseASCIIIdentifierSSE42(
const char *CurPtr,
const char *BufferEnd) {
2000 alignas(16)
static constexpr char AsciiIdentifierRange[16] = {
2001 '_',
'_',
'A',
'Z',
'a',
'z',
'0',
'9',
2003 constexpr ssize_t BytesPerRegister = 16;
2005 __m128i AsciiIdentifierRangeV =
2006 _mm_load_si128(
reinterpret_cast<const __m128i *
>(AsciiIdentifierRange));
2008 while (LLVM_LIKELY(BufferEnd - CurPtr >= BytesPerRegister)) {
2009 __m128i Cv =
_mm_loadu_si128(
reinterpret_cast<const __m128i *
>(CurPtr));
2011 const int Consumed =
2016 if (Consumed == BytesPerRegister)
2026 const char *BufferEnd) {
2028 if (LLVM_LIKELY(LLVM_CPU_SUPPORTS_SSE42))
2029 return fastParseASCIIIdentifierSSE42(CurPtr, BufferEnd);
2034bool Lexer::LexIdentifierContinue(
Token &
Result,
const char *CurPtr) {
2043 unsigned char C = getCharAndSize(CurPtr, Size);
2045 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2050 if (!LangOpts.DollarIdents)
2054 Diag(CurPtr, diag::ext_dollar_in_identifier);
2055 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2058 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2066 const char *IdStart = BufferPtr;
2067 FormTokenWithChars(
Result, CurPtr, tok::raw_identifier);
2068 Result.setRawIdentifierData(IdStart);
2077 const IdentifierInfo *II =
PP->LookUpIdentifierInfo(
Result);
2084 if (isCodeCompletionPoint(CurPtr)) {
2086 Result.setKind(tok::code_completion);
2092 assert(*CurPtr == 0 &&
"Completion character must be 0");
2097 if (CurPtr < BufferEnd) {
2109 return PP->HandleIdentifier(
Result);
2116bool Lexer::isHexaLiteral(
const char *Start,
const LangOptions &LangOpts) {
2118 char C1 = CharAndSize1.Char;
2124 char C2 = CharAndSize2.Char;
2125 return (C2 ==
'x' || C2 ==
'X');
2131bool Lexer::LexNumericConstant(
Token &
Result,
const char *CurPtr) {
2133 char C = getCharAndSize(CurPtr, Size);
2136 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2138 if (LangOpts.HLSL &&
C ==
'.' && (*CurPtr ==
'x' || *CurPtr ==
'r')) {
2142 C = getCharAndSize(CurPtr, Size);
2146 if ((
C ==
'-' ||
C ==
'+') && (PrevCh ==
'E' || PrevCh ==
'e')) {
2149 if (!LangOpts.MicrosoftExt || !isHexaLiteral(BufferPtr, LangOpts))
2150 return LexNumericConstant(
Result, ConsumeChar(CurPtr, Size,
Result));
2154 if ((
C ==
'-' ||
C ==
'+') && (PrevCh ==
'P' || PrevCh ==
'p')) {
2158 bool IsHexFloat =
true;
2159 if (!LangOpts.C99) {
2160 if (!isHexaLiteral(BufferPtr, LangOpts))
2162 else if (!LangOpts.CPlusPlus17 &&
2163 std::find(BufferPtr, CurPtr,
'_') != CurPtr)
2167 return LexNumericConstant(
Result, ConsumeChar(CurPtr, Size,
Result));
2171 if (
C ==
'\'' && LangOpts.AllowLiteralDigitSeparator) {
2176 Diag(CurPtr, LangOpts.CPlusPlus
2177 ? diag::warn_cxx11_compat_digit_separator
2178 : diag::warn_c23_compat_digit_separator);
2179 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2180 CurPtr = ConsumeChar(CurPtr, NextSize,
Result);
2181 return LexNumericConstant(
Result, CurPtr);
2185 if (
C ==
'$' && LangOpts.DollarIdents) {
2186 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2187 return LexNumericConstant(
Result, CurPtr);
2191 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2192 return LexNumericConstant(
Result, CurPtr);
2194 return LexNumericConstant(
Result, CurPtr);
2197 const char *TokStart = BufferPtr;
2198 FormTokenWithChars(
Result, CurPtr, tok::numeric_constant);
2199 Result.setLiteralData(TokStart);
2205const char *Lexer::LexUDSuffix(
Token &
Result,
const char *CurPtr,
2206 bool IsStringLiteral) {
2207 assert(LangOpts.CPlusPlus);
2211 char C = getCharAndSize(CurPtr, Size);
2212 bool Consumed =
false;
2215 if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result))
2217 else if (!
isASCII(
C) && tryConsumeIdentifierUTF8Char(CurPtr,
Result))
2223 if (!LangOpts.CPlusPlus11) {
2226 C ==
'_' ? diag::warn_cxx11_compat_user_defined_literal
2227 : diag::warn_cxx11_compat_reserved_user_defined_literal)
2238 bool IsUDSuffix =
false;
2241 else if (IsStringLiteral && LangOpts.CPlusPlus14) {
2245 const unsigned MaxStandardSuffixLength = 3;
2246 char Buffer[MaxStandardSuffixLength] = {
C };
2247 unsigned Consumed =
Size;
2250 auto [
Next, NextSize] =
2254 const StringRef CompleteSuffix(Buffer, Chars);
2260 if (Chars == MaxStandardSuffixLength)
2264 Buffer[Chars++] =
Next;
2265 Consumed += NextSize;
2271 Diag(CurPtr, LangOpts.MSVCCompat
2272 ? diag::ext_ms_reserved_user_defined_literal
2273 : diag::ext_reserved_user_defined_literal)
2278 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2283 C = getCharAndSize(CurPtr, Size);
2285 CurPtr = ConsumeChar(CurPtr, Size,
Result);
2286 }
else if (
C ==
'\\' && tryConsumeIdentifierUCN(CurPtr, Size,
Result)) {
2287 }
else if (!
isASCII(
C) && tryConsumeIdentifierUTF8Char(CurPtr,
Result)) {
2297bool Lexer::LexStringLiteral(
Token &
Result,
const char *CurPtr,
2299 const char *AfterQuote = CurPtr;
2301 const char *NulCharacter =
nullptr;
2304 (Kind == tok::utf8_string_literal ||
2305 Kind == tok::utf16_string_literal ||
2306 Kind == tok::utf32_string_literal))
2307 Diag(BufferPtr, LangOpts.CPlusPlus ? diag::warn_cxx98_compat_unicode_literal
2308 : diag::warn_c99_compat_unicode_literal);
2310 char C = getAndAdvanceChar(CurPtr,
Result);
2315 const char *SavedCurPtr = CurPtr;
2316 C = getAndAdvanceChar(CurPtr,
Result);
2334 CurPtr = SavedCurPtr;
2337 if (
C ==
'\n' ||
C ==
'\r' ||
2338 (
C == 0 && CurPtr-1 == BufferEnd)) {
2340 Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 1;
2341 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2346 if (isCodeCompletionPoint(CurPtr-1)) {
2348 codeCompleteIncludedFile(AfterQuote, CurPtr - 1,
false);
2350 PP->CodeCompleteNaturalLanguage();
2351 FormTokenWithChars(
Result, CurPtr - 1, tok::unknown);
2356 NulCharacter = CurPtr-1;
2358 C = getAndAdvanceChar(CurPtr,
Result);
2362 if (LangOpts.CPlusPlus)
2363 CurPtr = LexUDSuffix(
Result, CurPtr,
true);
2367 Diag(NulCharacter, diag::null_in_char_or_string) << 1;
2370 const char *TokStart = BufferPtr;
2371 FormTokenWithChars(
Result, CurPtr, Kind);
2372 Result.setLiteralData(TokStart);
2378bool Lexer::LexRawStringLiteral(
Token &
Result,
const char *CurPtr,
2386 Diag(BufferPtr, diag::warn_cxx98_compat_raw_string_literal);
2388 unsigned PrefixLen = 0;
2392 llvm::is_contained({
'$',
'@',
'`'}, CurPtr[PrefixLen])) {
2393 const char *Pos = &CurPtr[PrefixLen];
2394 Diag(Pos, LangOpts.CPlusPlus26
2395 ? diag::warn_cxx26_compat_raw_string_literal_character_set
2396 : diag::ext_cxx26_raw_string_literal_character_set)
2397 << StringRef(Pos, 1);
2403 if (CurPtr[PrefixLen] !=
'(') {
2405 const char *PrefixEnd = &CurPtr[PrefixLen];
2406 if (PrefixLen == 16) {
2407 Diag(PrefixEnd, diag::err_raw_delim_too_long);
2408 }
else if (*PrefixEnd ==
'\n') {
2409 Diag(PrefixEnd, diag::err_invalid_newline_raw_delim);
2411 Diag(PrefixEnd, diag::err_invalid_char_raw_delim)
2412 << StringRef(PrefixEnd, 1);
2424 if (
C == 0 && CurPtr-1 == BufferEnd) {
2430 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2435 const char *Prefix = CurPtr;
2436 CurPtr += PrefixLen + 1;
2443 if (strncmp(CurPtr, Prefix, PrefixLen) == 0 && CurPtr[PrefixLen] ==
'"') {
2444 CurPtr += PrefixLen + 1;
2447 }
else if (
C == 0 && CurPtr-1 == BufferEnd) {
2449 Diag(BufferPtr, diag::err_unterminated_raw_string)
2450 << StringRef(Prefix, PrefixLen);
2451 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2457 if (LangOpts.CPlusPlus)
2458 CurPtr = LexUDSuffix(
Result, CurPtr,
true);
2461 const char *TokStart = BufferPtr;
2462 FormTokenWithChars(
Result, CurPtr, Kind);
2463 Result.setLiteralData(TokStart);
2471bool Lexer::LexAngledStringLiteral(
Token &
Result,
const char *CurPtr) {
2473 const char *NulCharacter =
nullptr;
2474 const char *AfterLessPos = CurPtr;
2475 char C = getAndAdvanceChar(CurPtr,
Result);
2480 C = getAndAdvanceChar(CurPtr,
Result);
2483 (
C == 0 && (CurPtr - 1 == BufferEnd))) {
2489 if (isCodeCompletionPoint(CurPtr - 1)) {
2490 codeCompleteIncludedFile(AfterLessPos, CurPtr - 1,
true);
2492 FormTokenWithChars(
Result, CurPtr - 1, tok::unknown);
2495 NulCharacter = CurPtr-1;
2497 C = getAndAdvanceChar(CurPtr,
Result);
2502 Diag(NulCharacter, diag::null_in_char_or_string) << 1;
2505 const char *TokStart = BufferPtr;
2506 FormTokenWithChars(
Result, CurPtr, tok::header_name);
2507 Result.setLiteralData(TokStart);
2511void Lexer::codeCompleteIncludedFile(
const char *PathStart,
2512 const char *CompletionPoint,
2515 StringRef PartialPath(PathStart, CompletionPoint - PathStart);
2516 llvm::StringRef SlashChars = LangOpts.MSVCCompat ?
"/\\" :
"/";
2517 auto Slash = PartialPath.find_last_of(SlashChars);
2519 (Slash == StringRef::npos) ?
"" : PartialPath.take_front(Slash);
2520 const char *StartOfFilename =
2521 (Slash == StringRef::npos) ? PathStart : PathStart + Slash + 1;
2523 PP->setCodeCompletionIdentifierInfo(&
PP->getIdentifierTable().get(
2524 StringRef(StartOfFilename, CompletionPoint - StartOfFilename)));
2527 while (CompletionPoint < BufferEnd) {
2528 char Next = *(CompletionPoint + 1);
2532 if (
Next == (IsAngled ?
'>' :
'"'))
2534 if (SlashChars.contains(
Next))
2538 PP->setCodeCompletionTokenRange(
2539 FileLoc.getLocWithOffset(StartOfFilename - BufferStart),
2540 FileLoc.getLocWithOffset(CompletionPoint - BufferStart));
2541 PP->CodeCompleteIncludedFile(Dir, IsAngled);
2546bool Lexer::LexCharConstant(
Token &
Result,
const char *CurPtr,
2549 const char *NulCharacter =
nullptr;
2552 if (Kind == tok::utf16_char_constant || Kind == tok::utf32_char_constant)
2553 Diag(BufferPtr, LangOpts.CPlusPlus
2554 ? diag::warn_cxx98_compat_unicode_literal
2555 : diag::warn_c99_compat_unicode_literal);
2556 else if (Kind == tok::utf8_char_constant)
2557 Diag(BufferPtr, LangOpts.CPlusPlus
2558 ? diag::warn_cxx14_compat_u8_character_literal
2559 : diag::warn_c17_compat_u8_character_literal);
2562 char C = getAndAdvanceChar(CurPtr,
Result);
2565 Diag(BufferPtr, diag::ext_empty_character);
2566 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2573 C = getAndAdvanceChar(CurPtr,
Result);
2575 if (
C ==
'\n' ||
C ==
'\r' ||
2576 (
C == 0 && CurPtr-1 == BufferEnd)) {
2578 Diag(BufferPtr, diag::ext_unterminated_char_or_string) << 0;
2579 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2584 if (isCodeCompletionPoint(CurPtr-1)) {
2585 PP->CodeCompleteNaturalLanguage();
2586 FormTokenWithChars(
Result, CurPtr-1, tok::unknown);
2591 NulCharacter = CurPtr-1;
2593 C = getAndAdvanceChar(CurPtr,
Result);
2597 if (LangOpts.CPlusPlus)
2598 CurPtr = LexUDSuffix(
Result, CurPtr,
false);
2602 Diag(NulCharacter, diag::null_in_char_or_string) << 0;
2605 const char *TokStart = BufferPtr;
2606 FormTokenWithChars(
Result, CurPtr, Kind);
2607 Result.setLiteralData(TokStart);
2615bool Lexer::SkipWhitespace(
Token &
Result,
const char *CurPtr) {
2619 unsigned char Char = *CurPtr;
2621 const char *lastNewLine =
nullptr;
2622 auto setLastNewLine = [&](
const char *Ptr) {
2628 setLastNewLine(CurPtr - 1);
2647 if (*CurPtr ==
'\n')
2648 setLastNewLine(CurPtr);
2655 FormTokenWithChars(
Result, CurPtr, tok::unknown);
2657 IsAtStartOfLine =
true;
2658 IsAtPhysicalStartOfLine =
true;
2665 char PrevChar = CurPtr[-1];
2673 if (NewLinePtr && lastNewLine && NewLinePtr != lastNewLine &&
PP) {
2674 if (
auto *Handler =
PP->getEmptylineHandler())
2690bool Lexer::SkipLineComment(
Token &
Result,
const char *CurPtr) {
2695 Diag(BufferPtr, diag::ext_line_comment);
2713 bool UnicodeDecodingAlreadyDiagnosed =
false;
2720 C !=
'\n' &&
C !=
'\r') {
2722 UnicodeDecodingAlreadyDiagnosed =
false;
2726 unsigned Length = llvm::getUTF8SequenceSize(
2727 (
const llvm::UTF8 *)CurPtr, (
const llvm::UTF8 *)BufferEnd);
2730 Diag(CurPtr, diag::warn_invalid_utf8_in_comment);
2731 UnicodeDecodingAlreadyDiagnosed =
true;
2734 UnicodeDecodingAlreadyDiagnosed =
false;
2740 const char *NextLine = CurPtr;
2743 const char *EscapePtr = CurPtr-1;
2744 bool HasSpace =
false;
2750 if (*EscapePtr ==
'\\')
2753 else if (EscapePtr[0] ==
'/' && EscapePtr[-1] ==
'?' &&
2754 EscapePtr[-2] ==
'?' && LangOpts.Trigraphs)
2756 CurPtr = EscapePtr-2;
2762 Diag(EscapePtr, diag::backslash_newline_space);
2769 const char *OldPtr = CurPtr;
2772 C = getAndAdvanceChar(CurPtr,
Result);
2777 if (
C != 0 && CurPtr == OldPtr+1) {
2785 if (CurPtr != OldPtr + 1 &&
C !=
'/' &&
2786 (CurPtr == BufferEnd + 1 || CurPtr[0] !=
'/')) {
2787 for (; OldPtr != CurPtr; ++OldPtr)
2788 if (OldPtr[0] ==
'\n' || OldPtr[0] ==
'\r') {
2792 const char *ForwardPtr = CurPtr;
2795 if (ForwardPtr[0] ==
'/' && ForwardPtr[1] ==
'/')
2800 Diag(OldPtr-1, diag::ext_multi_line_line_comment);
2805 if (
C ==
'\r' ||
C ==
'\n' || CurPtr == BufferEnd + 1) {
2810 if (
C ==
'\0' && isCodeCompletionPoint(CurPtr-1)) {
2811 PP->CodeCompleteNaturalLanguage();
2828 return SaveLineComment(
Result, CurPtr);
2842 NewLinePtr = CurPtr++;
2855bool Lexer::SaveLineComment(
Token &
Result,
const char *CurPtr) {
2858 FormTokenWithChars(
Result, CurPtr, tok::comment);
2870 assert(Spelling[0] ==
'/' && Spelling[1] ==
'/' &&
"Not line comment?");
2874 Result.setKind(tok::comment);
2885 assert(CurPtr[0] ==
'\n' || CurPtr[0] ==
'\r');
2888 const char *TrigraphPos =
nullptr;
2890 const char *SpacePos =
nullptr;
2897 if (CurPtr[0] ==
'\n' || CurPtr[0] ==
'\r') {
2899 if (CurPtr[0] == CurPtr[1])
2913 if (*CurPtr ==
'\\') {
2915 }
else if (CurPtr[0] ==
'/' && CurPtr[-1] ==
'?' && CurPtr[-2] ==
'?') {
2917 TrigraphPos = CurPtr - 2;
2928 if (*CurPtr !=
'\n' && *CurPtr !=
'\r')
2937 L->
Diag(TrigraphPos, diag::trigraph_ignored_block_comment);
2941 L->
Diag(TrigraphPos, diag::trigraph_ends_block_comment);
2946 L->
Diag(CurPtr + 1, diag::escaped_newline_block_comment_end);
2950 L->
Diag(SpacePos, diag::backslash_newline_space);
2956#include <emmintrin.h>
2971bool Lexer::SkipBlockComment(
Token &
Result,
const char *CurPtr) {
2981 unsigned char C = getCharAndSize(CurPtr, CharSize);
2983 if (
C == 0 && CurPtr == BufferEnd+1) {
2985 Diag(BufferPtr, diag::err_unterminated_block_comment);
2991 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3008 bool UnicodeDecodingAlreadyDiagnosed =
false;
3013 if (CurPtr + 24 < BufferEnd &&
3016 !(
PP &&
PP->getCodeCompletionFileLoc() == FileLoc)) {
3018 while (
C !=
'/' && (
intptr_t)CurPtr % 16 != 0) {
3023 if (
C ==
'/')
goto FoundSlash;
3027 while (CurPtr + 16 < BufferEnd) {
3029 if (LLVM_UNLIKELY(Mask != 0)) {
3039 CurPtr += llvm::countr_zero<unsigned>(cmp) + 1;
3045 __vector
unsigned char LongUTF = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
3046 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
3047 0x80, 0x80, 0x80, 0x80};
3048 __vector
unsigned char Slashes = {
3049 '/',
'/',
'/',
'/',
'/',
'/',
'/',
'/',
3050 '/',
'/',
'/',
'/',
'/',
'/',
'/',
'/'
3052 while (CurPtr + 16 < BufferEnd) {
3054 vec_any_ge(*(
const __vector
unsigned char *)CurPtr, LongUTF)))
3056 if (
vec_any_eq(*(
const __vector
unsigned char *)CurPtr, Slashes)) {
3063 while (CurPtr + 16 < BufferEnd) {
3064 bool HasNonASCII =
false;
3065 for (
unsigned I = 0; I < 16; ++I)
3066 HasNonASCII |= !
isASCII(CurPtr[I]);
3068 if (LLVM_UNLIKELY(HasNonASCII))
3071 bool HasSlash =
false;
3072 for (
unsigned I = 0; I < 16; ++I)
3073 HasSlash |= CurPtr[I] ==
'/';
3087 while (
C !=
'/' &&
C !=
'\0') {
3089 UnicodeDecodingAlreadyDiagnosed =
false;
3096 unsigned Length = llvm::getUTF8SequenceSize(
3097 (
const llvm::UTF8 *)CurPtr - 1, (
const llvm::UTF8 *)BufferEnd);
3100 Diag(CurPtr - 1, diag::warn_invalid_utf8_in_comment);
3101 UnicodeDecodingAlreadyDiagnosed =
true;
3103 UnicodeDecodingAlreadyDiagnosed =
false;
3104 CurPtr += Length - 1;
3111 if (CurPtr[-2] ==
'*')
3114 if ((CurPtr[-2] ==
'\n' || CurPtr[-2] ==
'\r')) {
3116 LangOpts.Trigraphs)) {
3122 if (CurPtr[0] ==
'*' && CurPtr[1] !=
'/') {
3127 Diag(CurPtr-1, diag::warn_nested_block_comment);
3129 }
else if (
C == 0 && CurPtr == BufferEnd+1) {
3131 Diag(BufferPtr, diag::err_unterminated_block_comment);
3140 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3146 }
else if (
C ==
'\0' && isCodeCompletionPoint(CurPtr-1)) {
3147 PP->CodeCompleteNaturalLanguage();
3165 FormTokenWithChars(
Result, CurPtr, tok::comment);
3166 IsAtPhysicalStartOfLine =
Result.isAtPhysicalStartOfLine();
3175 SkipWhitespace(
Result, CurPtr + 1);
3193 "Must be in a preprocessing directive!");
3198 const char *CurPtr = BufferPtr;
3200 char Char = getAndAdvanceChar(CurPtr, Tmp);
3208 if (CurPtr-1 != BufferEnd) {
3209 if (isCodeCompletionPoint(CurPtr-1)) {
3210 PP->CodeCompleteNaturalLanguage();
3225 assert(CurPtr[-1] == Char &&
"Trigraphs for newline?");
3226 BufferPtr = CurPtr-1;
3230 if (Tmp.
is(tok::code_completion)) {
3232 PP->CodeCompleteNaturalLanguage();
3235 assert(Tmp.
is(tok::eod) &&
"Unexpected token!");
3247bool Lexer::LexEndOfFile(
Token &
Result,
const char *CurPtr) {
3255 FormTokenWithChars(
Result, CurPtr, tok::eod);
3267 BufferPtr = BufferEnd;
3268 FormTokenWithChars(
Result, BufferEnd, tok::eof);
3272 if (
PP->isRecordingPreamble() &&
PP->isInPrimaryFile()) {
3278 MIOpt.ExitTopLevelConditional();
3286 if (
PP->getCodeCompletionFileLoc() != FileLoc)
3288 diag::err_pp_unterminated_conditional);
3295 if (CurPtr != BufferStart && (CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r'))
3296 Diag(BufferEnd, diag::warn_no_newline_eof)
3308std::optional<Token> Lexer::peekNextPPToken() {
3309 assert(!
LexingRawMode &&
"How can we expand a macro from a skipping buffer?");
3311 if (isDependencyDirectivesLexer()) {
3312 if (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size())
3313 return std::nullopt;
3315 (void)convertDependencyDirectiveToken(
3316 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex],
Result);
3326 const char *TmpBufferPtr = BufferPtr;
3328 bool atStartOfLine = IsAtStartOfLine;
3329 bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
3330 bool leadingSpace = HasLeadingSpace;
3331 MultipleIncludeOpt MIOptState =
MIOpt;
3337 BufferPtr = TmpBufferPtr;
3339 HasLeadingSpace = leadingSpace;
3340 IsAtStartOfLine = atStartOfLine;
3341 IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
3346 if (
Tok.
is(tok::eof))
3347 return std::nullopt;
3354 const char *Terminator = CMK ==
CMK_Perforce ?
"<<<<\n" :
">>>>>>>";
3356 auto RestOfBuffer = StringRef(CurPtr, BufferEnd - CurPtr).substr(TermLen);
3357 size_t Pos = RestOfBuffer.find(Terminator);
3358 while (Pos != StringRef::npos) {
3361 (RestOfBuffer[Pos - 1] !=
'\r' && RestOfBuffer[Pos - 1] !=
'\n')) {
3362 RestOfBuffer = RestOfBuffer.substr(Pos+TermLen);
3363 Pos = RestOfBuffer.find(Terminator);
3366 return RestOfBuffer.data()+Pos;
3375bool Lexer::IsStartOfConflictMarker(
const char *CurPtr) {
3377 if (CurPtr != BufferStart &&
3378 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3382 if (!StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
"<<<<<<<") &&
3383 !StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
">>>> "))
3398 Diag(CurPtr, diag::err_conflict_marker);
3399 CurrentConflictMarkerState =
Kind;
3403 while (*CurPtr !=
'\r' && *CurPtr !=
'\n') {
3404 assert(CurPtr != BufferEnd &&
"Didn't find end of line");
3419bool Lexer::HandleEndOfConflictMarker(
const char *CurPtr) {
3421 if (CurPtr != BufferStart &&
3422 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3431 for (
unsigned i = 1; i != 4; ++i)
3432 if (CurPtr[i] != CurPtr[0])
3439 CurrentConflictMarkerState)) {
3443 while (CurPtr != BufferEnd && *CurPtr !=
'\r' && *CurPtr !=
'\n')
3449 CurrentConflictMarkerState =
CMK_None;
3457 const char *BufferEnd) {
3458 if (CurPtr == BufferEnd)
3461 for (; CurPtr != BufferEnd; ++CurPtr) {
3462 if (CurPtr[0] ==
'#' && CurPtr[1] ==
'>')
3468bool Lexer::lexEditorPlaceholder(
Token &
Result,
const char *CurPtr) {
3469 assert(CurPtr[-1] ==
'<' && CurPtr[0] ==
'#' &&
"Not a placeholder!");
3475 const char *Start = CurPtr - 1;
3476 if (!LangOpts.AllowEditorPlaceholders)
3477 Diag(Start, diag::err_placeholder_in_source);
3479 FormTokenWithChars(
Result, End, tok::raw_identifier);
3480 Result.setRawIdentifierData(Start);
3487bool Lexer::isCodeCompletionPoint(
const char *CurPtr)
const {
3488 if (
PP &&
PP->isCodeCompletionEnabled()) {
3489 SourceLocation Loc = FileLoc.getLocWithOffset(CurPtr-BufferStart);
3490 return Loc ==
PP->getCodeCompletionLoc();
3501 if (Opts.CPlusPlus23)
3502 DiagId = diag::warn_cxx23_delimited_escape_sequence;
3503 else if (Opts.C2y && !Named)
3504 DiagId = diag::warn_c2y_delimited_escape_sequence;
3506 DiagId = diag::ext_delimited_escape_sequence;
3512 if (!Opts.CPlusPlus)
3513 Ext = Named ? 2 : 1 ;
3517 Diags.
Report(Loc, DiagId) << Named << Ext;
3520std::optional<uint32_t> Lexer::tryReadNumericUCN(
const char *&StartPtr,
3521 const char *SlashLoc,
3524 char Kind = getCharAndSize(StartPtr, CharSize);
3525 assert((Kind ==
'u' || Kind ==
'U') &&
"expected a UCN");
3527 unsigned NumHexDigits;
3530 else if (Kind ==
'U')
3533 bool Delimited =
false;
3534 bool FoundEndDelimiter =
false;
3538 if (!LangOpts.CPlusPlus && !LangOpts.C99) {
3540 Diag(SlashLoc, diag::warn_ucn_not_valid_in_c89);
3541 return std::nullopt;
3544 const char *CurPtr = StartPtr + CharSize;
3545 const char *KindLoc = &CurPtr[-1];
3548 while (Count != NumHexDigits || Delimited) {
3549 char C = getCharAndSize(CurPtr, CharSize);
3550 if (!Delimited && Count == 0 &&
C ==
'{') {
3556 if (Delimited &&
C ==
'}') {
3558 FoundEndDelimiter =
true;
3562 unsigned Value = llvm::hexDigitValue(
C);
3563 if (
Value == std::numeric_limits<unsigned>::max()) {
3567 Diag(SlashLoc, diag::warn_delimited_ucn_incomplete)
3568 << StringRef(KindLoc, 1);
3569 return std::nullopt;
3572 if (CodePoint & 0xF000'0000) {
3574 Diag(KindLoc, diag::err_escape_too_large) << 0;
3575 return std::nullopt;
3586 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3587 : diag::warn_ucn_escape_no_digits)
3588 << StringRef(KindLoc, 1);
3589 return std::nullopt;
3592 if (Delimited && Kind ==
'U') {
3594 Diag(SlashLoc, diag::err_hex_escape_no_digits) << StringRef(KindLoc, 1);
3595 return std::nullopt;
3598 if (!Delimited && Count != NumHexDigits) {
3600 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3602 if (Count == 4 && NumHexDigits == 8) {
3603 CharSourceRange URange =
makeCharRange(*
this, KindLoc, KindLoc + 1);
3604 Diag(KindLoc, diag::note_ucn_four_not_eight)
3608 return std::nullopt;
3611 if (Delimited &&
PP)
3614 PP->getDiagnostics());
3621 if (CurPtr - StartPtr == (
ptrdiff_t)(Count + 1 + (Delimited ? 2 : 0)))
3624 while (StartPtr != CurPtr)
3625 (void)getAndAdvanceChar(StartPtr, *
Result);
3632std::optional<uint32_t> Lexer::tryReadNamedUCN(
const char *&StartPtr,
3633 const char *SlashLoc,
3638 char C = getCharAndSize(StartPtr, CharSize);
3639 assert(
C ==
'N' &&
"expected \\N{...}");
3641 const char *CurPtr = StartPtr + CharSize;
3642 const char *KindLoc = &CurPtr[-1];
3644 C = getCharAndSize(CurPtr, CharSize);
3647 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3648 return std::nullopt;
3651 const char *StartName = CurPtr;
3652 bool FoundEndDelimiter =
false;
3653 llvm::SmallVector<char, 30> Buffer;
3655 C = getCharAndSize(CurPtr, CharSize);
3658 FoundEndDelimiter =
true;
3664 Buffer.push_back(
C);
3667 if (!FoundEndDelimiter || Buffer.empty()) {
3669 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3670 : diag::warn_delimited_ucn_incomplete)
3671 << StringRef(KindLoc, 1);
3672 return std::nullopt;
3675 StringRef Name(Buffer.data(), Buffer.size());
3676 std::optional<char32_t>
Match =
3677 llvm::sys::unicode::nameToCodepointStrict(Name);
3678 std::optional<llvm::sys::unicode::LooseMatchingResult> LooseMatch;
3680 LooseMatch = llvm::sys::unicode::nameToCodepointLooseMatching(Name);
3682 Diag(StartName, diag::err_invalid_ucn_name)
3683 << StringRef(Buffer.data(), Buffer.size())
3686 Diag(StartName, diag::note_invalid_ucn_name_loose_matching)
3697 if (Diagnose &&
Match)
3700 PP->getDiagnostics());
3706 if (LooseMatch && Diagnose)
3707 Match = LooseMatch->CodePoint;
3714 if (CurPtr - StartPtr == (
ptrdiff_t)(Buffer.size() + 3))
3717 while (StartPtr != CurPtr)
3718 (void)getAndAdvanceChar(StartPtr, *
Result);
3722 return Match ? std::optional<uint32_t>(*
Match) : std::nullopt;
3725uint32_t Lexer::tryReadUCN(
const char *&StartPtr,
const char *SlashLoc,
3729 std::optional<uint32_t> CodePointOpt;
3730 char Kind = getCharAndSize(StartPtr, CharSize);
3731 if (Kind ==
'u' || Kind ==
'U')
3732 CodePointOpt = tryReadNumericUCN(StartPtr, SlashLoc,
Result);
3733 else if (Kind ==
'N')
3734 CodePointOpt = tryReadNamedUCN(StartPtr, SlashLoc,
Result);
3739 uint32_t CodePoint = *CodePointOpt;
3742 if (LangOpts.AsmPreprocessor)
3761 if (CodePoint < 0xA0) {
3765 if (CodePoint < 0x20 || CodePoint >= 0x7F)
3766 Diag(BufferPtr, diag::err_ucn_control_character);
3768 char C =
static_cast<char>(CodePoint);
3769 Diag(BufferPtr, diag::err_ucn_escape_basic_scs) << StringRef(&
C, 1);
3774 }
else if (CodePoint >= 0xD800 && CodePoint <= 0xDFFF) {
3779 if (LangOpts.CPlusPlus && !LangOpts.CPlusPlus11)
3780 Diag(BufferPtr, diag::warn_ucn_escape_surrogate);
3782 Diag(BufferPtr, diag::err_ucn_escape_invalid);
3791 const char *CurPtr) {
3794 Diag(BufferPtr, diag::ext_unicode_whitespace)
3804void Lexer::PropagateLineStartLeadingSpaceInfo(
Token &
Result) {
3805 IsAtStartOfLine =
Result.isAtStartOfLine();
3806 HasLeadingSpace =
Result.hasLeadingSpace();
3807 HasLeadingEmptyMacro =
Result.hasLeadingEmptyMacro();
3812 assert(!isDependencyDirectivesLexer());
3818 if (IsAtStartOfLine) {
3820 IsAtStartOfLine =
false;
3823 if (IsAtPhysicalStartOfLine) {
3825 IsAtPhysicalStartOfLine =
false;
3828 if (HasLeadingSpace) {
3830 HasLeadingSpace =
false;
3833 if (HasLeadingEmptyMacro) {
3835 HasLeadingEmptyMacro =
false;
3840 bool returnedToken = LexTokenInternal(
Result);
3842 assert((returnedToken || !isRawLex) &&
"Raw lex must succeed");
3843 return returnedToken;
3853 assert(!
Result.needsCleaning() &&
"Result needs cleaning");
3854 assert(!
Result.hasPtrData() &&
"Result has not been reset");
3857 const char *CurPtr = BufferPtr;
3871 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3880 unsigned SizeTmp, SizeTmp2;
3883 char Char = getAndAdvanceChar(CurPtr,
Result);
3887 NewLinePtr =
nullptr;
3892 if (CurPtr-1 == BufferEnd)
3893 return LexEndOfFile(
Result, CurPtr-1);
3896 if (isCodeCompletionPoint(CurPtr-1)) {
3899 FormTokenWithChars(
Result, CurPtr, tok::code_completion);
3904 Diag(CurPtr-1, diag::null_in_file);
3906 if (SkipWhitespace(
Result, CurPtr))
3915 if (LangOpts.MicrosoftExt) {
3917 Diag(CurPtr-1, diag::ext_ctrl_z_eof_microsoft);
3918 return LexEndOfFile(
Result, CurPtr-1);
3922 Kind = tok::unknown;
3926 if (CurPtr[0] ==
'\n')
3927 (void)getAndAdvanceChar(CurPtr,
Result);
3941 IsAtStartOfLine =
true;
3942 IsAtPhysicalStartOfLine =
true;
3943 NewLinePtr = CurPtr - 1;
3952 if (SkipWhitespace(
Result, CurPtr))
3962 SkipHorizontalWhitespace:
3964 if (SkipWhitespace(
Result, CurPtr))
3973 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP)) {
3974 if (SkipLineComment(
Result, CurPtr + 2))
3976 goto SkipIgnoredUnits;
3978 if (SkipBlockComment(
Result, CurPtr + 2))
3980 goto SkipIgnoredUnits;
3982 goto SkipHorizontalWhitespace;
3990 case '0':
case '1':
case '2':
case '3':
case '4':
3991 case '5':
case '6':
case '7':
case '8':
case '9':
3994 return LexNumericConstant(
Result, CurPtr);
4003 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4004 Char = getCharAndSize(CurPtr, SizeTmp);
4008 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4009 tok::utf16_string_literal);
4013 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4014 tok::utf16_char_constant);
4017 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4018 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4019 return LexRawStringLiteral(
Result,
4020 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4022 tok::utf16_string_literal);
4025 char Char2 = getCharAndSize(CurPtr + SizeTmp, SizeTmp2);
4029 return LexStringLiteral(
Result,
4030 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4032 tok::utf8_string_literal);
4033 if (Char2 ==
'\'' && (LangOpts.CPlusPlus17 || LangOpts.C23))
4034 return LexCharConstant(
4035 Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4037 tok::utf8_char_constant);
4039 if (Char2 ==
'R' && LangOpts.RawStringLiterals) {
4041 char Char3 = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4044 return LexRawStringLiteral(
Result,
4045 ConsumeChar(ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4048 tok::utf8_string_literal);
4055 return LexIdentifierContinue(
Result, CurPtr);
4061 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4062 Char = getCharAndSize(CurPtr, SizeTmp);
4066 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4067 tok::utf32_string_literal);
4071 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4072 tok::utf32_char_constant);
4075 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4076 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4077 return LexRawStringLiteral(
Result,
4078 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4080 tok::utf32_string_literal);
4084 return LexIdentifierContinue(
Result, CurPtr);
4090 if (LangOpts.RawStringLiterals) {
4091 Char = getCharAndSize(CurPtr, SizeTmp);
4094 return LexRawStringLiteral(
Result,
4095 ConsumeChar(CurPtr, SizeTmp,
Result),
4096 tok::string_literal);
4100 return LexIdentifierContinue(
Result, CurPtr);
4105 Char = getCharAndSize(CurPtr, SizeTmp);
4109 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4110 tok::wide_string_literal);
4113 if (LangOpts.RawStringLiterals && Char ==
'R' &&
4114 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4115 return LexRawStringLiteral(
Result,
4116 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4118 tok::wide_string_literal);
4122 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4123 tok::wide_char_constant);
4128 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
4129 case 'H':
case 'I':
case 'J':
case 'K':
case 'M':
case 'N':
4130 case 'O':
case 'P':
case 'Q':
case 'S':
case 'T':
4131 case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
4132 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
4133 case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
4134 case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
4135 case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
4139 return LexIdentifierContinue(
Result, CurPtr);
4141 if (LangOpts.DollarIdents) {
4143 Diag(CurPtr-1, diag::ext_dollar_in_identifier);
4146 return LexIdentifierContinue(
Result, CurPtr);
4149 Kind = tok::unknown;
4156 return LexCharConstant(
Result, CurPtr, tok::char_constant);
4162 return LexStringLiteral(
Result, CurPtr,
4164 : tok::string_literal);
4168 Kind = tok::question;
4171 Kind = tok::l_square;
4174 Kind = tok::r_square;
4177 Kind = tok::l_paren;
4180 Kind = tok::r_paren;
4183 Kind = tok::l_brace;
4186 Kind = tok::r_brace;
4189 Char = getCharAndSize(CurPtr, SizeTmp);
4190 if (Char >=
'0' && Char <=
'9') {
4194 return LexNumericConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result));
4195 }
else if (LangOpts.CPlusPlus && Char ==
'*') {
4196 Kind = tok::periodstar;
4198 }
else if (Char ==
'.' &&
4199 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'.') {
4200 Kind = tok::ellipsis;
4201 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4208 Char = getCharAndSize(CurPtr, SizeTmp);
4211 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4212 }
else if (Char ==
'=') {
4213 Kind = tok::ampequal;
4214 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4220 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4221 Kind = tok::starequal;
4222 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4228 Char = getCharAndSize(CurPtr, SizeTmp);
4230 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4231 Kind = tok::plusplus;
4232 }
else if (Char ==
'=') {
4233 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4234 Kind = tok::plusequal;
4240 Char = getCharAndSize(CurPtr, SizeTmp);
4242 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4243 Kind = tok::minusminus;
4244 }
else if (Char ==
'>' && LangOpts.CPlusPlus &&
4245 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'*') {
4246 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4248 Kind = tok::arrowstar;
4249 }
else if (Char ==
'>') {
4250 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4252 }
else if (Char ==
'=') {
4253 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4254 Kind = tok::minusequal;
4263 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4264 Kind = tok::exclaimequal;
4265 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4267 Kind = tok::exclaim;
4272 Char = getCharAndSize(CurPtr, SizeTmp);
4282 bool TreatAsComment =
4283 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP);
4284 if (!TreatAsComment)
4285 if (!(
PP &&
PP->isPreprocessedOutput()))
4286 TreatAsComment = getCharAndSize(CurPtr+SizeTmp, SizeTmp2) !=
'*';
4288 if (TreatAsComment) {
4289 if (SkipLineComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4295 goto SkipIgnoredUnits;
4300 if (SkipBlockComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4309 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4310 Kind = tok::slashequal;
4316 Char = getCharAndSize(CurPtr, SizeTmp);
4318 Kind = tok::percentequal;
4319 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4320 }
else if (LangOpts.Digraphs && Char ==
'>') {
4321 Kind = tok::r_brace;
4322 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4323 }
else if (LangOpts.Digraphs && Char ==
':') {
4324 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4325 Char = getCharAndSize(CurPtr, SizeTmp);
4326 if (Char ==
'%' && getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
':') {
4327 Kind = tok::hashhash;
4328 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4330 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4331 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4333 Diag(BufferPtr, diag::ext_charize_microsoft);
4342 goto HandleDirective;
4347 Kind = tok::percent;
4351 Char = getCharAndSize(CurPtr, SizeTmp);
4356 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4358 Kind = tok::lesslessequal;
4359 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4361 }
else if (After ==
'<' && IsStartOfConflictMarker(CurPtr-1)) {
4365 }
else if (After ==
'<' && HandleEndOfConflictMarker(CurPtr-1)) {
4369 }
else if (LangOpts.CUDA && After ==
'<') {
4370 Kind = tok::lesslessless;
4371 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4374 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4375 Kind = tok::lessless;
4377 }
else if (Char ==
'=') {
4378 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4380 if (LangOpts.CPlusPlus20) {
4382 Diag(BufferPtr, diag::warn_cxx17_compat_spaceship);
4383 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4385 Kind = tok::spaceship;
4391 Diag(BufferPtr, diag::warn_cxx20_compat_spaceship)
4396 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4397 Kind = tok::lessequal;
4398 }
else if (LangOpts.Digraphs && Char ==
':') {
4399 if (LangOpts.CPlusPlus11 &&
4400 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
':') {
4407 char After = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4408 if (After !=
':' && After !=
'>') {
4411 Diag(BufferPtr, diag::warn_cxx98_compat_less_colon_colon);
4416 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4417 Kind = tok::l_square;
4418 }
else if (LangOpts.Digraphs && Char ==
'%') {
4419 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4420 Kind = tok::l_brace;
4421 }
else if (Char ==
'#' && SizeTmp == 1 &&
4422 lexEditorPlaceholder(
Result, CurPtr)) {
4429 Char = getCharAndSize(CurPtr, SizeTmp);
4431 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4432 Kind = tok::greaterequal;
4433 }
else if (Char ==
'>') {
4434 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4436 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4438 Kind = tok::greatergreaterequal;
4439 }
else if (After ==
'>' && IsStartOfConflictMarker(CurPtr-1)) {
4443 }
else if (After ==
'>' && HandleEndOfConflictMarker(CurPtr-1)) {
4446 }
else if (LangOpts.CUDA && After ==
'>') {
4447 Kind = tok::greatergreatergreater;
4448 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4451 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4452 Kind = tok::greatergreater;
4455 Kind = tok::greater;
4459 Char = getCharAndSize(CurPtr, SizeTmp);
4461 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4462 Kind = tok::caretequal;
4463 }
else if (LangOpts.Reflection && Char ==
'^') {
4464 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4465 Kind = tok::caretcaret;
4467 if (LangOpts.OpenCL && Char ==
'^')
4468 Diag(CurPtr, diag::err_opencl_logical_exclusive_or);
4473 Char = getCharAndSize(CurPtr, SizeTmp);
4475 Kind = tok::pipeequal;
4476 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4477 }
else if (Char ==
'|') {
4479 if (CurPtr[1] ==
'|' && HandleEndOfConflictMarker(CurPtr-1))
4481 Kind = tok::pipepipe;
4482 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4488 Char = getCharAndSize(CurPtr, SizeTmp);
4489 if (LangOpts.Digraphs && Char ==
'>') {
4490 Kind = tok::r_square;
4491 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4492 }
else if (Char ==
':') {
4493 Kind = tok::coloncolon;
4494 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4503 Char = getCharAndSize(CurPtr, SizeTmp);
4506 if (CurPtr[1] ==
'=' && HandleEndOfConflictMarker(CurPtr-1))
4509 Kind = tok::equalequal;
4510 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4519 Char = getCharAndSize(CurPtr, SizeTmp);
4521 Kind = tok::hashhash;
4522 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4523 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4526 Diag(BufferPtr, diag::ext_charize_microsoft);
4527 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4534 goto HandleDirective;
4542 if (CurPtr[-1] ==
'@' && LangOpts.ObjC) {
4543 FormTokenWithChars(
Result, CurPtr, tok::at);
4549 llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
4551 auto NextTokOr = peekNextPPToken();
4552 if (NextTokOr.has_value()) {
4553 NextPPTok = *NextTokOr;
4556 if (NextPPTok.
is(tok::raw_identifier) &&
4564 Kind = tok::unknown;
4569 if (!LangOpts.AsmPreprocessor) {
4570 if (
uint32_t CodePoint = tryReadUCN(CurPtr, BufferPtr, &
Result)) {
4571 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4572 if (SkipWhitespace(
Result, CurPtr))
4580 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4584 Kind = tok::unknown;
4589 Kind = tok::unknown;
4593 llvm::UTF32 CodePoint;
4598 llvm::ConversionResult Status =
4599 llvm::convertUTF8Sequence((
const llvm::UTF8 **)&CurPtr,
4600 (
const llvm::UTF8 *)BufferEnd,
4602 llvm::strictConversion);
4603 if (Status == llvm::conversionOK) {
4604 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4605 if (SkipWhitespace(
Result, CurPtr))
4612 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4616 PP->isPreprocessedOutput()) {
4618 Kind = tok::unknown;
4625 Diag(CurPtr, diag::err_invalid_utf8);
4627 BufferPtr = CurPtr+1;
4639 FormTokenWithChars(
Result, CurPtr, Kind);
4645 FormTokenWithChars(
Result, CurPtr, tok::hash);
4648 if (
PP->hadModuleLoaderFatalFailure())
4660const char *Lexer::convertDependencyDirectiveToken(
4662 const char *TokPtr = BufferStart + DDTok.
Offset;
4668 if (
Result.is(tok::raw_identifier))
4669 Result.setRawIdentifierData(TokPtr);
4670 else if (
Result.isLiteral())
4671 Result.setLiteralData(TokPtr);
4672 BufferPtr = TokPtr + DDTok.
Length;
4676bool Lexer::LexDependencyDirectiveToken(
Token &
Result) {
4677 assert(isDependencyDirectivesLexer());
4679 using namespace dependency_directives_scan;
4681 if (BufferPtr == BufferEnd)
4682 return LexEndOfFile(
Result, BufferPtr);
4684 while (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size()) {
4685 if (DepDirectives.front().Kind == pp_eof)
4686 return LexEndOfFile(
Result, BufferEnd);
4687 if (DepDirectives.front().Kind == tokens_present_before_eof)
4689 NextDepDirectiveTokenIndex = 0;
4690 DepDirectives = DepDirectives.drop_front();
4693 const dependency_directives_scan::Token &DDTok =
4694 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex++];
4695 if (NextDepDirectiveTokenIndex > 1 || DDTok.
Kind != tok::hash) {
4700 const char *DDTokPtr = BufferStart + DDTok.
Offset;
4705 BufferPtr = DDTokPtr;
4706 if (!LexAngledStringLiteral(
Result, BufferPtr + 1)) {
4707 convertDependencyDirectiveToken(DDTok,
Result);
4715 const dependency_directives_scan::Token &NextTok =
4716 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex];
4717 if (BufferStart + NextTok.
Offset >= BufferPtr)
4719 ++NextDepDirectiveTokenIndex;
4724 const char *TokPtr = convertDependencyDirectiveToken(DDTok,
Result);
4726 if (
Result.is(tok::hash) &&
Result.isAtStartOfLine()) {
4728 if (
PP->hadModuleLoaderFatalFailure())
4734 auto NextTok = peekNextPPToken();
4735 if (NextTok && NextTok->
is(tok::raw_identifier) &&
4736 NextTok->getRawIdentifier() ==
"import") {
4738 if (
PP->hadModuleLoaderFatalFailure())
4743 if (
Result.is(tok::raw_identifier)) {
4744 Result.setRawIdentifierData(TokPtr);
4746 const IdentifierInfo *II =
PP->LookUpIdentifierInfo(
Result);
4747 if (LangOpts.CPlusPlusModules &&
Result.isModuleContextualKeyword() &&
4748 PP->HandleModuleContextualKeyword(
Result)) {
4753 return PP->HandleIdentifier(
Result);
4759 if (
Result.is(tok::colon)) {
4761 if (*BufferPtr ==
':') {
4762 assert(DepDirectives.front().Tokens[NextDepDirectiveTokenIndex].is(
4764 ++NextDepDirectiveTokenIndex;
4765 Result.setKind(tok::coloncolon);
4775bool Lexer::LexDependencyDirectiveTokenWhileSkipping(
Token &
Result) {
4776 assert(isDependencyDirectivesLexer());
4778 using namespace dependency_directives_scan;
4781 unsigned NestedIfs = 0;
4783 DepDirectives = DepDirectives.drop_front();
4784 switch (DepDirectives.front().Kind) {
4786 llvm_unreachable(
"unexpected 'pp_none'");
4827 NextDepDirectiveTokenIndex = 0;
4828 return LexEndOfFile(
Result, BufferEnd);
4832 const dependency_directives_scan::Token &DDTok =
4833 DepDirectives.front().Tokens.front();
4834 assert(DDTok.
is(tok::hash));
4835 NextDepDirectiveTokenIndex = 1;
4837 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.
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