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 std::binary_search(std::begin(ReservedMacro), std::end(ReservedMacro),
157 const StringRef MacroName) {
167 if (MacroName.starts_with(
"__STDC"))
170 if (MacroName ==
"__cplusplus")
173 if (MacroName.starts_with(
"__cpp"))
181 if (Lang.CPlusPlus &&
202 if (Lang.CPlusPlus11 && (
Text ==
"override" ||
Text ==
"final"))
227 if (::llvm::sys::path::begin(Include)->equals_insensitive(
"boost"))
232 static const size_t MaxStdHeaderNameLen = 18u;
233 if (Include.size() > MaxStdHeaderNameLen)
238 for (
char &Ch : LowerInclude) {
240 if (
static_cast<unsigned char>(Ch) > 0x7f)
243 if (Ch >=
'A' && Ch <=
'Z')
246 else if (::llvm::sys::path::is_separator(Ch))
251 return llvm::StringSwitch<bool>(LowerInclude)
253 .Cases(
"assert.h",
"complex.h",
"ctype.h",
"errno.h",
"fenv.h",
true)
254 .Cases(
"float.h",
"inttypes.h",
"iso646.h",
"limits.h",
"locale.h",
true)
255 .Cases(
"math.h",
"setjmp.h",
"signal.h",
"stdalign.h",
"stdarg.h",
true)
256 .Cases(
"stdatomic.h",
"stdbool.h",
"stdckdint.h",
"stddef.h",
true)
257 .Cases(
"stdint.h",
"stdio.h",
"stdlib.h",
"stdnoreturn.h",
true)
258 .Cases(
"string.h",
"tgmath.h",
"threads.h",
"time.h",
"uchar.h",
true)
259 .Cases(
"wchar.h",
"wctype.h",
true)
262 .Cases(
"cassert",
"ccomplex",
"cctype",
"cerrno",
"cfenv",
true)
263 .Cases(
"cfloat",
"cinttypes",
"ciso646",
"climits",
"clocale",
true)
264 .Cases(
"cmath",
"csetjmp",
"csignal",
"cstdalign",
"cstdarg",
true)
265 .Cases(
"cstdbool",
"cstddef",
"cstdint",
"cstdio",
"cstdlib",
true)
266 .Cases(
"cstring",
"ctgmath",
"ctime",
"cuchar",
"cwchar",
true)
267 .Case(
"cwctype",
true)
270 .Cases(
"algorithm",
"fstream",
"list",
"regex",
"thread",
true)
271 .Cases(
"array",
"functional",
"locale",
"scoped_allocator",
"tuple",
true)
272 .Cases(
"atomic",
"future",
"map",
"set",
"type_traits",
true)
273 .Cases(
"bitset",
"initializer_list",
"memory",
"shared_mutex",
"typeindex",
true)
274 .Cases(
"chrono",
"iomanip",
"mutex",
"sstream",
"typeinfo",
true)
275 .Cases(
"codecvt",
"ios",
"new",
"stack",
"unordered_map",
true)
276 .Cases(
"complex",
"iosfwd",
"numeric",
"stdexcept",
"unordered_set",
true)
277 .Cases(
"condition_variable",
"iostream",
"ostream",
"streambuf",
"utility",
true)
278 .Cases(
"deque",
"istream",
"queue",
"string",
"valarray",
true)
279 .Cases(
"exception",
"iterator",
"random",
"strstream",
"vector",
true)
280 .Cases(
"forward_list",
"limits",
"ratio",
"system_error",
true)
283 .Cases(
"aio.h",
"arpa/inet.h",
"cpio.h",
"dirent.h",
"dlfcn.h",
true)
284 .Cases(
"fcntl.h",
"fmtmsg.h",
"fnmatch.h",
"ftw.h",
"glob.h",
true)
285 .Cases(
"grp.h",
"iconv.h",
"langinfo.h",
"libgen.h",
"monetary.h",
true)
286 .Cases(
"mqueue.h",
"ndbm.h",
"net/if.h",
"netdb.h",
"netinet/in.h",
true)
287 .Cases(
"netinet/tcp.h",
"nl_types.h",
"poll.h",
"pthread.h",
"pwd.h",
true)
288 .Cases(
"regex.h",
"sched.h",
"search.h",
"semaphore.h",
"spawn.h",
true)
289 .Cases(
"strings.h",
"stropts.h",
"sys/ipc.h",
"sys/mman.h",
"sys/msg.h",
true)
290 .Cases(
"sys/resource.h",
"sys/select.h",
"sys/sem.h",
"sys/shm.h",
"sys/socket.h",
true)
291 .Cases(
"sys/stat.h",
"sys/statvfs.h",
"sys/time.h",
"sys/times.h",
"sys/types.h",
true)
292 .Cases(
"sys/uio.h",
"sys/un.h",
"sys/utsname.h",
"sys/wait.h",
"syslog.h",
true)
293 .Cases(
"tar.h",
"termios.h",
"trace.h",
"ulimit.h",
true)
294 .Cases(
"unistd.h",
"utime.h",
"utmpx.h",
"wordexp.h",
true)
306static std::optional<StringRef>
310 for (StringRef
C : Candidates) {
311 if (LHS.equals_insensitive(
C)) {
319 size_t Length = LHS.size();
320 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;
322 std::optional<std::pair<StringRef, size_t>> SimilarStr;
323 for (StringRef
C : Candidates) {
324 size_t CurDist = LHS.edit_distance(
C,
true);
325 if (CurDist <= MaxDist) {
328 SimilarStr = {
C, CurDist};
329 }
else if (CurDist < SimilarStr->second) {
331 SimilarStr = {
C, CurDist};
337 return SimilarStr->first;
346 if (MacroNameTok.
is(tok::eod))
347 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
351 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
357 ? diag::ext_pp_operator_used_as_macro_name
358 : diag::err_pp_operator_used_as_macro_name)
359 << II << MacroNameTok.
getKind();
366 return Diag(MacroNameTok, diag::err_defined_macro_name);
390 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
392 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_attribute_id)
409void Preprocessor::ReadMacroName(
Token &MacroNameTok,
MacroUse isDefineUndef,
414 if (MacroNameTok.
is(tok::code_completion)) {
426 if (MacroNameTok.
isNot(tok::eod)) {
427 MacroNameTok.
setKind(tok::eod);
451 while (Tmp.
is(tok::comment))
454 if (Tmp.
is(tok::eod))
462 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
465 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
469void Preprocessor::SuggestTypoedDirective(
const Token &Tok,
475 std::vector<StringRef> Candidates = {
476 "if",
"ifdef",
"ifndef",
"elif",
"else",
"endif"
478 if (LangOpts.C23 || LangOpts.CPlusPlus23)
479 Candidates.insert(Candidates.end(), {
"elifdef",
"elifndef"});
487 StringRef SuggValue = *Sugg;
490 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;
502void Preprocessor::SkipExcludedConditionalBlock(
SourceLocation HashTokenLoc,
504 bool FoundNonSkipPortion,
515 assert(!SkippingExcludedConditionalBlock &&
516 "calling SkipExcludedConditionalBlock recursively");
520 assert(!CurTokenLexer &&
"Conditional PP block cannot appear in a macro!");
521 assert(CurPPLexer &&
"Conditional PP block must be in a file!");
522 assert(CurLexer &&
"Conditional PP block but no current lexer set!");
524 if (PreambleConditionalStack.reachedEOFWhileSkipping())
525 PreambleConditionalStack.clearSkipInfo();
528 FoundNonSkipPortion, FoundElse);
538 struct SkippingRangeStateTy {
541 const char *BeginPtr =
nullptr;
542 unsigned *SkipRangePtr =
nullptr;
546 void beginLexPass() {
552 BeginPtr = PP.CurLexer->getBufferLocation();
553 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
555 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
560 void endLexPass(
const char *Hashptr) {
563 assert(PP.CurLexer->isDependencyDirectivesLexer());
568 if (!*SkipRangePtr) {
569 *SkipRangePtr = Hashptr - BeginPtr;
571 assert(*SkipRangePtr ==
unsigned(Hashptr - BeginPtr));
573 SkipRangePtr =
nullptr;
575 } SkippingRangeState(*
this);
578 if (CurLexer->isDependencyDirectivesLexer()) {
579 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
581 SkippingRangeState.beginLexPass();
585 if (Tok.
is(tok::code_completion)) {
593 if (Tok.
is(tok::eof)) {
597 if (PreambleConditionalStack.isRecording())
598 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,
611 if (Tok.
is(tok::eof))
618 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
620 assert(Tok.
is(tok::hash));
621 const char *Hashptr = CurLexer->getBufferLocation() - Tok.
getLength();
622 assert(CurLexer->getSourceLocation(Hashptr) == Tok.
getLocation());
629 if (Tok.
isNot(tok::raw_identifier)) {
632 if (CurLexer) CurLexer->resetExtendedTokenMode();
643 char FirstChar = RI[0];
644 if (FirstChar >=
'a' && FirstChar <=
'z' &&
645 FirstChar !=
'i' && FirstChar !=
'e') {
648 if (CurLexer) CurLexer->resetExtendedTokenMode();
655 char DirectiveBuf[20];
661 size_t IdLen = DirectiveStr.size();
665 if (CurLexer) CurLexer->resetExtendedTokenMode();
668 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
669 Directive = StringRef(DirectiveBuf, IdLen);
693 assert(!InCond &&
"Can't be skipping if not in a conditional!");
697 SkippingRangeState.endLexPass(Hashptr);
709 }
else if (Sub ==
"lse") {
716 SkippingRangeState.endLexPass(Hashptr);
720 Diag(Tok, diag::pp_err_else_after_else);
740 }
else if (Sub ==
"lif") {
744 SkippingRangeState.endLexPass(Hashptr);
761 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
764 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
768 const bool CondValue = DER.Conditional;
782 }
else if (Sub ==
"lifdef" ||
784 bool IsElifDef =
Sub ==
"lifdef";
786 Token DirectiveToken = Tok;
789 SkippingRangeState.endLexPass(Hashptr);
794 if (LangOpts.CPlusPlus)
795 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
796 : diag::ext_cxx23_pp_directive;
798 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
799 : diag::ext_c23_pp_directive;
804 Diag(Tok, diag::pp_err_elif_after_else)
818 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
821 ReadMacroName(MacroNameTok);
826 if (MacroNameTok.
is(tok::eod)) {
842 Callbacks->Elifdef(DirectiveToken.
getLocation(), MacroNameTok,
845 Callbacks->Elifndef(DirectiveToken.
getLocation(), MacroNameTok,
850 if (
static_cast<bool>(MI) == IsElifDef) {
864 if (CurLexer) CurLexer->resetExtendedTokenMode();
875 Callbacks->SourceRangeSkipped(
907 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
915 auto ID =
SM.getFileID(
SM.getExpansionLoc(
Loc));
916 auto FE =
SM.getFileEntryRefForID(ID);
925 bool InPrivateHeader =
false;
927 if (!Header.isAccessibleFrom(IncM)) {
932 InPrivateHeader =
true;
968 Loc =
SM.getIncludeLoc(ID);
980 bool *IsFrameworkFound,
bool SkipCache,
bool OpenFile,
bool CacheFailures) {
985 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
990 bool BuildSystemModule =
false;
991 if (!FromDir && !FromFile) {
1014 Includers.push_back(std::make_pair(std::nullopt, *IncludeDir));
1019 Includers.push_back(std::make_pair(*FileEnt, *CWD));
1022 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1028 if (LangOpts.MSVCCompat && !isAngled) {
1029 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1030 if (IsFileLexer(ISEntry))
1032 Includers.push_back(std::make_pair(*FileEnt, FileEnt->
getDir()));
1037 CurDir = CurDirLookup;
1045 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
1046 Includers, SearchPath, RelativePath, RequestingModule,
1047 SuggestedModule,
nullptr,
1048 nullptr, SkipCache)) {
1050 TmpFromDir = TmpCurDir;
1052 if (&FE->getFileEntry() == FromFile) {
1054 FromDir = TmpFromDir;
1063 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,
1064 RelativePath, RequestingModule, SuggestedModule, IsMapped,
1065 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);
1073 if (IsFileLexer()) {
1076 Filename, *CurFileEnt, SearchPath, RelativePath, RequestingModule,
1083 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1084 if (IsFileLexer(ISEntry)) {
1085 if ((CurFileEnt = ISEntry.ThePPLexer->
getFileEntry())) {
1087 Filename, *CurFileEnt, SearchPath, RelativePath,
1088 RequestingModule, SuggestedModule)) {
1096 return std::nullopt;
1103 if (llvm::sys::path::is_absolute(
Filename)) {
1107 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1111 StringRef StartingFrom, StringRef
FileName,
1112 bool RemoveInitialFileComponentFromLookupPath) {
1113 llvm::sys::path::native(StartingFrom, LookupPath);
1114 if (RemoveInitialFileComponentFromLookupPath)
1115 llvm::sys::path::remove_filename(LookupPath);
1116 if (!LookupPath.empty() &&
1117 !llvm::sys::path::is_separator(LookupPath.back())) {
1118 LookupPath.push_back(llvm::sys::path::get_separator().front());
1127 if (LookupFromFile) {
1130 if (!FullFileDir.empty()) {
1131 SeparateComponents(LookupPath, FullFileDir,
Filename,
true);
1133 LookupPath, OpenFile,
true,
false);
1135 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1136 llvm::consumeError(ShouldBeEntry.takeError());
1143 if (MaybeWorkingDirEntry) {
1145 StringRef WorkingDir = WorkingDirEntry.
getName();
1146 if (!WorkingDir.empty()) {
1147 SeparateComponents(LookupPath, WorkingDir,
Filename,
false);
1149 LookupPath, OpenFile,
true,
false);
1151 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1152 llvm::consumeError(ShouldBeEntry.takeError());
1157 for (
const auto &Entry : PPOpts->EmbedEntries) {
1159 SeparateComponents(LookupPath, Entry,
Filename,
false);
1161 LookupPath, OpenFile,
true,
false);
1163 return llvm::expectedToOptional(std::move(ShouldBeEntry));
1164 llvm::consumeError(ShouldBeEntry.takeError());
1166 return std::nullopt;
1176 : PP(pp), save(pp->DisableMacroExpansion) {
1177 if (pp->MacroExpansionInDirectivesOverride)
1178 pp->DisableMacroExpansion =
false;
1182 PP->DisableMacroExpansion = save;
1199 if (II->getPPKeywordID() == tok::pp_define) {
1200 return HandleDefineDirective(
Result,
1203 if (SkippingUntilPCHThroughHeader &&
1204 II->getPPKeywordID() == tok::pp_include) {
1205 return HandleIncludeDirective(HashLoc,
Result);
1207 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
1209 auto *II =
Result.getIdentifierInfo();
1210 if (II && II->getName() ==
"hdrstop")
1228 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
1230 bool ImmediatelyAfterTopLevelIfndef =
1258 switch (II->getPPKeywordID()) {
1259 case tok::pp_include:
1260 case tok::pp_import:
1261 case tok::pp_include_next:
1262 case tok::pp___include_macros:
1263 case tok::pp_pragma:
1265 Diag(
Result, diag::err_embedded_directive) << II->getName();
1266 Diag(*ArgMacro, diag::note_macro_expansion_here)
1281 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
1284 switch (
Result.getKind()) {
1291 case tok::code_completion:
1297 case tok::numeric_constant:
1304 return HandleDigitDirective(
Result);
1314 return HandleIfDirective(
Result, SavedHash, ReadAnyTokensBeforeDirective);
1316 return HandleIfdefDirective(
Result, SavedHash,
false,
1318 case tok::pp_ifndef:
1319 return HandleIfdefDirective(
Result, SavedHash,
true,
1320 ReadAnyTokensBeforeDirective);
1322 case tok::pp_elifdef:
1323 case tok::pp_elifndef:
1327 return HandleElseDirective(
Result, SavedHash);
1329 return HandleEndifDirective(
Result);
1332 case tok::pp_include:
1335 case tok::pp___include_macros:
1340 case tok::pp_define:
1341 return HandleDefineDirective(
Result, ImmediatelyAfterTopLevelIfndef);
1343 return HandleUndefDirective();
1347 return HandleLineDirective();
1351 return HandleUserDiagnosticDirective(
Result,
false);
1354 case tok::pp_pragma:
1358 case tok::pp_import:
1360 case tok::pp_include_next:
1363 case tok::pp_warning:
1364 if (LangOpts.CPlusPlus)
1366 ? diag::warn_cxx23_compat_warning_directive
1367 : diag::ext_pp_warning_directive)
1370 Diag(
Result, LangOpts.C23 ? diag::warn_c23_compat_warning_directive
1371 : diag::ext_pp_warning_directive)
1374 return HandleUserDiagnosticDirective(
Result,
true);
1376 return HandleIdentSCCSDirective(
Result);
1378 return HandleIdentSCCSDirective(
Result);
1384 case tok::pp_assert:
1387 case tok::pp_unassert:
1391 case tok::pp___public_macro:
1393 return HandleMacroPublicDirective(
Result);
1396 case tok::pp___private_macro:
1398 return HandleMacroPrivateDirective();
1409 auto Toks = std::make_unique<Token[]>(2);
1411 Toks[0] = SavedHash;
1416 if (
Result.is(tok::hashhash))
1417 Toks[1].setKind(tok::unknown);
1422 EnterTokenStream(std::move(Toks), 2,
false,
false);
1428 Diag(
Result, diag::err_pp_invalid_directive) << 0;
1440 bool IsGNULineDirective=
false) {
1441 if (DigitTok.
isNot(tok::numeric_constant)) {
1442 PP.
Diag(DigitTok, DiagID);
1444 if (DigitTok.
isNot(tok::eod))
1450 IntegerBuffer.resize(DigitTok.
getLength());
1451 const char *DigitTokBegin = &IntegerBuffer[0];
1461 for (
unsigned i = 0; i != ActualLength; ++i) {
1464 if (DigitTokBegin[i] ==
'\'')
1467 if (!
isDigit(DigitTokBegin[i])) {
1469 diag::err_pp_line_digit_sequence) << IsGNULineDirective;
1474 unsigned NextVal = Val*10+(DigitTokBegin[i]-
'0');
1475 if (NextVal < Val) {
1476 PP.
Diag(DigitTok, DiagID);
1483 if (DigitTokBegin[0] ==
'0' && Val)
1485 << IsGNULineDirective;
1497void Preprocessor::HandleLineDirective() {
1505 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*
this))
1509 Diag(DigitTok, diag::ext_pp_line_zero);
1513 unsigned LineLimit = 32768U;
1514 if (LangOpts.C99 || LangOpts.CPlusPlus11)
1515 LineLimit = 2147483648U;
1516 if (LineNo >= LineLimit)
1517 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
1518 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)
1519 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);
1521 int FilenameID = -1;
1527 if (StrTok.
is(tok::eod))
1529 else if (StrTok.
isNot(tok::string_literal)) {
1530 Diag(StrTok, diag::err_pp_line_invalid_filename);
1534 Diag(StrTok, diag::err_invalid_string_udl);
1540 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1546 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1581 if (FlagTok.
is(tok::eod))
return false;
1582 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1589 if (FlagTok.
is(tok::eod))
return false;
1590 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1592 }
else if (FlagVal == 2) {
1608 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {
1609 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
1615 if (FlagTok.
is(tok::eod))
return false;
1616 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1622 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1630 if (FlagTok.
is(tok::eod))
return false;
1631 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1636 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1644 if (FlagTok.
is(tok::eod))
return false;
1647 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1659void Preprocessor::HandleDigitDirective(
Token &DigitTok) {
1663 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
1670 bool IsFileEntry =
false, IsFileExit =
false;
1671 int FilenameID = -1;
1676 if (StrTok.
is(tok::eod)) {
1677 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1680 }
else if (StrTok.
isNot(tok::string_literal)) {
1681 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1685 Diag(StrTok, diag::err_invalid_string_udl);
1691 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1697 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1707 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1711 if (!(IsFileExit &&
Literal.GetString().empty()))
1717 IsFileExit, FileKind);
1726 else if (IsFileExit)
1735void Preprocessor::HandleUserDiagnosticDirective(
Token &Tok,
1743 CurLexer->ReadToEndOfLine(&Message);
1747 StringRef Msg = Message.str().ltrim(
' ');
1750 Diag(Tok, diag::pp_hash_warning) << Msg;
1752 Diag(Tok, diag::err_pp_hash_error) << Msg;
1757void Preprocessor::HandleIdentSCCSDirective(
Token &Tok) {
1759 Diag(Tok, diag::ext_pp_ident_directive);
1766 if (StrTok.
isNot(tok::string_literal) &&
1767 StrTok.
isNot(tok::wide_string_literal)) {
1768 Diag(StrTok, diag::err_pp_malformed_ident);
1769 if (StrTok.
isNot(tok::eod))
1775 Diag(StrTok, diag::err_invalid_string_udl);
1792void Preprocessor::HandleMacroPublicDirective(
Token &Tok) {
1794 ReadMacroName(MacroNameTok,
MU_Undef);
1797 if (MacroNameTok.
is(tok::eod))
1809 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1819void Preprocessor::HandleMacroPrivateDirective() {
1821 ReadMacroName(MacroNameTok,
MU_Undef);
1824 if (MacroNameTok.
is(tok::eod))
1836 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1856 StringRef &Buffer) {
1858 assert(!Buffer.empty() &&
"Can't have tokens with empty spellings!");
1870 if (Buffer[0] ==
'<') {
1871 if (Buffer.back() !=
'>') {
1872 Diag(
Loc, diag::err_pp_expects_filename);
1873 Buffer = StringRef();
1877 }
else if (Buffer[0] ==
'"') {
1878 if (Buffer.back() !=
'"') {
1879 Diag(
Loc, diag::err_pp_expects_filename);
1880 Buffer = StringRef();
1885 Diag(
Loc, diag::err_pp_expects_filename);
1886 Buffer = StringRef();
1891 if (Buffer.size() <= 2) {
1892 Diag(
Loc, diag::err_pp_empty_filename);
1893 Buffer = StringRef();
1898 Buffer = Buffer.substr(1, Buffer.size()-2);
1905 void *AnnotationVal) {
1908 auto Tok = std::make_unique<Token[]>(1);
1914 EnterTokenStream(std::move(Tok), 1,
true,
false);
1921 ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>
Path,
1924 for (
size_t I = 0, N =
Path.size(); I != N; ++I) {
1927 PathString +=
Path[I].first->getName();
1930 int IncludeKind = 0;
1932 case tok::pp_include:
1936 case tok::pp_import:
1940 case tok::pp_include_next:
1944 case tok::pp___include_macros:
1949 llvm_unreachable(
"unknown include directive kind");
1952 PP.
Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
1953 << IncludeKind << PathString;
1960 StringRef RealPathName,
1961 llvm::sys::path::Style Separator) {
1962 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
1963 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
1965 bool SuggestReplacement =
false;
1967 auto IsSep = [Separator](StringRef Component) {
1968 return Component.size() == 1 &&
1969 llvm::sys::path::is_separator(Component[0], Separator);
1974 for (
auto &Component : llvm::reverse(Components)) {
1975 if (
"." == Component) {
1976 }
else if (
".." == Component) {
1980 }
else if (RealPathComponentIter != RealPathComponentEnd) {
1981 if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&
1982 Component != *RealPathComponentIter) {
1986 SuggestReplacement =
1987 RealPathComponentIter->equals_insensitive(Component);
1988 if (!SuggestReplacement)
1990 Component = *RealPathComponentIter;
1992 ++RealPathComponentIter;
1995 return SuggestReplacement;
2004 Module *ShadowingModule =
nullptr;
2012 }
else if (ShadowingModule) {
2015 diag::note_previous_definition);
2026std::pair<ConstSearchDirIterator, const FileEntry *>
2027Preprocessor::getIncludeNextStart(
const Token &IncludeNextTok)
const {
2032 const FileEntry *LookupFromFile =
nullptr;
2040 Diag(IncludeNextTok, diag::pp_include_next_in_primary);
2041 }
else if (CurLexerSubmodule) {
2044 assert(CurPPLexer &&
"#include_next directive in macro?");
2046 LookupFromFile = *FE;
2048 }
else if (!Lookup) {
2053 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
2059 return {Lookup, LookupFromFile};
2075 if (FilenameTok.
isNot(tok::header_name)) {
2077 if (FilenameTok.
isNot(tok::eod))
2089 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
2090 EndLoc, LookupFrom, LookupFromFile);
2091 switch (Action.Kind) {
2092 case ImportAction::None:
2093 case ImportAction::SkippedModuleImport:
2095 case ImportAction::ModuleBegin:
2097 tok::annot_module_begin, Action.ModuleForHeader);
2099 case ImportAction::HeaderUnitImport:
2101 Action.ModuleForHeader);
2103 case ImportAction::ModuleImport:
2105 tok::annot_module_include, Action.ModuleForHeader);
2107 case ImportAction::Failure:
2109 "This should be an early exit only to a fatal error");
2112 CurLexer->cutOffLexing();
2120 const Token &FilenameTok,
bool &IsFrameworkFound,
bool IsImportDecl,
2122 const FileEntry *LookupFromFile, StringRef &LookupFilename,
2126 if (LangOpts.AsmPreprocessor)
2130 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
2131 bool RequestingModuleIsModuleInterface =
2135 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
2140 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,
2141 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2142 &SuggestedModule, &IsMapped, &IsFrameworkFound);
2144 DiagnoseHeaderInclusion(*
File);
2149 if (Callbacks && Callbacks->FileNotFound(
Filename))
2150 return std::nullopt;
2152 if (SuppressIncludeNotFoundError)
2153 return std::nullopt;
2160 FilenameLoc, LookupFilename,
false, LookupFrom, LookupFromFile, CurDir,
2161 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2162 &SuggestedModule, &IsMapped,
2165 DiagnoseHeaderInclusion(*
File);
2166 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
2176 StringRef OriginalFilename =
Filename;
2177 if (LangOpts.SpellChecking) {
2180 auto CorrectTypoFilename = [](llvm::StringRef
Filename) {
2187 StringRef TypoCorrectionName = CorrectTypoFilename(
Filename);
2188 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);
2191 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,
2192 LookupFromFile, CurDir, Callbacks ? &SearchPath :
nullptr,
2193 Callbacks ? &RelativePath :
nullptr, &SuggestedModule, &IsMapped,
2196 DiagnoseHeaderInclusion(*
File);
2199 FilenameRange,
"<" + TypoCorrectionName.str() +
">")
2201 FilenameRange,
"\"" + TypoCorrectionName.str() +
"\"");
2202 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
2203 << OriginalFilename << TypoCorrectionName << Hint;
2207 LookupFilename = TypoCorrectionLookupName;
2213 assert(!
File &&
"expected missing file");
2214 Diag(FilenameTok, diag::err_pp_file_not_found)
2215 << OriginalFilename << FilenameRange;
2216 if (IsFrameworkFound) {
2217 size_t SlashPos = OriginalFilename.find(
'/');
2218 assert(SlashPos != StringRef::npos &&
2219 "Include with framework name should have '/' in the filename");
2220 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
2223 assert(CacheEntry.
Directory &&
"Found framework should be in cache");
2224 Diag(FilenameTok, diag::note_pp_framework_without_header)
2225 << OriginalFilename.substr(SlashPos + 1) << FrameworkName
2229 return std::nullopt;
2244Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
2254 StringRef OriginalFilename =
Filename;
2261 return {ImportAction::None};
2263 bool IsImportDecl = HashLoc.
isInvalid();
2267 if (PragmaARCCFCodeAuditedInfo.second.isValid()) {
2268 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
2269 Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);
2276 if (PragmaAssumeNonNullLoc.
isValid()) {
2277 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
2278 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
2289 if (!NewName.empty())
2294 bool IsMapped =
false;
2295 bool IsFrameworkFound =
false;
2303 StringRef LookupFilename =
Filename;
2308 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;
2309 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {
2311 llvm::sys::path::native(NormalizedPath);
2312 LookupFilename = NormalizedPath;
2313 BackslashStyle = llvm::sys::path::Style::windows;
2317 &CurDir,
Filename, FilenameLoc, FilenameRange, FilenameTok,
2318 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
2319 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
2323 SkippingUntilPCHThroughHeader =
false;
2324 return {ImportAction::None};
2342 enum { Enter,
Import,
Skip, IncludeLimitReached } Action = Enter;
2344 if (PPOpts->SingleFileParseMode)
2345 Action = IncludeLimitReached;
2350 if (Action == Enter && HasReachedMaxIncludeDepth &&
File &&
2352 Action = IncludeLimitReached;
2359 bool MaybeTranslateInclude = Action == Enter &&
File && ModuleToImport &&
2363 bool UsableHeaderUnit =
false;
2364 if (
getLangOpts().CPlusPlusModules && ModuleToImport &&
2366 if (TrackGMFState.inGMF() || IsImportDecl)
2367 UsableHeaderUnit =
true;
2368 else if (!IsImportDecl) {
2370 ModuleToImport =
nullptr;
2374 bool UsableClangHeaderModule =
2381 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {
2389 diag::note_implicit_top_level_module_import_here)
2391 return {ImportAction::None};
2398 for (
Module *Mod = ModuleToImport; Mod; Mod = Mod->
Parent)
2401 std::reverse(
Path.begin(),
Path.end());
2414 assert((Imported ==
nullptr || Imported == ModuleToImport) &&
2415 "the imported module is different than the suggested one");
2421 static_cast<Module *
>(Imported)->getTopLevelModule());
2426 ModuleToImport =
nullptr;
2435 assert(CurLexer &&
"#include but no current lexer set!");
2437 CurLexer->FormTokenWithChars(
Result, CurLexer->BufferEnd, tok::eof);
2438 CurLexer->cutOffLexing();
2440 return {ImportAction::None};
2461 bool IsFirstIncludeOfFile =
false;
2465 if (Action == Enter &&
File &&
2468 IsFirstIncludeOfFile)) {
2479 if (UsableHeaderUnit && !
getLangOpts().CompilingPCH)
2480 Action = TrackGMFState.inGMF() ?
Import :
Skip;
2482 Action = (ModuleToImport && !
getLangOpts().CompilingPCH) ? Import :
Skip;
2490 if (Action == Enter &&
File && PreambleConditionalStack.isRecording() &&
2493 diag::err_pp_including_mainfile_in_preamble);
2494 return {ImportAction::None};
2497 if (Callbacks && !IsImportDecl) {
2500 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,
2501 FilenameRange,
File, SearchPath, RelativePath,
2502 SuggestedModule.
getModule(), Action == Import,
2505 Callbacks->FileSkipped(*
File, FilenameTok, FileCharacter);
2509 return {ImportAction::None};
2513 if (IsImportDecl && !ModuleToImport) {
2514 Diag(FilenameTok, diag::err_header_import_not_header_unit)
2515 << OriginalFilename <<
File->getName();
2516 return {ImportAction::None};
2521 const bool CheckIncludePathPortability =
2522 !IsMapped && !
File->getFileEntry().tryGetRealPathName().empty();
2524 if (CheckIncludePathPortability) {
2525 StringRef Name = LookupFilename;
2526 StringRef NameWithoriginalSlashes =
Filename;
2530 bool NameWasUNC = Name.consume_front(
"\\\\?\\");
2531 NameWithoriginalSlashes.consume_front(
"\\\\?\\");
2533 StringRef RealPathName =
File->getFileEntry().tryGetRealPathName();
2535 llvm::sys::path::end(Name));
2548 if (llvm::sys::path::is_absolute(Name) &&
2549 llvm::sys::path::is_absolute(RealPathName) &&
2552 assert(Components.size() >= 3 &&
"should have drive, backslash, name");
2553 assert(Components[0].size() == 2 &&
"should start with drive");
2554 assert(Components[0][1] ==
':' &&
"should have colon");
2555 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();
2556 RealPathName = FixedDriveRealPath;
2562 Path.reserve(Name.size()+2);
2563 Path.push_back(isAngled ?
'<' :
'"');
2565 const auto IsSep = [BackslashStyle](
char c) {
2566 return llvm::sys::path::is_separator(
c, BackslashStyle);
2569 for (
auto Component : Components) {
2581 if (!(Component.size() == 1 && IsSep(Component[0])))
2582 Path.append(Component);
2583 else if (
Path.size() != 1)
2587 if (
Path.size() > NameWithoriginalSlashes.size()) {
2588 Path.push_back(isAngled ?
'>' :
'"');
2591 assert(IsSep(NameWithoriginalSlashes[
Path.size()-1]));
2593 Path.push_back(NameWithoriginalSlashes[
Path.size()-1]);
2594 while (
Path.size() <= NameWithoriginalSlashes.size() &&
2595 IsSep(NameWithoriginalSlashes[
Path.size()-1]));
2601 Path = (
Path.substr(0, 1) +
"\\\\?\\" +
Path.substr(1)).str();
2608 ? diag::pp_nonportable_path
2609 : diag::pp_nonportable_system_path;
2610 Diag(FilenameTok, DiagId) <<
Path <<
2619 return {ImportAction::SkippedModuleImport, ModuleToImport};
2620 return {ImportAction::None};
2622 case IncludeLimitReached:
2625 return {ImportAction::None};
2629 assert(ModuleToImport &&
"no module to import");
2634 tok::pp___include_macros)
2635 return {ImportAction::None};
2637 return {ImportAction::ModuleImport, ModuleToImport};
2645 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
2646 Diag(FilenameTok, diag::err_pp_include_too_deep);
2647 HasReachedMaxIncludeDepth =
true;
2648 return {ImportAction::None};
2652 Diag(FilenameTok, diag::warn_pp_include_angled_in_module_purview)
2664 return ImportAction::Failure;
2669 IsFirstIncludeOfFile))
2670 return {ImportAction::None};
2674 if (ModuleToImport && !ModuleToImport->
isHeaderUnit()) {
2679 diag::err_module_build_shadowed_submodule)
2682 diag::note_previous_definition);
2683 return {ImportAction::None};
2695 return {ImportAction::None};
2697 assert(!CurLexerSubmodule &&
"should not have marked this as a module yet");
2698 CurLexerSubmodule = ModuleToImport;
2708 return {ImportAction::ModuleBegin, ModuleToImport};
2711 assert(!IsImportDecl &&
"failed to diagnose missing module for import decl");
2712 return {ImportAction::None};
2717void Preprocessor::HandleIncludeNextDirective(
SourceLocation HashLoc,
2718 Token &IncludeNextTok) {
2719 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
2723 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);
2725 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
2730void Preprocessor::HandleMicrosoftImportDirective(
Token &Tok) {
2736 Diag(Tok, diag::err_pp_import_directive_ms );
2747 if (!LangOpts.ObjC) {
2748 if (LangOpts.MSVCCompat)
2749 return HandleMicrosoftImportDirective(ImportTok);
2750 Diag(ImportTok, diag::ext_pp_import_directive);
2752 return HandleIncludeDirective(HashLoc, ImportTok);
2759void Preprocessor::HandleIncludeMacrosDirective(
SourceLocation HashLoc,
2760 Token &IncludeMacrosTok) {
2766 diag::pp_include_macros_out_of_predefines);
2773 HandleIncludeDirective(HashLoc, IncludeMacrosTok);
2778 assert(TmpTok.
isNot(tok::eof) &&
"Didn't find end of -imacros!");
2779 }
while (TmpTok.
isNot(tok::hashhash));
2790bool Preprocessor::ReadMacroParameterList(
MacroInfo *MI,
Token &Tok) {
2801 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
2805 Diag(Tok, LangOpts.CPlusPlus11 ?
2806 diag::warn_cxx98_compat_variadic_macro :
2807 diag::ext_variadic_macro);
2810 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
2811 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
2816 if (Tok.
isNot(tok::r_paren)) {
2817 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2826 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2834 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
2840 if (llvm::is_contained(Parameters, II)) {
2841 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
2853 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
2862 Diag(Tok, diag::ext_named_variadic_macro);
2866 if (Tok.
isNot(tok::r_paren)) {
2867 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2897 StringRef ValueText = II->
getName();
2898 StringRef TrimmedValue = ValueText;
2899 if (!ValueText.starts_with(
"__")) {
2900 if (ValueText.starts_with(
"_"))
2901 TrimmedValue = TrimmedValue.drop_front(1);
2905 TrimmedValue = TrimmedValue.drop_front(2);
2906 if (TrimmedValue.ends_with(
"__"))
2907 TrimmedValue = TrimmedValue.drop_back(2);
2909 return TrimmedValue == MacroText;
2916 return MacroName.
isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
2929MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
2930 const Token &MacroNameTok,
const bool ImmediatelyAfterHeaderGuard) {
2932 Token LastTok = MacroNameTok;
2940 auto _ = llvm::make_scope_exit([&]() {
2942 if (CurLexer->ParsingPreprocessorDirective)
2953 if (Tok.
is(tok::eod)) {
2954 if (ImmediatelyAfterHeaderGuard) {
2964 }
else if (Tok.
is(tok::l_paren)) {
2967 if (ReadMacroParameterList(MI, LastTok))
2981 }
else if (LangOpts.C99 || LangOpts.CPlusPlus11) {
2984 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
2993 if (Tok.
is(tok::at))
2995 else if (Tok.
is(tok::unknown)) {
3002 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
3004 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
3007 if (!Tok.
is(tok::eod))
3015 while (Tok.
isNot(tok::eod)) {
3017 Tokens.push_back(Tok);
3028 while (Tok.
isNot(tok::eod)) {
3031 if (!Tok.
isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
3032 Tokens.push_back(Tok);
3034 if (VAOCtx.isVAOptToken(Tok)) {
3036 if (VAOCtx.isInVAOpt()) {
3037 Diag(Tok, diag::err_pp_vaopt_nested_use);
3042 if (Tok.
isNot(tok::l_paren)) {
3043 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
3046 Tokens.push_back(Tok);
3047 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.
getLocation());
3049 if (Tok.
is(tok::hashhash)) {
3050 Diag(Tok, diag::err_vaopt_paste_at_start);
3054 }
else if (VAOCtx.isInVAOpt()) {
3055 if (Tok.
is(tok::r_paren)) {
3056 if (VAOCtx.sawClosingParen()) {
3057 assert(Tokens.size() >= 3 &&
3058 "Must have seen at least __VA_OPT__( "
3059 "and a subsequent tok::r_paren");
3060 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {
3061 Diag(Tok, diag::err_vaopt_paste_at_end);
3065 }
else if (Tok.
is(tok::l_paren)) {
3079 Tokens.push_back(Tok);
3086 if (Tok.
is(tok::hashhash)) {
3094 if (Tok.
is(tok::eod)) {
3095 Tokens.push_back(LastTok);
3100 Tokens[Tokens.size() - 1].is(tok::comma))
3104 Tokens.push_back(LastTok);
3113 if (!VAOCtx.isVAOptToken(Tok) &&
3122 LastTok.
setKind(tok::unknown);
3123 Tokens.push_back(LastTok);
3126 Diag(Tok, diag::err_pp_stringize_not_parameter)
3127 << LastTok.
is(tok::hashat);
3133 Tokens.push_back(LastTok);
3138 if (!VAOCtx.isVAOptToken(Tok)) {
3139 Tokens.push_back(Tok);
3146 if (VAOCtx.isInVAOpt()) {
3147 assert(Tok.
is(tok::eod) &&
"Must be at End Of preprocessing Directive");
3148 Diag(Tok, diag::err_pp_expected_after)
3149 << LastTok.
getKind() << tok::r_paren;
3150 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
3161 return II->
isStr(
"__strong") || II->
isStr(
"__weak") ||
3162 II->
isStr(
"__unsafe_unretained") || II->
isStr(
"__autoreleasing");
3167void Preprocessor::HandleDefineDirective(
3168 Token &DefineTok,
const bool ImmediatelyAfterHeaderGuard) {
3172 bool MacroShadowsKeyword;
3173 ReadMacroName(MacroNameTok,
MU_Define, &MacroShadowsKeyword);
3176 if (MacroNameTok.
is(tok::eod))
3183 emitFinalMacroWarning(MacroNameTok,
false);
3187 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
3189 MacroInfo *
const MI = ReadOptionalMacroParameterListAndBody(
3190 MacroNameTok, ImmediatelyAfterHeaderGuard);
3194 if (MacroShadowsKeyword &&
3196 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
3201 if (NumTokens != 0) {
3213 if (SkippingUntilPCHThroughHeader) {
3216 LangOpts.MicrosoftExt))
3220 if (!LangOpts.MicrosoftExt)
3231 emitFinalMacroWarning(MacroNameTok,
false);
3244 LangOpts.MicrosoftExt)) {
3263 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
3267 !MI->
isIdenticalTo(*OtherMI, *
this, LangOpts.MicrosoftExt)) {
3285 !MacroExpansionInDirectivesOverride &&
3294 Callbacks->MacroDefined(MacroNameTok, MD);
3307 Tok.
setKind(tok::kw__Static_assert);
3316void Preprocessor::HandleUndefDirective() {
3320 ReadMacroName(MacroNameTok,
MU_Undef);
3323 if (MacroNameTok.
is(tok::eod))
3335 emitFinalMacroWarning(MacroNameTok,
true);
3345 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
3350 Undef = AllocateUndefMacroDirective(MacroNameTok.
getLocation());
3356 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
3371void Preprocessor::HandleIfdefDirective(
Token &
Result,
3372 const Token &HashToken,
3374 bool ReadAnyTokensBeforeDirective) {
3379 ReadMacroName(MacroNameTok);
3382 if (MacroNameTok.
is(tok::eod)) {
3385 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3405 if (!ReadAnyTokensBeforeDirective && !MI) {
3406 assert(isIfndef &&
"#ifdef shouldn't reach here");
3418 Callbacks->Ifndef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3420 Callbacks->Ifdef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3423 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3427 if (PPOpts->SingleFileParseMode && !MI) {
3433 }
else if (!MI == isIfndef || RetainExcludedCB) {
3440 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3449void Preprocessor::HandleIfDirective(
Token &IfToken,
3450 const Token &HashToken,
3451 bool ReadAnyTokensBeforeDirective) {
3456 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
3457 const bool ConditionalTrue = DER.Conditional;
3466 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
3478 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3482 if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
3487 }
else if (ConditionalTrue || RetainExcludedCB) {
3501void Preprocessor::HandleEndifDirective(
Token &EndifToken) {
3510 Diag(EndifToken, diag::err_pp_endif_without_if);
3519 "This code should only be reachable in the non-skipping case!");
3527void Preprocessor::HandleElseDirective(
Token &
Result,
const Token &HashToken) {
3549 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3552 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3563 true,
Result.getLocation());
3567void Preprocessor::HandleElifFamilyDirective(
Token &ElifToken,
3568 const Token &HashToken,
3580 if (LangOpts.CPlusPlus)
3581 DiagID = LangOpts.CPlusPlus23 ? diag::warn_cxx23_compat_pp_directive
3582 : diag::ext_cxx23_pp_directive;
3584 DiagID = LangOpts.C23 ? diag::warn_c23_compat_pp_directive
3585 : diag::ext_c23_pp_directive;
3586 Diag(ElifToken, DiagID) << DirKind;
3599 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
3609 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
3614 Callbacks->Elif(ElifToken.
getLocation(), ConditionRange,
3617 case tok::pp_elifdef:
3620 case tok::pp_elifndef:
3624 assert(
false &&
"unexpected directive kind");
3629 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3632 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3641 SkipExcludedConditionalBlock(
3646std::optional<LexEmbedParametersResult>
3650 tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod;
3652 auto DiagMismatchedBracesAndSkipToEOD =
3654 std::pair<tok::TokenKind, SourceLocation> Matches) {
3656 Diag(Matches.second, diag::note_matching) << Matches.first;
3657 if (CurTok.
isNot(tok::eod))
3662 if (CurTok.
isNot(Kind)) {
3663 Diag(CurTok, diag::err_expected) << Kind;
3664 if (CurTok.
isNot(tok::eod))
3681 auto LexPPParameterName = [&]() -> std::optional<std::string> {
3684 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3685 return std::nullopt;
3692 if (CurTok.
is(tok::coloncolon)) {
3695 if (!ExpectOrDiagAndSkipToEOD(tok::identifier))
3696 return std::nullopt;
3702 return (llvm::Twine(Prefix->
getName()) +
"::" + Suffix->
getName()).str();
3704 return Prefix->
getName().str();
3711 auto NormalizeParameterName = [](StringRef Name) {
3712 if (Name.size() > 4 && Name.starts_with(
"__") && Name.ends_with(
"__"))
3713 return Name.substr(2, Name.size() - 4);
3717 auto LexParenthesizedIntegerExpr = [&]() -> std::optional<size_t> {
3720 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3721 return std::nullopt;
3726 bool EvaluatedDefined;
3727 DirectiveEvalResult LimitEvalResult = EvaluateDirectiveExpression(
3728 ParameterIfNDef, CurTok, EvaluatedDefined,
false);
3730 if (!LimitEvalResult.Value) {
3733 assert(CurTok.
is(tok::eod) &&
"expect to be at the end of directive");
3734 return std::nullopt;
3737 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3738 return std::nullopt;
3745 if (EvaluatedDefined) {
3746 Diag(CurTok, diag::err_defined_in_pp_embed);
3747 return std::nullopt;
3750 if (LimitEvalResult.Value) {
3751 const llvm::APSInt &
Result = *LimitEvalResult.Value;
3752 if (
Result.isNegative()) {
3753 Diag(CurTok, diag::err_requires_positive_value)
3755 return std::nullopt;
3757 return Result.getLimitedValue();
3759 return std::nullopt;
3765 return tok::r_paren;
3767 return tok::r_brace;
3769 return tok::r_square;
3771 llvm_unreachable(
"should not get here");
3775 auto LexParenthesizedBalancedTokenSoup =
3777 std::vector<std::pair<tok::TokenKind, SourceLocation>> BracketStack;
3780 if (!ExpectOrDiagAndSkipToEOD(tok::l_paren))
3784 bool WaitingForInnerCloseParen =
false;
3785 while (CurTok.
isNot(tok::eod) &&
3786 (WaitingForInnerCloseParen || CurTok.
isNot(tok::r_paren))) {
3791 WaitingForInnerCloseParen =
true;
3798 WaitingForInnerCloseParen =
false;
3801 case tok::r_square: {
3803 GetMatchingCloseBracket(BracketStack.back().first);
3804 if (BracketStack.empty() || CurTok.
getKind() != Matching) {
3805 DiagMismatchedBracesAndSkipToEOD(Matching, BracketStack.back());
3808 BracketStack.pop_back();
3811 Tokens.push_back(CurTok);
3816 if (!ExpectOrDiagAndSkipToEOD(tok::r_paren))
3824 while (!CurTok.
isOneOf(EndTokenKind, tok::eod)) {
3826 std::optional<std::string> ParamName = LexPPParameterName();
3828 return std::nullopt;
3829 StringRef
Parameter = NormalizeParameterName(*ParamName);
3836 if (
Result.MaybeLimitParam)
3839 std::optional<size_t> Limit = LexParenthesizedIntegerExpr();
3841 return std::nullopt;
3844 }
else if (
Parameter ==
"clang::offset") {
3845 if (
Result.MaybeOffsetParam)
3848 std::optional<size_t> Offset = LexParenthesizedIntegerExpr();
3850 return std::nullopt;
3854 if (
Result.MaybePrefixParam)
3858 if (!LexParenthesizedBalancedTokenSoup(Soup))
3859 return std::nullopt;
3861 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3863 if (
Result.MaybeSuffixParam)
3867 if (!LexParenthesizedBalancedTokenSoup(Soup))
3868 return std::nullopt;
3870 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3872 if (
Result.MaybeIfEmptyParam)
3876 if (!LexParenthesizedBalancedTokenSoup(Soup))
3877 return std::nullopt;
3879 std::move(Soup), {ParamStartLoc, CurTok.
getLocation()}};
3881 ++
Result.UnrecognizedParams;
3885 if (CurTok.
is(tok::l_paren)) {
3887 if (!LexParenthesizedBalancedTokenSoup(Soup))
3888 return std::nullopt;
3891 Diag(CurTok, diag::err_pp_unknown_parameter) << 1 <<
Parameter;
3892 return std::nullopt;
3899void Preprocessor::HandleEmbedDirectiveImpl(
3901 StringRef BinaryContents) {
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;
3933 Toks[CurIdx].startToken();
3934 Toks[CurIdx].setKind(tok::annot_embed);
3935 Toks[CurIdx].setAnnotationRange(HashLoc);
3936 Toks[CurIdx++].setAnnotationValue(
Data);
3941 CurIdx += NumSuffixToks;
3944 assert(CurIdx == TotalNumToks &&
"Calculated the incorrect number of tokens");
3945 EnterTokenStream(std::move(Toks), TotalNumToks,
true,
true);
3952 Diag(EmbedTok, diag::warn_compat_pp_embed_directive);
3954 Diag(EmbedTok, diag::ext_pp_embed_directive)
3955 << (LangOpts.CPlusPlus ? 1 : 0);
3962 if (FilenameTok.
isNot(tok::header_name)) {
3964 if (FilenameTok.
isNot(tok::eod))
3977 std::optional<LexEmbedParametersResult> Params =
3980 assert((Params || CurTok.
is(tok::eod)) &&
3981 "expected success or to be at the end of the directive");
3988 StringRef OriginalFilename =
Filename;
3996 if (!MaybeFileRef) {
3998 if (Callbacks && Callbacks->EmbedFileNotFound(OriginalFilename)) {
4001 Diag(FilenameTok, diag::err_pp_file_not_found) <<
Filename;
4004 std::optional<llvm::MemoryBufferRef> MaybeFile =
4008 Diag(FilenameTok, diag::err_cannot_open_file)
4009 <<
Filename <<
"a buffer to the contents could not be created";
4012 StringRef BinaryContents = MaybeFile->getBuffer();
4017 if (Params->MaybeOffsetParam) {
4022 BinaryContents = BinaryContents.substr(Params->MaybeOffsetParam->Offset);
4025 if (Params->MaybeLimitParam) {
4029 BinaryContents = BinaryContents.substr(0, Params->MaybeLimitParam->Limit);
4033 Callbacks->EmbedDirective(HashLoc,
Filename, isAngled, MaybeFileRef,
4035 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.
@ 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...
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_DEPRECATED("Functions returning DirectoryEntry are deprecated.", "getOptionalDirectoryRef()") llvm LLVM_DEPRECATED("Functions returning FileEntry are deprecated.", "getOptionalFileRef()") llvm llvm::Expected< FileEntryRef > getFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true, bool IsText=true)
Lookup, cache, and verify the specified directory (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
bool isNextPPTokenLParen()
Determine whether the next preprocessor token to be lexed is a '('.
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].
int hasAttribute(AttributeCommonInfo::Syntax Syntax, const IdentifierInfo *Scope, const IdentifierInfo *Attr, const TargetInfo &Target, const LangOptions &LangOpts)
Return the version number associated with the attribute if we recognize and implement the attribute s...
@ 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.