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