39#include "llvm/ADT/ArrayRef.h"
40#include "llvm/ADT/STLExtras.h"
41#include "llvm/ADT/ScopeExit.h"
42#include "llvm/ADT/SmallVector.h"
43#include "llvm/ADT/StringExtras.h"
44#include "llvm/ADT/StringRef.h"
45#include "llvm/ADT/StringSwitch.h"
46#include "llvm/Support/ErrorHandling.h"
47#include "llvm/Support/Path.h"
48#include "llvm/Support/SaveAndRestore.h"
63 static_assert(std::is_trivially_destructible_v<MacroInfo>,
"");
73Preprocessor::AllocateUndefMacroDirective(
SourceLocation UndefLoc) {
90 while (Tmp.
isNot(tok::eod)) {
91 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 llvm::binary_search(ReservedMacro, MacroName);
156 const StringRef MacroName) {
166 if (MacroName.starts_with(
"__STDC"))
169 if (MacroName ==
"__cplusplus")
172 if (MacroName.starts_with(
"__cpp"))
180 if (Lang.CPlusPlus &&
201 if (Lang.CPlusPlus11 && (
Text ==
"override" ||
Text ==
"final"))
226 if (::llvm::sys::path::begin(Include)->equals_insensitive(
"boost"))
231 static const size_t MaxStdHeaderNameLen = 18u;
232 if (Include.size() > MaxStdHeaderNameLen)
237 for (
char &Ch : LowerInclude) {
239 if (
static_cast<unsigned char>(Ch) > 0x7f)
242 if (Ch >=
'A' && Ch <=
'Z')
245 else if (::llvm::sys::path::is_separator(Ch))
250 return llvm::StringSwitch<bool>(LowerInclude)
252 .Cases(
"assert.h",
"complex.h",
"ctype.h",
"errno.h",
"fenv.h",
true)
253 .Cases(
"float.h",
"inttypes.h",
"iso646.h",
"limits.h",
"locale.h",
true)
254 .Cases(
"math.h",
"setjmp.h",
"signal.h",
"stdalign.h",
"stdarg.h",
true)
255 .Cases(
"stdatomic.h",
"stdbool.h",
"stdckdint.h",
"stdcountof.h",
true)
256 .Cases(
"stddef.h",
"stdint.h",
"stdio.h",
"stdlib.h",
"stdnoreturn.h",
true)
257 .Cases(
"string.h",
"tgmath.h",
"threads.h",
"time.h",
"uchar.h",
true)
258 .Cases(
"wchar.h",
"wctype.h",
true)
261 .Cases(
"cassert",
"ccomplex",
"cctype",
"cerrno",
"cfenv",
true)
262 .Cases(
"cfloat",
"cinttypes",
"ciso646",
"climits",
"clocale",
true)
263 .Cases(
"cmath",
"csetjmp",
"csignal",
"cstdalign",
"cstdarg",
true)
264 .Cases(
"cstdbool",
"cstddef",
"cstdint",
"cstdio",
"cstdlib",
true)
265 .Cases(
"cstring",
"ctgmath",
"ctime",
"cuchar",
"cwchar",
true)
266 .Case(
"cwctype",
true)
269 .Cases(
"algorithm",
"fstream",
"list",
"regex",
"thread",
true)
270 .Cases(
"array",
"functional",
"locale",
"scoped_allocator",
"tuple",
true)
271 .Cases(
"atomic",
"future",
"map",
"set",
"type_traits",
true)
272 .Cases(
"bitset",
"initializer_list",
"memory",
"shared_mutex",
"typeindex",
true)
273 .Cases(
"chrono",
"iomanip",
"mutex",
"sstream",
"typeinfo",
true)
274 .Cases(
"codecvt",
"ios",
"new",
"stack",
"unordered_map",
true)
275 .Cases(
"complex",
"iosfwd",
"numeric",
"stdexcept",
"unordered_set",
true)
276 .Cases(
"condition_variable",
"iostream",
"ostream",
"streambuf",
"utility",
true)
277 .Cases(
"deque",
"istream",
"queue",
"string",
"valarray",
true)
278 .Cases(
"exception",
"iterator",
"random",
"strstream",
"vector",
true)
279 .Cases(
"forward_list",
"limits",
"ratio",
"system_error",
true)
282 .Cases(
"aio.h",
"arpa/inet.h",
"cpio.h",
"dirent.h",
"dlfcn.h",
true)
283 .Cases(
"fcntl.h",
"fmtmsg.h",
"fnmatch.h",
"ftw.h",
"glob.h",
true)
284 .Cases(
"grp.h",
"iconv.h",
"langinfo.h",
"libgen.h",
"monetary.h",
true)
285 .Cases(
"mqueue.h",
"ndbm.h",
"net/if.h",
"netdb.h",
"netinet/in.h",
true)
286 .Cases(
"netinet/tcp.h",
"nl_types.h",
"poll.h",
"pthread.h",
"pwd.h",
true)
287 .Cases(
"regex.h",
"sched.h",
"search.h",
"semaphore.h",
"spawn.h",
true)
288 .Cases(
"strings.h",
"stropts.h",
"sys/ipc.h",
"sys/mman.h",
"sys/msg.h",
true)
289 .Cases(
"sys/resource.h",
"sys/select.h",
"sys/sem.h",
"sys/shm.h",
"sys/socket.h",
true)
290 .Cases(
"sys/stat.h",
"sys/statvfs.h",
"sys/time.h",
"sys/times.h",
"sys/types.h",
true)
291 .Cases(
"sys/uio.h",
"sys/un.h",
"sys/utsname.h",
"sys/wait.h",
"syslog.h",
true)
292 .Cases(
"tar.h",
"termios.h",
"trace.h",
"ulimit.h",
true)
293 .Cases(
"unistd.h",
"utime.h",
"utmpx.h",
"wordexp.h",
true)
305static std::optional<StringRef>
309 for (StringRef
C : Candidates) {
310 if (LHS.equals_insensitive(
C)) {
318 size_t Length = LHS.size();
319 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;
321 std::optional<std::pair<StringRef, size_t>> SimilarStr;
322 for (StringRef
C : Candidates) {
323 size_t CurDist = LHS.edit_distance(
C,
true);
324 if (CurDist <= MaxDist) {
327 SimilarStr = {
C, CurDist};
328 }
else if (CurDist < SimilarStr->second) {
330 SimilarStr = {
C, CurDist};
336 return SimilarStr->first;
345 if (MacroNameTok.
is(tok::eod))
346 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
350 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
356 ? diag::ext_pp_operator_used_as_macro_name
357 : diag::err_pp_operator_used_as_macro_name)
358 << II << MacroNameTok.
getKind();
365 return Diag(MacroNameTok, diag::err_defined_macro_name);
394 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
396 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_attribute_id)
413void Preprocessor::ReadMacroName(
Token &MacroNameTok,
MacroUse isDefineUndef,
418 if (MacroNameTok.
is(tok::code_completion)) {
430 if (MacroNameTok.
isNot(tok::eod)) {
431 MacroNameTok.
setKind(tok::eod);
455 while (Tmp.
is(tok::comment))
458 if (Tmp.
is(tok::eod))
466 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
469 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
473void Preprocessor::SuggestTypoedDirective(
const Token &Tok,
479 std::vector<StringRef> Candidates = {
480 "if",
"ifdef",
"ifndef",
"elif",
"else",
"endif"
482 if (LangOpts.C23 || LangOpts.CPlusPlus23)
483 Candidates.insert(Candidates.end(), {
"elifdef",
"elifndef"});
491 StringRef SuggValue = *Sugg;
494 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;
506void Preprocessor::SkipExcludedConditionalBlock(
SourceLocation HashTokenLoc,
508 bool FoundNonSkipPortion,
519 assert(!SkippingExcludedConditionalBlock &&
520 "calling SkipExcludedConditionalBlock recursively");
524 assert(!CurTokenLexer &&
"Conditional PP block cannot appear in a macro!");
525 assert(CurPPLexer &&
"Conditional PP block must be in a file!");
526 assert(CurLexer &&
"Conditional PP block but no current lexer set!");
528 if (PreambleConditionalStack.reachedEOFWhileSkipping())
529 PreambleConditionalStack.clearSkipInfo();
532 FoundNonSkipPortion, FoundElse);
542 struct SkippingRangeStateTy {
545 const char *BeginPtr =
nullptr;
546 unsigned *SkipRangePtr =
nullptr;
550 void beginLexPass() {
556 BeginPtr = PP.CurLexer->getBufferLocation();
557 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
559 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
564 void endLexPass(
const char *Hashptr) {
567 assert(PP.CurLexer->isDependencyDirectivesLexer());
572 if (!*SkipRangePtr) {
573 *SkipRangePtr = Hashptr - BeginPtr;
575 assert(*SkipRangePtr ==
unsigned(Hashptr - BeginPtr));
577 SkipRangePtr =
nullptr;
579 } SkippingRangeState(*
this);
582 if (CurLexer->isDependencyDirectivesLexer()) {
583 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
585 SkippingRangeState.beginLexPass();
589 if (Tok.
is(tok::code_completion)) {
597 if (Tok.
is(tok::eof)) {
601 if (PreambleConditionalStack.isRecording())
602 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,
615 if (Tok.
is(tok::eof))
622 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
624 assert(Tok.
is(tok::hash));
625 const char *Hashptr = CurLexer->getBufferLocation() - Tok.
getLength();
626 assert(CurLexer->getSourceLocation(Hashptr) == Tok.
getLocation());
633 if (Tok.
isNot(tok::raw_identifier)) {
636 if (CurLexer) CurLexer->resetExtendedTokenMode();
647 char FirstChar = RI[0];
648 if (FirstChar >=
'a' && FirstChar <=
'z' &&
649 FirstChar !=
'i' && FirstChar !=
'e') {
652 if (CurLexer) CurLexer->resetExtendedTokenMode();
659 char DirectiveBuf[20];
665 size_t IdLen = DirectiveStr.size();
669 if (CurLexer) CurLexer->resetExtendedTokenMode();
672 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
673 Directive = StringRef(DirectiveBuf, IdLen);
697 assert(!InCond &&
"Can't be skipping if not in a conditional!");
701 SkippingRangeState.endLexPass(Hashptr);
713 }
else if (Sub ==
"lse") {
720 SkippingRangeState.endLexPass(Hashptr);
724 Diag(Tok, diag::pp_err_else_after_else);
744 }
else if (Sub ==
"lif") {
748 SkippingRangeState.endLexPass(Hashptr);
765 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
768 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
772 const bool CondValue = DER.Conditional;
786 }
else if (Sub ==
"lifdef" ||
788 bool IsElifDef =
Sub ==
"lifdef";
790 Token DirectiveToken = Tok;
793 SkippingRangeState.endLexPass(Hashptr);
798 if (LangOpts.CPlusPlus)
799 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
800 : diag::ext_cxx23_pp_directive;
802 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
803 : diag::ext_c23_pp_directive;
808 Diag(Tok, diag::pp_err_elif_after_else)
822 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
825 ReadMacroName(MacroNameTok);
830 if (MacroNameTok.
is(tok::eod)) {
846 Callbacks->Elifdef(DirectiveToken.
getLocation(), MacroNameTok,
849 Callbacks->Elifndef(DirectiveToken.
getLocation(), MacroNameTok,
854 if (
static_cast<bool>(MI) == IsElifDef) {
868 if (CurLexer) CurLexer->resetExtendedTokenMode();
879 Callbacks->SourceRangeSkipped(
911 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
919 auto ID =
SM.getFileID(
SM.getExpansionLoc(
Loc));
920 auto FE =
SM.getFileEntryRefForID(ID);
929 bool InPrivateHeader =
false;
931 if (!Header.isAccessibleFrom(IncM)) {
936 InPrivateHeader =
true;
972 Loc =
SM.getIncludeLoc(ID);
984 bool *IsFrameworkFound,
bool SkipCache,
bool OpenFile,
bool CacheFailures) {
989 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
994 bool BuildSystemModule =
false;
995 if (!FromDir && !FromFile) {
1018 Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));
1023 Includers.push_back(std::make_pair(*FileEnt, *CWD));
1026 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1032 if (LangOpts.MSVCCompat && !isAngled) {
1033 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1034 if (IsFileLexer(ISEntry))
1036 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1041 CurDir = CurDirLookup;
1049 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
1050 Includers, SearchPath, RelativePath, RequestingModule,
1051 SuggestedModule,
nullptr,
1052 nullptr, SkipCache)) {
1054 TmpFromDir = TmpCurDir;
1056 if (&FE->getFileEntry() == FromFile) {
1058 FromDir = TmpFromDir;
1067 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,
1068 RelativePath, RequestingModule, SuggestedModule, IsMapped,
1069 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);
1077 if (IsFileLexer()) {
1080 Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,
1087 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1088 if (IsFileLexer(ISEntry)) {
1089 if ((CurFileEnt = ISEntry.ThePPLexer->
getFileEntry())) {
1091 Filename, *CurFileEnt, SearchPath, RelativePath,
1092 RequestingModule, SuggestedModule)) {
1100 return std::nullopt;
1107 if (llvm::sys::path::is_absolute(
Filename)) {
1111 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1115 StringRef StartingFrom, StringRef
FileName,
1116 bool RemoveInitialFileComponentFromLookupPath) {
1117 llvm::sys::path::native(StartingFrom, LookupPath);
1118 if (RemoveInitialFileComponentFromLookupPath)
1119 llvm::sys::path::remove_filename(LookupPath);
1120 if (!LookupPath.empty() &&
1121 !llvm::sys::path::is_separator(LookupPath.back())) {
1122 LookupPath.push_back(llvm::sys::path::get_separator().front());
1131 if (LookupFromFile) {
1134 if (!FullFileDir.empty()) {
1135 SeparateComponents(LookupPath, FullFileDir,
Filename,
true);
1137 LookupPath, OpenFile,
true,
false);
1139 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1140 llvm::consumeError(ShouldBeEntry.takeError());
1147 if (MaybeWorkingDirEntry) {
1149 StringRef WorkingDir = WorkingDirEntry.
getName();
1150 if (!WorkingDir.empty()) {
1151 SeparateComponents(LookupPath, WorkingDir,
Filename,
false);
1153 LookupPath, OpenFile,
true,
false);
1155 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1156 llvm::consumeError(ShouldBeEntry.takeError());
1163 SeparateComponents(LookupPath, Entry,
Filename,
false);
1165 LookupPath, OpenFile,
true,
false);
1167 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1168 llvm::consumeError(ShouldBeEntry.takeError());
1170 return std::nullopt;
1180 : PP(pp), save(pp->DisableMacroExpansion) {
1181 if (pp->MacroExpansionInDirectivesOverride)
1182 pp->DisableMacroExpansion =
false;
1186 PP->DisableMacroExpansion = save;
1203 if (II->getPPKeywordID() == tok::pp_define) {
1204 return HandleDefineDirective(
Result,
1207 if (SkippingUntilPCHThroughHeader &&
1208 II->getPPKeywordID() == tok::pp_include) {
1209 return HandleIncludeDirective(HashLoc,
Result);
1211 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
1213 auto *II =
Result.getIdentifierInfo();
1214 if (II && II->getName() ==
"hdrstop")
1232 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
1234 bool ImmediatelyAfterTopLevelIfndef =
1262 switch (II->getPPKeywordID()) {
1263 case tok::pp_include:
1264 case tok::pp_import:
1265 case tok::pp_include_next:
1266 case tok::pp___include_macros:
1267 case tok::pp_pragma:
1269 Diag(
Result, diag::err_embedded_directive) << II->getName();
1270 Diag(*ArgMacro, diag::note_macro_expansion_here)
1285 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
1288 switch (
Result.getKind()) {
1295 case tok::code_completion:
1301 case tok::numeric_constant:
1308 return HandleDigitDirective(
Result);
1318 return HandleIfDirective(
Result, SavedHash, ReadAnyTokensBeforeDirective);
1320 return HandleIfdefDirective(
Result, SavedHash,
false,
1322 case tok::pp_ifndef:
1323 return HandleIfdefDirective(
Result, SavedHash,
true,
1324 ReadAnyTokensBeforeDirective);
1326 case tok::pp_elifdef:
1327 case tok::pp_elifndef:
1331 return HandleElseDirective(
Result, SavedHash);
1333 return HandleEndifDirective(
Result);
1336 case tok::pp_include:
1339 case tok::pp___include_macros:
1344 case tok::pp_define:
1345 return HandleDefineDirective(
Result, ImmediatelyAfterTopLevelIfndef);
1347 return HandleUndefDirective();
1351 return HandleLineDirective();
1355 return HandleUserDiagnosticDirective(
Result,
false);
1358 case tok::pp_pragma:
1362 case tok::pp_import:
1364 case tok::pp_include_next:
1367 case tok::pp_warning:
1368 if (LangOpts.CPlusPlus)
1370 ? diag::warn_cxx23_compat_warning_directive
1371 : diag::ext_pp_warning_directive)
1374 Diag(
Result, LangOpts.C23 ? diag::warn_c23_compat_warning_directive
1375 : diag::ext_pp_warning_directive)
1378 return HandleUserDiagnosticDirective(
Result,
true);
1380 return HandleIdentSCCSDirective(
Result);
1382 return HandleIdentSCCSDirective(
Result);
1388 case tok::pp_assert:
1391 case tok::pp_unassert:
1395 case tok::pp___public_macro:
1397 return HandleMacroPublicDirective(
Result);
1400 case tok::pp___private_macro:
1402 return HandleMacroPrivateDirective();
1413 auto Toks = std::make_unique<Token[]>(2);
1415 Toks[0] = SavedHash;
1420 if (
Result.is(tok::hashhash))
1421 Toks[1].setKind(tok::unknown);
1426 EnterTokenStream(std::move(Toks), 2,
false,
false);
1432 Diag(
Result, diag::err_pp_invalid_directive) << 0;
1444 bool IsGNULineDirective=
false) {
1445 if (DigitTok.
isNot(tok::numeric_constant)) {
1446 PP.
Diag(DigitTok, DiagID);
1448 if (DigitTok.
isNot(tok::eod))
1454 IntegerBuffer.resize(DigitTok.
getLength());
1455 const char *DigitTokBegin = &IntegerBuffer[0];
1465 for (
unsigned i = 0; i != ActualLength; ++i) {
1468 if (DigitTokBegin[i] ==
'\'')
1471 if (!
isDigit(DigitTokBegin[i])) {
1473 diag::err_pp_line_digit_sequence) << IsGNULineDirective;
1478 unsigned NextVal = Val*10+(DigitTokBegin[i]-
'0');
1479 if (NextVal < Val) {
1480 PP.
Diag(DigitTok, DiagID);
1487 if (DigitTokBegin[0] ==
'0' && Val)
1489 << IsGNULineDirective;
1501void Preprocessor::HandleLineDirective() {
1509 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*
this))
1513 Diag(DigitTok, diag::ext_pp_line_zero);
1517 unsigned LineLimit = 32768U;
1518 if (LangOpts.C99 || LangOpts.CPlusPlus11)
1519 LineLimit = 2147483648U;
1520 if (LineNo >= LineLimit)
1521 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
1522 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)
1523 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);
1525 int FilenameID = -1;
1531 if (StrTok.
is(tok::eod))
1533 else if (StrTok.
isNot(tok::string_literal)) {
1534 Diag(StrTok, diag::err_pp_line_invalid_filename);
1538 Diag(StrTok, diag::err_invalid_string_udl);
1544 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1550 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1585 if (FlagTok.
is(tok::eod))
return false;
1586 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1593 if (FlagTok.
is(tok::eod))
return false;
1594 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1596 }
else if (FlagVal == 2) {
1612 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {
1613 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
1619 if (FlagTok.
is(tok::eod))
return false;
1620 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1626 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1634 if (FlagTok.
is(tok::eod))
return false;
1635 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1640 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1648 if (FlagTok.
is(tok::eod))
return false;
1651 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1663void Preprocessor::HandleDigitDirective(
Token &DigitTok) {
1667 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
1674 bool IsFileEntry =
false, IsFileExit =
false;
1675 int FilenameID = -1;
1680 if (StrTok.
is(tok::eod)) {
1681 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1684 }
else if (StrTok.
isNot(tok::string_literal)) {
1685 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1689 Diag(StrTok, diag::err_invalid_string_udl);
1695 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1701 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1710 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1714 if (!(IsFileExit &&
Literal.GetString().empty()))
1720 IsFileExit, FileKind);
1729 else if (IsFileExit)
1738void Preprocessor::HandleUserDiagnosticDirective(
Token &Tok,
1746 CurLexer->ReadToEndOfLine(&Message);
1750 StringRef Msg = Message.str().ltrim(
' ');
1753 Diag(Tok, diag::pp_hash_warning) << Msg;
1755 Diag(Tok, diag::err_pp_hash_error) << Msg;
1760void Preprocessor::HandleIdentSCCSDirective(
Token &Tok) {
1762 Diag(Tok, diag::ext_pp_ident_directive);
1769 if (StrTok.
isNot(tok::string_literal) &&
1770 StrTok.
isNot(tok::wide_string_literal)) {
1771 Diag(StrTok, diag::err_pp_malformed_ident);
1772 if (StrTok.
isNot(tok::eod))
1778 Diag(StrTok, diag::err_invalid_string_udl);
1795void Preprocessor::HandleMacroPublicDirective(
Token &Tok) {
1797 ReadMacroName(MacroNameTok,
MU_Undef);
1800 if (MacroNameTok.
is(tok::eod))
1812 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1822void Preprocessor::HandleMacroPrivateDirective() {
1824 ReadMacroName(MacroNameTok,
MU_Undef);
1827 if (MacroNameTok.
is(tok::eod))
1839 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1859 StringRef &Buffer) {
1861 assert(!Buffer.empty() &&
"Can't have tokens with empty spellings!");
1873 if (Buffer[0] ==
'<') {
1874 if (Buffer.back() !=
'>') {
1875 Diag(
Loc, diag::err_pp_expects_filename);
1876 Buffer = StringRef();
1880 }
else if (Buffer[0] ==
'"') {
1881 if (Buffer.back() !=
'"') {
1882 Diag(
Loc, diag::err_pp_expects_filename);
1883 Buffer = StringRef();
1888 Diag(
Loc, diag::err_pp_expects_filename);
1889 Buffer = StringRef();
1894 if (Buffer.size() <= 2) {
1895 Diag(
Loc, diag::err_pp_empty_filename);
1896 Buffer = StringRef();
1901 Buffer = Buffer.substr(1, Buffer.size()-2);
1908 void *AnnotationVal) {
1911 auto Tok = std::make_unique<Token[]>(1);
1917 EnterTokenStream(std::move(Tok), 1,
true,
false);
1927 for (
size_t I = 0, N =
Path.size(); I != N; ++I) {
1930 PathString +=
Path[I].getIdentifierInfo()->getName();
1933 int IncludeKind = 0;
1935 case tok::pp_include:
1939 case tok::pp_import:
1943 case tok::pp_include_next:
1947 case tok::pp___include_macros:
1952 llvm_unreachable(
"unknown include directive kind");
1955 PP.
Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
1956 << IncludeKind << PathString;
1963 StringRef RealPathName,
1964 llvm::sys::path::Style Separator) {
1965 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
1966 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
1968 bool SuggestReplacement =
false;
1970 auto IsSep = [Separator](StringRef Component) {
1971 return Component.size() == 1 &&
1972 llvm::sys::path::is_separator(Component[0], Separator);
1977 for (
auto &Component : llvm::reverse(Components)) {
1978 if (
"." == Component) {
1979 }
else if (
".." == Component) {
1983 }
else if (RealPathComponentIter != RealPathComponentEnd) {
1984 if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&
1985 Component != *RealPathComponentIter) {
1989 SuggestReplacement =
1990 RealPathComponentIter->equals_insensitive(Component);
1991 if (!SuggestReplacement)
1993 Component = *RealPathComponentIter;
1995 ++RealPathComponentIter;
1998 return SuggestReplacement;
2007 Module *ShadowingModule =
nullptr;
2015 }
else if (ShadowingModule) {
2018 diag::note_previous_definition);
2029std::pair<ConstSearchDirIterator, const FileEntry *>
2030Preprocessor::getIncludeNextStart(
const Token &IncludeNextTok)
const {
2035 const FileEntry *LookupFromFile =
nullptr;
2043 Diag(IncludeNextTok, diag::pp_include_next_in_primary);
2044 }
else if (CurLexerSubmodule) {
2047 assert(CurPPLexer &&
"#include_next directive in macro?");
2049 LookupFromFile = *FE;
2051 }
else if (!Lookup) {
2056 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
2062 return {Lookup, LookupFromFile};
2078 if (FilenameTok.
isNot(tok::header_name)) {
2089 if (FilenameTok.
isNot(tok::eod))
2101 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
2102 EndLoc, LookupFrom, LookupFromFile);
2103 switch (Action.Kind) {
2104 case ImportAction::None:
2105 case ImportAction::SkippedModuleImport:
2107 case ImportAction::ModuleBegin:
2109 tok::annot_module_begin, Action.ModuleForHeader);
2111 case ImportAction::HeaderUnitImport:
2113 Action.ModuleForHeader);
2115 case ImportAction::ModuleImport:
2117 tok::annot_module_include, Action.ModuleForHeader);
2119 case ImportAction::Failure:
2121 "This should be an early exit only to a fatal error");
2124 CurLexer->cutOffLexing();
2132 const Token &FilenameTok,
bool &IsFrameworkFound,
bool IsImportDecl,
2134 const FileEntry *LookupFromFile, StringRef &LookupFilename,
2138 if (LangOpts.AsmPreprocessor)
2142 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
2143 bool RequestingModuleIsModuleInterface =
2147 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
2152 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,
2153 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2154 &SuggestedModule, &IsMapped, &IsFrameworkFound);
2156 DiagnoseHeaderInclusion(*
File);
2161 if (Callbacks && Callbacks->FileNotFound(
Filename))
2162 return std::nullopt;
2164 if (SuppressIncludeNotFoundError)
2165 return std::nullopt;
2172 FilenameLoc, LookupFilename,
false, LookupFrom, LookupFromFile, CurDir,
2173 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2174 &SuggestedModule, &IsMapped,
2177 DiagnoseHeaderInclusion(*
File);
2178 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
2188 StringRef OriginalFilename =
Filename;
2189 if (LangOpts.SpellChecking) {
2192 auto CorrectTypoFilename = [](llvm::StringRef
Filename) {
2199 StringRef TypoCorrectionName = CorrectTypoFilename(
Filename);
2200 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);
2203 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,
2204 LookupFromFile, CurDir, Callbacks ? &SearchPath :
nullptr,
2205 Callbacks ? &RelativePath :
nullptr, &SuggestedModule, &IsMapped,
2208 DiagnoseHeaderInclusion(*
File);
2211 FilenameRange,
"<" + TypoCorrectionName.str() +
">")
2213 FilenameRange,
"\"" + TypoCorrectionName.str() +
"\"");
2214 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
2215 << OriginalFilename << TypoCorrectionName << Hint;
2219 LookupFilename = TypoCorrectionLookupName;
2225 assert(!
File &&
"expected missing file");
2226 Diag(FilenameTok, diag::err_pp_file_not_found)
2227 << OriginalFilename << FilenameRange;
2228 if (IsFrameworkFound) {
2229 size_t SlashPos = OriginalFilename.find(
'/');
2230 assert(SlashPos != StringRef::npos &&
2231 "Include with framework name should have '/' in the filename");
2232 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
2235 assert(CacheEntry.
Directory &&
"Found framework should be in cache");
2236 Diag(FilenameTok, diag::note_pp_framework_without_header)
2237 << OriginalFilename.substr(SlashPos + 1) << FrameworkName
2241 return std::nullopt;
2256Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
2266 StringRef OriginalFilename =
Filename;
2273 return {ImportAction::None};
2275 bool IsImportDecl = HashLoc.
isInvalid();
2280 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
2281 Diag(PragmaARCCFCodeAuditedInfo.
getLoc(), diag::note_pragma_entered_here);
2288 if (PragmaAssumeNonNullLoc.
isValid()) {
2289 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
2290 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
2301 if (!NewName.empty())
2306 bool IsMapped =
false;
2307 bool IsFrameworkFound =
false;
2315 StringRef LookupFilename =
Filename;
2320 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;
2321 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {
2323 llvm::sys::path::native(NormalizedPath);
2324 LookupFilename = NormalizedPath;
2325 BackslashStyle = llvm::sys::path::Style::windows;
2329 &CurDir,
Filename, FilenameLoc, FilenameRange, FilenameTok,
2330 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
2331 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
2335 SkippingUntilPCHThroughHeader =
false;
2336 return {ImportAction::None};
2354 enum { Enter,
Import,
Skip, IncludeLimitReached } Action = Enter;
2357 Action = IncludeLimitReached;
2362 if (Action == Enter && HasReachedMaxIncludeDepth &&
File &&
2364 Action = IncludeLimitReached;
2371 bool MaybeTranslateInclude = Action == Enter &&
File && ModuleToImport &&
2375 bool UsableHeaderUnit =
false;
2376 if (
getLangOpts().CPlusPlusModules && ModuleToImport &&
2378 if (TrackGMFState.inGMF() || IsImportDecl)
2379 UsableHeaderUnit =
true;
2380 else if (!IsImportDecl) {
2382 ModuleToImport =
nullptr;
2386 bool UsableClangHeaderModule =
2393 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {
2401 diag::note_implicit_top_level_module_import_here)
2403 return {ImportAction::None};
2410 for (
Module *Mod = ModuleToImport; Mod; Mod = Mod->
Parent)
2413 std::reverse(
Path.begin(),
Path.end());
2426 assert((Imported ==
nullptr || Imported == ModuleToImport) &&
2427 "the imported module is different than the suggested one");
2433 static_cast<Module *
>(Imported)->getTopLevelModule());
2438 ModuleToImport =
nullptr;
2447 assert(CurLexer &&
"#include but no current lexer set!");
2449 CurLexer->FormTokenWithChars(
Result, CurLexer->BufferEnd, tok::eof);
2450 CurLexer->cutOffLexing();
2452 return {ImportAction::None};
2473 bool IsFirstIncludeOfFile =
false;
2477 if (Action == Enter &&
File &&
2480 IsFirstIncludeOfFile)) {
2491 if (UsableHeaderUnit && !
getLangOpts().CompilingPCH)
2492 Action = TrackGMFState.inGMF() ?
Import :
Skip;
2494 Action = (ModuleToImport && !
getLangOpts().CompilingPCH) ? Import :
Skip;
2502 if (Action == Enter &&
File && PreambleConditionalStack.isRecording() &&
2505 diag::err_pp_including_mainfile_in_preamble);
2506 return {ImportAction::None};
2509 if (Callbacks && !IsImportDecl) {
2512 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,
2513 FilenameRange,
File, SearchPath, RelativePath,
2514 SuggestedModule.
getModule(), Action == Import,
2517 Callbacks->FileSkipped(*
File, FilenameTok, FileCharacter);
2521 return {ImportAction::None};
2525 if (IsImportDecl && !ModuleToImport) {
2526 Diag(FilenameTok, diag::err_header_import_not_header_unit)
2527 << OriginalFilename <<
File->getName();
2528 return {ImportAction::None};
2533 const bool CheckIncludePathPortability =
2534 !IsMapped && !
File->getFileEntry().tryGetRealPathName().empty();
2536 if (CheckIncludePathPortability) {
2537 StringRef Name = LookupFilename;
2538 StringRef NameWithoriginalSlashes =
Filename;
2542 bool NameWasUNC = Name.consume_front(
"\\\\?\\");
2543 NameWithoriginalSlashes.consume_front(
"\\\\?\\");
2545 StringRef RealPathName =
File->getFileEntry().tryGetRealPathName();
2547 llvm::sys::path::end(Name));
2560 if (llvm::sys::path::is_absolute(Name) &&
2561 llvm::sys::path::is_absolute(RealPathName) &&
2564 assert(Components.size() >= 3 &&
"should have drive, backslash, name");
2565 assert(Components[0].size() == 2 &&
"should start with drive");
2566 assert(Components[0][1] ==
':' &&
"should have colon");
2567 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();
2568 RealPathName = FixedDriveRealPath;
2574 Path.reserve(Name.size()+2);
2575 Path.push_back(isAngled ?
'<' :
'"');
2577 const auto IsSep = [BackslashStyle](
char c) {
2578 return llvm::sys::path::is_separator(
c, BackslashStyle);
2581 for (
auto Component : Components) {
2593 if (!(Component.size() == 1 && IsSep(Component[0])))
2594 Path.append(Component);
2595 else if (
Path.size() != 1)
2599 if (
Path.size() > NameWithoriginalSlashes.size()) {
2600 Path.push_back(isAngled ?
'>' :
'"');
2603 assert(IsSep(NameWithoriginalSlashes[
Path.size()-1]));
2605 Path.push_back(NameWithoriginalSlashes[
Path.size()-1]);
2606 while (
Path.size() <= NameWithoriginalSlashes.size() &&
2607 IsSep(NameWithoriginalSlashes[
Path.size()-1]));
2613 Path = (
Path.substr(0, 1) +
"\\\\?\\" +
Path.substr(1)).str();
2620 ? diag::pp_nonportable_path
2621 : diag::pp_nonportable_system_path;
2622 Diag(FilenameTok, DiagId) <<
Path <<
2631 return {ImportAction::SkippedModuleImport, ModuleToImport};
2632 return {ImportAction::None};
2634 case IncludeLimitReached:
2637 return {ImportAction::None};
2641 assert(ModuleToImport &&
"no module to import");
2646 tok::pp___include_macros)
2647 return {ImportAction::None};
2649 return {ImportAction::ModuleImport, ModuleToImport};
2657 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
2658 Diag(FilenameTok, diag::err_pp_include_too_deep);
2659 HasReachedMaxIncludeDepth =
true;
2660 return {ImportAction::None};
2664 Diag(FilenameTok, diag::warn_pp_include_angled_in_module_purview)
2676 return ImportAction::Failure;
2681 IsFirstIncludeOfFile))
2682 return {ImportAction::None};
2686 if (ModuleToImport && !ModuleToImport->
isHeaderUnit()) {
2691 diag::err_module_build_shadowed_submodule)
2694 diag::note_previous_definition);
2695 return {ImportAction::None};
2707 return {ImportAction::None};
2709 assert(!CurLexerSubmodule &&
"should not have marked this as a module yet");
2710 CurLexerSubmodule = ModuleToImport;
2720 return {ImportAction::ModuleBegin, ModuleToImport};
2723 assert(!IsImportDecl &&
"failed to diagnose missing module for import decl");
2724 return {ImportAction::None};
2729void Preprocessor::HandleIncludeNextDirective(
SourceLocation HashLoc,
2730 Token &IncludeNextTok) {
2731 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
2735 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);
2737 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
2742void Preprocessor::HandleMicrosoftImportDirective(
Token &Tok) {
2748 Diag(Tok, diag::err_pp_import_directive_ms );
2759 if (!LangOpts.ObjC) {
2760 if (LangOpts.MSVCCompat)
2761 return HandleMicrosoftImportDirective(ImportTok);
2762 Diag(ImportTok, diag::ext_pp_import_directive);
2764 return HandleIncludeDirective(HashLoc, ImportTok);
2771void Preprocessor::HandleIncludeMacrosDirective(
SourceLocation HashLoc,
2772 Token &IncludeMacrosTok) {
2778 diag::pp_include_macros_out_of_predefines);
2785 HandleIncludeDirective(HashLoc, IncludeMacrosTok);
2790 assert(TmpTok.
isNot(tok::eof) &&
"Didn't find end of -imacros!");
2791 }
while (TmpTok.
isNot(tok::hashhash));
2802bool Preprocessor::ReadMacroParameterList(
MacroInfo *MI,
Token &Tok) {
2813 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
2817 Diag(Tok, LangOpts.CPlusPlus11 ?
2818 diag::warn_cxx98_compat_variadic_macro :
2819 diag::ext_variadic_macro);
2822 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
2823 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
2828 if (Tok.
isNot(tok::r_paren)) {
2829 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2838 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2846 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
2852 if (llvm::is_contained(Parameters, II)) {
2853 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
2865 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
2874 Diag(Tok, diag::ext_named_variadic_macro);
2878 if (Tok.
isNot(tok::r_paren)) {
2879 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2909 StringRef ValueText = II->
getName();
2910 StringRef TrimmedValue = ValueText;
2911 if (!ValueText.starts_with(
"__")) {
2912 if (ValueText.starts_with(
"_"))
2913 TrimmedValue = TrimmedValue.drop_front(1);
2917 TrimmedValue = TrimmedValue.drop_front(2);
2918 if (TrimmedValue.ends_with(
"__"))
2919 TrimmedValue = TrimmedValue.drop_back(2);
2921 return TrimmedValue == MacroText;
2928 return MacroName.
isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
2941MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
2942 const Token &MacroNameTok,
const bool ImmediatelyAfterHeaderGuard) {
2944 Token LastTok = MacroNameTok;
2952 auto _ = llvm::make_scope_exit([&]() {
2954 if (CurLexer->ParsingPreprocessorDirective)
2965 if (Tok.
is(tok::eod)) {
2966 if (ImmediatelyAfterHeaderGuard) {
2976 }
else if (Tok.
is(tok::l_paren)) {
2979 if (ReadMacroParameterList(MI, LastTok))
2993 }
else if (LangOpts.C99 || LangOpts.CPlusPlus11) {
2996 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
3005 if (Tok.
is(tok::at))
3007 else if (Tok.
is(tok::unknown)) {
3014 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
3016 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
3019 if (!Tok.
is(tok::eod))
3027 while (Tok.
isNot(tok::eod)) {
3029 Tokens.push_back(Tok);
3040 while (Tok.
isNot(tok::eod)) {
3043 if (!Tok.
isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
3044 Tokens.push_back(Tok);
3046 if (VAOCtx.isVAOptToken(Tok)) {
3048 if (VAOCtx.isInVAOpt()) {
3049 Diag(Tok, diag::err_pp_vaopt_nested_use);
3054 if (Tok.
isNot(tok::l_paren)) {
3055 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
3058 Tokens.push_back(Tok);
3059 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.
getLocation());
3061 if (Tok.
is(tok::hashhash)) {
3062 Diag(Tok, diag::err_vaopt_paste_at_start);
3066 }
else if (VAOCtx.isInVAOpt()) {
3067 if (Tok.
is(tok::r_paren)) {
3068 if (VAOCtx.sawClosingParen()) {
3069 assert(Tokens.size() >= 3 &&
3070 "Must have seen at least __VA_OPT__( "
3071 "and a subsequent tok::r_paren");
3072 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {
3073 Diag(Tok, diag::err_vaopt_paste_at_end);
3077 }
else if (Tok.
is(tok::l_paren)) {
3091 Tokens.push_back(Tok);
3098 if (Tok.
is(tok::hashhash)) {
3106 if (Tok.
is(tok::eod)) {
3107 Tokens.push_back(LastTok);
3112 Tokens[Tokens.size() - 1].is(tok::comma))
3116 Tokens.push_back(LastTok);
3125 if (!VAOCtx.isVAOptToken(Tok) &&
3134 LastTok.
setKind(tok::unknown);
3135 Tokens.push_back(LastTok);
3138 Diag(Tok, diag::err_pp_stringize_not_parameter)
3139 << LastTok.
is(tok::hashat);
3145 Tokens.push_back(LastTok);
3150 if (!VAOCtx.isVAOptToken(Tok)) {
3151 Tokens.push_back(Tok);
3158 if (VAOCtx.isInVAOpt()) {
3159 assert(Tok.
is(tok::eod) &&
"Must be at End Of preprocessing Directive");
3160 Diag(Tok, diag::err_pp_expected_after)
3161 << LastTok.
getKind() << tok::r_paren;
3162 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
3173 return II->
isStr(
"__strong") || II->
isStr(
"__weak") ||
3174 II->
isStr(
"__unsafe_unretained") || II->
isStr(
"__autoreleasing");
3179void Preprocessor::HandleDefineDirective(
3180 Token &DefineTok,
const bool ImmediatelyAfterHeaderGuard) {
3184 bool MacroShadowsKeyword;
3185 ReadMacroName(MacroNameTok,
MU_Define, &MacroShadowsKeyword);
3188 if (MacroNameTok.
is(tok::eod))
3195 emitFinalMacroWarning(MacroNameTok,
false);
3199 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
3201 MacroInfo *
const MI = ReadOptionalMacroParameterListAndBody(
3202 MacroNameTok, ImmediatelyAfterHeaderGuard);
3206 if (MacroShadowsKeyword &&
3208 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
3213 if (NumTokens != 0) {
3225 if (SkippingUntilPCHThroughHeader) {
3228 LangOpts.MicrosoftExt))
3232 if (!LangOpts.MicrosoftExt)
3243 emitFinalMacroWarning(MacroNameTok,
false);
3256 LangOpts.MicrosoftExt)) {
3275 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
3279 !MI->
isIdenticalTo(*OtherMI, *
this, LangOpts.MicrosoftExt)) {
3297 !MacroExpansionInDirectivesOverride &&
3306 Callbacks->MacroDefined(MacroNameTok, MD);
3311void Preprocessor::HandleUndefDirective() {
3315 ReadMacroName(MacroNameTok,
MU_Undef);
3318 if (MacroNameTok.
is(tok::eod))
3330 emitFinalMacroWarning(MacroNameTok,
true);
3340 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
3345 Undef = AllocateUndefMacroDirective(MacroNameTok.
getLocation());
3351 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
3366void Preprocessor::HandleIfdefDirective(
Token &
Result,
3367 const Token &HashToken,
3369 bool ReadAnyTokensBeforeDirective) {
3374 ReadMacroName(MacroNameTok);
3377 if (MacroNameTok.
is(tok::eod)) {
3380 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3400 if (!ReadAnyTokensBeforeDirective && !MI) {
3401 assert(isIfndef &&
"#ifdef shouldn't reach here");
3413 Callbacks->Ifndef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3415 Callbacks->Ifdef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3428 }
else if (!MI == isIfndef || RetainExcludedCB) {
3435 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3444void Preprocessor::HandleIfDirective(
Token &IfToken,
3445 const Token &HashToken,
3446 bool ReadAnyTokensBeforeDirective) {
3451 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
3452 const bool ConditionalTrue = DER.Conditional;
3461 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
3482 }
else if (ConditionalTrue || RetainExcludedCB) {
3496void Preprocessor::HandleEndifDirective(
Token &EndifToken) {
3505 Diag(EndifToken, diag::err_pp_endif_without_if);
3514 "This code should only be reachable in the non-skipping case!");
3522void Preprocessor::HandleElseDirective(
Token &
Result,
const Token &HashToken) {
3558 true,
Result.getLocation());
3562void Preprocessor::HandleElifFamilyDirective(
Token &ElifToken,
3563 const Token &HashToken,
3575 if (LangOpts.CPlusPlus)
3576 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
3577 : diag::ext_cxx23_pp_directive;
3579 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
3580 : diag::ext_c23_pp_directive;
3581 Diag(ElifToken, DiagID) << DirKind;
3594 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
3604 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
3609 Callbacks->Elif(ElifToken.
getLocation(), ConditionRange,
3612 case tok::pp_elifdef:
3615 case tok::pp_elifndef:
3619 assert(
false &&
"unexpected directive kind");
3636 SkipExcludedConditionalBlock(
3641std::optional<LexEmbedParametersResult>
3644 tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod;
3646 auto DiagMismatchedBracesAndSkipToEOD =
3648 std::pair<tok::TokenKind, SourceLocation> Matches) {
3650 Diag(Matches.second, diag::note_matching) << Matches.first;
3651 if (CurTok.
isNot(tok::eod))
3656 if (CurTok.
isNot(Kind)) {
3657 Diag(CurTok, diag::err_expected) << Kind;
3658 if (CurTok.
isNot(tok::eod))
3675 auto LexPPParameterName = [&]() -> std::optional<std::string> {
3678 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3679 return std::nullopt;
3686 if (CurTok.
is(tok::coloncolon)) {
3689 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3690 return std::nullopt;
3696 return (llvm::Twine(Prefix->
getName()) +
"::" + Suffix->
getName()).str();
3698 return Prefix->
getName().str();
3705 auto NormalizeParameterName = [](StringRef Name) {
3706 if (Name.size() > 4 && Name.starts_with(
"__") && Name.ends_with(
"__"))
3707 return Name.substr(2, Name.size() - 4);
3711 auto LexParenthesizedIntegerExpr = [&]() -> std::optional<size_t> {
3714 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3715 return std::nullopt;
3720 bool EvaluatedDefined;
3721 DirectiveEvalResult LimitEvalResult = EvaluateDirectiveExpression(
3722 ParameterIfNDef, CurTok, EvaluatedDefined,
false);
3724 if (!LimitEvalResult.Value) {
3727 assert(CurTok.
is(tok::eod) &&
"expect to be at the end of directive");
3728 return std::nullopt;
3731 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3732 return std::nullopt;
3739 if (EvaluatedDefined) {
3740 Diag(CurTok, diag::err_defined_in_pp_embed);
3741 return std::nullopt;
3744 if (LimitEvalResult.Value) {
3745 const llvm::APSInt &
Result = *LimitEvalResult.Value;
3746 if (
Result.isNegative()) {
3747 Diag(CurTok, diag::err_requires_positive_value)
3749 return std::nullopt;
3751 return Result.getLimitedValue();
3753 return std::nullopt;
3759 return tok::r_paren;
3761 return tok::r_brace;
3763 return tok::r_square;
3765 llvm_unreachable(
"should not get here");
3769 auto LexParenthesizedBalancedTokenSoup =
3771 std::vector<std::pair<tok::TokenKind, SourceLocation>> BracketStack;
3774 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3778 bool WaitingForInnerCloseParen =
false;
3779 while (CurTok.
isNot(tok::eod) &&
3780 (WaitingForInnerCloseParen || CurTok.
isNot(tok::r_paren))) {
3785 WaitingForInnerCloseParen =
true;
3792 WaitingForInnerCloseParen =
false;
3795 case tok::r_square: {
3796 if (BracketStack.empty()) {
3797 ExpectOrDiagAndSkipToEOD(tok::r_paren);
3801 GetMatchingCloseBracket(BracketStack.back().first);
3802 if (CurTok.
getKind() != Matching) {
3803 DiagMismatchedBracesAndSkipToEOD(Matching, BracketStack.back());
3806 BracketStack.pop_back();
3809 Tokens.push_back(CurTok);
3814 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3822 while (!CurTok.
isOneOf(EndTokenKind, tok::eod)) {
3824 std::optional<std::string> ParamName = LexPPParameterName();
3826 return std::nullopt;
3827 StringRef
Parameter = NormalizeParameterName(*ParamName);
3834 if (
Result.MaybeLimitParam)
3837 std::optional<size_t> Limit = LexParenthesizedIntegerExpr();
3839 return std::nullopt;
3842 }
else if (
Parameter ==
"clang::offset") {
3843 if (
Result.MaybeOffsetParam)
3846 std::optional<size_t> Offset = LexParenthesizedIntegerExpr();
3848 return std::nullopt;
3852 if (
Result.MaybePrefixParam)
3856 if (!LexParenthesizedBalancedTokenSoup(Soup))
3857 return std::nullopt;
3859 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3861 if (
Result.MaybeSuffixParam)
3865 if (!LexParenthesizedBalancedTokenSoup(Soup))
3866 return std::nullopt;
3868 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3870 if (
Result.MaybeIfEmptyParam)
3874 if (!LexParenthesizedBalancedTokenSoup(Soup))
3875 return std::nullopt;
3877 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3879 ++
Result.UnrecognizedParams;
3883 if (CurTok.
is(tok::l_paren)) {
3885 if (!LexParenthesizedBalancedTokenSoup(Soup))
3886 return std::nullopt;
3889 Diag(ParamStartLoc, diag::err_pp_unknown_parameter) << 1 <<
Parameter;
3890 if (CurTok.
isNot(tok::eod))
3892 return std::nullopt;
3899void Preprocessor::HandleEmbedDirectiveImpl(
3901 StringRef BinaryContents, StringRef
FileName) {
3902 if (BinaryContents.empty()) {
3910 size_t TokCount = Toks.size();
3911 auto NewToks = std::make_unique<Token[]>(TokCount);
3912 llvm::copy(Toks, NewToks.get());
3913 EnterTokenStream(std::move(NewToks), TokCount,
true,
true);
3920 size_t TotalNumToks = 1 + NumPrefixToks + NumSuffixToks;
3922 auto Toks = std::make_unique<Token[]>(TotalNumToks);
3927 CurIdx += NumPrefixToks;
3931 Data->BinaryData = BinaryContents;
3934 Toks[CurIdx].startToken();
3935 Toks[CurIdx].setKind(tok::annot_embed);
3936 Toks[CurIdx].setAnnotationRange(HashLoc);
3937 Toks[CurIdx++].setAnnotationValue(
Data);
3942 CurIdx += NumSuffixToks;
3945 assert(CurIdx == TotalNumToks &&
"Calculated the incorrect number of tokens");
3946 EnterTokenStream(std::move(Toks), TotalNumToks,
true,
true);
3953 Diag(EmbedTok, diag::warn_compat_pp_embed_directive);
3955 Diag(EmbedTok, diag::ext_pp_embed_directive)
3956 << (LangOpts.CPlusPlus ? 1 : 0);
3963 if (FilenameTok.
isNot(tok::header_name)) {
3965 if (FilenameTok.
isNot(tok::eod))
3978 std::optional<LexEmbedParametersResult> Params =
3981 assert((Params || CurTok.
is(tok::eod)) &&
3982 "expected success or to be at the end of the directive");
3989 StringRef OriginalFilename =
Filename;
3997 if (!MaybeFileRef) {
3999 if (Callbacks && Callbacks->EmbedFileNotFound(OriginalFilename)) {
4002 Diag(FilenameTok, diag::err_pp_file_not_found) <<
Filename;
4007 Diag(FilenameTok, diag::err_pp_embed_device_file) <<
Filename;
4011 std::optional<llvm::MemoryBufferRef> MaybeFile =
4015 Diag(FilenameTok, diag::err_cannot_open_file)
4016 <<
Filename <<
"a buffer to the contents could not be created";
4019 StringRef BinaryContents = MaybeFile->getBuffer();
4024 if (Params->MaybeOffsetParam) {
4029 BinaryContents = BinaryContents.substr(Params->MaybeOffsetParam->Offset);
4032 if (Params->MaybeLimitParam) {
4036 BinaryContents = BinaryContents.substr(0, Params->MaybeLimitParam->Limit);
4040 Callbacks->EmbedDirective(HashLoc,
Filename, isAngled, MaybeFileRef,
4049 void *Mem = BP.Allocate(OriginalFilename.size(),
alignof(
char *));
4050 memcpy(Mem, OriginalFilename.data(), OriginalFilename.size());
4051 StringRef FilenameToGo =
4052 StringRef(
static_cast<char *
>(Mem), OriginalFilename.size());
4053 HandleEmbedDirectiveImpl(HashLoc, *Params, BinaryContents, FilenameToGo);
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 void diagnoseAutoModuleImport(Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok, ArrayRef< IdentifierLoc > Path, SourceLocation PathEnd)
Produce a diagnostic informing the user that a #include or similar was implicitly treated as a module...
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 bool trySimplifyPath(SmallVectorImpl< StringRef > &Components, StringRef RealPathName, llvm::sys::path::Style Separator)
static bool warnByDefaultOnWrongCase(StringRef Include)
MacroDiag
Enumerates possible cases of #define/#undef a reserved identifier.
@ MD_ReservedAttributeIdentifier
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 bool isReservedCXXAttributeName(Preprocessor &PP, IdentifierInfo *II)
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.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
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()
static AttrArgsInfo getCXX11AttrArgsInfo(const IdentifierInfo *Name)
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.
A reference to a DirectoryEntry that includes the name of the directory as it was accessed by the Fil...
StringRef getName() const
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
bool isDeviceFile() const
const FileEntry & getFileEntry() const
DirectoryEntryRef getDir() const
Cached information about one file (either on disk or in the virtual file system).
StringRef tryGetRealPathName() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
llvm::Expected< DirectoryEntryRef > getDirectoryRef(StringRef DirName, bool CacheFailure=true)
Lookup, cache, and verify the specified directory (real or virtual).
OptionalDirectoryEntryRef getOptionalDirectoryRef(StringRef DirName, bool CacheFailure=true)
Get a DirectoryEntryRef if it exists, without doing anything on error.
llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Lookup, cache, and verify the specified file (real or virtual).
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.
A simple pair of identifier info and location.
SourceLocation getLoc() const
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
OptionalDirectoryEntryRef 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.
bool isForBuilding(const LangOptions &LangOpts) const
Determine whether this module can be built in this compilation.
@ Hidden
All of the names in this module are hidden.
SourceLocation DefinitionLoc
The location of the module definition.
Module * Parent
The parent of this module.
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.
bool isAvailable() const
Determine whether this module is available for use within the current translation unit.
bool isHeaderUnit() const
Is this module a header unit.
Module * ShadowingModule
A module with the same name that shadows this module.
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this 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...
Preprocessor standard embed parameter "if_empty" if_empty( balanced-token-seq )
Preprocessor standard embed parameter "limit" limit( constant-expression )
Preprocessor extension embed parameter "clang::offset" clang::offset( constant-expression )
Preprocessor standard embed parameter "prefix" prefix( balanced-token-seq )
Preprocessor standard embed parameter "suffix" suffix( balanced-token-seq )
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...
OptionalFileEntryRef getFileEntry() const
getFileEntry - Return the FileEntry corresponding to this FileID.
PPConditionalInfo & peekConditionalLevel()
Return the top of the conditional stack.
virtual SourceLocation getSourceLocation()=0
Return the source location for the next observable location.
std::vector< std::string > EmbedEntries
User specified embed entries.
bool SingleFileParseMode
When enabled, preprocessor is in a mode for parsing a single file only.
bool RetainExcludedConditionalBlocks
When enabled, excluded conditional blocks retain in the main file.
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.
OptionalFileEntryRef LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, const FileEntry *LookupFromFile=nullptr)
Given a "Filename" or <Filename> reference, look up the indicated embed resource.
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 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...
void LexNonComment(Token &Result)
Lex a token.
SourceRange DiscardUntilEndOfDirective()
Read and discard all tokens remaining on the current line until the tok::eod token is found.
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)
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...
bool isNextPPTokenOneOf(Ts... Ks)
Check whether the next pp-token is one of the specificed token kind.
Module * getCurrentModule()
Retrieves the module that we're currently building, if any.
void makeModuleVisible(Module *M, SourceLocation Loc, bool IncludeExports=true)
bool hadModuleLoaderFatalFailure() const
const TargetInfo & getTargetInfo() const
FileManager & getFileManager() 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
void emitMacroExpansionWarnings(const Token &Identifier, bool IsIfnDef=false) const
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
std::optional< LexEmbedParametersResult > LexEmbedParameters(Token &Current, bool ForHasEmbed)
Lex the parameters for an #embed directive, returns nullopt on error.
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 isInPredefinedFile(SourceLocation Loc) const
Returns whether Loc is located in a built-in or command line source.
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.
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.
std::optional< llvm::MemoryBufferRef > getMemoryBufferForFileOrNone(FileEntryRef File)
Retrieve the memory buffer associated with the given file.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() 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 isOneOf(Ts... Ks) const
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
void setLocation(SourceLocation L)
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.
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.
Defines the clang::TargetInfo interface.
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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isReservedInAllContexts(ReservedIdentifierStatus Status)
Determine whether an identifier is reserved in all contexts.
int hasAttribute(AttributeCommonInfo::Syntax Syntax, llvm::StringRef ScopeName, llvm::StringRef AttrName, const TargetInfo &Target, const LangOptions &LangOpts, bool CheckPlugins)
Return the version number associated with the attribute if we recognize and implement the attribute s...
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].
@ Parameter
The parameter type of a method or function.
@ 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.
Helper class to shuttle information about #embed directives from the preprocessor to the parser throu...
This structure is used to record entries in our framework cache.
OptionalDirectoryEntryRef Directory
The directory entry which should be used for the cached framework.
std::optional< PPEmbedParameterIfEmpty > MaybeIfEmptyParam
size_t SuffixTokenCount() const
std::optional< PPEmbedParameterSuffix > MaybeSuffixParam
std::optional< PPEmbedParameterPrefix > MaybePrefixParam
size_t PrefixTokenCount() const
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.