diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 13:58:24 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 14:11:53 +0300 |
commit | 11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch) | |
tree | fabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/tools/extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp | |
parent | 9685917341315774aad5733b1793b1e533a88bbb (diff) | |
download | ydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz |
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/tools/extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp')
-rw-r--r-- | contrib/libs/clang16/tools/extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/contrib/libs/clang16/tools/extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/contrib/libs/clang16/tools/extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp new file mode 100644 index 0000000000..a20fe23b17 --- /dev/null +++ b/contrib/libs/clang16/tools/extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -0,0 +1,308 @@ +//===- ExpandModularHeadersPPCallbacks.h - clang-tidy -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ExpandModularHeadersPPCallbacks.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Lex/PreprocessorOptions.h" +#include "clang/Serialization/ASTReader.h" +#include <optional> + +#define DEBUG_TYPE "clang-tidy" + +namespace clang::tooling { + +class ExpandModularHeadersPPCallbacks::FileRecorder { +public: + /// Records that a given file entry is needed for replaying callbacks. + void addNecessaryFile(const FileEntry *File) { + // Don't record modulemap files because it breaks same file detection. + if (!(File->getName().endswith("module.modulemap") || + File->getName().endswith("module.private.modulemap") || + File->getName().endswith("module.map") || + File->getName().endswith("module_private.map"))) + FilesToRecord.insert(File); + } + + /// Records content for a file and adds it to the FileSystem. + void recordFileContent(const FileEntry *File, + const SrcMgr::ContentCache &ContentCache, + llvm::vfs::InMemoryFileSystem &InMemoryFs) { + // Return if we are not interested in the contents of this file. + if (!FilesToRecord.count(File)) + return; + + // FIXME: Why is this happening? We might be losing contents here. + std::optional<StringRef> Data = ContentCache.getBufferDataIfLoaded(); + if (!Data) + return; + + InMemoryFs.addFile(File->getName(), /*ModificationTime=*/0, + llvm::MemoryBuffer::getMemBufferCopy(*Data)); + // Remove the file from the set of necessary files. + FilesToRecord.erase(File); + } + + /// Makes sure we have contents for all the files we were interested in. Ideally + /// `FilesToRecord` should be empty. + void checkAllFilesRecorded() { + LLVM_DEBUG({ + for (auto FileEntry : FilesToRecord) + llvm::dbgs() << "Did not record contents for input file: " + << FileEntry->getName() << "\n"; + }); + } + +private: + /// A set of files whose contents are to be recorded. + llvm::DenseSet<const FileEntry *> FilesToRecord; +}; + +ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks( + CompilerInstance *CI, + IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS) + : Recorder(std::make_unique<FileRecorder>()), Compiler(*CI), + InMemoryFs(new llvm::vfs::InMemoryFileSystem), + Sources(Compiler.getSourceManager()), + // Forward the new diagnostics to the original DiagnosticConsumer. + Diags(new DiagnosticIDs, new DiagnosticOptions, + new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())), + LangOpts(Compiler.getLangOpts()) { + // Add a FileSystem containing the extra files needed in place of modular + // headers. + OverlayFS->pushOverlay(InMemoryFs); + + Diags.setSourceManager(&Sources); + + LangOpts.Modules = false; + + auto HSO = std::make_shared<HeaderSearchOptions>(); + *HSO = Compiler.getHeaderSearchOpts(); + + HeaderInfo = std::make_unique<HeaderSearch>(HSO, Sources, Diags, LangOpts, + &Compiler.getTarget()); + + auto PO = std::make_shared<PreprocessorOptions>(); + *PO = Compiler.getPreprocessorOpts(); + + PP = std::make_unique<clang::Preprocessor>(PO, Diags, LangOpts, Sources, + *HeaderInfo, ModuleLoader, + /*IILookup=*/nullptr, + /*OwnsHeaderSearch=*/false); + PP->Initialize(Compiler.getTarget(), Compiler.getAuxTarget()); + InitializePreprocessor(*PP, *PO, Compiler.getPCHContainerReader(), + Compiler.getFrontendOpts()); + ApplyHeaderSearchOptions(*HeaderInfo, *HSO, LangOpts, + Compiler.getTarget().getTriple()); +} + +ExpandModularHeadersPPCallbacks::~ExpandModularHeadersPPCallbacks() = default; + +Preprocessor *ExpandModularHeadersPPCallbacks::getPreprocessor() const { + return PP.get(); +} + +void ExpandModularHeadersPPCallbacks::handleModuleFile( + serialization::ModuleFile *MF) { + if (!MF) + return; + // Avoid processing a ModuleFile more than once. + if (VisitedModules.count(MF)) + return; + VisitedModules.insert(MF); + + // Visit all the input files of this module and mark them to record their + // contents later. + Compiler.getASTReader()->visitInputFiles( + *MF, true, false, + [this](const serialization::InputFile &IF, bool /*IsSystem*/) { + Recorder->addNecessaryFile(IF.getFile()); + }); + // Recursively handle all transitively imported modules. + for (auto *Import : MF->Imports) + handleModuleFile(Import); +} + +void ExpandModularHeadersPPCallbacks::parseToLocation(SourceLocation Loc) { + // Load all source locations present in the external sources. + for (unsigned I = 0, N = Sources.loaded_sloc_entry_size(); I != N; ++I) { + Sources.getLoadedSLocEntry(I, nullptr); + } + // Record contents of files we are interested in and add to the FileSystem. + for (auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It) { + Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs); + } + Recorder->checkAllFilesRecorded(); + + if (!StartedLexing) { + StartedLexing = true; + PP->Lex(CurrentToken); + } + while (!CurrentToken.is(tok::eof) && + Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) { + PP->Lex(CurrentToken); + } +} + +void ExpandModularHeadersPPCallbacks::FileChanged( + SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) { + if (!EnteredMainFile) { + EnteredMainFile = true; + PP->EnterMainSourceFile(); + } +} + +void ExpandModularHeadersPPCallbacks::InclusionDirective( + SourceLocation DirectiveLoc, const Token &IncludeToken, + StringRef IncludedFilename, bool IsAngled, CharSourceRange FilenameRange, + OptionalFileEntryRef IncludedFile, StringRef SearchPath, + StringRef RelativePath, const Module *Imported, + SrcMgr::CharacteristicKind FileType) { + if (Imported) { + serialization::ModuleFile *MF = + Compiler.getASTReader()->getModuleManager().lookup( + Imported->getASTFile()); + handleModuleFile(MF); + } + parseToLocation(DirectiveLoc); +} + +void ExpandModularHeadersPPCallbacks::EndOfMainFile() { + while (!CurrentToken.is(tok::eof)) + PP->Lex(CurrentToken); +} + +// Handle all other callbacks. +// Just parse to the corresponding location to generate the same callback for +// the PPCallbacks registered in our custom preprocessor. +void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc, + PragmaIntroducerKind) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc, + const IdentifierInfo *, + StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc, + StringRef, + StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc, + StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc, + StringRef, + PragmaMessageKind, + StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc, + StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc, + StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc, + StringRef, + diag::Severity, + StringRef) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef, + bool, OptionalFileEntryRef, + SrcMgr::CharacteristicKind) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension( + SourceLocation NameLoc, const IdentifierInfo *, SourceLocation StateLoc, + unsigned) { + // FIXME: Figure out whether it's the right location to parse to. + parseToLocation(NameLoc); +} +void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc, + PragmaWarningSpecifier, + ArrayRef<int>) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc, + int) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin( + SourceLocation Loc) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd( + SourceLocation Loc) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::MacroExpands(const Token &MacroNameTok, + const MacroDefinition &, + SourceRange Range, + const MacroArgs *) { + // FIXME: Figure out whether it's the right location to parse to. + parseToLocation(Range.getBegin()); +} +void ExpandModularHeadersPPCallbacks::MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) { + parseToLocation(MD->getLocation()); +} +void ExpandModularHeadersPPCallbacks::MacroUndefined( + const Token &, const MacroDefinition &, const MacroDirective *Undef) { + if (Undef) + parseToLocation(Undef->getLocation()); +} +void ExpandModularHeadersPPCallbacks::Defined(const Token &MacroNameTok, + const MacroDefinition &, + SourceRange Range) { + // FIXME: Figure out whether it's the right location to parse to. + parseToLocation(Range.getBegin()); +} +void ExpandModularHeadersPPCallbacks::SourceRangeSkipped( + SourceRange Range, SourceLocation EndifLoc) { + // FIXME: Figure out whether it's the right location to parse to. + parseToLocation(EndifLoc); +} +void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange, + ConditionValueKind) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange, + ConditionValueKind, SourceLocation) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc, const Token &, + const MacroDefinition &) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc, const Token &, + const MacroDefinition &) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) { + parseToLocation(Loc); +} +void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc, + SourceLocation) { + parseToLocation(Loc); +} + +} // namespace clang::tooling |