35#include "llvm/ADT/ArrayRef.h"
36#include "llvm/ADT/STLExtras.h"
37#include "llvm/ADT/ScopeExit.h"
38#include "llvm/ADT/SmallString.h"
39#include "llvm/ADT/SmallVector.h"
40#include "llvm/ADT/StringRef.h"
41#include "llvm/ADT/StringSwitch.h"
42#include "llvm/Support/AlignOf.h"
43#include "llvm/Support/ErrorHandling.h"
44#include "llvm/Support/Path.h"
45#include "llvm/Support/SaveAndRestore.h"
61 static_assert(std::is_trivially_destructible_v<MacroInfo>,
"");
71Preprocessor::AllocateUndefMacroDirective(
SourceLocation UndefLoc) {
89 while (Tmp.
isNot(tok::eod)) {
90 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 if (std::binary_search(std::begin(ReservedMacro), std::end(ReservedMacro),
160 if (Lang.CPlusPlus11 && (
Text.equals(
"override") ||
Text.equals(
"final")))
181 if (::llvm::sys::path::begin(Include)->equals_insensitive(
"boost"))
186 static const size_t MaxStdHeaderNameLen = 18u;
187 if (Include.size() > MaxStdHeaderNameLen)
192 for (
char &Ch : LowerInclude) {
194 if (
static_cast<unsigned char>(Ch) > 0x7f)
197 if (Ch >=
'A' && Ch <=
'Z')
200 else if (::llvm::sys::path::is_separator(Ch))
205 return llvm::StringSwitch<bool>(LowerInclude)
207 .Cases(
"assert.h",
"complex.h",
"ctype.h",
"errno.h",
"fenv.h",
true)
208 .Cases(
"float.h",
"inttypes.h",
"iso646.h",
"limits.h",
"locale.h",
true)
209 .Cases(
"math.h",
"setjmp.h",
"signal.h",
"stdalign.h",
"stdarg.h",
true)
210 .Cases(
"stdatomic.h",
"stdbool.h",
"stddef.h",
"stdint.h",
"stdio.h",
true)
211 .Cases(
"stdlib.h",
"stdnoreturn.h",
"string.h",
"tgmath.h",
"threads.h",
true)
212 .Cases(
"time.h",
"uchar.h",
"wchar.h",
"wctype.h",
true)
215 .Cases(
"cassert",
"ccomplex",
"cctype",
"cerrno",
"cfenv",
true)
216 .Cases(
"cfloat",
"cinttypes",
"ciso646",
"climits",
"clocale",
true)
217 .Cases(
"cmath",
"csetjmp",
"csignal",
"cstdalign",
"cstdarg",
true)
218 .Cases(
"cstdbool",
"cstddef",
"cstdint",
"cstdio",
"cstdlib",
true)
219 .Cases(
"cstring",
"ctgmath",
"ctime",
"cuchar",
"cwchar",
true)
220 .Case(
"cwctype",
true)
223 .Cases(
"algorithm",
"fstream",
"list",
"regex",
"thread",
true)
224 .Cases(
"array",
"functional",
"locale",
"scoped_allocator",
"tuple",
true)
225 .Cases(
"atomic",
"future",
"map",
"set",
"type_traits",
true)
226 .Cases(
"bitset",
"initializer_list",
"memory",
"shared_mutex",
"typeindex",
true)
227 .Cases(
"chrono",
"iomanip",
"mutex",
"sstream",
"typeinfo",
true)
228 .Cases(
"codecvt",
"ios",
"new",
"stack",
"unordered_map",
true)
229 .Cases(
"complex",
"iosfwd",
"numeric",
"stdexcept",
"unordered_set",
true)
230 .Cases(
"condition_variable",
"iostream",
"ostream",
"streambuf",
"utility",
true)
231 .Cases(
"deque",
"istream",
"queue",
"string",
"valarray",
true)
232 .Cases(
"exception",
"iterator",
"random",
"strstream",
"vector",
true)
233 .Cases(
"forward_list",
"limits",
"ratio",
"system_error",
true)
236 .Cases(
"aio.h",
"arpa/inet.h",
"cpio.h",
"dirent.h",
"dlfcn.h",
true)
237 .Cases(
"fcntl.h",
"fmtmsg.h",
"fnmatch.h",
"ftw.h",
"glob.h",
true)
238 .Cases(
"grp.h",
"iconv.h",
"langinfo.h",
"libgen.h",
"monetary.h",
true)
239 .Cases(
"mqueue.h",
"ndbm.h",
"net/if.h",
"netdb.h",
"netinet/in.h",
true)
240 .Cases(
"netinet/tcp.h",
"nl_types.h",
"poll.h",
"pthread.h",
"pwd.h",
true)
241 .Cases(
"regex.h",
"sched.h",
"search.h",
"semaphore.h",
"spawn.h",
true)
242 .Cases(
"strings.h",
"stropts.h",
"sys/ipc.h",
"sys/mman.h",
"sys/msg.h",
true)
243 .Cases(
"sys/resource.h",
"sys/select.h",
"sys/sem.h",
"sys/shm.h",
"sys/socket.h",
true)
244 .Cases(
"sys/stat.h",
"sys/statvfs.h",
"sys/time.h",
"sys/times.h",
"sys/types.h",
true)
245 .Cases(
"sys/uio.h",
"sys/un.h",
"sys/utsname.h",
"sys/wait.h",
"syslog.h",
true)
246 .Cases(
"tar.h",
"termios.h",
"trace.h",
"ulimit.h",
true)
247 .Cases(
"unistd.h",
"utime.h",
"utmpx.h",
"wordexp.h",
true)
259static std::optional<StringRef>
263 for (StringRef
C : Candidates) {
264 if (LHS.equals_insensitive(
C)) {
272 size_t Length = LHS.size();
273 size_t MaxDist = Length < 3 ? Length - 1 : Length / 3;
275 std::optional<std::pair<StringRef, size_t>> SimilarStr;
276 for (StringRef
C : Candidates) {
277 size_t CurDist = LHS.edit_distance(
C,
true);
278 if (CurDist <= MaxDist) {
281 SimilarStr = {
C, CurDist};
282 }
else if (CurDist < SimilarStr->second) {
284 SimilarStr = {
C, CurDist};
290 return SimilarStr->first;
299 if (MacroNameTok.
is(tok::eod))
300 return Diag(MacroNameTok, diag::err_pp_missing_macro_name);
304 return Diag(MacroNameTok, diag::err_pp_macro_not_identifier);
310 ? diag::ext_pp_operator_used_as_macro_name
311 : diag::err_pp_operator_used_as_macro_name)
312 << II << MacroNameTok.
getKind();
319 return Diag(MacroNameTok, diag::err_defined_macro_name);
327 Diag(MacroNameTok, diag::ext_pp_undef_builtin_macro);
352 Diag(MacroNameTok, diag::warn_pp_macro_is_reserved_id);
368void Preprocessor::ReadMacroName(
Token &MacroNameTok,
MacroUse isDefineUndef,
373 if (MacroNameTok.
is(tok::code_completion)) {
385 if (MacroNameTok.
isNot(tok::eod)) {
386 MacroNameTok.
setKind(tok::eod);
410 while (Tmp.
is(tok::comment))
413 if (Tmp.
is(tok::eod))
421 if ((LangOpts.GNUMode || LangOpts.C99 || LangOpts.CPlusPlus) &&
424 Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint;
428void Preprocessor::SuggestTypoedDirective(
const Token &Tok,
434 std::vector<StringRef> Candidates = {
435 "if",
"ifdef",
"ifndef",
"elif",
"else",
"endif"
437 if (LangOpts.C2x || LangOpts.CPlusPlus2b)
438 Candidates.insert(Candidates.end(), {
"elifdef",
"elifndef"});
446 StringRef SuggValue = *Sugg;
449 Diag(Tok, diag::warn_pp_invalid_directive) << 1 << SuggValue << Hint;
461void Preprocessor::SkipExcludedConditionalBlock(
SourceLocation HashTokenLoc,
463 bool FoundNonSkipPortion,
474 assert(!SkippingExcludedConditionalBlock &&
475 "calling SkipExcludedConditionalBlock recursively");
479 assert(!CurTokenLexer && CurPPLexer &&
"Lexing a macro, not a file?");
481 if (PreambleConditionalStack.reachedEOFWhileSkipping())
482 PreambleConditionalStack.clearSkipInfo();
485 FoundNonSkipPortion, FoundElse);
495 struct SkippingRangeStateTy {
498 const char *BeginPtr =
nullptr;
499 unsigned *SkipRangePtr =
nullptr;
503 void beginLexPass() {
509 BeginPtr = PP.CurLexer->getBufferLocation();
510 SkipRangePtr = &PP.RecordedSkippedRanges[BeginPtr];
512 PP.CurLexer->seek(PP.CurLexer->getCurrentBufferOffset() + *SkipRangePtr,
517 void endLexPass(
const char *Hashptr) {
520 assert(PP.CurLexer->isDependencyDirectivesLexer());
525 if (!*SkipRangePtr) {
526 *SkipRangePtr = Hashptr - BeginPtr;
528 assert(*SkipRangePtr == Hashptr - BeginPtr);
530 SkipRangePtr =
nullptr;
532 } SkippingRangeState(*
this);
535 if (CurLexer->isDependencyDirectivesLexer()) {
536 CurLexer->LexDependencyDirectiveTokenWhileSkipping(Tok);
538 SkippingRangeState.beginLexPass();
542 if (Tok.
is(tok::code_completion)) {
550 if (Tok.
is(tok::eof)) {
554 if (PreambleConditionalStack.isRecording())
555 PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc,
568 if (Tok.
is(tok::eof))
575 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
577 assert(Tok.
is(tok::hash));
578 const char *Hashptr = CurLexer->getBufferLocation() - Tok.
getLength();
579 assert(CurLexer->getSourceLocation(Hashptr) == Tok.
getLocation());
586 if (Tok.
isNot(tok::raw_identifier)) {
589 if (CurLexer) CurLexer->resetExtendedTokenMode();
600 char FirstChar = RI[0];
601 if (FirstChar >=
'a' && FirstChar <=
'z' &&
602 FirstChar !=
'i' && FirstChar !=
'e') {
605 if (CurLexer) CurLexer->resetExtendedTokenMode();
612 char DirectiveBuf[20];
618 size_t IdLen = DirectiveStr.size();
622 if (CurLexer) CurLexer->resetExtendedTokenMode();
625 memcpy(DirectiveBuf, &DirectiveStr[0], IdLen);
626 Directive = StringRef(DirectiveBuf, IdLen);
650 assert(!InCond &&
"Can't be skipping if not in a conditional!");
654 SkippingRangeState.endLexPass(Hashptr);
666 }
else if (Sub ==
"lse") {
673 SkippingRangeState.endLexPass(Hashptr);
677 Diag(Tok, diag::pp_err_else_after_else);
697 }
else if (Sub ==
"lif") {
701 SkippingRangeState.endLexPass(Hashptr);
718 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
721 DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
725 const bool CondValue = DER.Conditional;
739 }
else if (Sub ==
"lifdef" ||
741 bool IsElifDef =
Sub ==
"lifdef";
743 Token DirectiveToken = Tok;
746 SkippingRangeState.endLexPass(Hashptr);
751 if (LangOpts.CPlusPlus)
752 DiagID = LangOpts.CPlusPlus2b ? diag::warn_cxx2b_compat_pp_directive
753 : diag::ext_cxx2b_pp_directive;
755 DiagID = LangOpts.C2x ? diag::warn_c2x_compat_pp_directive
756 : diag::ext_c2x_pp_directive;
761 Diag(Tok, diag::pp_err_elif_after_else)
775 assert(CurPPLexer->
LexingRawMode &&
"We have to be skipping here!");
778 ReadMacroName(MacroNameTok);
783 if (MacroNameTok.
is(tok::eod)) {
799 Callbacks->Elifdef(DirectiveToken.
getLocation(), MacroNameTok,
802 Callbacks->Elifndef(DirectiveToken.
getLocation(), MacroNameTok,
807 if (
static_cast<bool>(MI) == IsElifDef) {
821 if (CurLexer) CurLexer->resetExtendedTokenMode();
832 Callbacks->SourceRangeSkipped(
864 IncLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
871 while (!Loc.
isInvalid() && !
SM.isInMainFile(Loc)) {
872 auto ID =
SM.getFileID(
SM.getExpansionLoc(Loc));
873 auto *FE =
SM.getFileEntryForID(ID);
882 bool InPrivateHeader =
false;
884 if (!Header.isAccessibleFrom(IncM)) {
889 InPrivateHeader =
true;
926 Loc =
SM.getIncludeLoc(ID);
938 bool *IsFrameworkFound,
bool SkipCache,
bool OpenFile,
bool CacheFailures) {
943 FilenameLoc, LangOpts.ModulesValidateTextualHeaderIncludes);
944 bool RequestingModuleIsModuleInterface = !SourceMgr.
isInMainFile(FilenameLoc);
950 bool BuildSystemModule =
false;
951 if (!FromDir && !FromFile) {
969 Includers.push_back(std::make_pair(
nullptr, MainFileDir));
971 }
else if ((FileEnt =
973 Includers.push_back(std::make_pair(FileEnt, *FileMgr.
getDirectory(
".")));
975 Includers.push_back(std::make_pair(FileEnt, FileEnt->
getDir()));
981 if (LangOpts.MSVCCompat && !isAngled) {
982 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
983 if (IsFileLexer(ISEntry))
984 if ((FileEnt = ISEntry.ThePPLexer->getFileEntry()))
985 Includers.push_back(std::make_pair(FileEnt, FileEnt->
getDir()));
990 CurDir = CurDirLookup;
998 Filename, FilenameLoc, isAngled, TmpFromDir, &TmpCurDir,
999 Includers, SearchPath, RelativePath, RequestingModule,
1000 SuggestedModule,
nullptr,
1001 nullptr, SkipCache)) {
1003 TmpFromDir = TmpCurDir;
1005 if (&FE->getFileEntry() == FromFile) {
1007 FromDir = TmpFromDir;
1016 Filename, FilenameLoc, isAngled, FromDir, &CurDir, Includers, SearchPath,
1017 RelativePath, RequestingModule, SuggestedModule, IsMapped,
1018 IsFrameworkFound, SkipCache, BuildSystemModule, OpenFile, CacheFailures);
1020 if (SuggestedModule && !LangOpts.AsmPreprocessor)
1022 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
1031 if (IsFileLexer()) {
1034 Filename, CurFileEnt, SearchPath, RelativePath, RequestingModule,
1036 if (SuggestedModule && !LangOpts.AsmPreprocessor)
1038 RequestingModule, RequestingModuleIsModuleInterface, FilenameLoc,
1045 for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
1046 if (IsFileLexer(ISEntry)) {
1047 if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {
1049 Filename, CurFileEnt, SearchPath, RelativePath,
1050 RequestingModule, SuggestedModule)) {
1051 if (SuggestedModule && !LangOpts.AsmPreprocessor)
1053 RequestingModule, RequestingModuleIsModuleInterface,
1062 return std::nullopt;
1072 : PP(pp), save(pp->DisableMacroExpansion) {
1073 if (pp->MacroExpansionInDirectivesOverride)
1074 pp->DisableMacroExpansion =
false;
1078 PP->DisableMacroExpansion = save;
1095 if (II->getPPKeywordID() == tok::pp_define) {
1096 return HandleDefineDirective(
Result,
1099 if (SkippingUntilPCHThroughHeader &&
1100 II->getPPKeywordID() == tok::pp_include) {
1101 return HandleIncludeDirective(HashLoc,
Result);
1103 if (SkippingUntilPragmaHdrStop && II->getPPKeywordID() == tok::pp_pragma) {
1105 auto *II =
Result.getIdentifierInfo();
1106 if (II && II->getName() ==
"hdrstop")
1124 if (CurLexer) CurLexer->SetKeepWhitespaceMode(
false);
1126 bool ImmediatelyAfterTopLevelIfndef =
1154 switch (II->getPPKeywordID()) {
1155 case tok::pp_include:
1156 case tok::pp_import:
1157 case tok::pp_include_next:
1158 case tok::pp___include_macros:
1159 case tok::pp_pragma:
1160 Diag(
Result, diag::err_embedded_directive) << II->getName();
1161 Diag(*ArgMacro, diag::note_macro_expansion_here)
1176 if (SkippingUntilPCHThroughHeader || SkippingUntilPragmaHdrStop)
1179 switch (
Result.getKind()) {
1182 case tok::code_completion:
1188 case tok::numeric_constant:
1191 return HandleDigitDirective(
Result);
1201 return HandleIfDirective(
Result, SavedHash, ReadAnyTokensBeforeDirective);
1203 return HandleIfdefDirective(
Result, SavedHash,
false,
1205 case tok::pp_ifndef:
1206 return HandleIfdefDirective(
Result, SavedHash,
true,
1207 ReadAnyTokensBeforeDirective);
1209 case tok::pp_elifdef:
1210 case tok::pp_elifndef:
1214 return HandleElseDirective(
Result, SavedHash);
1216 return HandleEndifDirective(
Result);
1219 case tok::pp_include:
1222 case tok::pp___include_macros:
1227 case tok::pp_define:
1228 return HandleDefineDirective(
Result, ImmediatelyAfterTopLevelIfndef);
1230 return HandleUndefDirective();
1234 return HandleLineDirective();
1238 return HandleUserDiagnosticDirective(
Result,
false);
1241 case tok::pp_pragma:
1245 case tok::pp_import:
1247 case tok::pp_include_next:
1250 case tok::pp_warning:
1251 if (LangOpts.CPlusPlus)
1253 ? diag::warn_cxx2b_compat_warning_directive
1254 : diag::ext_pp_warning_directive)
1257 Diag(
Result, LangOpts.C2x ? diag::warn_c2x_compat_warning_directive
1258 : diag::ext_pp_warning_directive)
1261 return HandleUserDiagnosticDirective(
Result,
true);
1263 return HandleIdentSCCSDirective(
Result);
1265 return HandleIdentSCCSDirective(
Result);
1266 case tok::pp_assert:
1269 case tok::pp_unassert:
1273 case tok::pp___public_macro:
1275 return HandleMacroPublicDirective(
Result);
1278 case tok::pp___private_macro:
1280 return HandleMacroPrivateDirective();
1291 auto Toks = std::make_unique<Token[]>(2);
1293 Toks[0] = SavedHash;
1298 if (
Result.is(tok::hashhash))
1299 Toks[1].setKind(tok::unknown);
1304 EnterTokenStream(std::move(Toks), 2,
false,
false);
1310 Diag(
Result, diag::err_pp_invalid_directive) << 0;
1322 bool IsGNULineDirective=
false) {
1323 if (DigitTok.
isNot(tok::numeric_constant)) {
1324 PP.
Diag(DigitTok, DiagID);
1326 if (DigitTok.
isNot(tok::eod))
1332 IntegerBuffer.resize(DigitTok.
getLength());
1333 const char *DigitTokBegin = &IntegerBuffer[0];
1343 for (
unsigned i = 0; i != ActualLength; ++i) {
1346 if (DigitTokBegin[i] ==
'\'')
1349 if (!
isDigit(DigitTokBegin[i])) {
1351 diag::err_pp_line_digit_sequence) << IsGNULineDirective;
1356 unsigned NextVal = Val*10+(DigitTokBegin[i]-
'0');
1357 if (NextVal < Val) {
1358 PP.
Diag(DigitTok, DiagID);
1365 if (DigitTokBegin[0] ==
'0' && Val)
1367 << IsGNULineDirective;
1379void Preprocessor::HandleLineDirective() {
1387 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*
this))
1391 Diag(DigitTok, diag::ext_pp_line_zero);
1395 unsigned LineLimit = 32768U;
1396 if (LangOpts.C99 || LangOpts.CPlusPlus11)
1397 LineLimit = 2147483648U;
1398 if (LineNo >= LineLimit)
1399 Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
1400 else if (LangOpts.CPlusPlus11 && LineNo >= 32768U)
1401 Diag(DigitTok, diag::warn_cxx98_compat_pp_line_too_big);
1403 int FilenameID = -1;
1409 if (StrTok.
is(tok::eod))
1411 else if (StrTok.
isNot(tok::string_literal)) {
1412 Diag(StrTok, diag::err_pp_line_invalid_filename);
1416 Diag(StrTok, diag::err_invalid_string_udl);
1422 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1428 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1463 if (FlagTok.
is(tok::eod))
return false;
1464 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1471 if (FlagTok.
is(tok::eod))
return false;
1472 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1474 }
else if (FlagVal == 2) {
1490 SM.getDecomposedExpansionLoc(IncLoc).first != CurFileID) {
1491 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_pop);
1497 if (FlagTok.
is(tok::eod))
return false;
1498 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag,PP))
1504 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1512 if (FlagTok.
is(tok::eod))
return false;
1513 if (
GetLineValue(FlagTok, FlagVal, diag::err_pp_linemarker_invalid_flag, PP))
1518 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1526 if (FlagTok.
is(tok::eod))
return false;
1529 PP.
Diag(FlagTok, diag::err_pp_linemarker_invalid_flag);
1541void Preprocessor::HandleDigitDirective(
Token &DigitTok) {
1545 if (
GetLineValue(DigitTok, LineNo, diag::err_pp_linemarker_requires_integer,
1552 bool IsFileEntry =
false, IsFileExit =
false;
1553 int FilenameID = -1;
1558 if (StrTok.
is(tok::eod)) {
1559 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1562 }
else if (StrTok.
isNot(tok::string_literal)) {
1563 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1567 Diag(StrTok, diag::err_invalid_string_udl);
1573 assert(
Literal.isOrdinary() &&
"Didn't allow wide strings in");
1579 Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
1589 Diag(StrTok, diag::ext_pp_gnu_line_directive);
1593 if (!(IsFileExit &&
Literal.GetString().empty()))
1599 IsFileExit, FileKind);
1608 else if (IsFileExit)
1617void Preprocessor::HandleUserDiagnosticDirective(
Token &Tok,
1625 CurLexer->ReadToEndOfLine(&Message);
1629 StringRef Msg =
Message.str().ltrim(
' ');
1632 Diag(Tok, diag::pp_hash_warning) << Msg;
1634 Diag(Tok, diag::err_pp_hash_error) << Msg;
1639void Preprocessor::HandleIdentSCCSDirective(
Token &Tok) {
1641 Diag(Tok, diag::ext_pp_ident_directive);
1648 if (StrTok.
isNot(tok::string_literal) &&
1649 StrTok.
isNot(tok::wide_string_literal)) {
1650 Diag(StrTok, diag::err_pp_malformed_ident);
1651 if (StrTok.
isNot(tok::eod))
1657 Diag(StrTok, diag::err_invalid_string_udl);
1674void Preprocessor::HandleMacroPublicDirective(
Token &Tok) {
1676 ReadMacroName(MacroNameTok,
MU_Undef);
1679 if (MacroNameTok.
is(tok::eod))
1691 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1701void Preprocessor::HandleMacroPrivateDirective() {
1703 ReadMacroName(MacroNameTok,
MU_Undef);
1706 if (MacroNameTok.
is(tok::eod))
1718 Diag(MacroNameTok, diag::err_pp_visibility_non_macro) << II;
1738 StringRef &Buffer) {
1740 assert(!Buffer.empty() &&
"Can't have tokens with empty spellings!");
1752 if (Buffer[0] ==
'<') {
1753 if (Buffer.back() !=
'>') {
1754 Diag(Loc, diag::err_pp_expects_filename);
1755 Buffer = StringRef();
1759 }
else if (Buffer[0] ==
'"') {
1760 if (Buffer.back() !=
'"') {
1761 Diag(Loc, diag::err_pp_expects_filename);
1762 Buffer = StringRef();
1767 Diag(Loc, diag::err_pp_expects_filename);
1768 Buffer = StringRef();
1773 if (Buffer.size() <= 2) {
1774 Diag(Loc, diag::err_pp_empty_filename);
1775 Buffer = StringRef();
1780 Buffer = Buffer.substr(1, Buffer.size()-2);
1787 void *AnnotationVal) {
1790 auto Tok = std::make_unique<Token[]>(1);
1796 EnterTokenStream(std::move(Tok), 1,
true,
false);
1803 ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,
1806 for (
size_t I = 0, N = Path.size(); I != N; ++I) {
1809 PathString += Path[I].first->getName();
1812 int IncludeKind = 0;
1814 case tok::pp_include:
1818 case tok::pp_import:
1822 case tok::pp_include_next:
1826 case tok::pp___include_macros:
1831 llvm_unreachable(
"unknown include directive kind");
1834 PP.
Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
1835 << IncludeKind << PathString;
1842 StringRef RealPathName) {
1843 auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
1844 auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
1846 bool SuggestReplacement =
false;
1849 for (
auto &Component : llvm::reverse(Components)) {
1850 if (
"." == Component) {
1851 }
else if (
".." == Component) {
1855 }
else if (RealPathComponentIter != RealPathComponentEnd) {
1856 if (Component != *RealPathComponentIter) {
1860 SuggestReplacement =
1861 RealPathComponentIter->equals_insensitive(Component);
1862 if (!SuggestReplacement)
1864 Component = *RealPathComponentIter;
1866 ++RealPathComponentIter;
1869 return SuggestReplacement;
1877 Module *ShadowingModule =
nullptr;
1885 }
else if (ShadowingModule) {
1888 diag::note_previous_definition);
1898std::pair<ConstSearchDirIterator, const FileEntry *>
1899Preprocessor::getIncludeNextStart(
const Token &IncludeNextTok)
const {
1904 const FileEntry *LookupFromFile =
nullptr;
1912 Diag(IncludeNextTok, diag::pp_include_next_in_primary);
1913 }
else if (CurLexerSubmodule) {
1916 assert(CurPPLexer &&
"#include_next directive in macro?");
1919 }
else if (!Lookup) {
1924 Diag(IncludeNextTok, diag::pp_include_next_absolute_path);
1930 return {Lookup, LookupFromFile};
1946 if (FilenameTok.
isNot(tok::header_name)) {
1948 if (FilenameTok.
isNot(tok::eod))
1960 auto Action = HandleHeaderIncludeOrImport(HashLoc, IncludeTok, FilenameTok,
1961 EndLoc, LookupFrom, LookupFromFile);
1962 switch (Action.Kind) {
1963 case ImportAction::None:
1964 case ImportAction::SkippedModuleImport:
1966 case ImportAction::ModuleBegin:
1968 tok::annot_module_begin, Action.ModuleForHeader);
1970 case ImportAction::HeaderUnitImport:
1972 Action.ModuleForHeader);
1974 case ImportAction::ModuleImport:
1976 tok::annot_module_include, Action.ModuleForHeader);
1978 case ImportAction::Failure:
1980 "This should be an early exit only to a fatal error");
1983 CurLexer->cutOffLexing();
1991 const Token &FilenameTok,
bool &IsFrameworkFound,
bool IsImportDecl,
1993 const FileEntry *LookupFromFile, StringRef &LookupFilename,
1997 FilenameLoc, LookupFilename, isAngled, LookupFrom, LookupFromFile, CurDir,
1998 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
1999 &SuggestedModule, &IsMapped, &IsFrameworkFound);
2004 if (Callbacks && Callbacks->FileNotFound(
Filename))
2005 return std::nullopt;
2007 if (SuppressIncludeNotFoundError)
2008 return std::nullopt;
2015 FilenameLoc, LookupFilename,
false, LookupFrom, LookupFromFile, CurDir,
2016 Callbacks ? &SearchPath :
nullptr, Callbacks ? &RelativePath :
nullptr,
2017 &SuggestedModule, &IsMapped,
2020 Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal)
2030 StringRef OriginalFilename =
Filename;
2031 if (LangOpts.SpellChecking) {
2034 auto CorrectTypoFilename = [](llvm::StringRef
Filename) {
2041 StringRef TypoCorrectionName = CorrectTypoFilename(
Filename);
2042 StringRef TypoCorrectionLookupName = CorrectTypoFilename(LookupFilename);
2045 FilenameLoc, TypoCorrectionLookupName, isAngled, LookupFrom,
2046 LookupFromFile, CurDir, Callbacks ? &SearchPath :
nullptr,
2047 Callbacks ? &RelativePath :
nullptr, &SuggestedModule, &IsMapped,
2052 FilenameRange,
"<" + TypoCorrectionName.str() +
">")
2054 FilenameRange,
"\"" + TypoCorrectionName.str() +
"\"");
2055 Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
2056 << OriginalFilename << TypoCorrectionName << Hint;
2060 LookupFilename = TypoCorrectionLookupName;
2066 assert(!
File &&
"expected missing file");
2067 Diag(FilenameTok, diag::err_pp_file_not_found)
2068 << OriginalFilename << FilenameRange;
2069 if (IsFrameworkFound) {
2070 size_t SlashPos = OriginalFilename.find(
'/');
2071 assert(SlashPos != StringRef::npos &&
2072 "Include with framework name should have '/' in the filename");
2073 StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
2076 assert(CacheEntry.
Directory &&
"Found framework should be in cache");
2077 Diag(FilenameTok, diag::note_pp_framework_without_header)
2078 << OriginalFilename.substr(SlashPos + 1) << FrameworkName
2082 return std::nullopt;
2097Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
2107 StringRef OriginalFilename =
Filename;
2114 return {ImportAction::None};
2116 bool IsImportDecl = HashLoc.
isInvalid();
2120 if (PragmaARCCFCodeAuditedInfo.second.isValid()) {
2121 Diag(StartLoc, diag::err_pp_include_in_arc_cf_code_audited) << IsImportDecl;
2122 Diag(PragmaARCCFCodeAuditedInfo.second, diag::note_pragma_entered_here);
2129 if (PragmaAssumeNonNullLoc.
isValid()) {
2130 Diag(StartLoc, diag::err_pp_include_in_assume_nonnull) << IsImportDecl;
2131 Diag(PragmaAssumeNonNullLoc, diag::note_pragma_entered_here);
2142 if (!NewName.empty())
2147 bool IsMapped =
false;
2148 bool IsFrameworkFound =
false;
2156 StringRef LookupFilename =
Filename;
2161 llvm::sys::path::Style BackslashStyle = llvm::sys::path::Style::native;
2162 if (is_style_posix(BackslashStyle) && LangOpts.MicrosoftExt) {
2164 llvm::sys::path::native(NormalizedPath);
2165 LookupFilename = NormalizedPath;
2166 BackslashStyle = llvm::sys::path::Style::windows;
2170 &CurDir,
Filename, FilenameLoc, FilenameRange, FilenameTok,
2171 IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
2172 LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
2176 SkippingUntilPCHThroughHeader =
false;
2177 return {ImportAction::None};
2195 enum { Enter,
Import, Skip, IncludeLimitReached } Action = Enter;
2197 if (PPOpts->SingleFileParseMode)
2198 Action = IncludeLimitReached;
2203 if (Action == Enter && HasReachedMaxIncludeDepth &&
File &&
2205 Action = IncludeLimitReached;
2211 bool MaybeTranslateInclude =
2215 bool UsableHeaderUnit =
false;
2217 if (TrackGMFState.inGMF() || IsImportDecl)
2218 UsableHeaderUnit =
true;
2219 else if (!IsImportDecl) {
2226 bool UsableClangHeaderModule =
2228 !
SM->isHeaderUnit();
2233 if (MaybeTranslateInclude && (UsableHeaderUnit || UsableClangHeaderModule)) {
2241 diag::note_implicit_top_level_module_import_here)
2243 return {ImportAction::None};
2250 for (
Module *Mod =
SM; Mod; Mod = Mod->Parent)
2253 std::reverse(Path.begin(), Path.end());
2266 assert((Imported ==
nullptr || Imported == SuggestedModule.
getModule()) &&
2267 "the imported module is different than the suggested one");
2273 static_cast<Module *
>(Imported)->getTopLevelModule());
2288 assert(CurLexer &&
"#include but no current lexer set!");
2290 CurLexer->FormTokenWithChars(
Result, CurLexer->BufferEnd, tok::eof);
2291 CurLexer->cutOffLexing();
2293 return {ImportAction::None};
2315 bool IsFirstIncludeOfFile =
false;
2319 if (Action == Enter &&
File &&
2322 IsFirstIncludeOfFile)) {
2333 if (UsableHeaderUnit && !
getLangOpts().CompilingPCH)
2334 Action = TrackGMFState.inGMF() ?
Import : Skip;
2336 Action = (SuggestedModule && !
getLangOpts().CompilingPCH) ? Import : Skip;
2344 if (Action == Enter &&
File && PreambleConditionalStack.isRecording() &&
2347 diag::err_pp_including_mainfile_in_preamble);
2348 return {ImportAction::None};
2351 if (Callbacks && !IsImportDecl) {
2354 Callbacks->InclusionDirective(HashLoc, IncludeTok, LookupFilename, isAngled,
2355 FilenameRange,
File, SearchPath, RelativePath,
2356 Action == Import ? SuggestedModule.
getModule()
2359 if (Action == Skip &&
File)
2360 Callbacks->FileSkipped(*
File, FilenameTok, FileCharacter);
2364 return {ImportAction::None};
2368 if (IsImportDecl && !SuggestedModule) {
2369 Diag(FilenameTok, diag::err_header_import_not_header_unit)
2370 << OriginalFilename <<
File->getName();
2371 return {ImportAction::None};
2376 const bool CheckIncludePathPortability =
2377 !IsMapped && !
File->getFileEntry().tryGetRealPathName().empty();
2379 if (CheckIncludePathPortability) {
2380 StringRef Name = LookupFilename;
2381 StringRef NameWithoriginalSlashes =
Filename;
2385 bool NameWasUNC = Name.consume_front(
"\\\\?\\");
2386 NameWithoriginalSlashes.consume_front(
"\\\\?\\");
2388 StringRef RealPathName =
File->getFileEntry().tryGetRealPathName();
2390 llvm::sys::path::end(Name));
2403 if (llvm::sys::path::is_absolute(Name) &&
2404 llvm::sys::path::is_absolute(RealPathName) &&
2407 assert(Components.size() >= 3 &&
"should have drive, backslash, name");
2408 assert(Components[0].size() == 2 &&
"should start with drive");
2409 assert(Components[0][1] ==
':' &&
"should have colon");
2410 FixedDriveRealPath = (Name.substr(0, 1) + RealPathName.substr(1)).str();
2411 RealPathName = FixedDriveRealPath;
2417 Path.reserve(Name.size()+2);
2418 Path.push_back(isAngled ?
'<' :
'"');
2420 const auto IsSep = [BackslashStyle](
char c) {
2421 return llvm::sys::path::is_separator(
c, BackslashStyle);
2424 for (
auto Component : Components) {
2436 if (!(Component.size() == 1 && IsSep(Component[0])))
2437 Path.append(Component);
2438 else if (!Path.empty())
2442 if (Path.size() > NameWithoriginalSlashes.size()) {
2443 Path.push_back(isAngled ?
'>' :
'"');
2446 assert(IsSep(NameWithoriginalSlashes[Path.size()-1]));
2448 Path.push_back(NameWithoriginalSlashes[Path.size()-1]);
2449 while (Path.size() <= NameWithoriginalSlashes.size() &&
2450 IsSep(NameWithoriginalSlashes[Path.size()-1]));
2456 Path = (Path.substr(0, 1) +
"\\\\?\\" + Path.substr(1)).str();
2463 ? diag::pp_nonportable_path
2464 : diag::pp_nonportable_system_path;
2465 Diag(FilenameTok, DiagId) << Path <<
2474 return {ImportAction::SkippedModuleImport,
SM};
2475 return {ImportAction::None};
2477 case IncludeLimitReached:
2480 return {ImportAction::None};
2484 assert(
SM &&
"no module to import");
2489 tok::pp___include_macros)
2490 return {ImportAction::None};
2492 return {ImportAction::ModuleImport,
SM};
2500 if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) {
2501 Diag(FilenameTok, diag::err_pp_include_too_deep);
2502 HasReachedMaxIncludeDepth =
true;
2503 return {ImportAction::None};
2515 return ImportAction::Failure;
2520 IsFirstIncludeOfFile))
2521 return {ImportAction::None};
2525 if (
SM && !
SM->isHeaderUnit()) {
2526 if (
SM->getTopLevelModule()->ShadowingModule) {
2529 Diag(
SM->DefinitionLoc, diag::err_module_build_shadowed_submodule)
2530 <<
SM->getFullModuleName();
2531 Diag(
SM->getTopLevelModule()->ShadowingModule->DefinitionLoc,
2532 diag::note_previous_definition);
2533 return {ImportAction::None};
2544 return {ImportAction::None};
2546 assert(!CurLexerSubmodule &&
"should not have marked this as a module yet");
2547 CurLexerSubmodule =
SM;
2557 return {ImportAction::ModuleBegin,
SM};
2560 assert(!IsImportDecl &&
"failed to diagnose missing module for import decl");
2561 return {ImportAction::None};
2566void Preprocessor::HandleIncludeNextDirective(
SourceLocation HashLoc,
2567 Token &IncludeNextTok) {
2568 Diag(IncludeNextTok, diag::ext_pp_include_next_directive);
2572 std::tie(Lookup, LookupFromFile) = getIncludeNextStart(IncludeNextTok);
2574 return HandleIncludeDirective(HashLoc, IncludeNextTok, Lookup,
2579void Preprocessor::HandleMicrosoftImportDirective(
Token &Tok) {
2585 Diag(Tok, diag::err_pp_import_directive_ms );
2596 if (!LangOpts.ObjC) {
2597 if (LangOpts.MSVCCompat)
2598 return HandleMicrosoftImportDirective(ImportTok);
2599 Diag(ImportTok, diag::ext_pp_import_directive);
2601 return HandleIncludeDirective(HashLoc, ImportTok);
2608void Preprocessor::HandleIncludeMacrosDirective(
SourceLocation HashLoc,
2609 Token &IncludeMacrosTok) {
2615 diag::pp_include_macros_out_of_predefines);
2622 HandleIncludeDirective(HashLoc, IncludeMacrosTok);
2627 assert(TmpTok.
isNot(tok::eof) &&
"Didn't find end of -imacros!");
2628 }
while (TmpTok.
isNot(tok::hashhash));
2639bool Preprocessor::ReadMacroParameterList(
MacroInfo *MI,
Token &Tok) {
2650 Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
2654 Diag(Tok, LangOpts.CPlusPlus11 ?
2655 diag::warn_cxx98_compat_variadic_macro :
2656 diag::ext_variadic_macro);
2659 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
2660 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
2665 if (Tok.
isNot(tok::r_paren)) {
2666 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2675 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2683 Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
2689 if (llvm::is_contained(Parameters, II)) {
2690 Diag(Tok, diag::err_pp_duplicate_name_in_arg_list) << II;
2702 Diag(Tok, diag::err_pp_expected_comma_in_arg_list);
2711 Diag(Tok, diag::ext_named_variadic_macro);
2715 if (Tok.
isNot(tok::r_paren)) {
2716 Diag(Tok, diag::err_pp_missing_rparen_in_macro_def);
2746 StringRef ValueText = II->
getName();
2747 StringRef TrimmedValue = ValueText;
2748 if (!ValueText.startswith(
"__")) {
2749 if (ValueText.startswith(
"_"))
2750 TrimmedValue = TrimmedValue.drop_front(1);
2754 TrimmedValue = TrimmedValue.drop_front(2);
2755 if (TrimmedValue.endswith(
"__"))
2756 TrimmedValue = TrimmedValue.drop_back(2);
2758 return TrimmedValue.equals(MacroText);
2765 return MacroName.
isOneOf(tok::kw_extern, tok::kw_inline, tok::kw_static,
2778MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
2779 const Token &MacroNameTok,
const bool ImmediatelyAfterHeaderGuard) {
2781 Token LastTok = MacroNameTok;
2789 auto _ = llvm::make_scope_exit([&]() {
2791 if (CurLexer->ParsingPreprocessorDirective)
2802 if (Tok.
is(tok::eod)) {
2803 if (ImmediatelyAfterHeaderGuard) {
2813 }
else if (Tok.
is(tok::l_paren)) {
2816 if (ReadMacroParameterList(MI, LastTok))
2830 }
else if (LangOpts.C99 || LangOpts.CPlusPlus11) {
2833 Diag(Tok, diag::ext_c99_whitespace_required_after_macro_name);
2842 if (Tok.
is(tok::at))
2844 else if (Tok.
is(tok::unknown)) {
2851 Diag(Tok, diag::ext_missing_whitespace_after_macro_name);
2853 Diag(Tok, diag::warn_missing_whitespace_after_macro_name);
2856 if (!Tok.
is(tok::eod))
2864 while (Tok.
isNot(tok::eod)) {
2866 Tokens.push_back(Tok);
2877 while (Tok.
isNot(tok::eod)) {
2880 if (!Tok.
isOneOf(tok::hash, tok::hashat, tok::hashhash)) {
2881 Tokens.push_back(Tok);
2883 if (VAOCtx.isVAOptToken(Tok)) {
2885 if (VAOCtx.isInVAOpt()) {
2886 Diag(Tok, diag::err_pp_vaopt_nested_use);
2891 if (Tok.
isNot(tok::l_paren)) {
2892 Diag(Tok, diag::err_pp_missing_lparen_in_vaopt_use);
2895 Tokens.push_back(Tok);
2896 VAOCtx.sawVAOptFollowedByOpeningParens(Tok.
getLocation());
2898 if (Tok.
is(tok::hashhash)) {
2899 Diag(Tok, diag::err_vaopt_paste_at_start);
2903 }
else if (VAOCtx.isInVAOpt()) {
2904 if (Tok.
is(tok::r_paren)) {
2905 if (VAOCtx.sawClosingParen()) {
2906 assert(Tokens.size() >= 3 &&
2907 "Must have seen at least __VA_OPT__( "
2908 "and a subsequent tok::r_paren");
2909 if (Tokens[Tokens.size() - 2].is(tok::hashhash)) {
2910 Diag(Tok, diag::err_vaopt_paste_at_end);
2914 }
else if (Tok.
is(tok::l_paren)) {
2928 Tokens.push_back(Tok);
2935 if (Tok.
is(tok::hashhash)) {
2943 if (Tok.
is(tok::eod)) {
2944 Tokens.push_back(LastTok);
2949 Tokens[Tokens.size() - 1].is(tok::comma))
2953 Tokens.push_back(LastTok);
2962 if (!VAOCtx.isVAOptToken(Tok) &&
2971 LastTok.
setKind(tok::unknown);
2972 Tokens.push_back(LastTok);
2975 Diag(Tok, diag::err_pp_stringize_not_parameter)
2976 << LastTok.
is(tok::hashat);
2982 Tokens.push_back(LastTok);
2987 if (!VAOCtx.isVAOptToken(Tok)) {
2988 Tokens.push_back(Tok);
2995 if (VAOCtx.isInVAOpt()) {
2996 assert(Tok.
is(tok::eod) &&
"Must be at End Of preprocessing Directive");
2997 Diag(Tok, diag::err_pp_expected_after)
2998 << LastTok.
getKind() << tok::r_paren;
2999 Diag(VAOCtx.getUnmatchedOpeningParenLoc(), diag::note_matching) << tok::l_paren;
3010void Preprocessor::HandleDefineDirective(
3011 Token &DefineTok,
const bool ImmediatelyAfterHeaderGuard) {
3015 bool MacroShadowsKeyword;
3016 ReadMacroName(MacroNameTok,
MU_Define, &MacroShadowsKeyword);
3019 if (MacroNameTok.
is(tok::eod))
3026 emitFinalMacroWarning(MacroNameTok,
false);
3030 if (CurLexer) CurLexer->SetCommentRetentionState(KeepMacroComments);
3032 MacroInfo *
const MI = ReadOptionalMacroParameterListAndBody(
3033 MacroNameTok, ImmediatelyAfterHeaderGuard);
3037 if (MacroShadowsKeyword &&
3039 Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword);
3044 if (NumTokens != 0) {
3056 if (SkippingUntilPCHThroughHeader) {
3059 LangOpts.MicrosoftExt))
3063 if (!LangOpts.MicrosoftExt)
3074 emitFinalMacroWarning(MacroNameTok,
false);
3079 auto isObjCProtectedMacro = [](
const IdentifierInfo *II) ->
bool {
3080 return II->
isStr(
"__strong") ||
3081 II->
isStr(
"__weak") ||
3082 II->
isStr(
"__unsafe_unretained") ||
3083 II->
isStr(
"__autoreleasing");
3093 LangOpts.MicrosoftExt)) {
3112 Diag(MacroNameTok, diag::ext_pp_redef_builtin_macro);
3116 !MI->
isIdenticalTo(*OtherMI, *
this, LangOpts.MicrosoftExt)) {
3134 !MacroExpansionInDirectivesOverride &&
3143 Callbacks->MacroDefined(MacroNameTok, MD);
3156 Tok.
setKind(tok::kw__Static_assert);
3165void Preprocessor::HandleUndefDirective() {
3169 ReadMacroName(MacroNameTok,
MU_Undef);
3172 if (MacroNameTok.
is(tok::eod))
3184 emitFinalMacroWarning(MacroNameTok,
true);
3194 Undef = AllocateUndefMacroDirective(MacroNameTok.
getLocation());
3200 Callbacks->MacroUndefined(MacroNameTok, MD, Undef);
3215void Preprocessor::HandleIfdefDirective(
Token &
Result,
3216 const Token &HashToken,
3218 bool ReadAnyTokensBeforeDirective) {
3223 ReadMacroName(MacroNameTok);
3226 if (MacroNameTok.
is(tok::eod)) {
3229 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3249 if (!ReadAnyTokensBeforeDirective && !MI) {
3250 assert(isIfndef &&
"#ifdef shouldn't reach here");
3262 Callbacks->Ifndef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3264 Callbacks->Ifdef(DirectiveTok.
getLocation(), MacroNameTok, MD);
3267 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3271 if (PPOpts->SingleFileParseMode && !MI) {
3277 }
else if (!MI == isIfndef || RetainExcludedCB) {
3284 SkipExcludedConditionalBlock(HashToken.
getLocation(),
3293void Preprocessor::HandleIfDirective(
Token &IfToken,
3294 const Token &HashToken,
3295 bool ReadAnyTokensBeforeDirective) {
3300 const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
3301 const bool ConditionalTrue = DER.Conditional;
3310 if (!ReadAnyTokensBeforeDirective && IfNDefMacro && ConditionalTrue)
3322 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3326 if (PPOpts->SingleFileParseMode && DER.IncludedUndefinedIds) {
3331 }
else if (ConditionalTrue || RetainExcludedCB) {
3345void Preprocessor::HandleEndifDirective(
Token &EndifToken) {
3354 Diag(EndifToken, diag::err_pp_endif_without_if);
3363 "This code should only be reachable in the non-skipping case!");
3371void Preprocessor::HandleElseDirective(
Token &
Result,
const Token &HashToken) {
3393 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3396 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3407 true,
Result.getLocation());
3411void Preprocessor::HandleElifFamilyDirective(
Token &ElifToken,
3412 const Token &HashToken,
3424 if (LangOpts.CPlusPlus)
3425 DiagID = LangOpts.CPlusPlus2b ? diag::warn_cxx2b_compat_pp_directive
3426 : diag::ext_cxx2b_pp_directive;
3428 DiagID = LangOpts.C2x ? diag::warn_c2x_compat_pp_directive
3429 : diag::ext_c2x_pp_directive;
3430 Diag(ElifToken, DiagID) << DirKind;
3443 Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
3453 Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
3458 Callbacks->Elif(ElifToken.
getLocation(), ConditionRange,
3461 case tok::pp_elifdef:
3464 case tok::pp_elifndef:
3468 assert(
false &&
"unexpected directive kind");
3473 bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
3476 if ((PPOpts->SingleFileParseMode && !CI.
FoundNonSkip) || RetainExcludedCB) {
3485 SkipExcludedConditionalBlock(
static bool isInMainFile(const clang::Diagnostic &D)
Defines the clang::FileManager interface and associated types.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the clang::Module class, which describes a module in the source code.
Defines the PPCallbacks interface.
static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, SrcMgr::CharacteristicKind &FileKind, Preprocessor &PP)
ReadLineMarkerFlags - Parse and validate any flags at the end of a GNU line marker directive.
static bool isConfigurationPattern(Token &MacroName, MacroInfo *MI, const LangOptions &LOptions)
static bool trySimplifyPath(SmallVectorImpl< StringRef > &Components, StringRef RealPathName)
static std::optional< StringRef > findSimilarStr(StringRef LHS, const std::vector< StringRef > &Candidates)
Find a similar string in Candidates.
static 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 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 MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II)
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
static bool isInvalid(LocType Loc, bool *Invalid)
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__device__ __2f16 float c
ResetMacroExpansionHelper(Preprocessor *pp)
~ResetMacroExpansionHelper()
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
SourceLocation getEnd() const
virtual void CodeCompleteMacroName(bool IsDefinition)
Callback invoked when performing code completion in a context where the name of a macro is expected.
virtual void CodeCompleteInConditionalExclusion()
Callback invoked when performing code completion within a block of code that was excluded due to prep...
virtual void CodeCompleteDirective(bool InConditional)
Callback invoked when performing code completion for a preprocessor directive.
A directive for a defined macro or a macro imported from a module.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
StringRef getName() const
Cached information about one file (either on disk or in the virtual file system).
const DirectoryEntry * getDir() const
Return the directory the file lives in.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
llvm::ErrorOr< const DirectoryEntry * > getDirectory(StringRef DirName, bool CacheFailure=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(const FileEntry *File, bool AllowTextual=false, bool AllowExcluded=false)
Retrieve the module that owns the given header file, if any.
@ ExcludedHeader
This header is explicitly excluded from the module.
@ TextualHeader
This header is part of the module (for layering purposes) but should be textually included.
Describes a module or submodule.
StringRef getTopLevelModuleName() const
Retrieve the name of the top-level module.
@ Hidden
All of the names in this module are hidden.
SourceLocation DefinitionLoc
The location of the module definition.
unsigned IsSystem
Whether this is a "system" module (which assumes that all headers in it are system headers).
std::string Name
The name of this module.
std::pair< std::string, bool > Requirement
An individual requirement: a feature name and a flag indicating the required state of that feature.
bool isAvailable() const
Determine whether this module is available for use within the current translation unit.
std::string getFullModuleName(bool AllowStringLiterals=false) const
Retrieve the full name of this module, including the path from its top-level module.
bool getHasReadAnyTokensVal() const
getHasReadAnyTokensVal - This is used for the #ifndef handshake at the top of the file when reading p...
void ExitTopLevelConditional()
Called when the lexer exits the top-level conditional.
void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc)
bool getImmediatelyAfterTopLevelIfndef() const
getImmediatelyAfterTopLevelIfndef - returns true if the last directive was an #ifndef at the beginnin...
void EnterTopLevelConditional()
Invoked when a top level conditional (except #ifndef) is found.
void resetImmediatelyAfterTopLevelIfndef()
void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc)
Called when entering a top-level #ifndef directive (or the "\#if !defined" equivalent) without any pr...
OptionalFileEntryRefDegradesToFileEntryPtr getFileEntry() const
getFileEntry - Return the FileEntry corresponding to this FileID.
void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, bool FoundNonSkip, bool FoundElse)
pushConditionalLevel - When we enter a #if directive, this keeps track of what we are currently in fo...
unsigned getConditionalStackDepth() const
bool LexingRawMode
True if in raw mode.
bool ParsingPreprocessorDirective
True when parsing #XXX; turns '\n' into a tok::eod token.
MultipleIncludeOpt MIOpt
A state machine that detects the #ifndef-wrapping a file idiom for the multiple-include optimization.
bool popConditionalLevel(PPConditionalInfo &CI)
popConditionalLevel - Remove an entry off the top of the conditional stack, returning information abo...
PPConditionalInfo & peekConditionalLevel()
Return the top of the conditional stack.
virtual SourceLocation getSourceLocation()=0
Return the source location for the next observable location.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
MacroDirective * getLocalMacroDirective(const IdentifierInfo *II) const
Given an identifier, return its latest non-imported MacroDirective if it is #define'd and not #undef'...
void markClangModuleAsAffecting(Module *M)
Mark the given clang module as affecting the current clang module or translation unit.
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
const FileEntry * getHeaderToIncludeForDiagnostics(SourceLocation IncLoc, SourceLocation MLoc)
We want to produce a diagnostic at location IncLoc concerning an unreachable effect at location MLoc ...
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.
void makeModuleVisible(Module *M, SourceLocation Loc)
void Lex(Token &Result)
Lex the next token for this preprocessor.
bool EnterSourceFile(FileID FID, ConstSearchDirIterator Dir, SourceLocation Loc, bool IsFirstIncludeOfFile=true)
Add a source file to the top of the include stack and start lexing tokens from it instead of the curr...
SourceLocation CheckEndOfDirective(const char *DirType, bool EnableMacros=false)
Ensure that the next token is a tok::eod token.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
SourceManager & getSourceManager() const
MacroDefinition getMacroDefinition(const IdentifierInfo *II)
bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag=nullptr)
bool isMacroDefined(StringRef Id)
SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const
Given a location that specifies the start of a token, return a new location that specifies a characte...
Module * getCurrentModule()
Retrieves the module that we're currently building, if any.
void emitMacroExpansionWarnings(const Token &Identifier) const
bool hadModuleLoaderFatalFailure() const
const TargetInfo & getTargetInfo() const
bool LexHeaderName(Token &Result, bool AllowMacroExpansion=true)
Lex a token, forming a header-name token if possible.
bool isPCHThroughHeader(const FileEntry *FE)
Returns true if the FileEntry is the PCH through header.
friend class VariadicMacroScopeGuard
MacroInfo * AllocateMacroInfo(SourceLocation L)
Allocate a new MacroInfo object with the provided SourceLocation.
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
FileID getPredefinesFileID() const
Returns the FileID for the preprocessor predefines.
static bool checkModuleIsAvailable(const LangOptions &LangOpts, const TargetInfo &TargetInfo, DiagnosticsEngine &Diags, Module *M)
Check that the given module is available, producing a diagnostic if not.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)
Turn the specified lexer token into a fully checked and spelled filename, e.g.
PreprocessorLexer * getCurrentFileLexer() const
Return the current file lexer being lexed from.
HeaderSearch & getHeaderSearchInfo() const
SourceRange DiscardUntilEndOfDirective()
Read and discard all tokens remaining on the current line until the tok::eod token is found.
void HandleDirective(Token &Result)
Callback invoked when the lexer sees a # token at the start of a line.
void EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind, void *AnnotationVal)
Enter an annotation token into the token stream.
bool alreadyIncluded(const FileEntry *File) const
Return true if this header has already been included.
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
DefMacroDirective * appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc)
void HandlePragmaHdrstop(Token &Tok)
DiagnosticsEngine & getDiagnostics() const
Module * getModuleForLocation(SourceLocation Loc, bool AllowTextual)
Find the module that owns the source or header file that Loc points to.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
bool usingPCHWithThroughHeader()
True if using a PCH with a through header.
void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD)
Add a directive to the macro directive history for this identifier.
Represents an unpacked "presumed" location which can be presented to the user.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
bool isWrittenInBuiltinFile(SourceLocation Loc) const
Returns whether Loc is located in a <built-in> file.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind)
Add a line note to the line table for the FileID and offset specified by Loc.
bool isWrittenInCommandLineFile(SourceLocation Loc) const
Returns whether Loc is located in a <command line> file.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
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.
FileID createFileID(const FileEntry *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...
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.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const
Return the file characteristic of the specified source location, indicating whether this is a normal ...
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
void setEnd(SourceLocation e)
StringLiteralParser - This decodes string escape characters and performs wide string analysis and Tra...
Exposes information about the current target.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
SourceLocation getEndLoc() const
void setAnnotationEndLoc(SourceLocation L)
void clearFlag(TokenFlags Flag)
Unset the specified flag.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
void setKind(tok::TokenKind K)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
void setLocation(SourceLocation L)
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
bool isNot(tok::TokenKind K) const
void setAnnotationValue(void *val)
bool hasUDSuffix() const
Return true if this token is a string or character literal which has a ud-suffix.
void startToken()
Reset all flags to cleared.
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
void setIdentifierInfo(IdentifierInfo *II)
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode),...
A directive for an undefined macro.
A class for tracking whether we're inside a VA_OPT during a traversal of the tokens of a variadic mac...
An RAII class that tracks when the Preprocessor starts and stops lexing the definition of a (ISO C/C+...
void enterScope()
Client code should call this function just before the Preprocessor is about to Lex tokens from the de...
Directive - Abstract class representing a parsed verify directive.
A directive for setting the module visibility of a macro.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
uint32_t Literal
Literals are represented as positive integers.
bool Sub(InterpState &S, CodePtr OpPC)
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
PPKeywordKind
Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line.
bool isReservedInAllContexts(ReservedIdentifierStatus Status)
Determine whether an identifier is reserved in all contexts.
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
MacroUse
Context in which macro name is used.
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
LLVM_READONLY bool isDigit(unsigned char c)
Return true if this character is an ASCII digit: [0-9].
LLVM_READONLY bool isLowercase(unsigned char c)
Return true if this character is a lowercase ASCII letter: [a-z].
@ PIK_HashPragma
The pragma was introduced via #pragma.
This structure is used to record entries in our framework cache.
OptionalDirectoryEntryRef Directory
The directory entry which should be used for the cached framework.
Information about the conditional stack (#if directives) currently active.
bool FoundNonSkip
True if we have emitted tokens already, and now we're in an #else block or something.
SourceLocation IfLoc
Location where the conditional started.
bool WasSkipping
True if this was contained in a skipping directive, e.g., in a "\#if 0" block.
bool FoundElse
True if we've seen a #else in this block.