diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Lex/Preprocessor.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Lex/Preprocessor.cpp | 408 |
1 files changed, 272 insertions, 136 deletions
diff --git a/contrib/llvm-project/clang/lib/Lex/Preprocessor.cpp b/contrib/llvm-project/clang/lib/Lex/Preprocessor.cpp index 177786d90390..7fdb5d4c0d7b 100644 --- a/contrib/llvm-project/clang/lib/Lex/Preprocessor.cpp +++ b/contrib/llvm-project/clang/lib/Lex/Preprocessor.cpp @@ -58,7 +58,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" @@ -66,6 +65,7 @@ #include <algorithm> #include <cassert> #include <memory> +#include <optional> #include <string> #include <utility> #include <vector> @@ -77,7 +77,7 @@ LLVM_INSTANTIATE_REGISTRY(PragmaHandlerRegistry) ExternalPreprocessorSource::~ExternalPreprocessorSource() = default; Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, - DiagnosticsEngine &diags, LangOptions &opts, + DiagnosticsEngine &diags, const LangOptions &opts, SourceManager &SM, HeaderSearch &Headers, ModuleLoader &TheModuleLoader, IdentifierInfoLookup *IILookup, bool OwnsHeaders, @@ -146,6 +146,10 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, Ident_AbnormalTermination = nullptr; } + // Default incremental processing to -fincremental-extensions, clients can + // override with `enableIncrementalProcessing` if desired. + IncrementalProcessing = LangOpts.IncrementalExtensions; + // If using a PCH where a #pragma hdrstop is expected, start skipping tokens. if (usingPCHWithPragmaHdrStop()) SkippingUntilPragmaHdrStop = true; @@ -158,11 +162,6 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, if (this->PPOpts->GeneratePreamble) PreambleConditionalStack.startRecording(); - ExcludedConditionalDirectiveSkipMappings = - this->PPOpts->ExcludedConditionalDirectiveSkipMappings; - if (ExcludedConditionalDirectiveSkipMappings) - ExcludedConditionalDirectiveSkipMappings->clear(); - MaxTokens = LangOpts.MaxTokens; } @@ -171,12 +170,6 @@ Preprocessor::~Preprocessor() { IncludeMacroStack.clear(); - // Destroy any macro definitions. - while (MacroInfoChain *I = MIChainHead) { - MIChainHead = I->Next; - I->~MacroInfoChain(); - } - // Free any cached macro expanders. // This populates MacroArgCache, so all TokenLexers need to be destroyed // before the code below that frees up the MacroArgCache list. @@ -208,6 +201,16 @@ void Preprocessor::Initialize(const TargetInfo &Target, // Populate the identifier table with info about keywords for the current language. Identifiers.AddKeywords(LangOpts); + + // Initialize the __FTL_EVAL_METHOD__ macro to the TargetInfo. + setTUFPEvalMethod(getTargetInfo().getFPEvalMethod()); + + if (getLangOpts().getFPEvalMethod() == LangOptions::FEM_UnsetOnCommandLine) + // Use setting from TargetInfo. + setCurrentFPEvalMethod(SourceLocation(), Target.getFPEvalMethod()); + else + // Set initial value of __FLT_EVAL_METHOD__ from the command line. + setCurrentFPEvalMethod(SourceLocation(), getLangOpts().getFPEvalMethod()); } void Preprocessor::InitializeForModelFile() { @@ -229,8 +232,10 @@ void Preprocessor::FinalizeForModelFile() { } void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const { - llvm::errs() << tok::getTokenName(Tok.getKind()) << " '" - << getSpelling(Tok) << "'"; + llvm::errs() << tok::getTokenName(Tok.getKind()); + + if (!Tok.isAnnotation()) + llvm::errs() << " '" << getSpelling(Tok) << "'"; if (!DumpFlags) return; @@ -274,7 +279,7 @@ void Preprocessor::PrintStats() { llvm::errs() << " " << NumEnteredSourceFiles << " source files entered.\n"; llvm::errs() << " " << MaxIncludeStackDepth << " max include stack depth\n"; llvm::errs() << " " << NumIf << " #if/#ifndef/#ifdef.\n"; - llvm::errs() << " " << NumElse << " #else/#elif.\n"; + llvm::errs() << " " << NumElse << " #else/#elif/#elifdef/#elifndef.\n"; llvm::errs() << " " << NumEndif << " #endif.\n"; llvm::errs() << " " << NumPragma << " #pragma.\n"; llvm::errs() << NumSkipped << " #if/#ifndef#ifdef regions skipped\n"; @@ -377,22 +382,23 @@ StringRef Preprocessor::getLastMacroWithSpelling( void Preprocessor::recomputeCurLexerKind() { if (CurLexer) - CurLexerKind = CLK_Lexer; + CurLexerCallback = CurLexer->isDependencyDirectivesLexer() + ? CLK_DependencyDirectivesLexer + : CLK_Lexer; else if (CurTokenLexer) - CurLexerKind = CLK_TokenLexer; + CurLexerCallback = CLK_TokenLexer; else - CurLexerKind = CLK_CachingLexer; + CurLexerCallback = CLK_CachingLexer; } -bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File, +bool Preprocessor::SetCodeCompletionPoint(FileEntryRef File, unsigned CompleteLine, unsigned CompleteColumn) { - assert(File); assert(CompleteLine && CompleteColumn && "Starts from 1:1"); assert(!CodeCompletionFile && "Already set"); // Load the actual file's contents. - Optional<llvm::MemoryBufferRef> Buffer = + std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getMemoryBufferForFileOrNone(File); if (!Buffer) return true; @@ -442,15 +448,15 @@ bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File, void Preprocessor::CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) { + setCodeCompletionReached(); if (CodeComplete) CodeComplete->CodeCompleteIncludedFile(Dir, IsAngled); - setCodeCompletionReached(); } void Preprocessor::CodeCompleteNaturalLanguage() { + setCodeCompletionReached(); if (CodeComplete) CodeComplete->CodeCompleteNaturalLanguage(); - setCodeCompletionReached(); } /// getSpelling - This method is used to get the spelling of a token into a @@ -521,6 +527,13 @@ Module *Preprocessor::getCurrentModule() { return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule); } +Module *Preprocessor::getCurrentModuleImplementation() { + if (!getLangOpts().isCompilingModuleImplementation()) + return nullptr; + + return getHeaderSearchInfo().lookupModule(getLangOpts().ModuleName); +} + //===----------------------------------------------------------------------===// // Preprocessor Initialization Methods //===----------------------------------------------------------------------===// @@ -548,8 +561,8 @@ void Preprocessor::EnterMainSourceFile() { // Tell the header info that the main file was entered. If the file is later // #imported, it won't be re-entered. - if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID)) - HeaderInfo.IncrementIncludeCount(FE); + if (OptionalFileEntryRef FE = SourceMgr.getFileEntryRefForID(MainFileID)) + markIncluded(*FE); } // Preprocess Predefines to populate the initial preprocessor state. @@ -566,11 +579,10 @@ void Preprocessor::EnterMainSourceFile() { if (!PPOpts->PCHThroughHeader.empty()) { // Lookup and save the FileID for the through header. If it isn't found // in the search path, it's a fatal error. - const DirectoryLookup *CurDir; - Optional<FileEntryRef> File = LookupFile( + OptionalFileEntryRef File = LookupFile( SourceLocation(), PPOpts->PCHThroughHeader, - /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir, - /*SearchPath=*/nullptr, /*RelativePath=*/nullptr, + /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, + /*CurDir=*/nullptr, /*SearchPath=*/nullptr, /*RelativePath=*/nullptr, /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr, /*IsFrameworkFound=*/nullptr); if (!File) { @@ -631,20 +643,7 @@ void Preprocessor::SkipTokensWhileUsingPCH() { while (true) { bool InPredefines = (CurLexer && CurLexer->getFileID() == getPredefinesFileID()); - switch (CurLexerKind) { - case CLK_Lexer: - CurLexer->Lex(Tok); - break; - case CLK_TokenLexer: - CurTokenLexer->Lex(Tok); - break; - case CLK_CachingLexer: - CachingLex(Tok); - break; - case CLK_LexAfterModuleImport: - LexAfterModuleImport(Tok); - break; - } + CurLexerCallback(*this, Tok); if (Tok.is(tok::eof) && !InPredefines) { ReachedMainFileEOF = true; break; @@ -716,12 +715,14 @@ IdentifierInfo *Preprocessor::LookUpIdentifierInfo(Token &Identifier) const { } // Update the token info (identifier info and appropriate token kind). + // FIXME: the raw_identifier may contain leading whitespace which is removed + // from the cleaned identifier token. The SourceLocation should be updated to + // refer to the non-whitespace character. For instance, the text "\\\nB" (a + // line continuation before 'B') is parsed as a single tok::raw_identifier and + // is cleaned to tok::identifier "B". After cleaning the token's length is + // still 3 and the SourceLocation refers to the location of the backslash. Identifier.setIdentifierInfo(II); - if (getLangOpts().MSVCCompat && II->isCPlusPlusOperatorKeyword() && - getSourceManager().isInSystemHeader(Identifier.getLocation())) - Identifier.setKind(tok::identifier); - else - Identifier.setKind(II->getTokenID()); + Identifier.setKind(II->getTokenID()); return II; } @@ -755,29 +756,6 @@ void Preprocessor::HandlePoisonedIdentifier(Token & Identifier) { Diag(Identifier,it->second) << Identifier.getIdentifierInfo(); } -/// Returns a diagnostic message kind for reporting a future keyword as -/// appropriate for the identifier and specified language. -static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II, - const LangOptions &LangOpts) { - assert(II.isFutureCompatKeyword() && "diagnostic should not be needed"); - - if (LangOpts.CPlusPlus) - return llvm::StringSwitch<diag::kind>(II.getName()) -#define CXX11_KEYWORD(NAME, FLAGS) \ - .Case(#NAME, diag::warn_cxx11_keyword) -#define CXX20_KEYWORD(NAME, FLAGS) \ - .Case(#NAME, diag::warn_cxx20_keyword) -#include "clang/Basic/TokenKinds.def" - // char8_t is not modeled as a CXX20_KEYWORD because it's not - // unconditionally enabled in C++20 mode. (It can be disabled - // by -fno-char8_t.) - .Case("char8_t", diag::warn_cxx20_keyword) - ; - - llvm_unreachable( - "Keyword not known to come from a newer Standard or proposed Standard"); -} - void Preprocessor::updateOutOfDateIdentifier(IdentifierInfo &II) const { assert(II.isOutOfDate() && "not out of date"); getExternalSource()->updateOutOfDateIdentifier(II); @@ -823,8 +801,8 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { } // If this is a macro to be expanded, do it. - if (MacroDefinition MD = getMacroDefinition(&II)) { - auto *MI = MD.getMacroInfo(); + if (const MacroDefinition MD = getMacroDefinition(&II)) { + const auto *MI = MD.getMacroInfo(); assert(MI && "macro definition with no macro info?"); if (!DisableMacroExpansion) { if (!Identifier.isExpandDisabled() && MI->isEnabled()) { @@ -849,7 +827,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { // FIXME: This warning is disabled in cases where it shouldn't be, like // "#define constexpr constexpr", "int constexpr;" if (II.isFutureCompatKeyword() && !DisableMacroExpansion) { - Diag(Identifier, getFutureCompatDiagKind(II, getLangOpts())) + Diag(Identifier, getIdentifierTable().getFutureCompatDiagKind(II, getLangOpts())) << II.getName(); // Don't diagnose this keyword again in this translation unit. II.setIsFutureCompatKeyword(false); @@ -869,16 +847,17 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { // keyword when we're in a caching lexer, because caching lexers only get // used in contexts where import declarations are disallowed. // - // Likewise if this is the C++ Modules TS import keyword. + // Likewise if this is the standard C++ import keyword. if (((LastTokenWasAt && II.isModulesImport()) || Identifier.is(tok::kw_import)) && !InMacroArgs && !DisableMacroExpansion && (getLangOpts().Modules || getLangOpts().DebuggerSupport) && - CurLexerKind != CLK_CachingLexer) { + CurLexerCallback != CLK_CachingLexer) { ModuleImportLoc = Identifier.getLocation(); - ModuleImportPath.clear(); + NamedModuleImportPath.clear(); + IsAtImport = true; ModuleImportExpectsIdentifier = true; - CurLexerKind = CLK_LexAfterModuleImport; + CurLexerCallback = CLK_LexAfterModuleImport; } return true; } @@ -887,24 +866,8 @@ void Preprocessor::Lex(Token &Result) { ++LexLevel; // We loop here until a lex function returns a token; this avoids recursion. - bool ReturnedToken; - do { - switch (CurLexerKind) { - case CLK_Lexer: - ReturnedToken = CurLexer->Lex(Result); - break; - case CLK_TokenLexer: - ReturnedToken = CurTokenLexer->Lex(Result); - break; - case CLK_CachingLexer: - CachingLex(Result); - ReturnedToken = true; - break; - case CLK_LexAfterModuleImport: - ReturnedToken = LexAfterModuleImport(Result); - break; - } - } while (!ReturnedToken); + while (!CurLexerCallback(*this, Result)) + ; if (Result.is(tok::unknown) && TheModuleLoader.HadFatalFailure) return; @@ -918,44 +881,75 @@ void Preprocessor::Lex(Token &Result) { Result.setIdentifierInfo(nullptr); } - // Update ImportSeqState to track our position within a C++20 import-seq + // Update StdCXXImportSeqState to track our position within a C++20 import-seq // if this token is being produced as a result of phase 4 of translation. + // Update TrackGMFState to decide if we are currently in a Global Module + // Fragment. GMF state updates should precede StdCXXImportSeq ones, since GMF state + // depends on the prevailing StdCXXImportSeq state in two cases. if (getLangOpts().CPlusPlusModules && LexLevel == 1 && !Result.getFlag(Token::IsReinjected)) { switch (Result.getKind()) { case tok::l_paren: case tok::l_square: case tok::l_brace: - ImportSeqState.handleOpenBracket(); + StdCXXImportSeqState.handleOpenBracket(); break; case tok::r_paren: case tok::r_square: - ImportSeqState.handleCloseBracket(); + StdCXXImportSeqState.handleCloseBracket(); break; case tok::r_brace: - ImportSeqState.handleCloseBrace(); + StdCXXImportSeqState.handleCloseBrace(); break; + // This token is injected to represent the translation of '#include "a.h"' + // into "import a.h;". Mimic the notional ';'. + case tok::annot_module_include: case tok::semi: - ImportSeqState.handleSemi(); + TrackGMFState.handleSemi(); + StdCXXImportSeqState.handleSemi(); + ModuleDeclState.handleSemi(); break; case tok::header_name: case tok::annot_header_unit: - ImportSeqState.handleHeaderName(); + StdCXXImportSeqState.handleHeaderName(); break; case tok::kw_export: - ImportSeqState.handleExport(); + TrackGMFState.handleExport(); + StdCXXImportSeqState.handleExport(); + ModuleDeclState.handleExport(); + break; + case tok::colon: + ModuleDeclState.handleColon(); + break; + case tok::period: + ModuleDeclState.handlePeriod(); break; case tok::identifier: - if (Result.getIdentifierInfo()->isModulesImport()) { - ImportSeqState.handleImport(); - if (ImportSeqState.afterImportSeq()) { - ModuleImportLoc = Result.getLocation(); - ModuleImportPath.clear(); - ModuleImportExpectsIdentifier = true; - CurLexerKind = CLK_LexAfterModuleImport; + // Check "import" and "module" when there is no open bracket. The two + // identifiers are not meaningful with open brackets. + if (StdCXXImportSeqState.atTopLevel()) { + if (Result.getIdentifierInfo()->isModulesImport()) { + TrackGMFState.handleImport(StdCXXImportSeqState.afterTopLevelSeq()); + StdCXXImportSeqState.handleImport(); + if (StdCXXImportSeqState.afterImportSeq()) { + ModuleImportLoc = Result.getLocation(); + NamedModuleImportPath.clear(); + IsAtImport = false; + ModuleImportExpectsIdentifier = true; + CurLexerCallback = CLK_LexAfterModuleImport; + } + break; + } else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) { + TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq()); + ModuleDeclState.handleModule(); + break; } - break; } - LLVM_FALLTHROUGH; + ModuleDeclState.handleIdentifier(Result.getIdentifierInfo()); + if (ModuleDeclState.isModuleCandidate()) + break; + [[fallthrough]]; default: - ImportSeqState.handleMisc(); + TrackGMFState.handleMisc(); + StdCXXImportSeqState.handleMisc(); + ModuleDeclState.handleMisc(); break; } } @@ -972,6 +966,18 @@ void Preprocessor::Lex(Token &Result) { } } +void Preprocessor::LexTokensUntilEOF(std::vector<Token> *Tokens) { + while (1) { + Token Tok; + Lex(Tok); + if (Tok.isOneOf(tok::unknown, tok::eof, tok::eod, + tok::annot_repl_input_end)) + break; + if (Tokens != nullptr) + Tokens->push_back(Tok); + } +} + /// Lex a header-name token (including one formed from header-name-tokens if /// \p AllowConcatenation is \c true). /// @@ -1136,9 +1142,18 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { // For now, we only support header-name imports in C++20 mode. // FIXME: Should we allow this in all language modes that support an import // declaration as an extension? - if (ModuleImportPath.empty() && getLangOpts().CPlusPlusModules) { + if (NamedModuleImportPath.empty() && getLangOpts().CPlusPlusModules) { if (LexHeaderName(Result)) return true; + + if (Result.is(tok::colon) && ModuleDeclState.isNamedModule()) { + std::string Name = ModuleDeclState.getPrimaryName().str(); + Name += ":"; + NamedModuleImportPath.push_back( + {getIdentifierInfo(Name), Result.getLocation()}); + CurLexerCallback = CLK_LexAfterModuleImport; + return true; + } } else { Lex(Result); } @@ -1152,9 +1167,10 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { /*DisableMacroExpansion*/ true, /*IsReinject*/ false); }; + bool ImportingHeader = Result.is(tok::header_name); // Check for a header-name. SmallVector<Token, 32> Suffix; - if (Result.is(tok::header_name)) { + if (ImportingHeader) { // Enter the header-name token into the token stream; a Lex action cannot // both return a token and cache tokens (doing so would corrupt the token // cache if the call to Lex comes from CachingLex / PeekAhead). @@ -1198,9 +1214,10 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { Suffix.back().setLocation(SemiLoc); Suffix.back().setAnnotationEndLoc(SemiLoc); Suffix.back().setAnnotationValue(Action.ModuleForHeader); - LLVM_FALLTHROUGH; + [[fallthrough]]; case ImportAction::ModuleImport: + case ImportAction::HeaderUnitImport: case ImportAction::SkippedModuleImport: // We chose to import (or textually enter) the file. Convert the // header-name token into a header unit annotation token. @@ -1231,24 +1248,24 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { if (ModuleImportExpectsIdentifier && Result.getKind() == tok::identifier) { // We expected to see an identifier here, and we did; continue handling // identifiers. - ModuleImportPath.push_back(std::make_pair(Result.getIdentifierInfo(), - Result.getLocation())); + NamedModuleImportPath.push_back( + std::make_pair(Result.getIdentifierInfo(), Result.getLocation())); ModuleImportExpectsIdentifier = false; - CurLexerKind = CLK_LexAfterModuleImport; + CurLexerCallback = CLK_LexAfterModuleImport; return true; } // If we're expecting a '.' or a ';', and we got a '.', then wait until we // see the next identifier. (We can also see a '[[' that begins an - // attribute-specifier-seq here under the C++ Modules TS.) + // attribute-specifier-seq here under the Standard C++ Modules.) if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) { ModuleImportExpectsIdentifier = true; - CurLexerKind = CLK_LexAfterModuleImport; + CurLexerCallback = CLK_LexAfterModuleImport; return true; } // If we didn't recognize a module name at all, this is not a (valid) import. - if (ModuleImportPath.empty() || Result.is(tok::eof)) + if (NamedModuleImportPath.empty() || Result.is(tok::eof)) return true; // Consume the pp-import-suffix and expand any macros in it now, if we're not @@ -1265,34 +1282,37 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { SemiLoc = Suffix.back().getLocation(); } - // Under the Modules TS, the dot is just part of the module name, and not - // a real hierarchy separator. Flatten such module names now. + // Under the standard C++ Modules, the dot is just part of the module name, + // and not a real hierarchy separator. Flatten such module names now. // // FIXME: Is this the right level to be performing this transformation? std::string FlatModuleName; - if (getLangOpts().ModulesTS || getLangOpts().CPlusPlusModules) { - for (auto &Piece : ModuleImportPath) { - if (!FlatModuleName.empty()) + if (getLangOpts().CPlusPlusModules) { + for (auto &Piece : NamedModuleImportPath) { + // If the FlatModuleName ends with colon, it implies it is a partition. + if (!FlatModuleName.empty() && FlatModuleName.back() != ':') FlatModuleName += "."; FlatModuleName += Piece.first->getName(); } - SourceLocation FirstPathLoc = ModuleImportPath[0].second; - ModuleImportPath.clear(); - ModuleImportPath.push_back( + SourceLocation FirstPathLoc = NamedModuleImportPath[0].second; + NamedModuleImportPath.clear(); + NamedModuleImportPath.push_back( std::make_pair(getIdentifierInfo(FlatModuleName), FirstPathLoc)); } Module *Imported = nullptr; - if (getLangOpts().Modules) { + // We don't/shouldn't load the standard c++20 modules when preprocessing. + if (getLangOpts().Modules && !isInImportingCXXNamedModules()) { Imported = TheModuleLoader.loadModule(ModuleImportLoc, - ModuleImportPath, + NamedModuleImportPath, Module::Hidden, /*IsInclusionDirective=*/false); if (Imported) makeModuleVisible(Imported, SemiLoc); } + if (Callbacks) - Callbacks->moduleImport(ModuleImportLoc, ModuleImportPath, Imported); + Callbacks->moduleImport(ModuleImportLoc, NamedModuleImportPath, Imported); if (!Suffix.empty()) { EnterTokens(Suffix); @@ -1344,7 +1364,7 @@ bool Preprocessor::FinishLexStringLiteral(Token &Result, std::string &String, // Concatenate and parse the strings. StringLiteralParser Literal(StrToks, *this); - assert(Literal.isAscii() && "Didn't allow wide strings in"); + assert(Literal.isOrdinary() && "Didn't allow wide strings in"); if (Literal.hadError) return false; @@ -1381,7 +1401,7 @@ bool Preprocessor::parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value) { void Preprocessor::addCommentHandler(CommentHandler *Handler) { assert(Handler && "NULL comment handler"); - assert(llvm::find(CommentHandlers, Handler) == CommentHandlers.end() && + assert(!llvm::is_contained(CommentHandlers, Handler) && "Comment handler already registered"); CommentHandlers.push_back(Handler); } @@ -1407,6 +1427,122 @@ bool Preprocessor::HandleComment(Token &result, SourceRange Comment) { return true; } +void Preprocessor::emitMacroDeprecationWarning(const Token &Identifier) const { + const MacroAnnotations &A = + getMacroAnnotations(Identifier.getIdentifierInfo()); + assert(A.DeprecationInfo && + "Macro deprecation warning without recorded annotation!"); + const MacroAnnotationInfo &Info = *A.DeprecationInfo; + if (Info.Message.empty()) + Diag(Identifier, diag::warn_pragma_deprecated_macro_use) + << Identifier.getIdentifierInfo() << 0; + else + Diag(Identifier, diag::warn_pragma_deprecated_macro_use) + << Identifier.getIdentifierInfo() << 1 << Info.Message; + Diag(Info.Location, diag::note_pp_macro_annotation) << 0; +} + +void Preprocessor::emitRestrictExpansionWarning(const Token &Identifier) const { + const MacroAnnotations &A = + getMacroAnnotations(Identifier.getIdentifierInfo()); + assert(A.RestrictExpansionInfo && + "Macro restricted expansion warning without recorded annotation!"); + const MacroAnnotationInfo &Info = *A.RestrictExpansionInfo; + if (Info.Message.empty()) + Diag(Identifier, diag::warn_pragma_restrict_expansion_macro_use) + << Identifier.getIdentifierInfo() << 0; + else + Diag(Identifier, diag::warn_pragma_restrict_expansion_macro_use) + << Identifier.getIdentifierInfo() << 1 << Info.Message; + Diag(Info.Location, diag::note_pp_macro_annotation) << 1; +} + +void Preprocessor::emitRestrictInfNaNWarning(const Token &Identifier, + unsigned DiagSelection) const { + Diag(Identifier, diag::warn_fp_nan_inf_when_disabled) << DiagSelection << 1; +} + +void Preprocessor::emitFinalMacroWarning(const Token &Identifier, + bool IsUndef) const { + const MacroAnnotations &A = + getMacroAnnotations(Identifier.getIdentifierInfo()); + assert(A.FinalAnnotationLoc && + "Final macro warning without recorded annotation!"); + + Diag(Identifier, diag::warn_pragma_final_macro) + << Identifier.getIdentifierInfo() << (IsUndef ? 0 : 1); + Diag(*A.FinalAnnotationLoc, diag::note_pp_macro_annotation) << 2; +} + +bool Preprocessor::isSafeBufferOptOut(const SourceManager &SourceMgr, + const SourceLocation &Loc) const { + // Try to find a region in `SafeBufferOptOutMap` where `Loc` is in: + auto FirstRegionEndingAfterLoc = llvm::partition_point( + SafeBufferOptOutMap, + [&SourceMgr, + &Loc](const std::pair<SourceLocation, SourceLocation> &Region) { + return SourceMgr.isBeforeInTranslationUnit(Region.second, Loc); + }); + + if (FirstRegionEndingAfterLoc != SafeBufferOptOutMap.end()) { + // To test if the start location of the found region precedes `Loc`: + return SourceMgr.isBeforeInTranslationUnit(FirstRegionEndingAfterLoc->first, + Loc); + } + // If we do not find a region whose end location passes `Loc`, we want to + // check if the current region is still open: + if (!SafeBufferOptOutMap.empty() && + SafeBufferOptOutMap.back().first == SafeBufferOptOutMap.back().second) + return SourceMgr.isBeforeInTranslationUnit(SafeBufferOptOutMap.back().first, + Loc); + return false; +} + +bool Preprocessor::enterOrExitSafeBufferOptOutRegion( + bool isEnter, const SourceLocation &Loc) { + if (isEnter) { + if (isPPInSafeBufferOptOutRegion()) + return true; // invalid enter action + InSafeBufferOptOutRegion = true; + CurrentSafeBufferOptOutStart = Loc; + + // To set the start location of a new region: + + if (!SafeBufferOptOutMap.empty()) { + [[maybe_unused]] auto *PrevRegion = &SafeBufferOptOutMap.back(); + assert(PrevRegion->first != PrevRegion->second && + "Shall not begin a safe buffer opt-out region before closing the " + "previous one."); + } + // If the start location equals to the end location, we call the region a + // open region or a unclosed region (i.e., end location has not been set + // yet). + SafeBufferOptOutMap.emplace_back(Loc, Loc); + } else { + if (!isPPInSafeBufferOptOutRegion()) + return true; // invalid enter action + InSafeBufferOptOutRegion = false; + + // To set the end location of the current open region: + + assert(!SafeBufferOptOutMap.empty() && + "Misordered safe buffer opt-out regions"); + auto *CurrRegion = &SafeBufferOptOutMap.back(); + assert(CurrRegion->first == CurrRegion->second && + "Set end location to a closed safe buffer opt-out region"); + CurrRegion->second = Loc; + } + return false; +} + +bool Preprocessor::isPPInSafeBufferOptOutRegion() { + return InSafeBufferOptOutRegion; +} +bool Preprocessor::isPPInSafeBufferOptOutRegion(SourceLocation &StartLoc) { + StartLoc = CurrentSafeBufferOptOutStart; + return InSafeBufferOptOutRegion; +} + ModuleLoader::~ModuleLoader() = default; CommentHandler::~CommentHandler() = default; |