54#include "llvm/ADT/APInt.h"
55#include "llvm/ADT/ArrayRef.h"
56#include "llvm/ADT/DenseMap.h"
57#include "llvm/ADT/STLExtras.h"
58#include "llvm/ADT/SmallString.h"
59#include "llvm/ADT/SmallVector.h"
60#include "llvm/ADT/StringRef.h"
61#include "llvm/ADT/iterator_range.h"
62#include "llvm/Support/Capacity.h"
63#include "llvm/Support/ErrorHandling.h"
64#include "llvm/Support/MemoryBuffer.h"
65#include "llvm/Support/raw_ostream.h"
89 : PPOpts(
std::move(PPOpts)), Diags(&diags), LangOpts(opts),
90 FileMgr(Headers.getFileMgr()), SourceMgr(
SM),
91 ScratchBuf(new
ScratchBuffer(SourceMgr)), HeaderInfo(Headers),
96 Identifiers(IILookup), PragmaHandlers(new
PragmaNamespace(StringRef())),
97 TUKind(TUKind), SkipMainFilePreamble(0,
true),
98 CurSubmoduleState(&NullSubmoduleState) {
99 OwnsHeaderSearch = OwnsHeaders;
102 KeepComments =
false;
103 KeepMacroComments =
false;
104 SuppressIncludeNotFoundError =
false;
107 DisableMacroExpansion =
false;
108 MacroExpansionInDirectivesOverride =
false;
111 InMacroArgPreExpansion =
false;
112 NumCachedTokenLexers = 0;
113 PragmasEnabled =
true;
114 ParsingIfOrElifDirective =
false;
115 PreprocessedOutput =
false;
118 ReadMacrosFromExternalSource =
false;
120 BuiltinInfo = std::make_unique<Builtin::Context>();
130 RegisterBuiltinPragmas();
133 RegisterBuiltinMacros();
135 if(LangOpts.Borland) {
146 Ident__exception_info = Ident__exception_code =
nullptr;
147 Ident__abnormal_termination = Ident___exception_info =
nullptr;
148 Ident___exception_code = Ident___abnormal_termination =
nullptr;
149 Ident_GetExceptionInfo = Ident_GetExceptionCode =
nullptr;
150 Ident_AbnormalTermination =
nullptr;
155 IncrementalProcessing = LangOpts.IncrementalExtensions;
159 SkippingUntilPragmaHdrStop =
true;
162 if (!this->PPOpts->PCHThroughHeader.empty() &&
163 !this->PPOpts->ImplicitPCHInclude.empty())
164 SkippingUntilPCHThroughHeader =
true;
166 if (this->PPOpts->GeneratePreamble)
167 PreambleConditionalStack.startRecording();
169 MaxTokens = LangOpts.MaxTokens;
175 IncludeMacroStack.clear();
180 std::fill(TokenLexerCache, TokenLexerCache + NumCachedTokenLexers,
nullptr);
181 CurTokenLexer.reset();
184 for (
MacroArgs *ArgList = MacroArgCache; ArgList;)
185 ArgList = ArgList->deallocate();
188 if (OwnsHeaderSearch)
194 assert((!this->Target || this->Target == &
Target) &&
195 "Invalid override of target information");
198 assert((!this->AuxTarget || this->AuxTarget == AuxTarget) &&
199 "Invalid override of aux target information.");
200 this->AuxTarget = AuxTarget;
203 BuiltinInfo->InitializeTarget(
Target, AuxTarget);
221 NumEnteredSourceFiles = 0;
224 PragmaHandlersBackup = std::move(PragmaHandlers);
225 PragmaHandlers = std::make_unique<PragmaNamespace>(StringRef());
226 RegisterBuiltinPragmas();
229 PredefinesFileID =
FileID();
233 NumEnteredSourceFiles = 1;
235 PragmaHandlers = std::move(PragmaHandlersBackup);
244 if (!DumpFlags)
return;
246 llvm::errs() <<
"\t";
248 llvm::errs() <<
" [StartOfLine]";
250 llvm::errs() <<
" [LeadingSpace]";
252 llvm::errs() <<
" [ExpandDisabled]";
255 llvm::errs() <<
" [UnClean='" << StringRef(Start, Tok.
getLength())
259 llvm::errs() <<
"\tLoc=<";
269 llvm::errs() <<
"MACRO: ";
270 for (
unsigned i = 0, e = MI.
getNumTokens(); i != e; ++i) {
274 llvm::errs() <<
"\n";
278 llvm::errs() <<
"\n*** Preprocessor Stats:\n";
279 llvm::errs() << NumDirectives <<
" directives found:\n";
280 llvm::errs() <<
" " << NumDefined <<
" #define.\n";
281 llvm::errs() <<
" " << NumUndefined <<
" #undef.\n";
282 llvm::errs() <<
" #include/#include_next/#import:\n";
283 llvm::errs() <<
" " << NumEnteredSourceFiles <<
" source files entered.\n";
284 llvm::errs() <<
" " << MaxIncludeStackDepth <<
" max include stack depth\n";
285 llvm::errs() <<
" " << NumIf <<
" #if/#ifndef/#ifdef.\n";
286 llvm::errs() <<
" " << NumElse <<
" #else/#elif/#elifdef/#elifndef.\n";
287 llvm::errs() <<
" " << NumEndif <<
" #endif.\n";
288 llvm::errs() <<
" " << NumPragma <<
" #pragma.\n";
289 llvm::errs() << NumSkipped <<
" #if/#ifndef#ifdef regions skipped\n";
291 llvm::errs() << NumMacroExpanded <<
"/" << NumFnMacroExpanded <<
"/"
292 << NumBuiltinMacroExpanded <<
" obj/fn/builtin macros expanded, "
293 << NumFastMacroExpanded <<
" on the fast path.\n";
294 llvm::errs() << (NumFastTokenPaste+NumTokenPaste)
295 <<
" token paste (##) operations performed, "
296 << NumFastTokenPaste <<
" on the fast path.\n";
298 llvm::errs() <<
"\nPreprocessor Memory: " <<
getTotalMemory() <<
"B total";
300 llvm::errs() <<
"\n BumpPtr: " << BP.getTotalMemory();
301 llvm::errs() <<
"\n Macro Expanded Tokens: "
302 << llvm::capacity_in_bytes(MacroExpandedTokens);
303 llvm::errs() <<
"\n Predefines Buffer: " << Predefines.capacity();
305 llvm::errs() <<
"\n Macros: "
306 << llvm::capacity_in_bytes(CurSubmoduleState->Macros);
307 llvm::errs() <<
"\n #pragma push_macro Info: "
308 << llvm::capacity_in_bytes(PragmaPushMacroInfo);
309 llvm::errs() <<
"\n Poison Reasons: "
310 << llvm::capacity_in_bytes(PoisonReasons);
311 llvm::errs() <<
"\n Comment Handlers: "
312 << llvm::capacity_in_bytes(CommentHandlers) <<
"\n";
318 !ReadMacrosFromExternalSource) {
319 ReadMacrosFromExternalSource =
true;
325 CurSubmoduleState->Macros.insert(std::make_pair(Macro.II, MacroState()));
327 return CurSubmoduleState->Macros.begin();
331 return BP.getTotalMemory()
332 + llvm::capacity_in_bytes(MacroExpandedTokens)
333 + Predefines.capacity()
336 + llvm::capacity_in_bytes(CurSubmoduleState->Macros)
337 + llvm::capacity_in_bytes(PragmaPushMacroInfo)
338 + llvm::capacity_in_bytes(PoisonReasons)
339 + llvm::capacity_in_bytes(CommentHandlers);
345 !ReadMacrosFromExternalSource) {
346 ReadMacrosFromExternalSource =
true;
350 return CurSubmoduleState->Macros.end();
357 std::equal(Tokens.begin(), Tokens.end(), MI->
tokens_begin());
364 StringRef BestSpelling;
368 Def = I->second.findDirectiveAtLoc(
Loc, SourceMgr);
380 BestLocation = Location;
381 BestSpelling = I->first->getName();
389 CurLexerCallback = CurLexer->isDependencyDirectivesLexer()
390 ? CLK_DependencyDirectivesLexer
392 else if (CurTokenLexer)
393 CurLexerCallback = CLK_TokenLexer;
395 CurLexerCallback = CLK_CachingLexer;
399 unsigned CompleteLine,
400 unsigned CompleteColumn) {
401 assert(CompleteLine && CompleteColumn &&
"Starts from 1:1");
402 assert(!CodeCompletionFile &&
"Already set");
405 std::optional<llvm::MemoryBufferRef> Buffer =
411 const char *Position = Buffer->getBufferStart();
413 for (; *Position; ++Position) {
414 if (*Position !=
'\r' && *Position !=
'\n')
418 if ((Position[1] ==
'\r' || Position[1] ==
'\n') &&
419 Position[0] != Position[1])
426 Position += CompleteColumn - 1;
430 if (SkipMainFilePreamble.first &&
432 if (Position - Buffer->getBufferStart() < SkipMainFilePreamble.first)
433 Position = Buffer->getBufferStart() + SkipMainFilePreamble.first;
436 if (Position > Buffer->getBufferEnd())
437 Position = Buffer->getBufferEnd();
439 CodeCompletionFile =
File;
440 CodeCompletionOffset = Position - Buffer->getBufferStart();
442 auto NewBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
443 Buffer->getBufferSize() + 1, Buffer->getBufferIdentifier());
444 char *NewBuf = NewBuffer->getBufferStart();
445 char *NewPos = std::copy(Buffer->getBufferStart(), Position, NewBuf);
447 std::copy(Position, Buffer->getBufferEnd(), NewPos+1);
473 if (Tok.
isNot(tok::raw_identifier) && !Tok.
hasUCN()) {
476 return II->getName();
483 const char *Ptr = Buffer.data();
485 return StringRef(Ptr, Len);
499 if (ExpansionLocStart.
isValid())
501 ExpansionLocEnd, Str.size());
505 if (Tok.
is(tok::raw_identifier))
514 std::pair<FileID, unsigned> LocInfo =
SM.getDecomposedLoc(SpellingLoc);
516 StringRef Buffer =
SM.getBufferData(LocInfo.first, &
Invalid);
523 ScratchBuf->getToken(Buffer.data() + LocInfo.second, Length, DestPtr);
535 if (!
getLangOpts().isCompilingModuleImplementation())
551 assert(NumEnteredSourceFiles == 0 &&
"Cannot reenter the main file!");
562 if (SkipMainFilePreamble.first > 0)
563 CurLexer->SetByteOffset(SkipMainFilePreamble.first,
564 SkipMainFilePreamble.second);
573 std::unique_ptr<llvm::MemoryBuffer> SB =
574 llvm::MemoryBuffer::getMemBufferCopy(Predefines,
"<built-in>");
575 assert(SB &&
"Cannot create predefined source buffer");
577 assert(FID.
isValid() &&
"Could not create FileID for predefines?");
578 setPredefinesFileID(FID);
583 if (!PPOpts->PCHThroughHeader.empty()) {
588 false,
nullptr,
nullptr,
589 nullptr,
nullptr,
nullptr,
594 << PPOpts->PCHThroughHeader;
597 setPCHThroughHeaderFileID(
607void Preprocessor::setPCHThroughHeaderFileID(
FileID FID) {
608 assert(PCHThroughHeaderFileID.
isInvalid() &&
609 "PCHThroughHeaderFileID already set!");
610 PCHThroughHeaderFileID = FID;
614 assert(PCHThroughHeaderFileID.
isValid() &&
615 "Invalid PCH through header FileID");
621 PCHThroughHeaderFileID.
isValid();
626 PCHThroughHeaderFileID.
isValid();
643 bool ReachedMainFileEOF =
false;
644 bool UsingPCHThroughHeader = SkippingUntilPCHThroughHeader;
645 bool UsingPragmaHdrStop = SkippingUntilPragmaHdrStop;
650 CurLexerCallback(*
this, Tok);
651 if (Tok.
is(tok::eof) && !InPredefines) {
652 ReachedMainFileEOF =
true;
655 if (UsingPCHThroughHeader && !SkippingUntilPCHThroughHeader)
657 if (UsingPragmaHdrStop && !SkippingUntilPragmaHdrStop)
660 if (ReachedMainFileEOF) {
661 if (UsingPCHThroughHeader)
663 << PPOpts->PCHThroughHeader << 1;
664 else if (!PPOpts->PCHWithHdrStopCreate)
669void Preprocessor::replayPreambleConditionalStack() {
671 if (PreambleConditionalStack.isReplaying()) {
673 "CurPPLexer is null when calling replayPreambleConditionalStack.");
675 PreambleConditionalStack.doneReplaying();
676 if (PreambleConditionalStack.reachedEOFWhileSkipping())
677 SkipExcludedConditionalBlock(
678 PreambleConditionalStack.SkipInfo->HashTokenLoc,
679 PreambleConditionalStack.SkipInfo->IfTokenLoc,
680 PreambleConditionalStack.SkipInfo->FoundNonSkipPortion,
681 PreambleConditionalStack.SkipInfo->FoundElse,
682 PreambleConditionalStack.SkipInfo->ElseLoc);
689 Callbacks->EndOfMainFile();
700 assert(!
Identifier.getRawIdentifier().empty() &&
"No raw identifier data!");
735 PoisonReasons[II] = DiagID;
739 assert(Ident__exception_code && Ident__exception_info);
740 assert(Ident___exception_code && Ident___exception_info);
754 "Can't handle identifiers without identifier info!");
755 llvm::DenseMap<IdentifierInfo*,unsigned>::const_iterator it =
756 PoisonReasons.find(
Identifier.getIdentifierInfo());
757 if(it == PoisonReasons.end())
763void Preprocessor::updateOutOfDateIdentifier(
const IdentifierInfo &II)
const {
778 "Can't handle identifiers without identifier info!");
788 bool CurrentIsPoisoned =
false;
789 const bool IsSpecialVariadicMacro =
790 &II == Ident__VA_ARGS__ || &II == Ident__VA_OPT__;
791 if (IsSpecialVariadicMacro)
794 updateOutOfDateIdentifier(II);
797 if (IsSpecialVariadicMacro)
809 const auto *MI = MD.getMacroInfo();
810 assert(MI &&
"macro definition with no macro info?");
811 if (!DisableMacroExpansion) {
812 if (!
Identifier.isExpandDisabled() && MI->isEnabled()) {
815 if (!MI->isFunctionLike() || isNextPPTokenLParen())
816 return HandleMacroExpandedIdentifier(
Identifier, MD);
822 if (MI->isObjectLike() || isNextPPTokenLParen())
857 !InMacroArgs && !DisableMacroExpansion &&
859 CurLexerCallback != CLK_CachingLexer) {
861 NamedModuleImportPath.clear();
863 ModuleImportExpectsIdentifier =
true;
864 CurLexerCallback = CLK_LexAfterModuleImport;
873 while (!CurLexerCallback(*
this,
Result))
879 if (
Result.is(tok::code_completion) &&
Result.getIdentifierInfo()) {
885 Result.setIdentifierInfo(
nullptr);
893 if (
getLangOpts().CPlusPlusModules && LexLevel == 1 &&
895 switch (
Result.getKind()) {
896 case tok::l_paren:
case tok::l_square:
case tok::l_brace:
897 StdCXXImportSeqState.handleOpenBracket();
899 case tok::r_paren:
case tok::r_square:
900 StdCXXImportSeqState.handleCloseBracket();
903 StdCXXImportSeqState.handleCloseBrace();
907 case tok::annot_module_include:
909 TrackGMFState.handleSemi();
910 StdCXXImportSeqState.handleSemi();
911 ModuleDeclState.handleSemi();
913 case tok::header_name:
914 case tok::annot_header_unit:
915 StdCXXImportSeqState.handleHeaderName();
918 TrackGMFState.handleExport();
919 StdCXXImportSeqState.handleExport();
920 ModuleDeclState.handleExport();
923 ModuleDeclState.handleColon();
926 ModuleDeclState.handlePeriod();
928 case tok::identifier:
931 if (StdCXXImportSeqState.atTopLevel()) {
932 if (
Result.getIdentifierInfo()->isModulesImport()) {
933 TrackGMFState.handleImport(StdCXXImportSeqState.afterTopLevelSeq());
934 StdCXXImportSeqState.handleImport();
935 if (StdCXXImportSeqState.afterImportSeq()) {
936 ModuleImportLoc =
Result.getLocation();
937 NamedModuleImportPath.clear();
939 ModuleImportExpectsIdentifier =
true;
940 CurLexerCallback = CLK_LexAfterModuleImport;
944 TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq());
945 ModuleDeclState.handleModule();
949 ModuleDeclState.handleIdentifier(
Result.getIdentifierInfo());
950 if (ModuleDeclState.isModuleCandidate())
954 TrackGMFState.handleMisc();
955 StdCXXImportSeqState.handleMisc();
956 ModuleDeclState.handleMisc();
962 CheckPoints[CurLexer->getFileID()].push_back(CurLexer->BufferPtr);
963 CheckPointCounter = 0;
966 LastTokenWasAt =
Result.is(tok::at);
969 if ((LexLevel == 0 || PreprocessToken) &&
982 if (Tok.
isOneOf(tok::unknown, tok::eof, tok::eod,
983 tok::annot_repl_input_end))
985 if (Tokens !=
nullptr)
986 Tokens->push_back(Tok);
1012 if (FilenameTok.
is(tok::less) && AllowMacroExpansion) {
1019 FilenameBuffer.push_back(
'<');
1025 while (FilenameTok.
isNot(tok::greater)) {
1027 if (FilenameTok.
isOneOf(tok::eod, tok::eof)) {
1029 Diag(Start, diag::note_matching) << tok::less;
1036 if (FilenameTok.
is(tok::code_completion)) {
1045 FilenameBuffer.push_back(
' ');
1049 size_t PreAppendSize = FilenameBuffer.size();
1050 FilenameBuffer.resize(PreAppendSize + FilenameTok.
getLength());
1052 const char *BufPtr = &FilenameBuffer[PreAppendSize];
1053 unsigned ActualLen =
getSpelling(FilenameTok, BufPtr);
1056 if (BufPtr != &FilenameBuffer[PreAppendSize])
1057 memcpy(&FilenameBuffer[PreAppendSize], BufPtr, ActualLen);
1060 if (FilenameTok.
getLength() != ActualLen)
1061 FilenameBuffer.resize(PreAppendSize + ActualLen);
1065 FilenameTok.
setKind(tok::header_name);
1070 }
else if (FilenameTok.
is(tok::string_literal) && AllowMacroExpansion) {
1081 StringRef Str =
getSpelling(FilenameTok, FilenameBuffer);
1082 if (Str.size() >= 2 && Str.front() ==
'"' && Str.back() ==
'"')
1083 FilenameTok.
setKind(tok::header_name);
1094 unsigned BracketDepth = 0;
1096 Toks.emplace_back();
1099 switch (Toks.back().getKind()) {
1100 case tok::l_paren:
case tok::l_square:
case tok::l_brace:
1104 case tok::r_paren:
case tok::r_square:
case tok::r_brace:
1105 if (BracketDepth == 0)
1111 if (BracketDepth == 0)
1154 if (NamedModuleImportPath.empty() &&
getLangOpts().CPlusPlusModules) {
1158 if (
Result.is(tok::colon) && ModuleDeclState.isNamedModule()) {
1159 std::string Name = ModuleDeclState.getPrimaryName().str();
1161 NamedModuleImportPath.push_back(
1163 CurLexerCallback = CLK_LexAfterModuleImport;
1173 auto ToksCopy = std::make_unique<Token[]>(Toks.size());
1174 std::copy(Toks.begin(), Toks.end(), ToksCopy.get());
1175 EnterTokenStream(std::move(ToksCopy), Toks.size(),
1179 bool ImportingHeader =
Result.is(tok::header_name);
1182 if (ImportingHeader) {
1186 Suffix.push_back(
Result);
1191 if (Suffix.back().isNot(tok::semi)) {
1193 EnterTokens(Suffix);
1202 Diag(SemiLoc, diag::err_header_import_semi_in_macro);
1207 ImportTok.
setKind(tok::kw_import);
1212 auto Action = HandleHeaderIncludeOrImport(
1214 switch (Action.Kind) {
1215 case ImportAction::None:
1218 case ImportAction::ModuleBegin:
1220 Suffix.emplace_back();
1221 Suffix.back().startToken();
1222 Suffix.back().setKind(tok::annot_module_begin);
1223 Suffix.back().setLocation(SemiLoc);
1224 Suffix.back().setAnnotationEndLoc(SemiLoc);
1225 Suffix.back().setAnnotationValue(Action.ModuleForHeader);
1228 case ImportAction::ModuleImport:
1229 case ImportAction::HeaderUnitImport:
1230 case ImportAction::SkippedModuleImport:
1233 Suffix[0].setKind(tok::annot_header_unit);
1234 Suffix[0].setAnnotationEndLoc(Suffix[0].getLocation());
1235 Suffix[0].setAnnotationValue(Action.ModuleForHeader);
1238 case ImportAction::Failure:
1240 "This should be an early exit only to a fatal error");
1241 Result.setKind(tok::eof);
1242 CurLexer->cutOffLexing();
1243 EnterTokens(Suffix);
1247 EnterTokens(Suffix);
1257 if (ModuleImportExpectsIdentifier &&
Result.getKind() == tok::identifier) {
1260 NamedModuleImportPath.push_back(
1261 std::make_pair(
Result.getIdentifierInfo(),
Result.getLocation()));
1262 ModuleImportExpectsIdentifier =
false;
1263 CurLexerCallback = CLK_LexAfterModuleImport;
1270 if (!ModuleImportExpectsIdentifier &&
Result.getKind() == tok::period) {
1271 ModuleImportExpectsIdentifier =
true;
1272 CurLexerCallback = CLK_LexAfterModuleImport;
1277 if (NamedModuleImportPath.empty() ||
Result.is(tok::eof))
1283 if (
Result.isNot(tok::semi)) {
1284 Suffix.push_back(
Result);
1286 if (Suffix.back().isNot(tok::semi)) {
1288 EnterTokens(Suffix);
1291 SemiLoc = Suffix.back().getLocation();
1298 std::string FlatModuleName;
1300 for (
auto &Piece : NamedModuleImportPath) {
1302 if (!FlatModuleName.empty() && FlatModuleName.back() !=
':')
1303 FlatModuleName +=
".";
1304 FlatModuleName += Piece.first->getName();
1307 NamedModuleImportPath.clear();
1308 NamedModuleImportPath.push_back(
1312 Module *Imported =
nullptr;
1315 Imported = TheModuleLoader.
loadModule(ModuleImportLoc,
1316 NamedModuleImportPath,
1324 Callbacks->moduleImport(ModuleImportLoc, NamedModuleImportPath, Imported);
1326 if (!Suffix.empty()) {
1327 EnterTokens(Suffix);
1334 CurSubmoduleState->VisibleModules.setVisible(
1339 Diag(ModuleImportLoc, diag::warn_module_conflict)
1340 <<
Path[0]->getFullModuleName()
1341 << Conflict->getFullModuleName()
1346 if (!BuildingSubmoduleStack.empty() && M != BuildingSubmoduleStack.back().M)
1347 BuildingSubmoduleStack.back().M->Imports.insert(M);
1351 const char *DiagnosticTag,
1352 bool AllowMacroExpansion) {
1354 if (
Result.isNot(tok::string_literal)) {
1355 Diag(
Result, diag::err_expected_string_literal)
1356 << 0 << DiagnosticTag;
1363 StrToks.push_back(
Result);
1365 if (
Result.hasUDSuffix())
1368 if (AllowMacroExpansion)
1372 }
while (
Result.is(tok::string_literal));
1376 assert(Literal.isOrdinary() &&
"Didn't allow wide strings in");
1378 if (Literal.hadError)
1381 if (Literal.Pascal) {
1382 Diag(StrToks[0].getLocation(), diag::err_expected_string_literal)
1383 << 0 << DiagnosticTag;
1387 String = std::string(Literal.GetString());
1392 assert(Tok.
is(tok::numeric_constant));
1394 bool NumberInvalid =
false;
1395 StringRef Spelling =
getSpelling(Tok, IntegerBuffer, &NumberInvalid);
1401 if (Literal.hadError || !Literal.isIntegerLiteral() || Literal.hasUDSuffix())
1403 llvm::APInt APVal(64, 0);
1404 if (Literal.GetIntegerValue(APVal))
1407 Value = APVal.getLimitedValue();
1412 assert(Handler &&
"NULL comment handler");
1413 assert(!llvm::is_contained(CommentHandlers, Handler) &&
1414 "Comment handler already registered");
1415 CommentHandlers.push_back(Handler);
1419 std::vector<CommentHandler *>::iterator Pos =
1420 llvm::find(CommentHandlers, Handler);
1421 assert(Pos != CommentHandlers.end() &&
"Comment handler not registered");
1422 CommentHandlers.erase(Pos);
1426 bool AnyPendingTokens =
false;
1427 for (std::vector<CommentHandler *>::iterator H = CommentHandlers.begin(),
1428 HEnd = CommentHandlers.end();
1430 if ((*H)->HandleComment(*
this, Comment))
1431 AnyPendingTokens =
true;
1439void Preprocessor::emitMacroDeprecationWarning(
const Token &
Identifier)
const {
1440 const MacroAnnotations &A =
1442 assert(A.DeprecationInfo &&
1443 "Macro deprecation warning without recorded annotation!");
1444 const MacroAnnotationInfo &Info = *A.DeprecationInfo;
1445 if (Info.Message.empty())
1450 <<
Identifier.getIdentifierInfo() << 1 << Info.Message;
1451 Diag(Info.Location, diag::note_pp_macro_annotation) << 0;
1454void Preprocessor::emitRestrictExpansionWarning(
const Token &
Identifier)
const {
1455 const MacroAnnotations &A =
1457 assert(A.RestrictExpansionInfo &&
1458 "Macro restricted expansion warning without recorded annotation!");
1459 const MacroAnnotationInfo &Info = *A.RestrictExpansionInfo;
1460 if (Info.Message.empty())
1465 <<
Identifier.getIdentifierInfo() << 1 << Info.Message;
1466 Diag(Info.Location, diag::note_pp_macro_annotation) << 1;
1470 unsigned DiagSelection)
const {
1471 Diag(
Identifier, diag::warn_fp_nan_inf_when_disabled) << DiagSelection << 1;
1475 bool IsUndef)
const {
1476 const MacroAnnotations &A =
1478 assert(A.FinalAnnotationLoc &&
1479 "Final macro warning without recorded annotation!");
1482 <<
Identifier.getIdentifierInfo() << (IsUndef ? 0 : 1);
1483 Diag(*A.FinalAnnotationLoc, diag::note_pp_macro_annotation) << 2;
1493 auto FirstRegionEndingAfterLoc = llvm::partition_point(
1495 &
Loc](
const std::pair<SourceLocation, SourceLocation> &Region) {
1499 if (FirstRegionEndingAfterLoc != Map.end()) {
1502 FirstRegionEndingAfterLoc->first,
Loc);
1506 if (!Map.empty() && Map.back().first == Map.back().second)
1530 return TestInMap(SafeBufferOptOutMap,
Loc);
1533 LoadedSafeBufferOptOutMap.lookupLoadedOptOutMap(
Loc, SourceMgr);
1545 InSafeBufferOptOutRegion =
true;
1546 CurrentSafeBufferOptOutStart =
Loc;
1550 if (!SafeBufferOptOutMap.empty()) {
1551 [[maybe_unused]]
auto *PrevRegion = &SafeBufferOptOutMap.back();
1552 assert(PrevRegion->first != PrevRegion->second &&
1553 "Shall not begin a safe buffer opt-out region before closing the "
1559 SafeBufferOptOutMap.emplace_back(
Loc,
Loc);
1563 InSafeBufferOptOutRegion =
false;
1567 assert(!SafeBufferOptOutMap.empty() &&
1568 "Misordered safe buffer opt-out regions");
1569 auto *CurrRegion = &SafeBufferOptOutMap.back();
1570 assert(CurrRegion->first == CurrRegion->second &&
1571 "Set end location to a closed safe buffer opt-out region");
1572 CurrRegion->second =
Loc;
1578 return InSafeBufferOptOutRegion;
1581 StartLoc = CurrentSafeBufferOptOutStart;
1582 return InSafeBufferOptOutRegion;
1587 assert(!InSafeBufferOptOutRegion &&
1588 "Attempt to serialize safe buffer opt-out regions before file being "
1589 "completely preprocessed");
1593 for (
const auto &[begin, end] : SafeBufferOptOutMap) {
1594 SrcSeq.push_back(begin);
1595 SrcSeq.push_back(end);
1607 if (SourceLocations.size() == 0)
1610 assert(SourceLocations.size() % 2 == 0 &&
1611 "ill-formed SourceLocation sequence");
1613 auto It = SourceLocations.begin();
1615 LoadedSafeBufferOptOutMap.findAndConsLoadedOptOutMap(*It, SourceMgr);
1621 Regions.emplace_back(
Begin, End);
1622 }
while (It != SourceLocations.end());
1643 if (
auto It = CheckPoints.find(FID); It != CheckPoints.end()) {
1645 const char *
Last =
nullptr;
1647 for (
const char *
P : FileCheckPoints) {
Defines enum values for all the target-independent builtin functions.
Defines the clang::FileManager interface and associated types.
Defines the FileSystemStatCache interface.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
llvm::MachO::Record Record
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the clang::Module class, which describes a module in the source code.
Defines the PreprocessorLexer interface.
static bool MacroDefinitionEquals(const MacroInfo *MI, ArrayRef< TokenValue > Tokens)
Compares macro tokens with a specified token value sequence.
static constexpr unsigned CheckPointStepSize
Minimum distance between two check points, in tokens.
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
virtual void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled)
Callback invoked when performing code completion inside the filename part of an #include directive.
virtual ~CodeCompletionHandler()
virtual void CodeCompleteNaturalLanguage()
Callback invoked when performing code completion in a part of the file where we expect natural langua...
Concrete class used by the front-end to report problems and issues.
virtual ~EmptylineHandler()
virtual ~ExternalPreprocessorSource()
virtual void updateOutOfDateIdentifier(const IdentifierInfo &II)=0
Update an out-of-date identifier.
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Provides lookups to, and iteration over, IdentiferInfo objects.
One of these records is kept for each identifier that is lexed.
bool isModulesImport() const
Determine whether this is the contextual keyword import.
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
void setIsPoisoned(bool Value=true)
setIsPoisoned - Mark this identifier as poisoned.
bool isPoisoned() const
Return true if this token has been poisoned.
bool isOutOfDate() const
Determine whether the information for this identifier is out of date with respect to the external sou...
void setIsFutureCompatKeyword(bool Val)
StringRef getName() const
Return the actual identifier string.
bool isFutureCompatKeyword() const
is/setIsFutureCompatKeyword - Initialize information about whether or not this language token is a ke...
bool isExtensionToken() const
get/setExtension - Initialize information about whether or not this language token is an extension.
void AddKeywords(const LangOptions &LangOpts)
Populate the identifier table with info about the language keywords for the language specified by Lan...
@ FEM_UnsetOnCommandLine
Used only for FE option processing; this is only used to indicate that the user did not specify an ex...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
A description of the current definition of a macro.
MacroInfo * getMacroInfo()
SourceLocation getLocation() const
Encapsulates the data about a macro definition (e.g.
const_tokens_iterator tokens_begin() const
unsigned getNumTokens() const
Return the number of tokens that this macro expands to.
const Token & getReplacementToken(unsigned Tok) const
bool isObjectLike() const
Abstract interface for a module loader.
virtual ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective)=0
Attempt to load the given module.
Represents a macro directive exported by a module.
Describes a module or submodule.
@ Hidden
All of the names in this module are hidden.
NumericLiteralParser - This performs strict semantic analysis of the content of a ppnumber,...
PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas, allowing hierarchical pragm...
A record of the steps taken while preprocessing a source file, including the various preprocessing di...
void setConditionalLevels(ArrayRef< PPConditionalInfo > CL)
void LexIncludeFilename(Token &FilenameTok)
Lex a token, producing a header-name token if possible.
bool markIncluded(FileEntryRef File)
Mark the file as included.
void FinalizeForModelFile()
Cleanup after model file parsing.
bool FinishLexStringLiteral(Token &Result, std::string &String, const char *DiagnosticTag, bool AllowMacroExpansion)
Complete the lexing of a string literal where the first token has already been lexed (see LexStringLi...
bool creatingPCHWithThroughHeader()
True if creating a PCH with a through header.
void DumpToken(const Token &Tok, bool DumpFlags=false) const
Print the token to stderr, used for debugging.
void InitializeForModelFile()
Initialize the preprocessor to parse a model file.
void CollectPpImportSuffix(SmallVectorImpl< Token > &Toks)
Collect the tokens of a C++20 pp-import-suffix.
void setCodeCompletionTokenRange(const SourceLocation Start, const SourceLocation End)
Set the code completion token range for detecting replacement range later on.
bool LexAfterModuleImport(Token &Result)
Lex a token following the 'import' contextual keyword.
macro_iterator macro_begin(bool IncludeExternalMacros=true) const
void CreateString(StringRef Str, Token &Tok, SourceLocation ExpansionLocStart=SourceLocation(), SourceLocation ExpansionLocEnd=SourceLocation())
Plop the specified string into a scratch buffer and set the specified token's location and length to ...
bool isSafeBufferOptOut(const SourceManager &SourceMgr, const SourceLocation &Loc) const
const char * getCheckPoint(FileID FID, const char *Start) const
Returns a pointer into the given file's buffer that's guaranteed to be between tokens.
IdentifierInfo * LookUpIdentifierInfo(Token &Identifier) const
Given a tok::raw_identifier token, look up the identifier information for the token and install it in...
void DumpMacro(const MacroInfo &MI) const
void setCodeCompletionReached()
Note that we hit the code-completion point.
bool SetCodeCompletionPoint(FileEntryRef File, unsigned Line, unsigned Column)
Specify the point at which code-completion will be performed.
void makeModuleVisible(Module *M, SourceLocation Loc)
bool isInImportingCXXNamedModules() const
If we're importing a standard C++20 Named Modules.
void Lex(Token &Result)
Lex the next token for this preprocessor.
const TranslationUnitKind TUKind
The kind of translation unit we are processing.
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 addCommentHandler(CommentHandler *Handler)
Add the specified comment handler to the preprocessor.
void removeCommentHandler(CommentHandler *Handler)
Remove the specified comment handler.
void HandlePoisonedIdentifier(Token &Identifier)
Display reason for poisoned identifier.
bool HandleIdentifier(Token &Identifier)
Callback invoked when the lexer reads an identifier and has filled in the tokens IdentifierInfo membe...
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
bool enterOrExitSafeBufferOptOutRegion(bool isEnter, const SourceLocation &Loc)
Alter the state of whether this PP currently is in a "-Wunsafe-buffer-usage" opt-out region.
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc.
const MacroAnnotations & getMacroAnnotations(const IdentifierInfo *II) const
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
macro_iterator macro_end(bool IncludeExternalMacros=true) const
SourceManager & getSourceManager() const
bool isBacktrackEnabled() const
True if EnableBacktrackAtThisPos() was called and caching of tokens is on.
MacroDefinition getMacroDefinition(const IdentifierInfo *II)
void SetPoisonReason(IdentifierInfo *II, unsigned DiagID)
Specifies the reason for poisoning an identifier.
bool getCommentRetentionState() const
Module * getCurrentModuleImplementation()
Retrieves the module whose implementation we're current compiling, if any.
MacroMap::const_iterator macro_iterator
void createPreprocessingRecord()
Create a new preprocessing record, which will keep track of all macro expansions, macro definitions,...
SourceLocation SplitToken(SourceLocation TokLoc, unsigned Length)
Split the first Length characters out of the token starting at TokLoc and return a location pointing ...
Module * getCurrentModule()
Retrieves the module that we're currently building, if any.
bool isPPInSafeBufferOptOutRegion()
void setCurrentFPEvalMethod(SourceLocation PragmaLoc, LangOptions::FPEvalMethodKind Val)
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.
void DumpLocation(SourceLocation Loc) const
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value)
Parses a simple integer literal to get its numeric value.
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
bool creatingPCHWithPragmaHdrStop()
True if creating a PCH with a #pragma hdrstop.
void Initialize(const TargetInfo &Target, const TargetInfo *AuxTarget=nullptr)
Initialize the preprocessor using information about the target.
FileID getPredefinesFileID() const
Returns the FileID for the preprocessor predefines.
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 HandleComment(Token &result, SourceRange Comment)
HeaderSearch & getHeaderSearchInfo() const
bool setDeserializedSafeBufferOptOutMap(const SmallVectorImpl< SourceLocation > &SrcLocSeqs)
ExternalPreprocessorSource * getExternalSource() const
SmallVector< SourceLocation, 64 > serializeSafeBufferOptOutMap() const
void recomputeCurLexerKind()
Recompute the current lexer kind based on the CurLexer/ CurTokenLexer pointers.
Preprocessor(std::shared_ptr< PreprocessorOptions > PPOpts, DiagnosticsEngine &diags, const LangOptions &LangOpts, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup=nullptr, bool OwnsHeaderSearch=false, TranslationUnitKind TUKind=TU_Complete)
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.
IdentifierTable & getIdentifierTable()
const LangOptions & getLangOpts() const
void setTUFPEvalMethod(LangOptions::FPEvalMethodKind Val)
void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled)
Hook used by the lexer to invoke the "included file" code completion point.
llvm::DenseMap< FileID, SafeBufferOptOutRegionsTy > LoadedRegions
void PoisonSEHIdentifiers(bool Poison=true)
size_t getTotalMemory() const
void LexTokensUntilEOF(std::vector< Token > *Tokens=nullptr)
Lex all tokens for this preprocessor until (and excluding) end of file.
bool usingPCHWithPragmaHdrStop()
True if using a PCH with a #pragma hdrstop.
void CodeCompleteNaturalLanguage()
Hook used by the lexer to invoke the "natural language" code completion point.
void EndSourceFile()
Inform the preprocessor callbacks that processing is complete.
DiagnosticsEngine & getDiagnostics() const
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
void setCodeCompletionIdentifierInfo(IdentifierInfo *Filter)
Set the code completion token for filtering purposes.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
void SkipTokensWhileUsingPCH()
Skip tokens until after the #include of the through header or until after a #pragma hdrstop.
bool usingPCHWithThroughHeader()
True if using a PCH with a through header.
ScratchBuffer - This class exposes a simple interface for the dynamic construction of tokens.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
void print(raw_ostream &OS, const SourceManager &SM) const
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.
bool isLocalSourceLocation(SourceLocation Loc) const
Returns true if Loc did not come from a PCH/Module.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
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...
FileID getMainFileID() const
Returns the FileID of the main source file.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
void overrideFileContents(FileEntryRef SourceFile, const llvm::MemoryBufferRef &Buffer)
Override the contents of the given source file by providing an already-allocated buffer.
bool isLoadedFileID(FileID FID) const
Returns true if FID came from a PCH/Module.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SourceLocation createExpansionLoc(SourceLocation SpellingLoc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned Length, bool ExpansionIsTokenRange=true, int LoadedID=0, SourceLocation::UIntTy LoadedOffset=0)
Creates an expansion SLocEntry for a macro use.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
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.
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
void setLiteralData(const char *Ptr)
bool hasUCN() const
Returns true if this token contains a universal character name.
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
void setLength(unsigned Len)
bool isExpandDisabled() const
Return true if this identifier token should never be expanded in the future, due to C99 6....
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 hasLeadingEmptyMacro() const
Return true if this token has an empty macro before it.
void setRawIdentifierData(const char *Ptr)
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
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)
void setFlagValue(TokenFlags Flag, bool Val)
Set a flag to either true or false.
Defines the clang::TargetInfo interface.
const char * getTokenName(TokenKind Kind) LLVM_READNONE
Determines the name of a token as used within the front end.
The JSON file list parser is used to communicate input to InstallAPI.
void expandUCNs(SmallVectorImpl< char > &Buf, StringRef Input)
Copy characters from Input to Buf, expanding any UCNs.
llvm::Registry< PragmaHandler > PragmaHandlerRegistry
Registry of pragma handlers added by plugins.
@ Result
The result type of a method or function.
TranslationUnitKind
Describes the kind of translation unit being processed.
@ TU_Prefix
The translation unit is a prefix to a translation unit, and is not complete.