37#include "llvm/ADT/ArrayRef.h"
38#include "llvm/ADT/STLExtras.h"
39#include "llvm/ADT/ScopeExit.h"
40#include "llvm/ADT/SmallString.h"
41#include "llvm/ADT/SmallVector.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ADT/StringSwitch.h"
44#include "llvm/Support/AlignOf.h"
45#include "llvm/Support/ErrorHandling.h"
46#include "llvm/Support/Path.h"
47#include "llvm/Support/SaveAndRestore.h"
63 static_assert(std::is_trivially_destructible_v<MacroInfo>,
"");
73Preprocessor::AllocateUndefMacroDirective(
SourceLocation UndefLoc) {
91 while (Tmp.
isNot(tok::eod)) {
92 assert(Tmp.
isNot(tok::eof) &&
"EOF seen while discarding directive tokens");
120 static constexpr StringRef ReservedMacro[] = {
123 "_CRT_NONSTDC_NO_WARNINGS",
124 "_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES",
125 "_CRT_SECURE_NO_WARNINGS",
128 "_GLIBCXX_ASSERTIONS",
129 "_GLIBCXX_CONCEPT_CHECKS",
131 "_GLIBCXX_DEBUG_PEDANTIC",
133 "_GLIBCXX_PARALLEL_ASSERTIONS",
134 "_GLIBCXX_SANITIZE_VECTOR",
135 "_GLIBCXX_USE_CXX11_ABI",
136 "_GLIBCXX_USE_DEPRECATED",
141 "_LARGEFILE64_SOURCE",
147 "_XOPEN_SOURCE_EXTENDED",
148 "__STDCPP_WANT_MATH_SPEC_FUNCS__",
149 "__STDC_FORMAT_MACROS",
151 return std::binary_search(std::begin(ReservedMacro), std::end(ReservedMacro),
157 const StringRef MacroName) {
167 if (MacroName.startswith(
"__STDC"))
170 if (MacroName ==
"__cplusplus")
173 if (MacroName.startswith(
"__cpp"))
186 if (Lang.CPlusPlus11 && (
Text.equals(
"override") ||
Text.equals(
"final")))
207 if (::llvm::sys::path::begin(Include)->equals_insensitive(
"boost"))
212 static const size_t MaxStdHeaderNameLen = 18u;
213 if (Include.size() > MaxStdHeaderNameLen)
218 for (
char &Ch : LowerInclude) {
220 if (
static_cast<unsigned char>(Ch) > 0x7f)
223 if (Ch >=
'A' && Ch <=
'Z')
226 else if (::llvm::sys::path::is_separator(Ch))
231 return llvm::StringSwitch<bool>(LowerInclude)
233 .Cases(
"assert.h",
"complex.h",
"ctype.h",
"errno.h",
"fenv.h",
true)
234 .Cases(
"float.h",
"inttypes.h",
"iso646.h",
"limits.h",
"locale.h",
true)
235 .Cases(
"math.h",
"setjmp.h",
"signal.h",
"stdalign.h",
"stdarg.h",
true)
236 .Cases(
"stdatomic.h",
"stdbool.h",
"stdckdint.h",
"stddef.h",
true)
237 .Cases(
"stdint.h",
"stdio.h",
"stdlib.h",
"stdnoreturn.h",
true)
238 .Cases(
"string.h",
"tgmath.h",
"threads.h",
"time.h",
"uchar.h",
true)
239 .Cases(
"wchar.h",
"wctype.h",
true)
242 .Cases(
"cassert",
"ccomplex",
"cctype",
"cerrno",
"cfenv",
true)
243 .Cases(
"cfloat",
"cinttypes",
"ciso646",
"climits",
"clocale",
true)
244 .Cases(
"cmath",
"csetjmp",
"csignal",
"cstdalign",
"cstdarg",
true)
245 .Cases(
"cstdbool",
"cstddef",
"cstdint",
"cstdio",
"cstdlib",
true)
246 .Cases(
"cstring",
"ctgmath",
"ctime",
"cuchar",
"cwchar",
true)
247 .Case(
"cwctype",
true)
250 .Cases(
"algorithm",
"fstream",
"list",
"regex",
"thread",
true)
251 .Cases(
"array",
"functional",
"locale",
"scoped_allocator",
"tuple",
true)
252 .Cases(
"atomic",
"future",
"map",
"set",
"type_traits",
true)
253 .Cases(
"bitset",
"initializer_list",
"memory",
"shared_mutex",
"typeindex",
true)
254 .Cases(
"chrono",
"iomanip",
"mutex",
"sstream",
"typeinfo",
true)
255 .Cases(
"codecvt",
"ios",
"new",
"stack",
"unordered_map",
true)
256 .Cases(
"complex",
"iosfwd",
"numeric",
"stdexcept",
"unordered_set",
true)
257 .Cases(
"condition_variable",
"iostream",
"ostream",
"streambuf",
"utility",
true)
258 .Cases(
"deque",
"istream",
"queue",
"string",
"valarray",
true)
259 .Cases(
"exception",
"iterator",
"random",
"strstream",
"vector",
true)
260 .Cases(
"forward_list",
"limits",
"ratio",
"system_error",
true)
263 .Cases(
"aio.h",
"arpa/inet.h",
"cpio.h",
"dirent.h",
"dlfcn.h",
true)
264 .Cases(
"fcntl.h",
"fmtmsg.h",
"fnmatch.h",
"ftw.h",
"glob.h",
true)
265 .Cases(
"grp.h",
"iconv.h",
"langinfo.h",
"libgen.h",
"monetary.h",
true)
266 .Cases(
"mqueue.h",
"ndbm.h",
"net/if.h",
"netdb.h",
"netinet/in.h",
true)
267 .Cases(
"netinet/tcp.h",
"nl_types.h",
"poll.h",
"pthread.h",
"pwd.h",
true)
268 .Cases(
"regex.h",
"sched.h",
"search.h",
"semaphore.h",
"spawn.h",
true)
269 .Cases(
"strings.h",
"stropts.h",
"sys/ipc.h",
"sys/mman.h",
"sys/msg.h",
true)
270 .Cases(
"sys/resource.h",
"sys/select.h",
"sys/sem.h",
"sys/shm.h",
"sys/socket.h",
true)
271 .Cases(
"sys/stat.h",
"sys/statvfs.h",
"sys/time.h",
"sys/times.h",
"sys/types.h",
true)
272 .Cases(
"sys/uio.h",
"sys/un.h",
"sys/utsname.h",
"sys/wait.h",
"syslog.h",
true)
273 .Cases(
"tar.h",
"termios.h",
"trace.h",
"ulimit.h",
true)
274 .Cases(
"unistd.h",
"utime.h",
"utmpx.h",
"wordexp.h",
true)
286static std::optional<StringRef>
290 for (StringRef
C : Candidates) {
291 if (LHS.equals_insensitive(
C)) {
299 size_t Length = LHS.size();
300 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;
302 std::optional<std::pair<StringRef, size_t>> SimilarStr;
303 for (StringRef
C : Candidates) {
304 size_t CurDist = LHS.edit_distance(
C,
true);
305 if (CurDist <= MaxDist) {
308 SimilarStr = {
C, CurDist};
309 }
else if (CurDist < SimilarStr->second) {
311 SimilarStr = {
C, CurDist};
317 return SimilarStr->first;
326 if (MacroNameTok.
is(tok::eod))
327 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
331 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
337 ? diag::ext_pp_operator_used_as_macro_name
338 : diag::err_pp_operator_used_as_macro_name)
339 << II << MacroNameTok.
getKind();
346 return Diag(MacroNameTok, diag::err_defined_macro_name);
370 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
386void Preprocessor::ReadMacroName(
Token &MacroNameTok,
MacroUse isDefineUndef,
391 if (MacroNameTok.
is(tok::code_completion)) {
403 if (MacroNameTok.
isNot(tok::eod)) {
404 MacroNameTok.
setKind(tok::eod);
428 while (Tmp.
is(tok::comment))
431 if (Tmp.
is(tok::eod))
439 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
442 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
446void Preprocessor::SuggestTypoedDirective(
const Token &Tok,
452 std::vector<StringRef> Candidates = {
453 "if",
"ifdef",
"ifndef",
"elif",
"else",
"endif"
455 if (LangOpts.C23 || LangOpts.CPlusPlus23)
456 Candidates.insert(Candidates.end(), {
"elifdef",
"elifndef"});
464 StringRef SuggValue = *Sugg;
467 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;
479void Preprocessor::SkipExcludedConditionalBlock(
SourceLocation HashTokenLoc,
481 bool FoundNonSkipPortion,
492 assert(!SkippingExcludedConditionalBlock &&
493 "calling SkipExcludedConditionalBlock recursively");
497 assert(!CurTokenLexer &&
"Conditional PP block cannot appear in a macro!");
498 assert(CurPPLexer &&
"Conditional PP block must be in a file!");
499 assert(CurLexer &&
"Conditional PP block but no current lexer set!");
501 if (PreambleConditionalStack.reachedEOFWhileSkipping())
502 PreambleConditionalStack.clearSkipInfo();
505 FoundNonSkipPortion, FoundElse);
515 struct SkippingRangeStateTy {
518 const char *BeginPtr =
nullptr;
519 unsigned *SkipRangePtr =
nullptr;
523 void beginLexPass() {
529 BeginPtr = PP.CurLexer->getBufferLocation();
530 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
532 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
537 void endLexPass(
const char *Hashptr) {
540 assert(PP.CurLexer->isDependencyDirectivesLexer());
545 if (!*SkipRangePtr) {
546 *SkipRangePtr = Hashptr - BeginPtr;
548 assert(*SkipRangePtr == Hashptr - BeginPtr);
550 SkipRangePtr =
nullptr;
552 } SkippingRangeState(*
this);
555 if (CurLexer->isDependencyDirectivesLexer()) {
556 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
558 SkippingRangeState.beginLexPass();
562 if (Tok.
is(tok::code_completion)) {
570 if (Tok.
is(tok::eof)) {
574 if (PreambleConditionalStack.isRecording())
575 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,
588 if (Tok.
is(tok::eof))
595 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
597 assert(Tok.
is(tok::hash));
598 const char *Hashptr = CurLexer->getBufferLocation() - Tok.
getLength();
599 assert(CurLexer->getSourceLocation(Hashptr) == Tok.
getLocation());
606 if (Tok.
isNot(tok::raw_identifier)) {
609 if (CurLexer) CurLexer->resetExtendedTokenMode();
620 char FirstChar = RI[0];
621 if (FirstChar >=
'a' && FirstChar <=
'z' &&
622 FirstChar !=
'i' && FirstChar !=
'e') {
625 if (CurLexer) CurLexer->resetExtendedTokenMode();
632 char DirectiveBuf[20];
638 size_t IdLen = DirectiveStr.size();
642 if (CurLexer) CurLexer->resetExtendedTokenMode();
645 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
646 Directive = StringRef(DirectiveBuf, IdLen);
670 assert(!InCond &&
"Can't be skipping if not in a conditional!");
674 SkippingRangeState.endLexPass(Hashptr);
686 }
else if (Sub ==
"lse") {
693 SkippingRangeState.endLexPass(Hashptr);
697 Diag(Tok, diag::pp_err_else_after_else);
717 }
else if (Sub ==
"lif") {
721 SkippingRangeState.endLexPass(Hashptr);
738 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
741 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
745 const bool CondValue = DER.Conditional;
759 }
else if (Sub ==
"lifdef" ||
761 bool IsElifDef =
Sub ==
"lifdef";
763 Token DirectiveToken = Tok;
766 SkippingRangeState.endLexPass(Hashptr);
771 if (LangOpts.CPlusPlus)
772 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
773 : diag::ext_cxx23_pp_directive;
775 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
776 : diag::ext_c23_pp_directive;
781 Diag(Tok, diag::pp_err_elif_after_else)
795 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
798 ReadMacroName(MacroNameTok);
803 if (MacroNameTok.
is(tok::eod)) {
819 Callbacks->Elifdef(DirectiveToken.
getLocation(), MacroNameTok,
822 Callbacks->Elifndef(DirectiveToken.
getLocation(), MacroNameTok,
827 if (
static_cast<bool>(MI) == IsElifDef) {
841 if (CurLexer) CurLexer->resetExtendedTokenMode();
852 Callbacks->SourceRangeSkipped(
884 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
891 while (!Loc.
isInvalid() && !
SM.isInMainFile(Loc)) {
892 auto ID =
SM.getFileID(
SM.getExpansionLoc(Loc));
893 auto FE =
SM.getFileEntryRefForID(ID);
902 bool InPrivateHeader =
false;
904 if (!Header.isAccessibleFrom(IncM)) {
909 InPrivateHeader =
true;
945 Loc =
SM.getIncludeLoc(ID);
957 bool *IsFrameworkFound,
bool SkipCache,
bool OpenFile,
bool CacheFailures) {
962 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
967 bool BuildSystemModule =
false;
968 if (!FromDir && !FromFile) {
991 Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));
996 Includers.push_back(std::make_pair(*FileEnt, *CWD));
999 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1005 if (LangOpts.MSVCCompat && !isAngled) {
1006 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1007 if (IsFileLexer(ISEntry))
1009 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1014 CurDir = CurDirLookup;
1022 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
1023 Includers, SearchPath, RelativePath, RequestingModule,
1024 SuggestedModule,
nullptr,
1025 nullptr, SkipCache)) {
1027 TmpFromDir = TmpCurDir;
1029 if (&FE->getFileEntry() == FromFile) {
1031 FromDir = TmpFromDir;
1040 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,
1041 RelativePath, RequestingModule, SuggestedModule, IsMapped,
1042 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);
1050 if (IsFileLexer()) {
1053 Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,
1060 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1061 if (IsFileLexer(ISEntry)) {
1062 if ((CurFileEnt = ISEntry.ThePPLexer->
getFileEntry())) {
1064 Filename, *CurFileEnt, SearchPath, RelativePath,
1065 RequestingModule, SuggestedModule)) {
1073 return std::nullopt;
1083 : PP(pp), save(pp->DisableMacroExpansion) {
1084 if (pp->MacroExpansionInDirectivesOverride)
1085 pp->DisableMacroExpansion =
false;
1089 PP->DisableMacroExpansion = save;
1106 if (II->getPPKeywordID() == tok::pp_define) {
1107 return HandleDefineDirective(
Result,
1110 if (SkippingUntilPCHThroughHeader &&
1111 II->getPPKeywordID() == tok::pp_include) {
1112 return HandleIncludeDirective(HashLoc,
Result);
1114 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
1116 auto *II =
Result.getIdentifierInfo();
1117 if (II && II->getName() ==
"hdrstop")
1135 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
1137 bool ImmediatelyAfterTopLevelIfndef =
1165 switch (II->getPPKeywordID()) {
1166 case tok::pp_include:
1167 case tok::pp_import:
1168 case tok::pp_include_next:
1169 case tok::pp___include_macros:
1170 case tok::pp_pragma:
1171 Diag(
Result, diag::err_embedded_directive) << II->getName();
1172 Diag(*ArgMacro, diag::note_macro_expansion_here)
1187 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
1190 switch (
Result.getKind()) {
1197 case tok::code_completion:
1203 case tok::numeric_constant:
1210 return HandleDigitDirective(
Result);
1220 return HandleIfDirective(
Result, SavedHash, ReadAnyTokensBeforeDirective);
1222 return HandleIfdefDirective(
Result, SavedHash,
false,
1224 case tok::pp_ifndef:
1225 return HandleIfdefDirective(
Result, SavedHash,
true,
1226 ReadAnyTokensBeforeDirective);
1228 case tok::pp_elifdef:
1229 case tok::pp_elifndef:
1233 return HandleElseDirective(
Result, SavedHash);
1235 return HandleEndifDirective(
Result);
1238 case tok::pp_include:
1241 case tok::pp___include_macros:
1246 case tok::pp_define:
1247 return HandleDefineDirective(
Result, ImmediatelyAfterTopLevelIfndef);
1249 return HandleUndefDirective();
1253 return HandleLineDirective();
1257 return HandleUserDiagnosticDirective(
Result,
false);
1260 case tok::pp_pragma:
1264 case tok::pp_import:
1266 case tok::pp_include_next:
1269 case tok::pp_warning:
1270 if (LangOpts.CPlusPlus)
1272 ? diag::warn_cxx23_compat_warning_directive
1273 : diag::ext_pp_warning_directive)
1276 Diag(
Result, LangOpts.C23 ? diag::warn_c23_compat_warning_directive
1277 : diag::ext_pp_warning_directive)
1280 return HandleUserDiagnosticDirective(
Result,
true);
1282 return HandleIdentSCCSDirective(
Result);
1284 return HandleIdentSCCSDirective(
Result);
1285 case tok::pp_assert:
1288 case tok::pp_unassert:
1292 case tok::pp___public_macro:
1294 return HandleMacroPublicDirective(
Result);
1297 case tok::pp___private_macro:
1299 return HandleMacroPrivateDirective();
1310 auto Toks = std::make_unique<Token[]>(2);
1312 Toks[0] = SavedHash;
1317 if (
Result.is(tok::hashhash))
1318 Toks[1].setKind(tok::unknown);
1323 EnterTokenStream(std::move(Toks), 2,
false,
false);
1329 Diag(
Result, diag::err_pp_invalid_directive) << 0;
1341 bool IsGNULineDirective=
false) {
1342 if (DigitTok.
isNot(tok::numeric_constant)) {
1343 PP.
Diag(DigitTok, DiagID);
1345 if (DigitTok.
isNot(tok::eod))
1351 IntegerBuffer.resize(DigitTok.
getLength());
1352 const char *DigitTokBegin = &IntegerBuffer[0];
1362 for (
unsigned i = 0; i != ActualLength; ++i) {
1365 if (DigitTokBegin[i] ==
'\'')
1368 if (!
isDigit(DigitTokBegin[i])) {
1370 diag::err_pp_line_digit_sequence) << IsGNULineDirective;
1375 unsigned NextVal = Val*10+(DigitTokBegin[i]-
'0');
1376 if (NextVal < Val) {
1377 PP.
Diag(DigitTok, DiagID);
1384 if (DigitTokBegin[0] ==
'0' && Val)
1386 << IsGNULineDirective;
1398void Preprocessor::HandleLineDirective() {
1406 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*
this))
1410 Diag(DigitTok, diag::ext_pp_line_zero);
1414 unsigned LineLimit = 32768U;
1415 if (LangOpts.C99 || LangOpts.CPlusPlus11)
1416 LineLimit = 2147483648U;
1417 if (LineNo >= LineLimit)
1418 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
1419 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)
1420 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);
1422 int FilenameID = -1;
1428 if (StrTok.
is(tok::eod))
1430 else if (StrTok.
isNot(tok::string_literal)) {
1431 Diag(StrTok, diag::err_pp_line_invalid_filename);
1435 Diag(StrTok, diag::err_invalid_string_udl);
1441 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1447 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1482 if (FlagTok.
is(tok::eod))
return false;
1483 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1490 if (FlagTok.
is(tok::eod))
return false;
1491 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1493 }
else if (FlagVal == 2) {
1509 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {
1510 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
1516 if (FlagTok.
is(tok::eod))
return false;
1517 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1523 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1531 if (FlagTok.
is(tok::eod))
return false;
1532 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1537 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1545 if (FlagTok.
is(tok::eod))
return false;
1548 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1560void Preprocessor::HandleDigitDirective(
Token &DigitTok) {
1564 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
1571 bool IsFileEntry =
false, IsFileExit =
false;
1572 int FilenameID = -1;
1577 if (StrTok.
is(tok::eod)) {
1578 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1581 }
else if (StrTok.
isNot(tok::string_literal)) {
1582 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1586 Diag(StrTok, diag::err_invalid_string_udl);
1592 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1598 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1608 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1612 if (!(IsFileExit &&
Literal.GetString().empty()))
1618 IsFileExit, FileKind);
1627 else if (IsFileExit)
1636void Preprocessor::HandleUserDiagnosticDirective(
Token &Tok,
1644 CurLexer->ReadToEndOfLine(&Message);
1648 StringRef Msg = Message.str().ltrim(
' ');
1651 Diag(Tok, diag::pp_hash_warning) << Msg;
1653 Diag(Tok, diag::err_pp_hash_error) << Msg;
1658void Preprocessor::HandleIdentSCCSDirective(
Token &Tok) {
1660 Diag(Tok, diag::ext_pp_ident_directive);
1667 if (StrTok.
isNot(tok::string_literal) &&
1668 StrTok.
isNot(tok::wide_string_literal)) {
1669 Diag(StrTok, diag::err_pp_malformed_ident);
1670 if (StrTok.
isNot(tok::eod))
1676 Diag(StrTok, diag::err_invalid_string_udl);
1693void Preprocessor::HandleMacroPublicDirective(
Token &Tok) {
1695 ReadMacroName(MacroNameTok,
MU_Undef);
1698 if (MacroNameTok.
is(tok::eod))
1710 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1720void Preprocessor::HandleMacroPrivateDirective() {
1722 ReadMacroName(MacroNameTok,
MU_Undef);
1725 if (MacroNameTok.
is(tok::eod))
1737 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1757 StringRef &Buffer) {
1759 assert(!Buffer.empty() &&
"Can't have tokens with empty spellings!");
1771 if (Buffer[0] ==
'<') {
1772 if (Buffer.back() !=
'>') {
1773 Diag(Loc, diag::err_pp_expects_filename);
1774 Buffer = StringRef();
1778 }
else if (Buffer[0] ==
'"') {
1779 if (Buffer.back() !=
'"') {
1780 Diag(Loc, diag::err_pp_expects_filename);
1781 Buffer = StringRef();
1786 Diag(Loc, diag::err_pp_expects_filename);
1787 Buffer = StringRef();
1792 if (Buffer.size() <= 2) {
1793 Diag(Loc, diag::err_pp_empty_filename);
1794 Buffer = StringRef();
1799 Buffer = Buffer.substr(1, Buffer.size()-2);
1806 void *AnnotationVal) {
1809 auto Tok = std::make_unique<Token[]>(1);
1815 EnterTokenStream(std::move(Tok), 1,
true,
false);
1822 ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,
1825 for (
size_t I = 0, N = Path.size(); I != N; ++I) {
1828 PathString += Path[I].first->getName();
1831 int IncludeKind = 0;
1833 case tok::pp_include:
1837 case tok::pp_import:
1841 case tok::pp_include_next:
1845 case tok::pp___include_macros:
1850 llvm_unreachable(
"unknown include directive kind");
1853 PP.
Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
1854 << IncludeKind << PathString;
1861 StringRef RealPathName) {
1862 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
1863 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
1865 bool SuggestReplacement =
false;
1868 for (
auto &Component : llvm::reverse(Components)) {
1869 if (
"." == Component) {
1870 }
else if (
".." == Component) {
1874 }
else if (RealPathComponentIter != RealPathComponentEnd) {
1875 if (Component != *RealPathComponentIter) {
1879 SuggestReplacement =
1880 RealPathComponentIter->equals_insensitive(Component);
1881 if (!SuggestReplacement)
1883 Component = *RealPathComponentIter;
1885 ++RealPathComponentIter;
1888 return SuggestReplacement;
1897 Module *ShadowingModule =
nullptr;
1905 }
else if (ShadowingModule) {
1908 diag::note_previous_definition);
1918std::pair<ConstSearchDirIterator, const FileEntry *>
1919Preprocessor::getIncludeNextStart(
const Token &IncludeNextTok)
const {
1924 const FileEntry *LookupFromFile =
nullptr;
1932 Diag(IncludeNextTok, diag::pp_include_next_in_primary);
1933 }
else if (CurLexerSubmodule) {
1936 assert(CurPPLexer &&
"#include_next directive in macro?");
1939 }
else if (!Lookup) {
1944 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
1950 return {Lookup, LookupFromFile};
1966 if (FilenameTok.
isNot(tok::header_name)) {
1968 if (FilenameTok.
isNot(tok::eod))
1980 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
1981 EndLoc, LookupFrom, LookupFromFile);
1982 switch (Action.Kind) {
1983 case ImportAction::None:
1984 case ImportAction::SkippedModuleImport:
1986 case ImportAction::ModuleBegin:
1988 tok::annot_module_begin, Action.ModuleForHeader);
1990 case ImportAction::HeaderUnitImport:
1992 Action.ModuleForHeader);
1994 case ImportAction::ModuleImport:
1996 tok::annot_module_include, Action.ModuleForHeader);
1998 case ImportAction::Failure:
2000 "This should be an early exit only to a fatal error");
2003 CurLexer->cutOffLexing();
2011 const Token &FilenameTok,
bool &IsFrameworkFound,
bool IsImportDecl,
2013 const FileEntry *LookupFromFile, StringRef &LookupFilename,
2017 if (LangOpts.AsmPreprocessor)
2021 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
2022 bool RequestingModuleIsModuleInterface =
2026 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
2031 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,
2032 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2033 &SuggestedModule, &IsMapped, &IsFrameworkFound);
2035 DiagnoseHeaderInclusion(*
File);
2040 if (Callbacks && Callbacks->FileNotFound(
Filename))
2041 return std::nullopt;
2043 if (SuppressIncludeNotFoundError)
2044 return std::nullopt;
2051 FilenameLoc, LookupFilename,
false, LookupFrom, LookupFromFile, CurDir,
2052 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2053 &SuggestedModule, &IsMapped,
2056 DiagnoseHeaderInclusion(*
File);
2057 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
2067 StringRef OriginalFilename =
Filename;
2068 if (LangOpts.SpellChecking) {
2071 auto CorrectTypoFilename = [](llvm::StringRef
Filename) {
2078 StringRef TypoCorrectionName = CorrectTypoFilename(
Filename);
2079 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);
2082 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,
2083 LookupFromFile, CurDir, Callbacks ? &SearchPath :
nullptr,
2084 Callbacks ? &RelativePath :
nullptr, &SuggestedModule, &IsMapped,
2087 DiagnoseHeaderInclusion(*
File);
2090 FilenameRange,
"<" + TypoCorrectionName.str() +
">")
2092 FilenameRange,
"\"" + TypoCorrectionName.str() +
"\"");
2093 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
2094 << OriginalFilename << TypoCorrectionName << Hint;
2098 LookupFilename = TypoCorrectionLookupName;
2104 assert(!
File &&
"expected missing file");
2105 Diag(FilenameTok, diag::err_pp_file_not_found)
2106 << OriginalFilename << FilenameRange;
2107 if (IsFrameworkFound) {
2108 size_t SlashPos = OriginalFilename.find(
'/');
2109 assert(SlashPos != StringRef::npos &&
2110 "Include with framework name should have '/' in the filename");
2111 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
2114 assert(CacheEntry.
Directory &&
"Found framework should be in cache");
2115 Diag(FilenameTok, diag::note_pp_framework_without_header)
2116 << OriginalFilename.substr(SlashPos + 1) << FrameworkName
2120 return std::nullopt;
2135Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
2145 StringRef OriginalFilename =
Filename;
2152 return {ImportAction::None};
2154 bool IsImportDecl = HashLoc.
isInvalid();
2158 if (PragmaARCCFCodeAuditedInfo.second.isValid()) {
2159 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
2160 Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);
2167 if (PragmaAssumeNonNullLoc.
isValid()) {
2168 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
2169 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
2180 if (!NewName.empty())
2185 bool IsMapped =
false;
2186 bool IsFrameworkFound =
false;
2194 StringRef LookupFilename =
Filename;
2199 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;
2200 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {
2202 llvm::sys::path::native(NormalizedPath);
2203 LookupFilename = NormalizedPath;
2204 BackslashStyle = llvm::sys::path::Style::windows;
2208 &CurDir,
Filename, FilenameLoc, FilenameRange, FilenameTok,
2209 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
2210 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
2214 SkippingUntilPCHThroughHeader =
false;
2215 return {ImportAction::None};
2233 enum { Enter,
Import, Skip, IncludeLimitReached } Action = Enter;
2235 if (PPOpts->SingleFileParseMode)
2236 Action = IncludeLimitReached;
2241 if (Action == Enter && HasReachedMaxIncludeDepth &&
File &&
2243 Action = IncludeLimitReached;
2249 bool MaybeTranslateInclude =
2253 bool UsableHeaderUnit =
false;
2255 if (TrackGMFState.inGMF() || IsImportDecl)
2256 UsableHeaderUnit =
true;
2257 else if (!IsImportDecl) {
2264 bool UsableClangHeaderModule =
2266 !
SM->isHeaderUnit();
2271 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {
2280 diag::note_implicit_top_level_module_import_here)
2282 return {ImportAction::None};
2289 for (
Module *Mod =
SM; Mod; Mod = Mod->Parent)
2292 std::reverse(Path.begin(), Path.end());
2305 assert((Imported ==
nullptr || Imported == SuggestedModule.
getModule()) &&
2306 "the imported module is different than the suggested one");
2312 static_cast<Module *
>(Imported)->getTopLevelModule());
2327 assert(CurLexer &&
"#include but no current lexer set!");
2329 CurLexer->FormTokenWithChars(
Result, CurLexer->BufferEnd, tok::eof);
2330 CurLexer->cutOffLexing();
2332 return {ImportAction::None};
2353 bool IsFirstIncludeOfFile =
false;
2357 if (Action == Enter &&
File &&
2360 IsFirstIncludeOfFile)) {
2371 if (UsableHeaderUnit && !
getLangOpts().CompilingPCH)
2372 Action = TrackGMFState.inGMF() ?
Import : Skip;
2374 Action = (SuggestedModule && !
getLangOpts().CompilingPCH) ? Import : Skip;
2382 if (Action == Enter &&
File && PreambleConditionalStack.isRecording() &&
2385 diag::err_pp_including_mainfile_in_preamble);
2386 return {ImportAction::None};
2389 if (Callbacks && !IsImportDecl) {
2392 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,
2393 FilenameRange,
File, SearchPath, RelativePath,
2394 Action == Import ? SuggestedModule.
getModule()
2397 if (Action == Skip &&
File)
2398 Callbacks->FileSkipped(*
File, FilenameTok, FileCharacter);
2402 return {ImportAction::None};
2406 if (IsImportDecl && !SuggestedModule) {
2407 Diag(FilenameTok, diag::err_header_import_not_header_unit)
2408 << OriginalFilename <<
File->getName();
2409 return {ImportAction::None};
2414 const bool CheckIncludePathPortability =
2415 !IsMapped && !
File->getFileEntry().tryGetRealPathName().empty();
2417 if (CheckIncludePathPortability) {
2418 StringRef Name = LookupFilename;
2419 StringRef NameWithoriginalSlashes =
Filename;
2423 bool NameWasUNC = Name.consume_front(
"\\\\?\\");
2424 NameWithoriginalSlashes.consume_front(
"\\\\?\\");
2426 StringRef RealPathName =
File->getFileEntry().tryGetRealPathName();
2428 llvm::sys::path::end(Name));
2441 if (llvm::sys::path::is_absolute(Name) &&
2442 llvm::sys::path::is_absolute(RealPathName) &&
2445 assert(Components.size() >= 3 &&
"should have drive, backslash, name");
2446 assert(Components[0].size() == 2 &&
"should start with drive");
2447 assert(Components[0][1] ==
':' &&
"should have colon");
2448 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();
2449 RealPathName = FixedDriveRealPath;
2455 Path.reserve(Name.size()+2);
2456 Path.push_back(isAngled ?
'<' :
'"');
2458 const auto IsSep = [BackslashStyle](
char c) {
2459 return llvm::sys::path::is_separator(
c, BackslashStyle);
2462 for (
auto Component : Components) {
2474 if (!(Component.size() == 1 && IsSep(Component[0])))
2475 Path.append(Component);
2476 else if (!Path.empty())
2480 if (Path.size() > NameWithoriginalSlashes.size()) {
2481 Path.push_back(isAngled ?
'>' :
'"');
2484 assert(IsSep(NameWithoriginalSlashes[Path.size()-1]));
2486 Path.push_back(NameWithoriginalSlashes[Path.size()-1]);
2487 while (Path.size() <= NameWithoriginalSlashes.size() &&
2488 IsSep(NameWithoriginalSlashes[Path.size()-1]));
2494 Path = (Path.substr(0, 1) +
"\\\\?\\" + Path.substr(1)).str();
2501 ? diag::pp_nonportable_path
2502 : diag::pp_nonportable_system_path;
2503 Diag(FilenameTok, DiagId) << Path <<
2512 return {ImportAction::SkippedModuleImport,
SM};
2513 return {ImportAction::None};
2515 case IncludeLimitReached:
2518 return {ImportAction::None};
2522 assert(
SM &&
"no module to import");
2527 tok::pp___include_macros)
2528 return {ImportAction::None};
2530 return {ImportAction::ModuleImport,
SM};
2538 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
2539 Diag(FilenameTok, diag::err_pp_include_too_deep);
2540 HasReachedMaxIncludeDepth =
true;
2541 return {ImportAction::None};
2545 Diag(FilenameTok, diag::warn_pp_include_angled_in_module_purview)
2557 return ImportAction::Failure;
2562 IsFirstIncludeOfFile))
2563 return {ImportAction::None};
2567 if (
SM && !
SM->isHeaderUnit()) {
2568 if (
SM->getTopLevelModule()->ShadowingModule) {
2571 Diag(
SM->DefinitionLoc, diag::err_module_build_shadowed_submodule)
2572 <<
SM->getFullModuleName();
2573 Diag(
SM->getTopLevelModule()->ShadowingModule->DefinitionLoc,
2574 diag::note_previous_definition);
2575 return {ImportAction::None};
2586 return {ImportAction::None};
2588 assert(!CurLexerSubmodule &&
"should not have marked this as a module yet");
2589 CurLexerSubmodule =
SM;
2599 return {ImportAction::ModuleBegin,
SM};
2602 assert(!IsImportDecl &&
"failed to diagnose missing module for import decl");
2603 return {ImportAction::None};
2608void Preprocessor::HandleIncludeNextDirective(
SourceLocation HashLoc,
2609 Token &IncludeNextTok) {
2610 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
2614 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);
2616 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
2621void Preprocessor::HandleMicrosoftImportDirective(
Token &Tok) {
2627 Diag(Tok, diag::err_pp_import_directive_ms );
2638 if (!LangOpts.ObjC) {
2639 if (LangOpts.MSVCCompat)
2640 return HandleMicrosoftImportDirective(ImportTok);
2641 Diag(ImportTok, diag::ext_pp_import_directive);
2643 return HandleIncludeDirective(HashLoc, ImportTok);
2650void Preprocessor::HandleIncludeMacrosDirective(
SourceLocation HashLoc,
2651 Token &IncludeMacrosTok) {
2657 diag::pp_include_macros_out_of_predefines);
2664 HandleIncludeDirective(HashLoc, IncludeMacrosTok);
2669 assert(TmpTok.
isNot(tok::eof) &&
"Didn't find end of -imacros!");
2670 }
while (TmpTok.
isNot(tok::hashhash));
2681bool Preprocessor::ReadMacroParameterList(
MacroInfo *MI,
Token &Tok) {
2692 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
2696 Diag(Tok, LangOpts.CPlusPlus11 ?
2697 diag::warn_cxx98_compat_variadic_macro :
2698 diag::ext_variadic_macro);
2701 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
2702 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
2707 if (Tok.
isNot(tok::r_paren)) {
2708 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2717 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2725 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
2731 if (llvm::is_contained(Parameters, II)) {
2732 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
2744 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
2753 Diag(Tok, diag::ext_named_variadic_macro);
2757 if (Tok.
isNot(tok::r_paren)) {
2758 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2788 StringRef ValueText = II->
getName();
2789 StringRef TrimmedValue = ValueText;
2790 if (!ValueText.startswith(
"__")) {
2791 if (ValueText.startswith(
"_"))
2792 TrimmedValue = TrimmedValue.drop_front(1);
2796 TrimmedValue = TrimmedValue.drop_front(2);
2797 if (TrimmedValue.endswith(
"__"))
2798 TrimmedValue = TrimmedValue.drop_back(2);
2800 return TrimmedValue.equals(MacroText);
2807 return MacroName.
isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
2820MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
2821 const Token &MacroNameTok,
const bool ImmediatelyAfterHeaderGuard) {
2823 Token LastTok = MacroNameTok;
2831 auto _ = llvm::make_scope_exit([&]() {
2833 if (CurLexer->ParsingPreprocessorDirective)
2844 if (Tok.
is(tok::eod)) {
2845 if (ImmediatelyAfterHeaderGuard) {
2855 }
else if (Tok.
is(tok::l_paren)) {
2858 if (ReadMacroParameterList(MI, LastTok))
2872 }
else if (LangOpts.C99 || LangOpts.CPlusPlus11) {
2875 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
2884 if (Tok.
is(tok::at))
2886 else if (Tok.
is(tok::unknown)) {
2893 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
2895 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
2898 if (!Tok.
is(tok::eod))
2906 while (Tok.
isNot(tok::eod)) {
2908 Tokens.push_back(Tok);
2919 while (Tok.
isNot(tok::eod)) {
2922 if (!Tok.
isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
2923 Tokens.push_back(Tok);
2925 if (VAOCtx.isVAOptToken(Tok)) {
2927 if (VAOCtx.isInVAOpt()) {
2928 Diag(Tok, diag::err_pp_vaopt_nested_use);
2933 if (Tok.
isNot(tok::l_paren)) {
2934 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
2937 Tokens.push_back(Tok);
2938 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.
getLocation());
2940 if (Tok.
is(tok::hashhash)) {
2941 Diag(Tok, diag::err_vaopt_paste_at_start);
2945 }
else if (VAOCtx.isInVAOpt()) {
2946 if (Tok.
is(tok::r_paren)) {
2947 if (VAOCtx.sawClosingParen()) {
2948 assert(Tokens.size() >= 3 &&
2949 "Must have seen at least __VA_OPT__( "
2950 "and a subsequent tok::r_paren");
2951 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {
2952 Diag(Tok, diag::err_vaopt_paste_at_end);
2956 }
else if (Tok.
is(tok::l_paren)) {
2970 Tokens.push_back(Tok);
2977 if (Tok.
is(tok::hashhash)) {
2985 if (Tok.
is(tok::eod)) {
2986 Tokens.push_back(LastTok);
2991 Tokens[Tokens.size() - 1].is(tok::comma))
2995 Tokens.push_back(LastTok);
3004 if (!VAOCtx.isVAOptToken(Tok) &&
3013 LastTok.
setKind(tok::unknown);
3014 Tokens.push_back(LastTok);
3017 Diag(Tok, diag::err_pp_stringize_not_parameter)
3018 << LastTok.
is(tok::hashat);
3024 Tokens.push_back(LastTok);
3029 if (!VAOCtx.isVAOptToken(Tok)) {
3030 Tokens.push_back(Tok);
3037 if (VAOCtx.isInVAOpt()) {
3038 assert(Tok.
is(tok::eod) &&
"Must be at End Of preprocessing Directive");
3039 Diag(Tok, diag::err_pp_expected_after)
3040 << LastTok.
getKind() << tok::r_paren;
3041 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
3052 return II->
isStr(
"__strong") || II->
isStr(
"__weak") ||
3053 II->
isStr(
"__unsafe_unretained") || II->
isStr(
"__autoreleasing");
3058void Preprocessor::HandleDefineDirective(
3059 Token &DefineTok,
const bool ImmediatelyAfterHeaderGuard) {
3063 bool MacroShadowsKeyword;
3064 ReadMacroName(MacroNameTok,
MU_Define, &MacroShadowsKeyword);
3067 if (MacroNameTok.
is(tok::eod))
3074 emitFinalMacroWarning(MacroNameTok,
false);
3078 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
3080 MacroInfo *
const MI = ReadOptionalMacroParameterListAndBody(
3081 MacroNameTok, ImmediatelyAfterHeaderGuard);
3085 if (MacroShadowsKeyword &&
3087 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
3092 if (NumTokens != 0) {
3104 if (SkippingUntilPCHThroughHeader) {
3107 LangOpts.MicrosoftExt))
3111 if (!LangOpts.MicrosoftExt)
3122 emitFinalMacroWarning(MacroNameTok,
false);
3135 LangOpts.MicrosoftExt)) {
3154 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
3158 !MI->
isIdenticalTo(*OtherMI, *
this, LangOpts.MicrosoftExt)) {
3176 !MacroExpansionInDirectivesOverride &&
3185 Callbacks->MacroDefined(MacroNameTok, MD);
3198 Tok.
setKind(tok::kw__Static_assert);
3207void Preprocessor::HandleUndefDirective() {
3211 ReadMacroName(MacroNameTok,
MU_Undef);
3214 if (MacroNameTok.
is(tok::eod))
3226 emitFinalMacroWarning(MacroNameTok,
true);
3236 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
3241 Undef = AllocateUndefMacroDirective(MacroNameTok.
getLocation());
3247 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
3262void Preprocessor::HandleIfdefDirective(
Token &
Result,
3263 const Token &HashToken,
3265 bool ReadAnyTokensBeforeDirective) {
3270 ReadMacroName(MacroNameTok);
3273 if (MacroNameTok.
is(tok::eod)) {
3276 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3296 if (!ReadAnyTokensBeforeDirective && !MI) {
3297 assert(isIfndef &&
"#ifdef shouldn't reach here");
3309 Callbacks->Ifndef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3311 Callbacks->Ifdef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3314 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3318 if (PPOpts->SingleFileParseMode && !MI) {
3324 }
else if (!MI == isIfndef || RetainExcludedCB) {
3331 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3340void Preprocessor::HandleIfDirective(
Token &IfToken,
3341 const Token &HashToken,
3342 bool ReadAnyTokensBeforeDirective) {
3347 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
3348 const bool ConditionalTrue = DER.Conditional;
3357 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
3369 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3373 if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
3378 }
else if (ConditionalTrue || RetainExcludedCB) {
3392void Preprocessor::HandleEndifDirective(
Token &EndifToken) {
3401 Diag(EndifToken, diag::err_pp_endif_without_if);
3410 "This code should only be reachable in the non-skipping case!");
3418void Preprocessor::HandleElseDirective(
Token &
Result,
const Token &HashToken) {
3440 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3443 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3454 true,
Result.getLocation());
3458void Preprocessor::HandleElifFamilyDirective(
Token &ElifToken,
3459 const Token &HashToken,
3471 if (LangOpts.CPlusPlus)
3472 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
3473 : diag::ext_cxx23_pp_directive;
3475 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
3476 : diag::ext_c23_pp_directive;
3477 Diag(ElifToken, DiagID) << DirKind;
3490 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
3500 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
3505 Callbacks->Elif(ElifToken.
getLocation(), ConditionRange,
3508 case tok::pp_elifdef:
3511 case tok::pp_elifndef:
3515 assert(
false &&
"unexpected directive kind");
3520 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3523 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3532 SkipExcludedConditionalBlock(
static bool isInMainFile(const clang::Diagnostic &D)
Defines interfaces for clang::DirectoryEntry and clang::DirectoryEntryRef.
Defines the clang::FileManager interface and associated types.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the clang::Module class, which describes a module in the source code.
Defines the PPCallbacks interface.
static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, SrcMgr::CharacteristicKind &FileKind, Preprocessor &PP)
ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line marker directive.
static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI, const LangOptions &LOptions)
static bool trySimplifyPath(SmallVectorImpl< StringRef > &Components, StringRef RealPathName)
static std::optional< StringRef > findSimilarStr(StringRef LHS, const std::vector< StringRef > &Candidates)
Find a similar string in Candidates.
static bool isLanguageDefinedBuiltin(const SourceManager &SourceMgr, const MacroInfo *MI, const StringRef MacroName)
static void diagnoseAutoModuleImport(Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok, ArrayRef< std::pair< IdentifierInfo *, SourceLocation > > Path, SourceLocation PathEnd)
Produce a diagnostic informing the user that a #include or similar was implicitly treated as a module...
static bool warnByDefaultOnWrongCase(StringRef Include)
MacroDiag
Enumerates possible cases of #define/#undef a reserved identifier.
static bool isFeatureTestMacro(StringRef MacroName)
static bool GetLineValue(Token &DigitTok, unsigned &Val, unsigned DiagID, Preprocessor &PP, bool IsGNULineDirective=false)
GetLineValue - Convert a numeric token into an unsigned value, emitting Diagnostic DiagID if it is in...
PPElifDiag
Enumerates possible select values for the pp_err_elif_after_else and pp_err_elif_without_if diagnosti...
static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II)
static bool isObjCProtectedMacro(const IdentifierInfo *II)
static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II)
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
static bool isInvalid(LocType Loc, bool *Invalid)
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__device__ __2f16 float c
ResetMacroExpansionHelper(Preprocessor *pp)
~ResetMacroExpansionHelper()
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getEnd() const
virtual void CodeCompleteMacroName(bool IsDefinition)
Callback invoked when performing code completion in a context where the name of a macro is expected.
virtual void CodeCompleteInConditionalExclusion()
Callback invoked when performing code completion within a block of code that was excluded due to prep...
virtual void CodeCompleteDirective(bool InConditional)
Callback invoked when performing code completion for a preprocessor directive.
A directive for a defined macro or a macro imported from a module.
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.
StringRef getName() const
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
const FileEntry & getFileEntry() const
DirectoryEntryRef getDir() const
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
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 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.
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
bool isCPlusPlusOperatorKeyword() const
bool hadMacroDefinition() const
Returns true if this identifier was #defined to some value at any moment.
bool hasMacroDefinition() const
Return true if this identifier is #defined to some other value.
const char * getNameStart() const
Return the beginning of the actual null-terminated string for this identifier.
bool isKeyword(const LangOptions &LangOpts) const
Return true if this token is a keyword in the specified language.
ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const
Determine whether this is a name reserved for the implementation (C99 7.1.3, C++ [lib....
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool IsHeaderFile
Indicates whether the front-end is explicitly told that the input is a header file (i....
std::string CurrentModule
The name of the current module, of which the main source file is a part.
Encapsulates changes to the "macros namespace" (the location where the macro name became active,...
const MacroInfo * getMacroInfo() const
Encapsulates the data about a macro definition (e.g.
bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, bool Syntactically) const
Return true if the specified macro definition is equal to this macro in spelling, arguments,...
bool isUsed() const
Return false if this macro is defined in the main file and has not yet been used.
bool isC99Varargs() const
bool isAllowRedefinitionsWithoutWarning() const
Return true if this macro can be redefined without warning.
void setHasCommaPasting()
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
const Token & getReplacementToken(unsigned Tok) const
void setDefinitionEndLoc(SourceLocation EndLoc)
Set the location of the last token in the macro.
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
void setTokens(ArrayRef< Token > Tokens, llvm::BumpPtrAllocator &PPAllocator)
void setParameterList(ArrayRef< IdentifierInfo * > List, llvm::BumpPtrAllocator &PPAllocator)
Set the specified list of identifiers as the parameter list for this macro.
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
void setIsFunctionLike()
Function/Object-likeness.
bool isObjectLike() const
void setIsWarnIfUnused(bool val)
Set the value of the IsWarnIfUnused flag.
int getParameterNum(const IdentifierInfo *Arg) const
Return the parameter number of the specified identifier, or -1 if the identifier is not a formal para...
bool isWarnIfUnused() const
Return true if we should emit a warning if the macro is unused.
void setIsC99Varargs()
Varargs querying methods. This can only be set for function-like macros.
Describes the result of attempting to load a module.
bool isMissingExpected() const
Determines whether the module, which failed to load, was actually a submodule that we expected to see...
bool isConfigMismatch() const
Determines whether the module failed to load due to a configuration mismatch with an explicitly-named...
virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective)=0
Attempt to load the given module.
void diagnoseHeaderInclusion(Module *RequestingModule, bool RequestingModuleIsModuleInterface, SourceLocation FilenameLoc, StringRef Filename, FileEntryRef File)
Reports errors if a module must not include a specific file.
KnownHeader findModuleForHeader(FileEntryRef File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
bool shouldImportRelativeToBuiltinIncludeDir(StringRef FileName, Module *Module) const
OptionalDirectoryEntryRefDegradesToDirectoryEntryPtr getBuiltinDir() const
Get the directory that contains Clang-supplied include files.
@ ExcludedHeader
This header is explicitly excluded from the module.
@ TextualHeader
This header is part of the module (for layering purposes) but should be textually included.
Describes a module or submodule.
StringRef getTopLevelModuleName() const
Retrieve the name of the top-level module.
@ Hidden
All of the names in this module are hidden.
SourceLocation DefinitionLoc
The location of the module definition.
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
std::string Name
The name of this module.
std::pair< std::string, bool > Requirement
An individual requirement: a feature name and a flag indicating the required state of that feature.
bool isAvailable() const
Determine whether this module is available for use within the current translation unit.
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
bool getHasReadAnyTokensVal() const
getHasReadAnyTokensVal - This is used for the #ifndef handshake at the top of the file when reading p...
void ExitTopLevelConditional()
Called when the lexer exits the top-level conditional.
void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc)
void SetReadToken(bool Value)
SetReadToken - Set whether the value of 'ReadAnyTokens'.
bool getImmediatelyAfterTopLevelIfndef() const
getImmediatelyAfterTopLevelIfndef - returns true if the last directive was an #ifndef at the beginnin...
void EnterTopLevelConditional()
Invoked when a top level conditional (except #ifndef) is found.
void resetImmediatelyAfterTopLevelIfndef()
void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc)
Called when entering a top-level #ifndef directive (or the "\#if !defined" equivalent) without any pr...
OptionalFileEntryRefDegradesToFileEntryPtr getFileEntry() const
getFileEntry - Return the FileEntry corresponding to this FileID.
void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, bool FoundNonSkip, bool FoundElse)
pushConditionalLevel - When we enter a #if directive, this keeps track of what we are currently in fo...
unsigned getConditionalStackDepth() const
bool LexingRawMode
True if in raw mode.
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 popConditionalLevel(PPConditionalInfo &CI)
popConditionalLevel - Remove an entry off the top of the conditional stack, returning information abo...
PPConditionalInfo & peekConditionalLevel()
Return the top of the conditional stack.
virtual SourceLocation getSourceLocation()=0
Return the source location for the next observable location.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
MacroDirective * getLocalMacroDirective(const IdentifierInfo *II) const
Given an identifier, return its latest non-imported MacroDirective if it is #define'd and not #undef'...
void markClangModuleAsAffecting(Module *M)
Mark the given clang module as affecting the current clang module or translation unit.
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
bool isRecordingPreamble() const
void HandleSkippedDirectiveWhileUsingPCH(Token &Result, SourceLocation HashLoc)
Process directives while skipping until the through header or #pragma hdrstop is found.
bool isInPrimaryFile() const
Return true if we're in the top-level file, not in a #include.
void markMacroAsUsed(MacroInfo *MI)
A macro is used, update information about macros that need unused warnings.
void EnterSubmodule(Module *M, SourceLocation ImportLoc, bool ForPragma)
void setCodeCompletionReached()
Note that we hit the code-completion point.
StringRef getNamedModuleName() const
Get the named module name we're preprocessing.
void makeModuleVisible(Module *M, SourceLocation Loc)
void Lex(Token &Result)
Lex the next token for this preprocessor.
bool EnterSourceFile(FileID FID, ConstSearchDirIterator Dir, SourceLocation Loc, bool IsFirstIncludeOfFile=true)
Add a source file to the top of the include stack and start lexing tokens from it instead of the curr...
SourceLocation CheckEndOfDirective(const char *DirType, bool EnableMacros=false)
Ensure that the next token is a tok::eod token.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
SourceManager & getSourceManager() const
MacroDefinition getMacroDefinition(const IdentifierInfo *II)
bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag=nullptr)
bool isMacroDefined(StringRef Id)
static bool checkModuleIsAvailable(const LangOptions &LangOpts, const TargetInfo &TargetInfo, const Module &M, DiagnosticsEngine &Diags)
Check that the given module is available, producing a diagnostic if not.
SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const
Given a location that specifies the start of a token, return a new location that specifies a characte...
Module * getCurrentModule()
Retrieves the module that we're currently building, if any.
void emitMacroExpansionWarnings(const Token &Identifier) const
bool hadModuleLoaderFatalFailure() const
const TargetInfo & getTargetInfo() const
bool LexHeaderName(Token &Result, bool AllowMacroExpansion=true)
Lex a token, forming a header-name token if possible.
bool isPCHThroughHeader(const FileEntry *FE)
Returns true if the FileEntry is the PCH through header.
friend class VariadicMacroScopeGuard
MacroInfo * AllocateMacroInfo(SourceLocation L)
Allocate a new MacroInfo object with the provided SourceLocation.
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
bool alreadyIncluded(FileEntryRef File) const
Return true if this header has already been included.
FileID getPredefinesFileID() const
Returns the FileID for the preprocessor predefines.
void LexUnexpandedNonComment(Token &Result)
Like LexNonComment, but this disables macro expansion of identifier tokens.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)
Turn the specified lexer token into a fully checked and spelled filename, e.g.
PreprocessorLexer * getCurrentFileLexer() const
Return the current file lexer being lexed from.
HeaderSearch & getHeaderSearchInfo() const
SourceRange DiscardUntilEndOfDirective()
Read and discard all tokens remaining on the current line until the tok::eod token is found.
void HandleDirective(Token &Result)
Callback invoked when the lexer sees a # token at the start of a line.
void EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind, void *AnnotationVal)
Enter an annotation token into the token stream.
OptionalFileEntryRef LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, ConstSearchDirIterator FromDir, const FileEntry *FromFile, ConstSearchDirIterator *CurDir, SmallVectorImpl< char > *SearchPath, SmallVectorImpl< char > *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool *IsFrameworkFound, bool SkipCache=false, bool OpenFile=true, bool CacheFailures=true)
Given a "foo" or <foo> reference, look up the indicated file.
const LangOptions & getLangOpts() const
bool isInNamedModule() const
If we are preprocessing a named module.
OptionalFileEntryRef getHeaderToIncludeForDiagnostics(SourceLocation IncLoc, SourceLocation MLoc)
We want to produce a diagnostic at location IncLoc concerning an unreachable effect at location MLoc ...
DefMacroDirective * appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc)
void HandlePragmaHdrstop(Token &Tok)
DiagnosticsEngine & getDiagnostics() const
Module * getModuleForLocation(SourceLocation Loc, bool AllowTextual)
Find the module that owns the source or header file that Loc points to.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
bool usingPCHWithThroughHeader()
True if using a PCH with a through header.
void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD)
Add a directive to the macro directive history for this identifier.
Represents an unpacked "presumed" location which can be presented to the user.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
Encodes a location in the source.
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.
This class handles loading and caching of source files into memory.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isWrittenInBuiltinFile(SourceLocation Loc) const
Returns whether Loc is located in a <built-in> file.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table for the FileID and offset specified by Loc.
bool isWrittenInCommandLineFile(SourceLocation Loc) const
Returns whether Loc is located in a <command line> file.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
FileID createFileID(FileEntryRef SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
bool isMainFile(const FileEntry &SourceFile)
Returns true when the given FileEntry corresponds to the main file.
FileID getMainFileID() const
Returns the FileID of the main source file.
CharSourceRange getExpansionRange(SourceLocation Loc) const
Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate fi...
unsigned getLineTableFilenameID(StringRef Str)
Return the uniqued ID for the specified filename.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
void setEnd(SourceLocation e)
StringLiteralParser - This decodes string escape characters and performs wide string analysis and Tra...
Exposes information about the current target.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
SourceLocation getEndLoc() const
void setAnnotationEndLoc(SourceLocation L)
void clearFlag(TokenFlags Flag)
Unset the specified flag.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
void setKind(tok::TokenKind K)
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 hasLeadingSpace() const
Return true if this token has whitespace before it.
void setLocation(SourceLocation L)
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
bool isNot(tok::TokenKind K) const
void setAnnotationValue(void *val)
bool hasUDSuffix() const
Return true if this token is a string or character literal which has a ud-suffix.
void startToken()
Reset all flags to cleared.
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
void setIdentifierInfo(IdentifierInfo *II)
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode),...
A directive for an undefined macro.
A class for tracking whether we're inside a VA_OPT during a traversal of the tokens of a variadic mac...
An RAII class that tracks when the Preprocessor starts and stops lexing the definition of a (ISO C/C+...
void enterScope()
Client code should call this function just before the Preprocessor is about to Lex tokens from the de...
Directive - Abstract class representing a parsed verify directive.
A directive for setting the module visibility of a macro.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
uint32_t Literal
Literals are represented as positive integers.
bool Sub(InterpState &S, CodePtr OpPC)
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
PPKeywordKind
Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line.
bool isReservedInAllContexts(ReservedIdentifierStatus Status)
Determine whether an identifier is reserved in all contexts.
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
MacroUse
Context in which macro name is used.
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
@ Result
The result type of a method or function.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
LLVM_READONLY bool isLowercase(unsigned char c)
Return true if this character is a lowercase ASCII letter: [a-z].
@ PIK_HashPragma
The pragma was introduced via #pragma.
This structure is used to record entries in our framework cache.
OptionalDirectoryEntryRef Directory
The directory entry which should be used for the cached framework.
Information about the conditional stack (#if directives) currently active.
bool FoundNonSkip
True if we have emitted tokens already, and now we're in an #else block or something.
SourceLocation IfLoc
Location where the conditional started.
bool WasSkipping
True if this was contained in a skipping directive, e.g., in a "\#if 0" block.
bool FoundElse
True if we've seen a #else in this block.