reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
//===- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
#define LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_

#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseSet.h"

namespace clang {
class CompilerInstance;

namespace serialization {
class ModuleFile;
} // namespace serialization

namespace tooling {

/// Handles PPCallbacks and re-runs preprocessing of the whole
/// translation unit with modules disabled.
///
/// This way it's possible to get PPCallbacks for the whole translation unit
/// including the contents of the modular headers and all their transitive
/// includes.
///
/// This allows existing tools based on PPCallbacks to retain their functionality
/// when running with C++ modules enabled. This only works in the backwards
/// compatible modules mode, i.e. when code can still be parsed in non-modular
/// way.
class ExpandModularHeadersPPCallbacks : public PPCallbacks {
public:
  ExpandModularHeadersPPCallbacks(
      CompilerInstance *Compiler,
      IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS);
  ~ExpandModularHeadersPPCallbacks();

  /// Returns the preprocessor that provides callbacks for the whole
  /// translation unit, including the main file, textual headers, and modular
  /// headers.
  ///
  /// This preprocessor is separate from the one used by the rest of the
  /// compiler.
  Preprocessor *getPreprocessor() const;

private:
  class FileRecorder;

  void handleModuleFile(serialization::ModuleFile *MF);
  void parseToLocation(SourceLocation Loc);

  // Handle PPCallbacks.
  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
                   SrcMgr::CharacteristicKind FileType,
                   FileID PrevFID) override;

  void InclusionDirective(SourceLocation DirectiveLoc,
                          const Token &IncludeToken, StringRef IncludedFilename,
                          bool IsAngled, CharSourceRange FilenameRange,
                          const FileEntry *IncludedFile, StringRef SearchPath,
                          StringRef RelativePath, const Module *Imported,
                          SrcMgr::CharacteristicKind FileType) override;

  void EndOfMainFile() override;

  // Handle all other callbacks.
  // Just parse to the corresponding location to generate PPCallbacks for the
  // corresponding range
  void Ident(SourceLocation Loc, StringRef) override;
  void PragmaDirective(SourceLocation Loc, PragmaIntroducerKind) override;
  void PragmaComment(SourceLocation Loc, const IdentifierInfo *,
                     StringRef) override;
  void PragmaDetectMismatch(SourceLocation Loc, StringRef, StringRef) override;
  void PragmaDebug(SourceLocation Loc, StringRef) override;
  void PragmaMessage(SourceLocation Loc, StringRef, PragmaMessageKind,
                     StringRef) override;
  void PragmaDiagnosticPush(SourceLocation Loc, StringRef) override;
  void PragmaDiagnosticPop(SourceLocation Loc, StringRef) override;
  void PragmaDiagnostic(SourceLocation Loc, StringRef, diag::Severity,
                        StringRef) override;
  void HasInclude(SourceLocation Loc, StringRef, bool, Optional<FileEntryRef> ,
                  SrcMgr::CharacteristicKind) override;
  void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *,
                             SourceLocation StateLoc, unsigned) override;
  void PragmaWarning(SourceLocation Loc, StringRef, ArrayRef<int>) override;
  void PragmaWarningPush(SourceLocation Loc, int) override;
  void PragmaWarningPop(SourceLocation Loc) override;
  void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
  void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &,
                    SourceRange Range, const MacroArgs *) override;
  void MacroDefined(const Token &MacroNameTok,
                    const MacroDirective *MD) override;
  void MacroUndefined(const Token &, const MacroDefinition &,
                      const MacroDirective *Undef) override;
  void Defined(const Token &MacroNameTok, const MacroDefinition &,
               SourceRange Range) override;
  void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
  void If(SourceLocation Loc, SourceRange, ConditionValueKind) override;
  void Elif(SourceLocation Loc, SourceRange, ConditionValueKind,
            SourceLocation) override;
  void Ifdef(SourceLocation Loc, const Token &,
             const MacroDefinition &) override;
  void Ifndef(SourceLocation Loc, const Token &,
              const MacroDefinition &) override;
  void Else(SourceLocation Loc, SourceLocation) override;
  void Endif(SourceLocation Loc, SourceLocation) override;

  std::unique_ptr<FileRecorder> Recorder;
  // Set of all the modules visited. Avoids processing a module more than once.
  llvm::DenseSet<serialization::ModuleFile *> VisitedModules;

  CompilerInstance &Compiler;
  // Additional filesystem for replay. Provides all input files from modules.
  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFs;

  SourceManager &Sources;
  DiagnosticsEngine Diags;
  LangOptions LangOpts;
  TrivialModuleLoader ModuleLoader;

  std::unique_ptr<HeaderSearch> HeaderInfo;
  std::unique_ptr<Preprocessor> PP;
  bool EnteredMainFile = false;
  bool StartedLexing = false;
  Token CurrentToken;
};

} // namespace tooling
} // namespace clang

#endif // LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_