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/Traits.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)
260 FileID SpellingFID =
SM.getFileID(SpellingLoc);
261 llvm::MemoryBufferRef InputFile =
SM.getBufferOrFake(SpellingFID);
262 auto L = std::make_unique<Lexer>(SpellingFID, InputFile,
PP);
267 const char *StrData =
SM.getCharacterData(SpellingLoc);
269 L->BufferPtr = StrData;
270 L->BufferEnd = StrData+TokLen;
271 assert(L->BufferEnd[0] == 0 &&
"Buffer is not nul terminated!");
275 L->FileLoc =
SM.createExpansionLoc(
SM.getLocForStartOfFile(SpellingFID),
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();
520 Loc =
SM.getExpansionLoc(Loc);
523 const StringRef Buffer =
SM.getBufferData(LocInfo.first, &
Invalid);
527 const char *StrData = Buffer.data() + LocInfo.second;
528 if (StrData >= Buffer.end())
533 Lexer TheLexer(
SM.getLocForStartOfFile(LocInfo.first), LangOpts,
534 Buffer.begin(), StrData, Buffer.end());
537 TheLexer.LexIdentifierContinue(
Tok, StrData);
546 bool IgnoreWhiteSpace) {
555 Loc =
SM.getExpansionLoc(Loc);
558 StringRef Buffer =
SM.getBufferData(LocInfo.first, &
Invalid);
562 const char *StrData = Buffer.data()+LocInfo.second;
564 if (!IgnoreWhiteSpace &&
isWhitespace(SkipEscapedNewLines(StrData)[0]))
568 Lexer TheLexer(
SM.getLocForStartOfFile(LocInfo.first), LangOpts,
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())
603 StringRef Buffer =
SM.getBufferData(LocInfo.first, &
Invalid);
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);
648 if (!
SM.isMacroArgExpansion(Loc))
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;
830 const char *TokPtr =
SM.getCharacterData(TokStart, &
Invalid);
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;
894 const FileID LocFileID =
SM.getFileID(Loc);
897 if (!
SM.getSLocEntry(LocFileID).getExpansion().isExpansionTokenRange())
919 if (!
SM.isAtStartOfImmediateMacroExpansion(loc, &expansionLoc))
925 *MacroBegin = expansionLoc;
949 if (
SM.isInFileID(afterLoc,
FID)) {
950 if (!
SM.isAtEndOfImmediateMacroExpansion(afterLoc, &expansionLoc))
959 assert(Entry.
isExpansion() &&
"Should be in an expansion");
966 *MacroEnd = expansionLoc;
979 if (Range.isTokenRange()) {
986 auto [FID, BeginOffs] =
SM.getDecomposedLoc(Begin);
991 if (!
SM.isInFileID(End, FID, &EndOffs) ||
1001 return SM.getSLocEntry(
SM.getFileID(Loc))
1003 .isExpansionTokenRange();
1020 Range.setBegin(Begin);
1025 if (Range.isTokenRange()) {
1043 Range.setBegin(MacroBegin);
1044 Range.setEnd(MacroEnd);
1046 if (Range.isTokenRange())
1066 Range.setBegin(
SM.getImmediateSpellingLoc(Begin));
1067 Range.setEnd(
SM.getImmediateSpellingLoc(End));
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");
1130 Loc =
SM.getImmediateExpansionRange(Loc).getBegin();
1137 FileID MacroFID =
SM.getFileID(Loc);
1138 if (
SM.isInFileID(SpellLoc, MacroFID))
1148 Loc =
SM.getSpellingLoc(Loc);
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");
1162 while (
SM.isMacroArgExpansion(Loc))
1163 Loc =
SM.getImmediateExpansionRange(Loc).getBegin();
1169 if (!SpellLoc.
isFileID() ||
SM.isWrittenInScratchSpace(SpellLoc))
1175 Loc =
SM.getSpellingLoc(
SM.getImmediateExpansionRange(Loc).getBegin());
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())
1217 StringRef Buffer =
SM.getBufferData(LocInfo.first, &
Invalid);
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");
1259 return SM.createExpansionLoc(SpellingLoc, II.
getBegin(), II.
getEnd(), TokLen);
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;
1391 StringRef
File =
SM.getBufferData(LocInfo.first, &InvalidTemp);
1393 return std::nullopt;
1395 const char *TokenBegin =
File.data() + LocInfo.second;
1398 Lexer lexer(
SM.getLocForStartOfFile(LocInfo.first), LangOpts,
File.begin(),
1399 TokenBegin,
File.end());
1410 bool IncludeComments) {
1411 const auto StartOfFile =
SM.getLocForStartOfFile(
SM.getFileID(Loc));
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) {
1443 const char *TokenEnd =
SM.getCharacterData(TokenLoc) +
Tok->getLength();
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);
2469bool Lexer::LexAngledStringLiteral(
Token &
Result,
const char *CurPtr) {
2471 const char *NulCharacter =
nullptr;
2472 const char *AfterLessPos = CurPtr;
2473 char C = getAndAdvanceChar(CurPtr,
Result);
2478 C = getAndAdvanceChar(CurPtr,
Result);
2481 (
C == 0 && (CurPtr - 1 == BufferEnd))) {
2484 FormTokenWithChars(
Result, AfterLessPos, tok::less);
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);
3174 SkipWhitespace(
Result, CurPtr + 1);
3192 "Must be in a preprocessing directive!");
3197 const char *CurPtr = BufferPtr;
3199 char Char = getAndAdvanceChar(CurPtr, Tmp);
3207 if (CurPtr-1 != BufferEnd) {
3208 if (isCodeCompletionPoint(CurPtr-1)) {
3209 PP->CodeCompleteNaturalLanguage();
3224 assert(CurPtr[-1] == Char &&
"Trigraphs for newline?");
3225 BufferPtr = CurPtr-1;
3229 if (Tmp.
is(tok::code_completion)) {
3231 PP->CodeCompleteNaturalLanguage();
3234 assert(Tmp.
is(tok::eod) &&
"Unexpected token!");
3246bool Lexer::LexEndOfFile(
Token &
Result,
const char *CurPtr) {
3254 FormTokenWithChars(
Result, CurPtr, tok::eod);
3266 BufferPtr = BufferEnd;
3267 FormTokenWithChars(
Result, BufferEnd, tok::eof);
3271 if (
PP->isRecordingPreamble() &&
PP->isInPrimaryFile()) {
3277 MIOpt.ExitTopLevelConditional();
3285 if (
PP->getCodeCompletionFileLoc() != FileLoc)
3287 diag::err_pp_unterminated_conditional);
3294 if (CurPtr != BufferStart && (CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r'))
3295 Diag(BufferEnd, diag::warn_no_newline_eof)
3307std::optional<Token> Lexer::peekNextPPToken() {
3308 assert(!
LexingRawMode &&
"How can we expand a macro from a skipping buffer?");
3310 if (isDependencyDirectivesLexer()) {
3311 if (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size())
3312 return std::nullopt;
3314 (void)convertDependencyDirectiveToken(
3315 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex],
Result);
3325 const char *TmpBufferPtr = BufferPtr;
3327 bool atStartOfLine = IsAtStartOfLine;
3328 bool atPhysicalStartOfLine = IsAtPhysicalStartOfLine;
3329 bool leadingSpace = HasLeadingSpace;
3330 MultipleIncludeOpt MIOptState =
MIOpt;
3336 BufferPtr = TmpBufferPtr;
3338 HasLeadingSpace = leadingSpace;
3339 IsAtStartOfLine = atStartOfLine;
3340 IsAtPhysicalStartOfLine = atPhysicalStartOfLine;
3345 if (
Tok.
is(tok::eof))
3346 return std::nullopt;
3353 const char *Terminator = CMK ==
CMK_Perforce ?
"<<<<\n" :
">>>>>>>";
3355 auto RestOfBuffer = StringRef(CurPtr, BufferEnd - CurPtr).substr(TermLen);
3356 size_t Pos = RestOfBuffer.find(Terminator);
3357 while (Pos != StringRef::npos) {
3360 (RestOfBuffer[Pos - 1] !=
'\r' && RestOfBuffer[Pos - 1] !=
'\n')) {
3361 RestOfBuffer = RestOfBuffer.substr(Pos+TermLen);
3362 Pos = RestOfBuffer.find(Terminator);
3365 return RestOfBuffer.data()+Pos;
3374bool Lexer::IsStartOfConflictMarker(
const char *CurPtr) {
3376 if (CurPtr != BufferStart &&
3377 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3381 if (!StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
"<<<<<<<") &&
3382 !StringRef(CurPtr, BufferEnd - CurPtr).starts_with(
">>>> "))
3397 Diag(CurPtr, diag::err_conflict_marker);
3398 CurrentConflictMarkerState =
Kind;
3402 while (*CurPtr !=
'\r' && *CurPtr !=
'\n') {
3403 assert(CurPtr != BufferEnd &&
"Didn't find end of line");
3418bool Lexer::HandleEndOfConflictMarker(
const char *CurPtr) {
3420 if (CurPtr != BufferStart &&
3421 CurPtr[-1] !=
'\n' && CurPtr[-1] !=
'\r')
3430 for (
unsigned i = 1; i != 4; ++i)
3431 if (CurPtr[i] != CurPtr[0])
3438 CurrentConflictMarkerState)) {
3442 while (CurPtr != BufferEnd && *CurPtr !=
'\r' && *CurPtr !=
'\n')
3448 CurrentConflictMarkerState =
CMK_None;
3456 const char *BufferEnd) {
3457 if (CurPtr == BufferEnd)
3460 for (; CurPtr != BufferEnd; ++CurPtr) {
3461 if (CurPtr[0] ==
'#' && CurPtr[1] ==
'>')
3467bool Lexer::lexEditorPlaceholder(
Token &
Result,
const char *CurPtr) {
3468 assert(CurPtr[-1] ==
'<' && CurPtr[0] ==
'#' &&
"Not a placeholder!");
3474 const char *Start = CurPtr - 1;
3475 if (!LangOpts.AllowEditorPlaceholders)
3476 Diag(Start, diag::err_placeholder_in_source);
3478 FormTokenWithChars(
Result, End, tok::raw_identifier);
3479 Result.setRawIdentifierData(Start);
3486bool Lexer::isCodeCompletionPoint(
const char *CurPtr)
const {
3487 if (
PP &&
PP->isCodeCompletionEnabled()) {
3488 SourceLocation Loc = FileLoc.getLocWithOffset(CurPtr-BufferStart);
3489 return Loc ==
PP->getCodeCompletionLoc();
3500 if (Opts.CPlusPlus23)
3501 DiagId = diag::warn_cxx23_delimited_escape_sequence;
3502 else if (Opts.C2y && !Named)
3503 DiagId = diag::warn_c2y_delimited_escape_sequence;
3505 DiagId = diag::ext_delimited_escape_sequence;
3511 if (!Opts.CPlusPlus)
3512 Ext = Named ? 2 : 1 ;
3516 Diags.
Report(Loc, DiagId) << Named << Ext;
3519std::optional<uint32_t> Lexer::tryReadNumericUCN(
const char *&StartPtr,
3520 const char *SlashLoc,
3523 char Kind = getCharAndSize(StartPtr, CharSize);
3524 assert((Kind ==
'u' || Kind ==
'U') &&
"expected a UCN");
3526 unsigned NumHexDigits;
3529 else if (Kind ==
'U')
3532 bool Delimited =
false;
3533 bool FoundEndDelimiter =
false;
3537 if (!LangOpts.CPlusPlus && !LangOpts.C99) {
3539 Diag(SlashLoc, diag::warn_ucn_not_valid_in_c89);
3540 return std::nullopt;
3543 const char *CurPtr = StartPtr + CharSize;
3544 const char *KindLoc = &CurPtr[-1];
3547 while (Count != NumHexDigits || Delimited) {
3548 char C = getCharAndSize(CurPtr, CharSize);
3549 if (!Delimited && Count == 0 &&
C ==
'{') {
3555 if (Delimited &&
C ==
'}') {
3557 FoundEndDelimiter =
true;
3561 unsigned Value = llvm::hexDigitValue(
C);
3562 if (
Value == std::numeric_limits<unsigned>::max()) {
3566 Diag(SlashLoc, diag::warn_delimited_ucn_incomplete)
3567 << StringRef(KindLoc, 1);
3568 return std::nullopt;
3571 if (CodePoint & 0xF000'0000) {
3573 Diag(KindLoc, diag::err_escape_too_large) << 0;
3574 return std::nullopt;
3585 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3586 : diag::warn_ucn_escape_no_digits)
3587 << StringRef(KindLoc, 1);
3588 return std::nullopt;
3591 if (Delimited && Kind ==
'U') {
3593 Diag(SlashLoc, diag::err_hex_escape_no_digits) << StringRef(KindLoc, 1);
3594 return std::nullopt;
3597 if (!Delimited && Count != NumHexDigits) {
3599 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3601 if (Count == 4 && NumHexDigits == 8) {
3602 CharSourceRange URange =
makeCharRange(*
this, KindLoc, KindLoc + 1);
3603 Diag(KindLoc, diag::note_ucn_four_not_eight)
3607 return std::nullopt;
3610 if (Delimited &&
PP)
3613 PP->getDiagnostics());
3620 if (CurPtr - StartPtr == (
ptrdiff_t)(Count + 1 + (Delimited ? 2 : 0)))
3623 while (StartPtr != CurPtr)
3624 (void)getAndAdvanceChar(StartPtr, *
Result);
3631std::optional<uint32_t> Lexer::tryReadNamedUCN(
const char *&StartPtr,
3632 const char *SlashLoc,
3637 char C = getCharAndSize(StartPtr, CharSize);
3638 assert(
C ==
'N' &&
"expected \\N{...}");
3640 const char *CurPtr = StartPtr + CharSize;
3641 const char *KindLoc = &CurPtr[-1];
3643 C = getCharAndSize(CurPtr, CharSize);
3646 Diag(SlashLoc, diag::warn_ucn_escape_incomplete);
3647 return std::nullopt;
3650 const char *StartName = CurPtr;
3651 bool FoundEndDelimiter =
false;
3652 llvm::SmallVector<char, 30> Buffer;
3654 C = getCharAndSize(CurPtr, CharSize);
3657 FoundEndDelimiter =
true;
3663 Buffer.push_back(
C);
3666 if (!FoundEndDelimiter || Buffer.empty()) {
3668 Diag(SlashLoc, FoundEndDelimiter ? diag::warn_delimited_ucn_empty
3669 : diag::warn_delimited_ucn_incomplete)
3670 << StringRef(KindLoc, 1);
3671 return std::nullopt;
3674 StringRef Name(Buffer.data(), Buffer.size());
3675 std::optional<char32_t>
Match =
3676 llvm::sys::unicode::nameToCodepointStrict(Name);
3677 std::optional<llvm::sys::unicode::LooseMatchingResult> LooseMatch;
3679 LooseMatch = llvm::sys::unicode::nameToCodepointLooseMatching(Name);
3681 Diag(StartName, diag::err_invalid_ucn_name)
3682 << StringRef(Buffer.data(), Buffer.size())
3685 Diag(StartName, diag::note_invalid_ucn_name_loose_matching)
3696 if (Diagnose &&
Match)
3699 PP->getDiagnostics());
3705 if (LooseMatch && Diagnose)
3706 Match = LooseMatch->CodePoint;
3713 if (CurPtr - StartPtr == (
ptrdiff_t)(Buffer.size() + 3))
3716 while (StartPtr != CurPtr)
3717 (void)getAndAdvanceChar(StartPtr, *
Result);
3721 return Match ? std::optional<uint32_t>(*
Match) : std::nullopt;
3724uint32_t Lexer::tryReadUCN(
const char *&StartPtr,
const char *SlashLoc,
3728 std::optional<uint32_t> CodePointOpt;
3729 char Kind = getCharAndSize(StartPtr, CharSize);
3730 if (Kind ==
'u' || Kind ==
'U')
3731 CodePointOpt = tryReadNumericUCN(StartPtr, SlashLoc,
Result);
3732 else if (Kind ==
'N')
3733 CodePointOpt = tryReadNamedUCN(StartPtr, SlashLoc,
Result);
3738 uint32_t CodePoint = *CodePointOpt;
3741 if (LangOpts.AsmPreprocessor)
3760 if (CodePoint < 0xA0) {
3764 if (CodePoint < 0x20 || CodePoint >= 0x7F)
3765 Diag(BufferPtr, diag::err_ucn_control_character);
3767 char C =
static_cast<char>(CodePoint);
3768 Diag(BufferPtr, diag::err_ucn_escape_basic_scs) << StringRef(&
C, 1);
3773 }
else if (CodePoint >= 0xD800 && CodePoint <= 0xDFFF) {
3778 if (LangOpts.CPlusPlus && !LangOpts.CPlusPlus11)
3779 Diag(BufferPtr, diag::warn_ucn_escape_surrogate);
3781 Diag(BufferPtr, diag::err_ucn_escape_invalid);
3790 const char *CurPtr) {
3793 Diag(BufferPtr, diag::ext_unicode_whitespace)
3803void Lexer::PropagateLineStartLeadingSpaceInfo(
Token &
Result) {
3804 IsAtStartOfLine =
Result.isAtStartOfLine();
3805 HasLeadingSpace =
Result.hasLeadingSpace();
3806 HasLeadingEmptyMacro =
Result.hasLeadingEmptyMacro();
3811 assert(!isDependencyDirectivesLexer());
3817 if (IsAtStartOfLine) {
3819 IsAtStartOfLine =
false;
3822 if (IsAtPhysicalStartOfLine) {
3824 IsAtPhysicalStartOfLine =
false;
3827 if (HasLeadingSpace) {
3829 HasLeadingSpace =
false;
3832 if (HasLeadingEmptyMacro) {
3834 HasLeadingEmptyMacro =
false;
3839 bool returnedToken = LexTokenInternal(
Result);
3841 assert((returnedToken || !isRawLex) &&
"Raw lex must succeed");
3842 return returnedToken;
3852 assert(!
Result.needsCleaning() &&
"Result needs cleaning");
3853 assert(!
Result.hasPtrData() &&
"Result has not been reset");
3856 const char *CurPtr = BufferPtr;
3870 FormTokenWithChars(
Result, CurPtr, tok::unknown);
3879 unsigned SizeTmp, SizeTmp2;
3882 char Char = getAndAdvanceChar(CurPtr,
Result);
3886 NewLinePtr =
nullptr;
3891 if (CurPtr-1 == BufferEnd)
3892 return LexEndOfFile(
Result, CurPtr-1);
3895 if (isCodeCompletionPoint(CurPtr-1)) {
3898 FormTokenWithChars(
Result, CurPtr, tok::code_completion);
3903 Diag(CurPtr-1, diag::null_in_file);
3905 if (SkipWhitespace(
Result, CurPtr))
3914 if (LangOpts.MicrosoftExt) {
3916 Diag(CurPtr-1, diag::ext_ctrl_z_eof_microsoft);
3917 return LexEndOfFile(
Result, CurPtr-1);
3921 Kind = tok::unknown;
3925 if (CurPtr[0] ==
'\n')
3926 (void)getAndAdvanceChar(CurPtr,
Result);
3940 IsAtStartOfLine =
true;
3941 IsAtPhysicalStartOfLine =
true;
3942 NewLinePtr = CurPtr - 1;
3951 if (SkipWhitespace(
Result, CurPtr))
3961 SkipHorizontalWhitespace:
3963 if (SkipWhitespace(
Result, CurPtr))
3972 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP)) {
3973 if (SkipLineComment(
Result, CurPtr + 2))
3975 goto SkipIgnoredUnits;
3977 if (SkipBlockComment(
Result, CurPtr + 2))
3979 goto SkipIgnoredUnits;
3981 goto SkipHorizontalWhitespace;
3989 case '0':
case '1':
case '2':
case '3':
case '4':
3990 case '5':
case '6':
case '7':
case '8':
case '9':
3993 return LexNumericConstant(
Result, CurPtr);
4002 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4003 Char = getCharAndSize(CurPtr, SizeTmp);
4007 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4008 tok::utf16_string_literal);
4012 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4013 tok::utf16_char_constant);
4016 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4017 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4018 return LexRawStringLiteral(
Result,
4019 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4021 tok::utf16_string_literal);
4024 char Char2 = getCharAndSize(CurPtr + SizeTmp, SizeTmp2);
4028 return LexStringLiteral(
Result,
4029 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4031 tok::utf8_string_literal);
4032 if (Char2 ==
'\'' && (LangOpts.CPlusPlus17 || LangOpts.C23))
4033 return LexCharConstant(
4034 Result, ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4036 tok::utf8_char_constant);
4038 if (Char2 ==
'R' && LangOpts.RawStringLiterals) {
4040 char Char3 = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4043 return LexRawStringLiteral(
Result,
4044 ConsumeChar(ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4047 tok::utf8_string_literal);
4054 return LexIdentifierContinue(
Result, CurPtr);
4060 if (LangOpts.CPlusPlus11 || LangOpts.C11) {
4061 Char = getCharAndSize(CurPtr, SizeTmp);
4065 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4066 tok::utf32_string_literal);
4070 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4071 tok::utf32_char_constant);
4074 if (Char ==
'R' && LangOpts.RawStringLiterals &&
4075 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4076 return LexRawStringLiteral(
Result,
4077 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4079 tok::utf32_string_literal);
4083 return LexIdentifierContinue(
Result, CurPtr);
4089 if (LangOpts.RawStringLiterals) {
4090 Char = getCharAndSize(CurPtr, SizeTmp);
4093 return LexRawStringLiteral(
Result,
4094 ConsumeChar(CurPtr, SizeTmp,
Result),
4095 tok::string_literal);
4099 return LexIdentifierContinue(
Result, CurPtr);
4104 Char = getCharAndSize(CurPtr, SizeTmp);
4108 return LexStringLiteral(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4109 tok::wide_string_literal);
4112 if (LangOpts.RawStringLiterals && Char ==
'R' &&
4113 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
'"')
4114 return LexRawStringLiteral(
Result,
4115 ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4117 tok::wide_string_literal);
4121 return LexCharConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result),
4122 tok::wide_char_constant);
4127 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
4128 case 'H':
case 'I':
case 'J':
case 'K':
case 'M':
case 'N':
4129 case 'O':
case 'P':
case 'Q':
case 'S':
case 'T':
4130 case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
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 'l':
case 'm':
case 'n':
4133 case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
4134 case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
4138 return LexIdentifierContinue(
Result, CurPtr);
4140 if (LangOpts.DollarIdents) {
4142 Diag(CurPtr-1, diag::ext_dollar_in_identifier);
4145 return LexIdentifierContinue(
Result, CurPtr);
4148 Kind = tok::unknown;
4155 return LexCharConstant(
Result, CurPtr, tok::char_constant);
4161 return LexStringLiteral(
Result, CurPtr,
4163 : tok::string_literal);
4167 Kind = tok::question;
4170 Kind = tok::l_square;
4173 Kind = tok::r_square;
4176 Kind = tok::l_paren;
4179 Kind = tok::r_paren;
4182 Kind = tok::l_brace;
4185 Kind = tok::r_brace;
4188 Char = getCharAndSize(CurPtr, SizeTmp);
4189 if (Char >=
'0' && Char <=
'9') {
4193 return LexNumericConstant(
Result, ConsumeChar(CurPtr, SizeTmp,
Result));
4194 }
else if (LangOpts.CPlusPlus && Char ==
'*') {
4195 Kind = tok::periodstar;
4197 }
else if (Char ==
'.' &&
4198 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'.') {
4199 Kind = tok::ellipsis;
4200 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4207 Char = getCharAndSize(CurPtr, SizeTmp);
4210 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4211 }
else if (Char ==
'=') {
4212 Kind = tok::ampequal;
4213 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4219 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4220 Kind = tok::starequal;
4221 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4227 Char = getCharAndSize(CurPtr, SizeTmp);
4229 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4230 Kind = tok::plusplus;
4231 }
else if (Char ==
'=') {
4232 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4233 Kind = tok::plusequal;
4239 Char = getCharAndSize(CurPtr, SizeTmp);
4241 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4242 Kind = tok::minusminus;
4243 }
else if (Char ==
'>' && LangOpts.CPlusPlus &&
4244 getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
'*') {
4245 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4247 Kind = tok::arrowstar;
4248 }
else if (Char ==
'>') {
4249 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4251 }
else if (Char ==
'=') {
4252 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4253 Kind = tok::minusequal;
4262 if (getCharAndSize(CurPtr, SizeTmp) ==
'=') {
4263 Kind = tok::exclaimequal;
4264 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4266 Kind = tok::exclaim;
4271 Char = getCharAndSize(CurPtr, SizeTmp);
4281 bool TreatAsComment =
4282 LineComment && (LangOpts.CPlusPlus || !LangOpts.TraditionalCPP);
4283 if (!TreatAsComment)
4284 if (!(
PP &&
PP->isPreprocessedOutput()))
4285 TreatAsComment = getCharAndSize(CurPtr+SizeTmp, SizeTmp2) !=
'*';
4287 if (TreatAsComment) {
4288 if (SkipLineComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4294 goto SkipIgnoredUnits;
4299 if (SkipBlockComment(
Result, ConsumeChar(CurPtr, SizeTmp,
Result)))
4308 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4309 Kind = tok::slashequal;
4315 Char = getCharAndSize(CurPtr, SizeTmp);
4317 Kind = tok::percentequal;
4318 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4319 }
else if (LangOpts.Digraphs && Char ==
'>') {
4320 Kind = tok::r_brace;
4321 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4322 }
else if (LangOpts.Digraphs && Char ==
':') {
4323 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4324 Char = getCharAndSize(CurPtr, SizeTmp);
4325 if (Char ==
'%' && getCharAndSize(CurPtr+SizeTmp, SizeTmp2) ==
':') {
4326 Kind = tok::hashhash;
4327 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4329 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4330 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4332 Diag(BufferPtr, diag::ext_charize_microsoft);
4341 goto HandleDirective;
4346 Kind = tok::percent;
4350 Char = getCharAndSize(CurPtr, SizeTmp);
4352 return LexAngledStringLiteral(
Result, CurPtr);
4353 }
else if (Char ==
'<') {
4354 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4356 Kind = tok::lesslessequal;
4357 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4359 }
else if (After ==
'<' && IsStartOfConflictMarker(CurPtr-1)) {
4363 }
else if (After ==
'<' && HandleEndOfConflictMarker(CurPtr-1)) {
4367 }
else if (LangOpts.CUDA && After ==
'<') {
4368 Kind = tok::lesslessless;
4369 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4372 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4373 Kind = tok::lessless;
4375 }
else if (Char ==
'=') {
4376 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4378 if (LangOpts.CPlusPlus20) {
4380 Diag(BufferPtr, diag::warn_cxx17_compat_spaceship);
4381 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4383 Kind = tok::spaceship;
4389 Diag(BufferPtr, diag::warn_cxx20_compat_spaceship)
4394 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4395 Kind = tok::lessequal;
4396 }
else if (LangOpts.Digraphs && Char ==
':') {
4397 if (LangOpts.CPlusPlus11 &&
4398 getCharAndSize(CurPtr + SizeTmp, SizeTmp2) ==
':') {
4405 char After = getCharAndSize(CurPtr + SizeTmp + SizeTmp2, SizeTmp3);
4406 if (After !=
':' && After !=
'>') {
4409 Diag(BufferPtr, diag::warn_cxx98_compat_less_colon_colon);
4414 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4415 Kind = tok::l_square;
4416 }
else if (LangOpts.Digraphs && Char ==
'%') {
4417 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4418 Kind = tok::l_brace;
4419 }
else if (Char ==
'#' && SizeTmp == 1 &&
4420 lexEditorPlaceholder(
Result, CurPtr)) {
4427 Char = getCharAndSize(CurPtr, SizeTmp);
4429 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4430 Kind = tok::greaterequal;
4431 }
else if (Char ==
'>') {
4432 char After = getCharAndSize(CurPtr+SizeTmp, SizeTmp2);
4434 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4436 Kind = tok::greatergreaterequal;
4437 }
else if (After ==
'>' && IsStartOfConflictMarker(CurPtr-1)) {
4441 }
else if (After ==
'>' && HandleEndOfConflictMarker(CurPtr-1)) {
4444 }
else if (LangOpts.CUDA && After ==
'>') {
4445 Kind = tok::greatergreatergreater;
4446 CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp,
Result),
4449 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4450 Kind = tok::greatergreater;
4453 Kind = tok::greater;
4457 Char = getCharAndSize(CurPtr, SizeTmp);
4459 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4460 Kind = tok::caretequal;
4461 }
else if (LangOpts.Reflection && Char ==
'^') {
4462 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4463 Kind = tok::caretcaret;
4465 if (LangOpts.OpenCL && Char ==
'^')
4466 Diag(CurPtr, diag::err_opencl_logical_exclusive_or);
4471 Char = getCharAndSize(CurPtr, SizeTmp);
4473 Kind = tok::pipeequal;
4474 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4475 }
else if (Char ==
'|') {
4477 if (CurPtr[1] ==
'|' && HandleEndOfConflictMarker(CurPtr-1))
4479 Kind = tok::pipepipe;
4480 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4486 Char = getCharAndSize(CurPtr, SizeTmp);
4487 if (LangOpts.Digraphs && Char ==
'>') {
4488 Kind = tok::r_square;
4489 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4490 }
else if (Char ==
':') {
4491 Kind = tok::coloncolon;
4492 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4501 Char = getCharAndSize(CurPtr, SizeTmp);
4504 if (CurPtr[1] ==
'=' && HandleEndOfConflictMarker(CurPtr-1))
4507 Kind = tok::equalequal;
4508 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4517 Char = getCharAndSize(CurPtr, SizeTmp);
4519 Kind = tok::hashhash;
4520 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4521 }
else if (Char ==
'@' && LangOpts.MicrosoftExt) {
4524 Diag(BufferPtr, diag::ext_charize_microsoft);
4525 CurPtr = ConsumeChar(CurPtr, SizeTmp,
Result);
4532 goto HandleDirective;
4540 if (CurPtr[-1] ==
'@' && LangOpts.ObjC) {
4541 FormTokenWithChars(
Result, CurPtr, tok::at);
4547 llvm::SaveAndRestore<bool> SavedParsingPreprocessorDirective(
4549 auto NextTokOr = peekNextPPToken();
4550 if (NextTokOr.has_value()) {
4551 NextPPTok = *NextTokOr;
4554 if (NextPPTok.
is(tok::raw_identifier) &&
4562 Kind = tok::unknown;
4567 if (!LangOpts.AsmPreprocessor) {
4568 if (
uint32_t CodePoint = tryReadUCN(CurPtr, BufferPtr, &
Result)) {
4569 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4570 if (SkipWhitespace(
Result, CurPtr))
4578 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4582 Kind = tok::unknown;
4587 Kind = tok::unknown;
4591 llvm::UTF32 CodePoint;
4596 llvm::ConversionResult Status =
4597 llvm::convertUTF8Sequence((
const llvm::UTF8 **)&CurPtr,
4598 (
const llvm::UTF8 *)BufferEnd,
4600 llvm::strictConversion);
4601 if (Status == llvm::conversionOK) {
4602 if (CheckUnicodeWhitespace(
Result, CodePoint, CurPtr)) {
4603 if (SkipWhitespace(
Result, CurPtr))
4610 return LexUnicodeIdentifierStart(
Result, CodePoint, CurPtr);
4614 PP->isPreprocessedOutput()) {
4616 Kind = tok::unknown;
4623 Diag(CurPtr, diag::err_invalid_utf8);
4625 BufferPtr = CurPtr+1;
4637 FormTokenWithChars(
Result, CurPtr, Kind);
4643 FormTokenWithChars(
Result, CurPtr, tok::hash);
4646 if (
PP->hadModuleLoaderFatalFailure())
4658const char *Lexer::convertDependencyDirectiveToken(
4660 const char *TokPtr = BufferStart + DDTok.
Offset;
4666 if (
Result.is(tok::raw_identifier))
4667 Result.setRawIdentifierData(TokPtr);
4668 else if (
Result.isLiteral())
4669 Result.setLiteralData(TokPtr);
4670 BufferPtr = TokPtr + DDTok.
Length;
4674bool Lexer::LexDependencyDirectiveToken(
Token &
Result) {
4675 assert(isDependencyDirectivesLexer());
4677 using namespace dependency_directives_scan;
4679 if (BufferPtr == BufferEnd)
4680 return LexEndOfFile(
Result, BufferPtr);
4682 while (NextDepDirectiveTokenIndex == DepDirectives.front().Tokens.size()) {
4683 if (DepDirectives.front().Kind == pp_eof)
4684 return LexEndOfFile(
Result, BufferEnd);
4685 if (DepDirectives.front().Kind == tokens_present_before_eof)
4687 NextDepDirectiveTokenIndex = 0;
4688 DepDirectives = DepDirectives.drop_front();
4691 const dependency_directives_scan::Token &DDTok =
4692 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex++];
4693 if (NextDepDirectiveTokenIndex > 1 || DDTok.
Kind != tok::hash) {
4699 BufferPtr = BufferStart + DDTok.
Offset;
4700 LexAngledStringLiteral(
Result, BufferPtr + 1);
4701 if (
Result.isNot(tok::header_name))
4705 const dependency_directives_scan::Token &NextTok =
4706 DepDirectives.front().Tokens[NextDepDirectiveTokenIndex];
4707 if (BufferStart + NextTok.
Offset >= BufferPtr)
4709 ++NextDepDirectiveTokenIndex;
4714 const char *TokPtr = convertDependencyDirectiveToken(DDTok,
Result);
4716 if (
Result.is(tok::hash) &&
Result.isAtStartOfLine()) {
4718 if (
PP->hadModuleLoaderFatalFailure())
4724 auto NextTok = peekNextPPToken();
4725 if (NextTok && NextTok->
is(tok::raw_identifier) &&
4726 NextTok->getRawIdentifier() ==
"import") {
4728 if (
PP->hadModuleLoaderFatalFailure())
4733 if (
Result.is(tok::raw_identifier)) {
4734 Result.setRawIdentifierData(TokPtr);
4736 const IdentifierInfo *II =
PP->LookUpIdentifierInfo(
Result);
4737 if (LangOpts.CPlusPlusModules &&
Result.isModuleContextualKeyword() &&
4738 PP->HandleModuleContextualKeyword(
Result)) {
4743 return PP->HandleIdentifier(
Result);
4749 if (
Result.is(tok::colon)) {
4751 if (*BufferPtr ==
':') {
4752 assert(DepDirectives.front().Tokens[NextDepDirectiveTokenIndex].is(
4754 ++NextDepDirectiveTokenIndex;
4755 Result.setKind(tok::coloncolon);
4765bool Lexer::LexDependencyDirectiveTokenWhileSkipping(
Token &
Result) {
4766 assert(isDependencyDirectivesLexer());
4768 using namespace dependency_directives_scan;
4771 unsigned NestedIfs = 0;
4773 DepDirectives = DepDirectives.drop_front();
4774 switch (DepDirectives.front().Kind) {
4776 llvm_unreachable(
"unexpected 'pp_none'");
4817 NextDepDirectiveTokenIndex = 0;
4818 return LexEndOfFile(
Result, BufferEnd);
4822 const dependency_directives_scan::Token &DDTok =
4823 DepDirectives.front().Tokens.front();
4824 assert(DDTok.
is(tok::hash));
4825 NextDepDirectiveTokenIndex = 1;
4827 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.
Each ExpansionInfo encodes the expansion location - where the token was ultimately expanded,...
SourceLocation getExpansionLocStart() 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.
The JSON file list parser is used to communicate input to InstallAPI.
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