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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
10 #define LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
11 
12 #include "clang/Lex/PPCallbacks.h"
13 #include "clang/Lex/Preprocessor.h"
14 #include "llvm/ADT/DenseSet.h"
15 
16 namespace llvm {
17 namespace vfs {
18 class OverlayFileSystem;
19 class InMemoryFileSystem;
20 } // namespace vfs
21 } // namespace llvm
22 
23 namespace clang {
24 class CompilerInstance;
25 
26 namespace serialization {
27 class ModuleFile;
28 } // namespace serialization
29 
30 namespace tooling {
31 
32 /// Handles PPCallbacks and re-runs preprocessing of the whole
33 /// translation unit with modules disabled.
34 ///
35 /// This way it's possible to get PPCallbacks for the whole translation unit
36 /// including the contents of the modular headers and all their transitive
37 /// includes.
38 ///
39 /// This allows existing tools based on PPCallbacks to retain their functionality
40 /// when running with C++ modules enabled. This only works in the backwards
41 /// compatible modules mode, i.e. when code can still be parsed in non-modular
42 /// way.
43 class ExpandModularHeadersPPCallbacks : public PPCallbacks {
44 public:
45   ExpandModularHeadersPPCallbacks(
46       CompilerInstance *Compiler,
47       IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS);
48   ~ExpandModularHeadersPPCallbacks();
49 
50   /// Returns the preprocessor that provides callbacks for the whole
51   /// translation unit, including the main file, textual headers, and modular
52   /// headers.
53   ///
54   /// This preprocessor is separate from the one used by the rest of the
55   /// compiler.
56   Preprocessor *getPreprocessor() const;
57 
58 private:
59   class FileRecorder;
60 
61   void handleModuleFile(serialization::ModuleFile *MF);
62   void parseToLocation(SourceLocation Loc);
63 
64   // Handle PPCallbacks.
65   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
66                    SrcMgr::CharacteristicKind FileType,
67                    FileID PrevFID) override;
68 
69   void InclusionDirective(SourceLocation DirectiveLoc,
70                           const Token &IncludeToken, StringRef IncludedFilename,
71                           bool IsAngled, CharSourceRange FilenameRange,
72                           Optional<FileEntryRef> IncludedFile,
73                           StringRef SearchPath, StringRef RelativePath,
74                           const Module *Imported,
75                           SrcMgr::CharacteristicKind FileType) override;
76 
77   void EndOfMainFile() override;
78 
79   // Handle all other callbacks.
80   // Just parse to the corresponding location to generate PPCallbacks for the
81   // corresponding range
82   void Ident(SourceLocation Loc, StringRef) override;
83   void PragmaDirective(SourceLocation Loc, PragmaIntroducerKind) override;
84   void PragmaComment(SourceLocation Loc, const IdentifierInfo *,
85                      StringRef) override;
86   void PragmaDetectMismatch(SourceLocation Loc, StringRef, StringRef) override;
87   void PragmaDebug(SourceLocation Loc, StringRef) override;
88   void PragmaMessage(SourceLocation Loc, StringRef, PragmaMessageKind,
89                      StringRef) override;
90   void PragmaDiagnosticPush(SourceLocation Loc, StringRef) override;
91   void PragmaDiagnosticPop(SourceLocation Loc, StringRef) override;
92   void PragmaDiagnostic(SourceLocation Loc, StringRef, diag::Severity,
93                         StringRef) override;
94   void HasInclude(SourceLocation Loc, StringRef, bool, Optional<FileEntryRef> ,
95                   SrcMgr::CharacteristicKind) override;
96   void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *,
97                              SourceLocation StateLoc, unsigned) override;
98   void PragmaWarning(SourceLocation Loc, PragmaWarningSpecifier,
99                      ArrayRef<int>) override;
100   void PragmaWarningPush(SourceLocation Loc, int) override;
101   void PragmaWarningPop(SourceLocation Loc) override;
102   void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
103   void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
104   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &,
105                     SourceRange Range, const MacroArgs *) override;
106   void MacroDefined(const Token &MacroNameTok,
107                     const MacroDirective *MD) override;
108   void MacroUndefined(const Token &, const MacroDefinition &,
109                       const MacroDirective *Undef) override;
110   void Defined(const Token &MacroNameTok, const MacroDefinition &,
111                SourceRange Range) override;
112   void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
113   void If(SourceLocation Loc, SourceRange, ConditionValueKind) override;
114   void Elif(SourceLocation Loc, SourceRange, ConditionValueKind,
115             SourceLocation) override;
116   void Ifdef(SourceLocation Loc, const Token &,
117              const MacroDefinition &) override;
118   void Ifndef(SourceLocation Loc, const Token &,
119               const MacroDefinition &) override;
120   void Else(SourceLocation Loc, SourceLocation) override;
121   void Endif(SourceLocation Loc, SourceLocation) override;
122 
123   std::unique_ptr<FileRecorder> Recorder;
124   // Set of all the modules visited. Avoids processing a module more than once.
125   llvm::DenseSet<serialization::ModuleFile *> VisitedModules;
126 
127   CompilerInstance &Compiler;
128   // Additional filesystem for replay. Provides all input files from modules.
129   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFs;
130 
131   SourceManager &Sources;
132   DiagnosticsEngine Diags;
133   LangOptions LangOpts;
134   TrivialModuleLoader ModuleLoader;
135 
136   std::unique_ptr<HeaderSearch> HeaderInfo;
137   std::unique_ptr<Preprocessor> PP;
138   bool EnteredMainFile = false;
139   bool StartedLexing = false;
140   Token CurrentToken;
141 };
142 
143 } // namespace tooling
144 } // namespace clang
145 
146 #endif // LLVM_CLANG_TOOLING_EXPANDMODULARHEADERSPPCALLBACKS_H_
147