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