summaryrefslogtreecommitdiffstats
path: root/clang-tidy/ExpandModularHeadersPPCallbacks.h
blob: 4b431042527fa3ab91be8657bf9746b1d1c5ace6 (plain)
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 {

/// \brief 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();

  /// \brief 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, const FileEntry *,
                  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_