brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.3 KiB · 9a4fc7a Raw
307 lines · cpp
1//===- ExpandModularHeadersPPCallbacks.h - clang-tidy -----------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ExpandModularHeadersPPCallbacks.h"10#include "clang/Basic/FileManager.h"11#include "clang/Basic/TargetInfo.h"12#include "clang/Frontend/CompilerInstance.h"13#include "clang/Lex/PreprocessorOptions.h"14#include "clang/Serialization/ASTReader.h"15#include <optional>16 17#define DEBUG_TYPE "clang-tidy"18 19namespace clang::tooling {20 21class ExpandModularHeadersPPCallbacks::FileRecorder {22public:23  /// Records that a given file entry is needed for replaying callbacks.24  void addNecessaryFile(FileEntryRef File) {25    // Don't record modulemap files because it breaks same file detection.26    if (!(File.getName().ends_with("module.modulemap") ||27          File.getName().ends_with("module.private.modulemap") ||28          File.getName().ends_with("module.map") ||29          File.getName().ends_with("module_private.map")))30      FilesToRecord.insert(File);31  }32 33  /// Records content for a file and adds it to the FileSystem.34  void recordFileContent(FileEntryRef File,35                         const SrcMgr::ContentCache &ContentCache,36                         llvm::vfs::InMemoryFileSystem &InMemoryFs) {37    // Return if we are not interested in the contents of this file.38    if (!FilesToRecord.contains(File))39      return;40 41    // FIXME: Why is this happening? We might be losing contents here.42    std::optional<StringRef> Data = ContentCache.getBufferDataIfLoaded();43    if (!Data)44      return;45 46    InMemoryFs.addFile(File.getName(), /*ModificationTime=*/0,47                       llvm::MemoryBuffer::getMemBufferCopy(*Data));48    // Remove the file from the set of necessary files.49    FilesToRecord.erase(File);50  }51 52  /// Makes sure we have contents for all the files we were interested in.53  /// Ideally `FilesToRecord` should be empty.54  void checkAllFilesRecorded() {55    LLVM_DEBUG({56      for (auto FileEntry : FilesToRecord)57        llvm::dbgs() << "Did not record contents for input file: "58                     << FileEntry.getName() << "\n";59    });60  }61 62private:63  /// A set of files whose contents are to be recorded.64  llvm::DenseSet<FileEntryRef> FilesToRecord;65};66 67ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks(68    CompilerInstance *CI, llvm::vfs::OverlayFileSystem &OverlayFS)69    : Recorder(std::make_unique<FileRecorder>()), Compiler(*CI),70      InMemoryFs(new llvm::vfs::InMemoryFileSystem),71      Sources(Compiler.getSourceManager()),72      // Forward the new diagnostics to the original DiagnosticConsumer.73      Diags(DiagnosticIDs::create(), DiagOpts,74            new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())),75      LangOpts(Compiler.getLangOpts()), HSOpts(Compiler.getHeaderSearchOpts()) {76  // Add a FileSystem containing the extra files needed in place of modular77  // headers.78  OverlayFS.pushOverlay(InMemoryFs);79 80  Diags.setSourceManager(&Sources);81  // FIXME: Investigate whatever is there better way to initialize DiagEngine82  // or whatever DiagEngine can be shared by multiple preprocessors83  ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts(),84                        Compiler.getVirtualFileSystem());85 86  LangOpts.Modules = false;87 88  HeaderInfo = std::make_unique<HeaderSearch>(HSOpts, Sources, Diags, LangOpts,89                                              &Compiler.getTarget());90 91  PP = std::make_unique<clang::Preprocessor>(Compiler.getPreprocessorOpts(),92                                             Diags, LangOpts, Sources,93                                             *HeaderInfo, ModuleLoader,94                                             /*IILookup=*/nullptr,95                                             /*OwnsHeaderSearch=*/false);96  PP->Initialize(Compiler.getTarget(), Compiler.getAuxTarget());97  InitializePreprocessor(*PP, Compiler.getPreprocessorOpts(),98                         Compiler.getPCHContainerReader(),99                         Compiler.getFrontendOpts(), Compiler.getCodeGenOpts());100  ApplyHeaderSearchOptions(*HeaderInfo, HSOpts, LangOpts,101                           Compiler.getTarget().getTriple());102}103 104ExpandModularHeadersPPCallbacks::~ExpandModularHeadersPPCallbacks() = default;105 106Preprocessor *ExpandModularHeadersPPCallbacks::getPreprocessor() const {107  return PP.get();108}109 110void ExpandModularHeadersPPCallbacks::handleModuleFile(111    serialization::ModuleFile *MF) {112  if (!MF)113    return;114  // Avoid processing a ModuleFile more than once.115  if (!VisitedModules.insert(MF).second)116    return;117 118  // Visit all the input files of this module and mark them to record their119  // contents later.120  Compiler.getASTReader()->visitInputFiles(121      *MF, true, false,122      [this](const serialization::InputFile &IF, bool /*IsSystem*/) {123        Recorder->addNecessaryFile(*IF.getFile());124      });125  // Recursively handle all transitively imported modules.126  for (auto *Import : MF->Imports)127    handleModuleFile(Import);128}129 130void ExpandModularHeadersPPCallbacks::parseToLocation(SourceLocation Loc) {131  // Load all source locations present in the external sources.132  for (unsigned I = 0, N = Sources.loaded_sloc_entry_size(); I != N; ++I) {133    Sources.getLoadedSLocEntry(I, nullptr);134  }135  // Record contents of files we are interested in and add to the FileSystem.136  for (auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It) {137    Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs);138  }139  Recorder->checkAllFilesRecorded();140 141  if (!StartedLexing) {142    StartedLexing = true;143    PP->Lex(CurrentToken);144  }145  while (!CurrentToken.is(tok::eof) &&146         Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) {147    PP->Lex(CurrentToken);148  }149}150 151void ExpandModularHeadersPPCallbacks::FileChanged(152    SourceLocation Loc, FileChangeReason Reason,153    SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) {154  if (!EnteredMainFile) {155    EnteredMainFile = true;156    PP->EnterMainSourceFile();157  }158}159 160void ExpandModularHeadersPPCallbacks::InclusionDirective(161    SourceLocation DirectiveLoc, const Token &IncludeToken,162    StringRef IncludedFilename, bool IsAngled, CharSourceRange FilenameRange,163    OptionalFileEntryRef IncludedFile, StringRef SearchPath,164    StringRef RelativePath, const Module *SuggestedModule, bool ModuleImported,165    SrcMgr::CharacteristicKind FileType) {166  if (ModuleImported) {167    serialization::ModuleFile *MF =168        Compiler.getASTReader()->getModuleManager().lookup(169            *SuggestedModule->getASTFile());170    handleModuleFile(MF);171  }172  parseToLocation(DirectiveLoc);173}174 175void ExpandModularHeadersPPCallbacks::EndOfMainFile() {176  while (!CurrentToken.is(tok::eof))177    PP->Lex(CurrentToken);178}179 180// Handle all other callbacks.181// Just parse to the corresponding location to generate the same callback for182// the PPCallbacks registered in our custom preprocessor.183void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) {184  parseToLocation(Loc);185}186void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc,187                                                      PragmaIntroducerKind) {188  parseToLocation(Loc);189}190void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc,191                                                    const IdentifierInfo *,192                                                    StringRef) {193  parseToLocation(Loc);194}195void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,196                                                           StringRef,197                                                           StringRef) {198  parseToLocation(Loc);199}200void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc,201                                                  StringRef) {202  parseToLocation(Loc);203}204void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc,205                                                    StringRef,206                                                    PragmaMessageKind,207                                                    StringRef) {208  parseToLocation(Loc);209}210void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc,211                                                           StringRef) {212  parseToLocation(Loc);213}214void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc,215                                                          StringRef) {216  parseToLocation(Loc);217}218void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc,219                                                       StringRef,220                                                       diag::Severity,221                                                       StringRef) {222  parseToLocation(Loc);223}224void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef,225                                                 bool, OptionalFileEntryRef,226                                                 SrcMgr::CharacteristicKind) {227  parseToLocation(Loc);228}229void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension(230    SourceLocation NameLoc, const IdentifierInfo *, SourceLocation StateLoc,231    unsigned) {232  // FIXME: Figure out whether it's the right location to parse to.233  parseToLocation(NameLoc);234}235void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc,236                                                    PragmaWarningSpecifier,237                                                    ArrayRef<int>) {238  parseToLocation(Loc);239}240void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc,241                                                        int) {242  parseToLocation(Loc);243}244void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) {245  parseToLocation(Loc);246}247void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin(248    SourceLocation Loc) {249  parseToLocation(Loc);250}251void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(252    SourceLocation Loc) {253  parseToLocation(Loc);254}255void ExpandModularHeadersPPCallbacks::MacroExpands(const Token &MacroNameTok,256                                                   const MacroDefinition &,257                                                   SourceRange Range,258                                                   const MacroArgs *) {259  // FIXME: Figure out whether it's the right location to parse to.260  parseToLocation(Range.getBegin());261}262void ExpandModularHeadersPPCallbacks::MacroDefined(const Token &MacroNameTok,263                                                   const MacroDirective *MD) {264  parseToLocation(MD->getLocation());265}266void ExpandModularHeadersPPCallbacks::MacroUndefined(267    const Token &, const MacroDefinition &, const MacroDirective *Undef) {268  if (Undef)269    parseToLocation(Undef->getLocation());270}271void ExpandModularHeadersPPCallbacks::Defined(const Token &MacroNameTok,272                                              const MacroDefinition &,273                                              SourceRange Range) {274  // FIXME: Figure out whether it's the right location to parse to.275  parseToLocation(Range.getBegin());276}277void ExpandModularHeadersPPCallbacks::SourceRangeSkipped(278    SourceRange Range, SourceLocation EndifLoc) {279  // FIXME: Figure out whether it's the right location to parse to.280  parseToLocation(EndifLoc);281}282void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange,283                                         ConditionValueKind) {284  parseToLocation(Loc);285}286void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange,287                                           ConditionValueKind, SourceLocation) {288  parseToLocation(Loc);289}290void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc, const Token &,291                                            const MacroDefinition &) {292  parseToLocation(Loc);293}294void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc, const Token &,295                                             const MacroDefinition &) {296  parseToLocation(Loc);297}298void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) {299  parseToLocation(Loc);300}301void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc,302                                            SourceLocation) {303  parseToLocation(Loc);304}305 306} // namespace clang::tooling307