38#include "llvm/ADT/ArrayRef.h"
39#include "llvm/ADT/STLExtras.h"
40#include "llvm/ADT/ScopeExit.h"
41#include "llvm/ADT/SmallString.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/AlignOf.h"
47#include "llvm/Support/ErrorHandling.h"
48#include "llvm/Support/Path.h"
49#include "llvm/Support/SaveAndRestore.h"
65 static_assert(std::is_trivially_destructible_v<MacroInfo>,
"");
75Preprocessor::AllocateUndefMacroDirective(
SourceLocation UndefLoc) {
92 while (Tmp.
isNot(tok::eod)) {
93 assert(Tmp.
isNot(tok::eof) &&
"EOF seen while discarding directive tokens");
121 static constexpr StringRef ReservedMacro[] = {
124 "_CRT_NONSTDC_NO_WARNINGS",
125 "_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES",
126 "_CRT_SECURE_NO_WARNINGS",
129 "_GLIBCXX_ASSERTIONS",
130 "_GLIBCXX_CONCEPT_CHECKS",
132 "_GLIBCXX_DEBUG_PEDANTIC",
134 "_GLIBCXX_PARALLEL_ASSERTIONS",
135 "_GLIBCXX_SANITIZE_VECTOR",
136 "_GLIBCXX_USE_CXX11_ABI",
137 "_GLIBCXX_USE_DEPRECATED",
142 "_LARGEFILE64_SOURCE",
148 "_XOPEN_SOURCE_EXTENDED",
149 "__STDCPP_WANT_MATH_SPEC_FUNCS__",
150 "__STDC_FORMAT_MACROS",
152 return std::binary_search(std::begin(ReservedMacro), std::end(ReservedMacro),
158 const StringRef MacroName) {
168 if (MacroName.starts_with(
"__STDC"))
171 if (MacroName ==
"__cplusplus")
174 if (MacroName.starts_with(
"__cpp"))
187 if (Lang.CPlusPlus11 && (
Text ==
"override" ||
Text ==
"final"))
208 if (::llvm::sys::path::begin(Include)->equals_insensitive(
"boost"))
213 static const size_t MaxStdHeaderNameLen = 18u;
214 if (Include.size() > MaxStdHeaderNameLen)
219 for (
char &Ch : LowerInclude) {
221 if (
static_cast<unsigned char>(Ch) > 0x7f)
224 if (Ch >=
'A' && Ch <=
'Z')
227 else if (::llvm::sys::path::is_separator(Ch))
232 return llvm::StringSwitch<bool>(LowerInclude)
234 .Cases(
"assert.h",
"complex.h",
"ctype.h",
"errno.h",
"fenv.h",
true)
235 .Cases(
"float.h",
"inttypes.h",
"iso646.h",
"limits.h",
"locale.h",
true)
236 .Cases(
"math.h",
"setjmp.h",
"signal.h",
"stdalign.h",
"stdarg.h",
true)
237 .Cases(
"stdatomic.h",
"stdbool.h",
"stdckdint.h",
"stddef.h",
true)
238 .Cases(
"stdint.h",
"stdio.h",
"stdlib.h",
"stdnoreturn.h",
true)
239 .Cases(
"string.h",
"tgmath.h",
"threads.h",
"time.h",
"uchar.h",
true)
240 .Cases(
"wchar.h",
"wctype.h",
true)
243 .Cases(
"cassert",
"ccomplex",
"cctype",
"cerrno",
"cfenv",
true)
244 .Cases(
"cfloat",
"cinttypes",
"ciso646",
"climits",
"clocale",
true)
245 .Cases(
"cmath",
"csetjmp",
"csignal",
"cstdalign",
"cstdarg",
true)
246 .Cases(
"cstdbool",
"cstddef",
"cstdint",
"cstdio",
"cstdlib",
true)
247 .Cases(
"cstring",
"ctgmath",
"ctime",
"cuchar",
"cwchar",
true)
248 .Case(
"cwctype",
true)
251 .Cases(
"algorithm",
"fstream",
"list",
"regex",
"thread",
true)
252 .Cases(
"array",
"functional",
"locale",
"scoped_allocator",
"tuple",
true)
253 .Cases(
"atomic",
"future",
"map",
"set",
"type_traits",
true)
254 .Cases(
"bitset",
"initializer_list",
"memory",
"shared_mutex",
"typeindex",
true)
255 .Cases(
"chrono",
"iomanip",
"mutex",
"sstream",
"typeinfo",
true)
256 .Cases(
"codecvt",
"ios",
"new",
"stack",
"unordered_map",
true)
257 .Cases(
"complex",
"iosfwd",
"numeric",
"stdexcept",
"unordered_set",
true)
258 .Cases(
"condition_variable",
"iostream",
"ostream",
"streambuf",
"utility",
true)
259 .Cases(
"deque",
"istream",
"queue",
"string",
"valarray",
true)
260 .Cases(
"exception",
"iterator",
"random",
"strstream",
"vector",
true)
261 .Cases(
"forward_list",
"limits",
"ratio",
"system_error",
true)
264 .Cases(
"aio.h",
"arpa/inet.h",
"cpio.h",
"dirent.h",
"dlfcn.h",
true)
265 .Cases(
"fcntl.h",
"fmtmsg.h",
"fnmatch.h",
"ftw.h",
"glob.h",
true)
266 .Cases(
"grp.h",
"iconv.h",
"langinfo.h",
"libgen.h",
"monetary.h",
true)
267 .Cases(
"mqueue.h",
"ndbm.h",
"net/if.h",
"netdb.h",
"netinet/in.h",
true)
268 .Cases(
"netinet/tcp.h",
"nl_types.h",
"poll.h",
"pthread.h",
"pwd.h",
true)
269 .Cases(
"regex.h",
"sched.h",
"search.h",
"semaphore.h",
"spawn.h",
true)
270 .Cases(
"strings.h",
"stropts.h",
"sys/ipc.h",
"sys/mman.h",
"sys/msg.h",
true)
271 .Cases(
"sys/resource.h",
"sys/select.h",
"sys/sem.h",
"sys/shm.h",
"sys/socket.h",
true)
272 .Cases(
"sys/stat.h",
"sys/statvfs.h",
"sys/time.h",
"sys/times.h",
"sys/types.h",
true)
273 .Cases(
"sys/uio.h",
"sys/un.h",
"sys/utsname.h",
"sys/wait.h",
"syslog.h",
true)
274 .Cases(
"tar.h",
"termios.h",
"trace.h",
"ulimit.h",
true)
275 .Cases(
"unistd.h",
"utime.h",
"utmpx.h",
"wordexp.h",
true)
287static std::optional<StringRef>
291 for (StringRef
C : Candidates) {
292 if (LHS.equals_insensitive(
C)) {
300 size_t Length = LHS.size();
301 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;
303 std::optional<std::pair<StringRef, size_t>> SimilarStr;
304 for (StringRef
C : Candidates) {
305 size_t CurDist = LHS.edit_distance(
C,
true);
306 if (CurDist <= MaxDist) {
309 SimilarStr = {
C, CurDist};
310 }
else if (CurDist < SimilarStr->second) {
312 SimilarStr = {
C, CurDist};
318 return SimilarStr->first;
327 if (MacroNameTok.
is(tok::eod))
328 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
332 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
338 ? diag::ext_pp_operator_used_as_macro_name
339 : diag::err_pp_operator_used_as_macro_name)
340 << II << MacroNameTok.
getKind();
347 return Diag(MacroNameTok, diag::err_defined_macro_name);
371 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
387void Preprocessor::ReadMacroName(
Token &MacroNameTok,
MacroUse isDefineUndef,
392 if (MacroNameTok.
is(tok::code_completion)) {
404 if (MacroNameTok.
isNot(tok::eod)) {
405 MacroNameTok.
setKind(tok::eod);
429 while (Tmp.
is(tok::comment))
432 if (Tmp.
is(tok::eod))
440 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
443 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
447void Preprocessor::SuggestTypoedDirective(
const Token &Tok,
453 std::vector<StringRef> Candidates = {
454 "if",
"ifdef",
"ifndef",
"elif",
"else",
"endif"
456 if (LangOpts.C23 || LangOpts.CPlusPlus23)
457 Candidates.insert(Candidates.end(), {
"elifdef",
"elifndef"});
465 StringRef SuggValue = *Sugg;
468 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;
480void Preprocessor::SkipExcludedConditionalBlock(
SourceLocation HashTokenLoc,
482 bool FoundNonSkipPortion,
493 assert(!SkippingExcludedConditionalBlock &&
494 "calling SkipExcludedConditionalBlock recursively");
498 assert(!CurTokenLexer &&
"Conditional PP block cannot appear in a macro!");
499 assert(CurPPLexer &&
"Conditional PP block must be in a file!");
500 assert(CurLexer &&
"Conditional PP block but no current lexer set!");
502 if (PreambleConditionalStack.reachedEOFWhileSkipping())
503 PreambleConditionalStack.clearSkipInfo();
506 FoundNonSkipPortion, FoundElse);
516 struct SkippingRangeStateTy {
519 const char *BeginPtr =
nullptr;
520 unsigned *SkipRangePtr =
nullptr;
524 void beginLexPass() {
530 BeginPtr = PP.CurLexer->getBufferLocation();
531 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
533 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
538 void endLexPass(
const char *Hashptr) {
541 assert(PP.CurLexer->isDependencyDirectivesLexer());
546 if (!*SkipRangePtr) {
547 *SkipRangePtr = Hashptr - BeginPtr;
549 assert(*SkipRangePtr ==
unsigned(Hashptr - BeginPtr));
551 SkipRangePtr =
nullptr;
553 } SkippingRangeState(*
this);
556 if (CurLexer->isDependencyDirectivesLexer()) {
557 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
559 SkippingRangeState.beginLexPass();
563 if (Tok.
is(tok::code_completion)) {
571 if (Tok.
is(tok::eof)) {
575 if (PreambleConditionalStack.isRecording())
576 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,
589 if (Tok.
is(tok::eof))
596 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
598 assert(Tok.
is(tok::hash));
599 const char *Hashptr = CurLexer->getBufferLocation() - Tok.
getLength();
600 assert(CurLexer->getSourceLocation(Hashptr) == Tok.
getLocation());
607 if (Tok.
isNot(tok::raw_identifier)) {
610 if (CurLexer) CurLexer->resetExtendedTokenMode();
621 char FirstChar = RI[0];
622 if (FirstChar >=
'a' && FirstChar <=
'z' &&
623 FirstChar !=
'i' && FirstChar !=
'e') {
626 if (CurLexer) CurLexer->resetExtendedTokenMode();
633 char DirectiveBuf[20];
639 size_t IdLen = DirectiveStr.size();
643 if (CurLexer) CurLexer->resetExtendedTokenMode();
646 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
647 Directive = StringRef(DirectiveBuf, IdLen);
671 assert(!InCond &&
"Can't be skipping if not in a conditional!");
675 SkippingRangeState.endLexPass(Hashptr);
687 }
else if (Sub ==
"lse") {
694 SkippingRangeState.endLexPass(Hashptr);
698 Diag(Tok, diag::pp_err_else_after_else);
718 }
else if (Sub ==
"lif") {
722 SkippingRangeState.endLexPass(Hashptr);
739 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
742 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
746 const bool CondValue = DER.Conditional;
760 }
else if (Sub ==
"lifdef" ||
762 bool IsElifDef =
Sub ==
"lifdef";
764 Token DirectiveToken = Tok;
767 SkippingRangeState.endLexPass(Hashptr);
772 if (LangOpts.CPlusPlus)
773 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
774 : diag::ext_cxx23_pp_directive;
776 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
777 : diag::ext_c23_pp_directive;
782 Diag(Tok, diag::pp_err_elif_after_else)
796 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
799 ReadMacroName(MacroNameTok);
804 if (MacroNameTok.
is(tok::eod)) {
820 Callbacks->Elifdef(DirectiveToken.
getLocation(), MacroNameTok,
823 Callbacks->Elifndef(DirectiveToken.
getLocation(), MacroNameTok,
828 if (
static_cast<bool>(MI) == IsElifDef) {
842 if (CurLexer) CurLexer->resetExtendedTokenMode();
853 Callbacks->SourceRangeSkipped(
885 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
893 auto ID =
SM.getFileID(
SM.getExpansionLoc(
Loc));
894 auto FE =
SM.getFileEntryRefForID(ID);
903 bool InPrivateHeader =
false;
905 if (!Header.isAccessibleFrom(IncM)) {
910 InPrivateHeader =
true;
946 Loc =
SM.getIncludeLoc(ID);
958 bool *IsFrameworkFound,
bool SkipCache,
bool OpenFile,
bool CacheFailures) {
963 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
968 bool BuildSystemModule =
false;
969 if (!FromDir && !FromFile) {
992 Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));
997 Includers.push_back(std::make_pair(*FileEnt, *CWD));
1000 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1006 if (LangOpts.MSVCCompat && !isAngled) {
1007 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1008 if (IsFileLexer(ISEntry))
1010 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1015 CurDir = CurDirLookup;
1023 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
1024 Includers, SearchPath, RelativePath, RequestingModule,
1025 SuggestedModule,
nullptr,
1026 nullptr, SkipCache)) {
1028 TmpFromDir = TmpCurDir;
1030 if (&FE->getFileEntry() == FromFile) {
1032 FromDir = TmpFromDir;
1041 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,
1042 RelativePath, RequestingModule, SuggestedModule, IsMapped,
1043 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);
1051 if (IsFileLexer()) {
1054 Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,
1061 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1062 if (IsFileLexer(ISEntry)) {
1063 if ((CurFileEnt = ISEntry.ThePPLexer->
getFileEntry())) {
1065 Filename, *CurFileEnt, SearchPath, RelativePath,
1066 RequestingModule, SuggestedModule)) {
1074 return std::nullopt;
1081 if (llvm::sys::path::is_absolute(
Filename)) {
1085 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1089 StringRef StartingFrom, StringRef
FileName,
1090 bool RemoveInitialFileComponentFromLookupPath) {
1091 llvm::sys::path::native(StartingFrom, LookupPath);
1092 if (RemoveInitialFileComponentFromLookupPath)
1093 llvm::sys::path::remove_filename(LookupPath);
1094 if (!LookupPath.empty() &&
1095 !llvm::sys::path::is_separator(LookupPath.back())) {
1096 LookupPath.push_back(llvm::sys::path::get_separator().front());
1105 if (LookupFromFile) {
1108 if (!FullFileDir.empty()) {
1109 SeparateComponents(LookupPath, FullFileDir,
Filename,
true);
1113 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1114 llvm::consumeError(ShouldBeEntry.takeError());
1121 if (MaybeWorkingDirEntry) {
1123 StringRef WorkingDir = WorkingDirEntry.
getName();
1124 if (!WorkingDir.empty()) {
1125 SeparateComponents(LookupPath, WorkingDir,
Filename,
false);
1129 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1130 llvm::consumeError(ShouldBeEntry.takeError());
1135 for (
const auto &Entry : PPOpts->EmbedEntries) {
1137 SeparateComponents(LookupPath, Entry,
Filename,
false);
1141 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1142 llvm::consumeError(ShouldBeEntry.takeError());
1144 return std::nullopt;
1154 : PP(pp), save(pp->DisableMacroExpansion) {
1155 if (pp->MacroExpansionInDirectivesOverride)
1156 pp->DisableMacroExpansion =
false;
1160 PP->DisableMacroExpansion = save;
1177 if (II->getPPKeywordID() == tok::pp_define) {
1178 return HandleDefineDirective(
Result,
1181 if (SkippingUntilPCHThroughHeader &&
1182 II->getPPKeywordID() == tok::pp_include) {
1183 return HandleIncludeDirective(HashLoc,
Result);
1185 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
1187 auto *II =
Result.getIdentifierInfo();
1188 if (II && II->getName() ==
"hdrstop")
1206 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
1208 bool ImmediatelyAfterTopLevelIfndef =
1236 switch (II->getPPKeywordID()) {
1237 case tok::pp_include:
1238 case tok::pp_import:
1239 case tok::pp_include_next:
1240 case tok::pp___include_macros:
1241 case tok::pp_pragma:
1243 Diag(
Result, diag::err_embedded_directive) << II->getName();
1244 Diag(*ArgMacro, diag::note_macro_expansion_here)
1259 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
1262 switch (
Result.getKind()) {
1269 case tok::code_completion:
1275 case tok::numeric_constant:
1282 return HandleDigitDirective(
Result);
1292 return HandleIfDirective(
Result, SavedHash, ReadAnyTokensBeforeDirective);
1294 return HandleIfdefDirective(
Result, SavedHash,
false,
1296 case tok::pp_ifndef:
1297 return HandleIfdefDirective(
Result, SavedHash,
true,
1298 ReadAnyTokensBeforeDirective);
1300 case tok::pp_elifdef:
1301 case tok::pp_elifndef:
1305 return HandleElseDirective(
Result, SavedHash);
1307 return HandleEndifDirective(
Result);
1310 case tok::pp_include:
1313 case tok::pp___include_macros:
1318 case tok::pp_define:
1319 return HandleDefineDirective(
Result, ImmediatelyAfterTopLevelIfndef);
1321 return HandleUndefDirective();
1325 return HandleLineDirective();
1329 return HandleUserDiagnosticDirective(
Result,
false);
1332 case tok::pp_pragma:
1336 case tok::pp_import:
1338 case tok::pp_include_next:
1341 case tok::pp_warning:
1342 if (LangOpts.CPlusPlus)
1344 ? diag::warn_cxx23_compat_warning_directive
1345 : diag::ext_pp_warning_directive)
1348 Diag(
Result, LangOpts.C23 ? diag::warn_c23_compat_warning_directive
1349 : diag::ext_pp_warning_directive)
1352 return HandleUserDiagnosticDirective(
Result,
true);
1354 return HandleIdentSCCSDirective(
Result);
1356 return HandleIdentSCCSDirective(
Result);
1362 case tok::pp_assert:
1365 case tok::pp_unassert:
1369 case tok::pp___public_macro:
1371 return HandleMacroPublicDirective(
Result);
1374 case tok::pp___private_macro:
1376 return HandleMacroPrivateDirective();
1387 auto Toks = std::make_unique<Token[]>(2);
1389 Toks[0] = SavedHash;
1394 if (
Result.is(tok::hashhash))
1395 Toks[1].setKind(tok::unknown);
1400 EnterTokenStream(std::move(Toks), 2,
false,
false);
1406 Diag(
Result, diag::err_pp_invalid_directive) << 0;
1418 bool IsGNULineDirective=
false) {
1419 if (DigitTok.
isNot(tok::numeric_constant)) {
1420 PP.
Diag(DigitTok, DiagID);
1422 if (DigitTok.
isNot(tok::eod))
1428 IntegerBuffer.resize(DigitTok.
getLength());
1429 const char *DigitTokBegin = &IntegerBuffer[0];
1439 for (
unsigned i = 0; i != ActualLength; ++i) {
1442 if (DigitTokBegin[i] ==
'\'')
1445 if (!
isDigit(DigitTokBegin[i])) {
1447 diag::err_pp_line_digit_sequence) << IsGNULineDirective;
1452 unsigned NextVal = Val*10+(DigitTokBegin[i]-
'0');
1453 if (NextVal < Val) {
1454 PP.
Diag(DigitTok, DiagID);
1461 if (DigitTokBegin[0] ==
'0' && Val)
1463 << IsGNULineDirective;
1475void Preprocessor::HandleLineDirective() {
1483 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*
this))
1487 Diag(DigitTok, diag::ext_pp_line_zero);
1491 unsigned LineLimit = 32768U;
1492 if (LangOpts.C99 || LangOpts.CPlusPlus11)
1493 LineLimit = 2147483648U;
1494 if (LineNo >= LineLimit)
1495 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
1496 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)
1497 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);
1499 int FilenameID = -1;
1505 if (StrTok.
is(tok::eod))
1507 else if (StrTok.
isNot(tok::string_literal)) {
1508 Diag(StrTok, diag::err_pp_line_invalid_filename);
1512 Diag(StrTok, diag::err_invalid_string_udl);
1518 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1524 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1559 if (FlagTok.
is(tok::eod))
return false;
1560 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1567 if (FlagTok.
is(tok::eod))
return false;
1568 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1570 }
else if (FlagVal == 2) {
1586 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {
1587 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
1593 if (FlagTok.
is(tok::eod))
return false;
1594 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1600 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1608 if (FlagTok.
is(tok::eod))
return false;
1609 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1614 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1622 if (FlagTok.
is(tok::eod))
return false;
1625 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1637void Preprocessor::HandleDigitDirective(
Token &DigitTok) {
1641 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
1648 bool IsFileEntry =
false, IsFileExit =
false;
1649 int FilenameID = -1;
1654 if (StrTok.
is(tok::eod)) {
1655 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1658 }
else if (StrTok.
isNot(tok::string_literal)) {
1659 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1663 Diag(StrTok, diag::err_invalid_string_udl);
1669 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1675 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1685 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1689 if (!(IsFileExit &&
Literal.GetString().empty()))
1695 IsFileExit, FileKind);
1704 else if (IsFileExit)
1713void Preprocessor::HandleUserDiagnosticDirective(
Token &Tok,
1721 CurLexer->ReadToEndOfLine(&Message);
1725 StringRef Msg = Message.str().ltrim(
' ');
1728 Diag(Tok, diag::pp_hash_warning) << Msg;
1730 Diag(Tok, diag::err_pp_hash_error) << Msg;
1735void Preprocessor::HandleIdentSCCSDirective(
Token &Tok) {
1737 Diag(Tok, diag::ext_pp_ident_directive);
1744 if (StrTok.
isNot(tok::string_literal) &&
1745 StrTok.
isNot(tok::wide_string_literal)) {
1746 Diag(StrTok, diag::err_pp_malformed_ident);
1747 if (StrTok.
isNot(tok::eod))
1753 Diag(StrTok, diag::err_invalid_string_udl);
1770void Preprocessor::HandleMacroPublicDirective(
Token &Tok) {
1772 ReadMacroName(MacroNameTok,
MU_Undef);
1775 if (MacroNameTok.
is(tok::eod))
1787 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1797void Preprocessor::HandleMacroPrivateDirective() {
1799 ReadMacroName(MacroNameTok,
MU_Undef);
1802 if (MacroNameTok.
is(tok::eod))
1814 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1834 StringRef &Buffer) {
1836 assert(!Buffer.empty() &&
"Can't have tokens with empty spellings!");
1848 if (Buffer[0] ==
'<') {
1849 if (Buffer.back() !=
'>') {
1850 Diag(
Loc, diag::err_pp_expects_filename);
1851 Buffer = StringRef();
1855 }
else if (Buffer[0] ==
'"') {
1856 if (Buffer.back() !=
'"') {
1857 Diag(
Loc, diag::err_pp_expects_filename);
1858 Buffer = StringRef();
1863 Diag(
Loc, diag::err_pp_expects_filename);
1864 Buffer = StringRef();
1869 if (Buffer.size() <= 2) {
1870 Diag(
Loc, diag::err_pp_empty_filename);
1871 Buffer = StringRef();
1876 Buffer = Buffer.substr(1, Buffer.size()-2);
1883 void *AnnotationVal) {
1886 auto Tok = std::make_unique<Token[]>(1);
1892 EnterTokenStream(std::move(Tok), 1,
true,
false);
1899 ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>
Path,
1902 for (
size_t I = 0, N =
Path.size(); I != N; ++I) {
1905 PathString +=
Path[I].first->getName();
1908 int IncludeKind = 0;
1910 case tok::pp_include:
1914 case tok::pp_import:
1918 case tok::pp_include_next:
1922 case tok::pp___include_macros:
1927 llvm_unreachable(
"unknown include directive kind");
1930 PP.
Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
1931 << IncludeKind << PathString;
1938 StringRef RealPathName,
1939 llvm::sys::path::Style Separator) {
1940 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
1941 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
1943 bool SuggestReplacement =
false;
1945 auto IsSep = [Separator](StringRef Component) {
1946 return Component.size() == 1 &&
1947 llvm::sys::path::is_separator(Component[0], Separator);
1952 for (
auto &Component : llvm::reverse(Components)) {
1953 if (
"." == Component) {
1954 }
else if (
".." == Component) {
1958 }
else if (RealPathComponentIter != RealPathComponentEnd) {
1959 if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&
1960 Component != *RealPathComponentIter) {
1964 SuggestReplacement =
1965 RealPathComponentIter->equals_insensitive(Component);
1966 if (!SuggestReplacement)
1968 Component = *RealPathComponentIter;
1970 ++RealPathComponentIter;
1973 return SuggestReplacement;
1982 Module *ShadowingModule =
nullptr;
1990 }
else if (ShadowingModule) {
1993 diag::note_previous_definition);
2004std::pair<ConstSearchDirIterator, const FileEntry *>
2005Preprocessor::getIncludeNextStart(
const Token &IncludeNextTok)
const {
2010 const FileEntry *LookupFromFile =
nullptr;
2018 Diag(IncludeNextTok, diag::pp_include_next_in_primary);
2019 }
else if (CurLexerSubmodule) {
2022 assert(CurPPLexer &&
"#include_next directive in macro?");
2024 LookupFromFile = *FE;
2026 }
else if (!Lookup) {
2031 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
2037 return {Lookup, LookupFromFile};
2053 if (FilenameTok.
isNot(tok::header_name)) {
2055 if (FilenameTok.
isNot(tok::eod))
2067 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
2068 EndLoc, LookupFrom, LookupFromFile);
2069 switch (Action.Kind) {
2070 case ImportAction::None:
2071 case ImportAction::SkippedModuleImport:
2073 case ImportAction::ModuleBegin:
2075 tok::annot_module_begin, Action.ModuleForHeader);
2077 case ImportAction::HeaderUnitImport:
2079 Action.ModuleForHeader);
2081 case ImportAction::ModuleImport:
2083 tok::annot_module_include, Action.ModuleForHeader);
2085 case ImportAction::Failure:
2087 "This should be an early exit only to a fatal error");
2090 CurLexer->cutOffLexing();
2098 const Token &FilenameTok,
bool &IsFrameworkFound,
bool IsImportDecl,
2100 const FileEntry *LookupFromFile, StringRef &LookupFilename,
2104 if (LangOpts.AsmPreprocessor)
2108 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
2109 bool RequestingModuleIsModuleInterface =
2113 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
2118 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,
2119 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2120 &SuggestedModule, &IsMapped, &IsFrameworkFound);
2122 DiagnoseHeaderInclusion(*
File);
2127 if (Callbacks && Callbacks->FileNotFound(
Filename))
2128 return std::nullopt;
2130 if (SuppressIncludeNotFoundError)
2131 return std::nullopt;
2138 FilenameLoc, LookupFilename,
false, LookupFrom, LookupFromFile, CurDir,
2139 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2140 &SuggestedModule, &IsMapped,
2143 DiagnoseHeaderInclusion(*
File);
2144 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
2154 StringRef OriginalFilename =
Filename;
2155 if (LangOpts.SpellChecking) {
2158 auto CorrectTypoFilename = [](llvm::StringRef
Filename) {
2165 StringRef TypoCorrectionName = CorrectTypoFilename(
Filename);
2166 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);
2169 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,
2170 LookupFromFile, CurDir, Callbacks ? &SearchPath :
nullptr,
2171 Callbacks ? &RelativePath :
nullptr, &SuggestedModule, &IsMapped,
2174 DiagnoseHeaderInclusion(*
File);
2177 FilenameRange,
"<" + TypoCorrectionName.str() +
">")
2179 FilenameRange,
"\"" + TypoCorrectionName.str() +
"\"");
2180 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
2181 << OriginalFilename << TypoCorrectionName << Hint;
2185 LookupFilename = TypoCorrectionLookupName;
2191 assert(!
File &&
"expected missing file");
2192 Diag(FilenameTok, diag::err_pp_file_not_found)
2193 << OriginalFilename << FilenameRange;
2194 if (IsFrameworkFound) {
2195 size_t SlashPos = OriginalFilename.find(
'/');
2196 assert(SlashPos != StringRef::npos &&
2197 "Include with framework name should have '/' in the filename");
2198 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
2201 assert(CacheEntry.
Directory &&
"Found framework should be in cache");
2202 Diag(FilenameTok, diag::note_pp_framework_without_header)
2203 << OriginalFilename.substr(SlashPos + 1) << FrameworkName
2207 return std::nullopt;
2222Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
2232 StringRef OriginalFilename =
Filename;
2239 return {ImportAction::None};
2241 bool IsImportDecl = HashLoc.
isInvalid();
2245 if (PragmaARCCFCodeAuditedInfo.second.isValid()) {
2246 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
2247 Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);
2254 if (PragmaAssumeNonNullLoc.
isValid()) {
2255 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
2256 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
2267 if (!NewName.empty())
2272 bool IsMapped =
false;
2273 bool IsFrameworkFound =
false;
2281 StringRef LookupFilename =
Filename;
2286 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;
2287 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {
2289 llvm::sys::path::native(NormalizedPath);
2290 LookupFilename = NormalizedPath;
2291 BackslashStyle = llvm::sys::path::Style::windows;
2295 &CurDir,
Filename, FilenameLoc, FilenameRange, FilenameTok,
2296 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
2297 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
2301 SkippingUntilPCHThroughHeader =
false;
2302 return {ImportAction::None};
2320 enum { Enter,
Import, Skip, IncludeLimitReached } Action = Enter;
2322 if (PPOpts->SingleFileParseMode)
2323 Action = IncludeLimitReached;
2328 if (Action == Enter && HasReachedMaxIncludeDepth &&
File &&
2330 Action = IncludeLimitReached;
2337 bool MaybeTranslateInclude = Action == Enter &&
File && ModuleToImport &&
2341 bool UsableHeaderUnit =
false;
2342 if (
getLangOpts().CPlusPlusModules && ModuleToImport &&
2344 if (TrackGMFState.inGMF() || IsImportDecl)
2345 UsableHeaderUnit =
true;
2346 else if (!IsImportDecl) {
2348 ModuleToImport =
nullptr;
2352 bool UsableClangHeaderModule =
2359 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {
2367 diag::note_implicit_top_level_module_import_here)
2369 return {ImportAction::None};
2376 for (
Module *Mod = ModuleToImport; Mod; Mod = Mod->
Parent)
2379 std::reverse(
Path.begin(),
Path.end());
2392 assert((Imported ==
nullptr || Imported == ModuleToImport) &&
2393 "the imported module is different than the suggested one");
2399 static_cast<Module *
>(Imported)->getTopLevelModule());
2404 ModuleToImport =
nullptr;
2413 assert(CurLexer &&
"#include but no current lexer set!");
2415 CurLexer->FormTokenWithChars(
Result, CurLexer->BufferEnd, tok::eof);
2416 CurLexer->cutOffLexing();
2418 return {ImportAction::None};
2439 bool IsFirstIncludeOfFile =
false;
2443 if (Action == Enter &&
File &&
2446 IsFirstIncludeOfFile)) {
2457 if (UsableHeaderUnit && !
getLangOpts().CompilingPCH)
2458 Action = TrackGMFState.inGMF() ?
Import : Skip;
2460 Action = (ModuleToImport && !
getLangOpts().CompilingPCH) ? Import : Skip;
2468 if (Action == Enter &&
File && PreambleConditionalStack.isRecording() &&
2471 diag::err_pp_including_mainfile_in_preamble);
2472 return {ImportAction::None};
2475 if (Callbacks && !IsImportDecl) {
2478 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,
2479 FilenameRange,
File, SearchPath, RelativePath,
2480 SuggestedModule.
getModule(), Action == Import,
2482 if (Action == Skip &&
File)
2483 Callbacks->FileSkipped(*
File, FilenameTok, FileCharacter);
2487 return {ImportAction::None};
2491 if (IsImportDecl && !ModuleToImport) {
2492 Diag(FilenameTok, diag::err_header_import_not_header_unit)
2493 << OriginalFilename <<
File->getName();
2494 return {ImportAction::None};
2499 const bool CheckIncludePathPortability =
2500 !IsMapped && !
File->getFileEntry().tryGetRealPathName().empty();
2502 if (CheckIncludePathPortability) {
2503 StringRef Name = LookupFilename;
2504 StringRef NameWithoriginalSlashes =
Filename;
2508 bool NameWasUNC = Name.consume_front(
"\\\\?\\");
2509 NameWithoriginalSlashes.consume_front(
"\\\\?\\");
2511 StringRef RealPathName =
File->getFileEntry().tryGetRealPathName();
2513 llvm::sys::path::end(Name));
2526 if (llvm::sys::path::is_absolute(Name) &&
2527 llvm::sys::path::is_absolute(RealPathName) &&
2530 assert(Components.size() >= 3 &&
"should have drive, backslash, name");
2531 assert(Components[0].size() == 2 &&
"should start with drive");
2532 assert(Components[0][1] ==
':' &&
"should have colon");
2533 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();
2534 RealPathName = FixedDriveRealPath;
2540 Path.reserve(Name.size()+2);
2541 Path.push_back(isAngled ?
'<' :
'"');
2543 const auto IsSep = [BackslashStyle](
char c) {
2544 return llvm::sys::path::is_separator(
c, BackslashStyle);
2547 for (
auto Component : Components) {
2559 if (!(Component.size() == 1 && IsSep(Component[0])))
2560 Path.append(Component);
2561 else if (
Path.size() != 1)
2565 if (
Path.size() > NameWithoriginalSlashes.size()) {
2566 Path.push_back(isAngled ?
'>' :
'"');
2569 assert(IsSep(NameWithoriginalSlashes[
Path.size()-1]));
2571 Path.push_back(NameWithoriginalSlashes[
Path.size()-1]);
2572 while (
Path.size() <= NameWithoriginalSlashes.size() &&
2573 IsSep(NameWithoriginalSlashes[
Path.size()-1]));
2579 Path = (
Path.substr(0, 1) +
"\\\\?\\" +
Path.substr(1)).str();
2586 ? diag::pp_nonportable_path
2587 : diag::pp_nonportable_system_path;
2588 Diag(FilenameTok, DiagId) <<
Path <<
2597 return {ImportAction::SkippedModuleImport, ModuleToImport};
2598 return {ImportAction::None};
2600 case IncludeLimitReached:
2603 return {ImportAction::None};
2607 assert(ModuleToImport &&
"no module to import");
2612 tok::pp___include_macros)
2613 return {ImportAction::None};
2615 return {ImportAction::ModuleImport, ModuleToImport};
2623 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
2624 Diag(FilenameTok, diag::err_pp_include_too_deep);
2625 HasReachedMaxIncludeDepth =
true;
2626 return {ImportAction::None};
2630 Diag(FilenameTok, diag::warn_pp_include_angled_in_module_purview)
2642 return ImportAction::Failure;
2647 IsFirstIncludeOfFile))
2648 return {ImportAction::None};
2652 if (ModuleToImport && !ModuleToImport->
isHeaderUnit()) {
2657 diag::err_module_build_shadowed_submodule)
2660 diag::note_previous_definition);
2661 return {ImportAction::None};
2673 return {ImportAction::None};
2675 assert(!CurLexerSubmodule &&
"should not have marked this as a module yet");
2676 CurLexerSubmodule = ModuleToImport;
2686 return {ImportAction::ModuleBegin, ModuleToImport};
2689 assert(!IsImportDecl &&
"failed to diagnose missing module for import decl");
2690 return {ImportAction::None};
2695void Preprocessor::HandleIncludeNextDirective(
SourceLocation HashLoc,
2696 Token &IncludeNextTok) {
2697 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
2701 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);
2703 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
2708void Preprocessor::HandleMicrosoftImportDirective(
Token &Tok) {
2714 Diag(Tok, diag::err_pp_import_directive_ms );
2725 if (!LangOpts.ObjC) {
2726 if (LangOpts.MSVCCompat)
2727 return HandleMicrosoftImportDirective(ImportTok);
2728 Diag(ImportTok, diag::ext_pp_import_directive);
2730 return HandleIncludeDirective(HashLoc, ImportTok);
2737void Preprocessor::HandleIncludeMacrosDirective(
SourceLocation HashLoc,
2738 Token &IncludeMacrosTok) {
2744 diag::pp_include_macros_out_of_predefines);
2751 HandleIncludeDirective(HashLoc, IncludeMacrosTok);
2756 assert(TmpTok.
isNot(tok::eof) &&
"Didn't find end of -imacros!");
2757 }
while (TmpTok.
isNot(tok::hashhash));
2768bool Preprocessor::ReadMacroParameterList(
MacroInfo *MI,
Token &Tok) {
2779 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
2783 Diag(Tok, LangOpts.CPlusPlus11 ?
2784 diag::warn_cxx98_compat_variadic_macro :
2785 diag::ext_variadic_macro);
2788 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
2789 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
2794 if (Tok.
isNot(tok::r_paren)) {
2795 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2804 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2812 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
2818 if (llvm::is_contained(Parameters, II)) {
2819 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
2831 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
2840 Diag(Tok, diag::ext_named_variadic_macro);
2844 if (Tok.
isNot(tok::r_paren)) {
2845 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2875 StringRef ValueText = II->
getName();
2876 StringRef TrimmedValue = ValueText;
2877 if (!ValueText.starts_with(
"__")) {
2878 if (ValueText.starts_with(
"_"))
2879 TrimmedValue = TrimmedValue.drop_front(1);
2883 TrimmedValue = TrimmedValue.drop_front(2);
2884 if (TrimmedValue.ends_with(
"__"))
2885 TrimmedValue = TrimmedValue.drop_back(2);
2887 return TrimmedValue == MacroText;
2894 return MacroName.
isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
2907MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
2908 const Token &MacroNameTok,
const bool ImmediatelyAfterHeaderGuard) {
2910 Token LastTok = MacroNameTok;
2918 auto _ = llvm::make_scope_exit([&]() {
2920 if (CurLexer->ParsingPreprocessorDirective)
2931 if (Tok.
is(tok::eod)) {
2932 if (ImmediatelyAfterHeaderGuard) {
2942 }
else if (Tok.
is(tok::l_paren)) {
2945 if (ReadMacroParameterList(MI, LastTok))
2959 }
else if (LangOpts.C99 || LangOpts.CPlusPlus11) {
2962 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
2971 if (Tok.
is(tok::at))
2973 else if (Tok.
is(tok::unknown)) {
2980 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
2982 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
2985 if (!Tok.
is(tok::eod))
2993 while (Tok.
isNot(tok::eod)) {
2995 Tokens.push_back(Tok);
3006 while (Tok.
isNot(tok::eod)) {
3009 if (!Tok.
isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
3010 Tokens.push_back(Tok);
3012 if (VAOCtx.isVAOptToken(Tok)) {
3014 if (VAOCtx.isInVAOpt()) {
3015 Diag(Tok, diag::err_pp_vaopt_nested_use);
3020 if (Tok.
isNot(tok::l_paren)) {
3021 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
3024 Tokens.push_back(Tok);
3025 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.
getLocation());
3027 if (Tok.
is(tok::hashhash)) {
3028 Diag(Tok, diag::err_vaopt_paste_at_start);
3032 }
else if (VAOCtx.isInVAOpt()) {
3033 if (Tok.
is(tok::r_paren)) {
3034 if (VAOCtx.sawClosingParen()) {
3035 assert(Tokens.size() >= 3 &&
3036 "Must have seen at least __VA_OPT__( "
3037 "and a subsequent tok::r_paren");
3038 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {
3039 Diag(Tok, diag::err_vaopt_paste_at_end);
3043 }
else if (Tok.
is(tok::l_paren)) {
3057 Tokens.push_back(Tok);
3064 if (Tok.
is(tok::hashhash)) {
3072 if (Tok.
is(tok::eod)) {
3073 Tokens.push_back(LastTok);
3078 Tokens[Tokens.size() - 1].is(tok::comma))
3082 Tokens.push_back(LastTok);
3091 if (!VAOCtx.isVAOptToken(Tok) &&
3100 LastTok.
setKind(tok::unknown);
3101 Tokens.push_back(LastTok);
3104 Diag(Tok, diag::err_pp_stringize_not_parameter)
3105 << LastTok.
is(tok::hashat);
3111 Tokens.push_back(LastTok);
3116 if (!VAOCtx.isVAOptToken(Tok)) {
3117 Tokens.push_back(Tok);
3124 if (VAOCtx.isInVAOpt()) {
3125 assert(Tok.
is(tok::eod) &&
"Must be at End Of preprocessing Directive");
3126 Diag(Tok, diag::err_pp_expected_after)
3127 << LastTok.
getKind() << tok::r_paren;
3128 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
3139 return II->
isStr(
"__strong") || II->
isStr(
"__weak") ||
3140 II->
isStr(
"__unsafe_unretained") || II->
isStr(
"__autoreleasing");
3145void Preprocessor::HandleDefineDirective(
3146 Token &DefineTok,
const bool ImmediatelyAfterHeaderGuard) {
3150 bool MacroShadowsKeyword;
3151 ReadMacroName(MacroNameTok,
MU_Define, &MacroShadowsKeyword);
3154 if (MacroNameTok.
is(tok::eod))
3161 emitFinalMacroWarning(MacroNameTok,
false);
3165 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
3167 MacroInfo *
const MI = ReadOptionalMacroParameterListAndBody(
3168 MacroNameTok, ImmediatelyAfterHeaderGuard);
3172 if (MacroShadowsKeyword &&
3174 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
3179 if (NumTokens != 0) {
3191 if (SkippingUntilPCHThroughHeader) {
3194 LangOpts.MicrosoftExt))
3198 if (!LangOpts.MicrosoftExt)
3209 emitFinalMacroWarning(MacroNameTok,
false);
3222 LangOpts.MicrosoftExt)) {
3241 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
3245 !MI->
isIdenticalTo(*OtherMI, *
this, LangOpts.MicrosoftExt)) {
3263 !MacroExpansionInDirectivesOverride &&
3272 Callbacks->MacroDefined(MacroNameTok, MD);
3285 Tok.
setKind(tok::kw__Static_assert);
3294void Preprocessor::HandleUndefDirective() {
3298 ReadMacroName(MacroNameTok,
MU_Undef);
3301 if (MacroNameTok.
is(tok::eod))
3313 emitFinalMacroWarning(MacroNameTok,
true);
3323 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
3328 Undef = AllocateUndefMacroDirective(MacroNameTok.
getLocation());
3334 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
3349void Preprocessor::HandleIfdefDirective(
Token &
Result,
3350 const Token &HashToken,
3352 bool ReadAnyTokensBeforeDirective) {
3357 ReadMacroName(MacroNameTok);
3360 if (MacroNameTok.
is(tok::eod)) {
3363 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3383 if (!ReadAnyTokensBeforeDirective && !MI) {
3384 assert(isIfndef &&
"#ifdef shouldn't reach here");
3396 Callbacks->Ifndef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3398 Callbacks->Ifdef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3401 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3405 if (PPOpts->SingleFileParseMode && !MI) {
3411 }
else if (!MI == isIfndef || RetainExcludedCB) {
3418 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3427void Preprocessor::HandleIfDirective(
Token &IfToken,
3428 const Token &HashToken,
3429 bool ReadAnyTokensBeforeDirective) {
3434 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
3435 const bool ConditionalTrue = DER.Conditional;
3444 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
3456 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3460 if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
3465 }
else if (ConditionalTrue || RetainExcludedCB) {
3479void Preprocessor::HandleEndifDirective(
Token &EndifToken) {
3488 Diag(EndifToken, diag::err_pp_endif_without_if);
3497 "This code should only be reachable in the non-skipping case!");
3505void Preprocessor::HandleElseDirective(
Token &
Result,
const Token &HashToken) {
3527 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3530 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3541 true,
Result.getLocation());
3545void Preprocessor::HandleElifFamilyDirective(
Token &ElifToken,
3546 const Token &HashToken,
3558 if (LangOpts.CPlusPlus)
3559 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
3560 : diag::ext_cxx23_pp_directive;
3562 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
3563 : diag::ext_c23_pp_directive;
3564 Diag(ElifToken, DiagID) << DirKind;
3577 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
3587 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
3592 Callbacks->Elif(ElifToken.
getLocation(), ConditionRange,
3595 case tok::pp_elifdef:
3598 case tok::pp_elifndef:
3602 assert(
false &&
"unexpected directive kind");
3607 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3610 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3619 SkipExcludedConditionalBlock(
3624std::optional<LexEmbedParametersResult>
3628 tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod;
3630 auto DiagMismatchedBracesAndSkipToEOD =
3632 std::pair<tok::TokenKind, SourceLocation> Matches) {
3634 Diag(Matches.second, diag::note_matching) << Matches.first;
3635 if (CurTok.
isNot(tok::eod))
3640 if (CurTok.
isNot(Kind)) {
3641 Diag(CurTok, diag::err_expected) << Kind;
3642 if (CurTok.
isNot(tok::eod))
3659 auto LexPPParameterName = [&]() -> std::optional<std::string> {
3662 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3663 return std::nullopt;
3670 if (CurTok.
is(tok::coloncolon)) {
3673 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3674 return std::nullopt;
3680 return (llvm::Twine(Prefix->
getName()) +
"::" + Suffix->
getName()).str();
3682 return Prefix->
getName().str();
3689 auto NormalizeParameterName = [](StringRef Name) {
3690 if (Name.size() > 4 && Name.starts_with(
"__") && Name.ends_with(
"__"))
3691 return Name.substr(2, Name.size() - 4);
3695 auto LexParenthesizedIntegerExpr = [&]() -> std::optional<size_t> {
3698 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3699 return std::nullopt;
3704 bool EvaluatedDefined;
3705 DirectiveEvalResult LimitEvalResult = EvaluateDirectiveExpression(
3706 ParameterIfNDef, CurTok, EvaluatedDefined,
false);
3708 if (!LimitEvalResult.Value) {
3711 assert(CurTok.
is(tok::eod) &&
"expect to be at the end of directive");
3712 return std::nullopt;
3715 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3716 return std::nullopt;
3723 if (EvaluatedDefined) {
3724 Diag(CurTok, diag::err_defined_in_pp_embed);
3725 return std::nullopt;
3728 if (LimitEvalResult.Value) {
3729 const llvm::APSInt &
Result = *LimitEvalResult.Value;
3730 if (
Result.isNegative()) {
3731 Diag(CurTok, diag::err_requires_positive_value)
3733 return std::nullopt;
3735 return Result.getLimitedValue();
3737 return std::nullopt;
3743 return tok::r_paren;
3745 return tok::r_brace;
3747 return tok::r_square;
3749 llvm_unreachable(
"should not get here");
3753 auto LexParenthesizedBalancedTokenSoup =
3755 std::vector<std::pair<tok::TokenKind, SourceLocation>> BracketStack;
3758 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3762 bool WaitingForInnerCloseParen =
false;
3763 while (CurTok.
isNot(tok::eod) &&
3764 (WaitingForInnerCloseParen || CurTok.
isNot(tok::r_paren))) {
3769 WaitingForInnerCloseParen =
true;
3776 WaitingForInnerCloseParen =
false;
3779 case tok::r_square: {
3781 GetMatchingCloseBracket(BracketStack.back().first);
3782 if (BracketStack.empty() || CurTok.
getKind() != Matching) {
3783 DiagMismatchedBracesAndSkipToEOD(Matching, BracketStack.back());
3786 BracketStack.pop_back();
3789 Tokens.push_back(CurTok);
3794 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3802 while (!CurTok.
isOneOf(EndTokenKind, tok::eod)) {
3804 std::optional<std::string> ParamName = LexPPParameterName();
3806 return std::nullopt;
3807 StringRef
Parameter = NormalizeParameterName(*ParamName);
3814 if (
Result.MaybeLimitParam)
3817 std::optional<size_t> Limit = LexParenthesizedIntegerExpr();
3819 return std::nullopt;
3822 }
else if (
Parameter ==
"clang::offset") {
3823 if (
Result.MaybeOffsetParam)
3826 std::optional<size_t> Offset = LexParenthesizedIntegerExpr();
3828 return std::nullopt;
3832 if (
Result.MaybePrefixParam)
3836 if (!LexParenthesizedBalancedTokenSoup(Soup))
3837 return std::nullopt;
3839 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3841 if (
Result.MaybeSuffixParam)
3845 if (!LexParenthesizedBalancedTokenSoup(Soup))
3846 return std::nullopt;
3848 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3850 if (
Result.MaybeIfEmptyParam)
3854 if (!LexParenthesizedBalancedTokenSoup(Soup))
3855 return std::nullopt;
3857 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3859 ++
Result.UnrecognizedParams;
3863 if (CurTok.
is(tok::l_paren)) {
3865 if (!LexParenthesizedBalancedTokenSoup(Soup))
3866 return std::nullopt;
3869 Diag(CurTok, diag::err_pp_unknown_parameter) << 1 <<
Parameter;
3870 return std::nullopt;
3877void Preprocessor::HandleEmbedDirectiveImpl(
3879 StringRef BinaryContents) {
3880 if (BinaryContents.empty()) {
3888 size_t TokCount = Toks.size();
3889 auto NewToks = std::make_unique<Token[]>(TokCount);
3890 llvm::copy(Toks, NewToks.get());
3891 EnterTokenStream(std::move(NewToks), TokCount,
true,
true);
3898 size_t TotalNumToks = 1 + NumPrefixToks + NumSuffixToks;
3900 auto Toks = std::make_unique<Token[]>(TotalNumToks);
3905 CurIdx += NumPrefixToks;
3909 Data->BinaryData = BinaryContents;
3911 Toks[CurIdx].startToken();
3912 Toks[CurIdx].setKind(tok::annot_embed);
3913 Toks[CurIdx].setAnnotationRange(HashLoc);
3914 Toks[CurIdx++].setAnnotationValue(
Data);
3919 CurIdx += NumSuffixToks;
3922 assert(CurIdx == TotalNumToks &&
"Calculated the incorrect number of tokens");
3923 EnterTokenStream(std::move(Toks), TotalNumToks,
true,
true);
3930 Diag(EmbedTok, diag::warn_compat_pp_embed_directive);
3932 Diag(EmbedTok, diag::ext_pp_embed_directive)
3933 << (LangOpts.CPlusPlus ? 1 : 0);
3940 if (FilenameTok.
isNot(tok::header_name)) {
3942 if (FilenameTok.
isNot(tok::eod))
3955 std::optional<LexEmbedParametersResult> Params =
3958 assert((Params || CurTok.
is(tok::eod)) &&
3959 "expected success or to be at the end of the directive");
3966 StringRef OriginalFilename =
Filename;
3974 if (!MaybeFileRef) {
3976 if (Callbacks && Callbacks->EmbedFileNotFound(OriginalFilename)) {
3979 Diag(FilenameTok, diag::err_pp_file_not_found) <<
Filename;
3982 std::optional<llvm::MemoryBufferRef> MaybeFile =
3986 Diag(FilenameTok, diag::err_cannot_open_file)
3987 <<
Filename <<
"a buffer to the contents could not be created";
3990 StringRef BinaryContents = MaybeFile->getBuffer();
3995 if (Params->MaybeOffsetParam) {
4000 BinaryContents = BinaryContents.substr(Params->MaybeOffsetParam->Offset);
4003 if (Params->MaybeLimitParam) {
4007 BinaryContents = BinaryContents.substr(0, Params->MaybeLimitParam->Limit);
4011 Callbacks->EmbedDirective(HashLoc,
Filename, isAngled, MaybeFileRef,
4013 HandleEmbedDirectiveImpl(HashLoc, *Params, BinaryContents);
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 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 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.
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()
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...
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)
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.
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.
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 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...
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)
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.
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 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.
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 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.
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.
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.