llvm-project

Форк
0
/
ExpandModularHeadersPPCallbacks.cpp 
311 строк · 12.3 Кб
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
#include "ExpandModularHeadersPPCallbacks.h"
10
#include "clang/Basic/FileManager.h"
11
#include "clang/Basic/TargetInfo.h"
12
#include "clang/Frontend/CompilerInstance.h"
13
#include "clang/Lex/PreprocessorOptions.h"
14
#include "clang/Serialization/ASTReader.h"
15
#include <optional>
16

17
#define DEBUG_TYPE "clang-tidy"
18

19
namespace clang::tooling {
20

21
class ExpandModularHeadersPPCallbacks::FileRecorder {
22
public:
23
  /// Records that a given file entry is needed for replaying callbacks.
24
  void addNecessaryFile(FileEntryRef File) {
25
    // Don't record modulemap files because it breaks same file detection.
26
    if (!(File.getName().ends_with("module.modulemap") ||
27
          File.getName().ends_with("module.private.modulemap") ||
28
          File.getName().ends_with("module.map") ||
29
          File.getName().ends_with("module_private.map")))
30
      FilesToRecord.insert(File);
31
  }
32

33
  /// Records content for a file and adds it to the FileSystem.
34
  void recordFileContent(FileEntryRef File,
35
                         const SrcMgr::ContentCache &ContentCache,
36
                         llvm::vfs::InMemoryFileSystem &InMemoryFs) {
37
    // Return if we are not interested in the contents of this file.
38
    if (!FilesToRecord.count(File))
39
      return;
40

41
    // FIXME: Why is this happening? We might be losing contents here.
42
    std::optional<StringRef> Data = ContentCache.getBufferDataIfLoaded();
43
    if (!Data)
44
      return;
45

46
    InMemoryFs.addFile(File.getName(), /*ModificationTime=*/0,
47
                       llvm::MemoryBuffer::getMemBufferCopy(*Data));
48
    // Remove the file from the set of necessary files.
49
    FilesToRecord.erase(File);
50
  }
51

52
  /// Makes sure we have contents for all the files we were interested in. Ideally
53
  /// `FilesToRecord` should be empty.
54
  void checkAllFilesRecorded() {
55
    LLVM_DEBUG({
56
      for (auto FileEntry : FilesToRecord)
57
        llvm::dbgs() << "Did not record contents for input file: "
58
                     << FileEntry.getName() << "\n";
59
    });
60
  }
61

62
private:
63
  /// A set of files whose contents are to be recorded.
64
  llvm::DenseSet<FileEntryRef> FilesToRecord;
65
};
66

67
ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks(
68
    CompilerInstance *CI,
69
    IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
70
    : Recorder(std::make_unique<FileRecorder>()), Compiler(*CI),
71
      InMemoryFs(new llvm::vfs::InMemoryFileSystem),
72
      Sources(Compiler.getSourceManager()),
73
      // Forward the new diagnostics to the original DiagnosticConsumer.
74
      Diags(new DiagnosticIDs, new DiagnosticOptions,
75
            new ForwardingDiagnosticConsumer(Compiler.getDiagnosticClient())),
76
      LangOpts(Compiler.getLangOpts()) {
77
  // Add a FileSystem containing the extra files needed in place of modular
78
  // headers.
79
  OverlayFS->pushOverlay(InMemoryFs);
80

81
  Diags.setSourceManager(&Sources);
82
  // FIXME: Investigate whatever is there better way to initialize DiagEngine
83
  // or whatever DiagEngine can be shared by multiple preprocessors
84
  ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts());
85

86
  LangOpts.Modules = false;
87

88
  auto HSO = std::make_shared<HeaderSearchOptions>();
89
  *HSO = Compiler.getHeaderSearchOpts();
90

91
  HeaderInfo = std::make_unique<HeaderSearch>(HSO, Sources, Diags, LangOpts,
92
                                               &Compiler.getTarget());
93

94
  auto PO = std::make_shared<PreprocessorOptions>();
95
  *PO = Compiler.getPreprocessorOpts();
96

97
  PP = std::make_unique<clang::Preprocessor>(PO, Diags, LangOpts, Sources,
98
                                              *HeaderInfo, ModuleLoader,
99
                                              /*IILookup=*/nullptr,
100
                                              /*OwnsHeaderSearch=*/false);
101
  PP->Initialize(Compiler.getTarget(), Compiler.getAuxTarget());
102
  InitializePreprocessor(*PP, *PO, Compiler.getPCHContainerReader(),
103
                         Compiler.getFrontendOpts(), Compiler.getCodeGenOpts());
104
  ApplyHeaderSearchOptions(*HeaderInfo, *HSO, LangOpts,
105
                           Compiler.getTarget().getTriple());
106
}
107

108
ExpandModularHeadersPPCallbacks::~ExpandModularHeadersPPCallbacks() = default;
109

110
Preprocessor *ExpandModularHeadersPPCallbacks::getPreprocessor() const {
111
  return PP.get();
112
}
113

114
void ExpandModularHeadersPPCallbacks::handleModuleFile(
115
    serialization::ModuleFile *MF) {
116
  if (!MF)
117
    return;
118
  // Avoid processing a ModuleFile more than once.
119
  if (VisitedModules.count(MF))
120
    return;
121
  VisitedModules.insert(MF);
122

123
  // Visit all the input files of this module and mark them to record their
124
  // contents later.
125
  Compiler.getASTReader()->visitInputFiles(
126
      *MF, true, false,
127
      [this](const serialization::InputFile &IF, bool /*IsSystem*/) {
128
        Recorder->addNecessaryFile(*IF.getFile());
129
      });
130
  // Recursively handle all transitively imported modules.
131
  for (auto *Import : MF->Imports)
132
    handleModuleFile(Import);
133
}
134

135
void ExpandModularHeadersPPCallbacks::parseToLocation(SourceLocation Loc) {
136
  // Load all source locations present in the external sources.
137
  for (unsigned I = 0, N = Sources.loaded_sloc_entry_size(); I != N; ++I) {
138
    Sources.getLoadedSLocEntry(I, nullptr);
139
  }
140
  // Record contents of files we are interested in and add to the FileSystem.
141
  for (auto It = Sources.fileinfo_begin(); It != Sources.fileinfo_end(); ++It) {
142
    Recorder->recordFileContent(It->getFirst(), *It->getSecond(), *InMemoryFs);
143
  }
144
  Recorder->checkAllFilesRecorded();
145

146
  if (!StartedLexing) {
147
    StartedLexing = true;
148
    PP->Lex(CurrentToken);
149
  }
150
  while (!CurrentToken.is(tok::eof) &&
151
         Sources.isBeforeInTranslationUnit(CurrentToken.getLocation(), Loc)) {
152
    PP->Lex(CurrentToken);
153
  }
154
}
155

156
void ExpandModularHeadersPPCallbacks::FileChanged(
157
    SourceLocation Loc, FileChangeReason Reason,
158
    SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) {
159
  if (!EnteredMainFile) {
160
    EnteredMainFile = true;
161
    PP->EnterMainSourceFile();
162
  }
163
}
164

165
void ExpandModularHeadersPPCallbacks::InclusionDirective(
166
    SourceLocation DirectiveLoc, const Token &IncludeToken,
167
    StringRef IncludedFilename, bool IsAngled, CharSourceRange FilenameRange,
168
    OptionalFileEntryRef IncludedFile, StringRef SearchPath,
169
    StringRef RelativePath, const Module *SuggestedModule, bool ModuleImported,
170
    SrcMgr::CharacteristicKind FileType) {
171
  if (ModuleImported) {
172
    serialization::ModuleFile *MF =
173
        Compiler.getASTReader()->getModuleManager().lookup(
174
            *SuggestedModule->getASTFile());
175
    handleModuleFile(MF);
176
  }
177
  parseToLocation(DirectiveLoc);
178
}
179

180
void ExpandModularHeadersPPCallbacks::EndOfMainFile() {
181
  while (!CurrentToken.is(tok::eof))
182
    PP->Lex(CurrentToken);
183
}
184

185
// Handle all other callbacks.
186
// Just parse to the corresponding location to generate the same callback for
187
// the PPCallbacks registered in our custom preprocessor.
188
void ExpandModularHeadersPPCallbacks::Ident(SourceLocation Loc, StringRef) {
189
  parseToLocation(Loc);
190
}
191
void ExpandModularHeadersPPCallbacks::PragmaDirective(SourceLocation Loc,
192
                                                      PragmaIntroducerKind) {
193
  parseToLocation(Loc);
194
}
195
void ExpandModularHeadersPPCallbacks::PragmaComment(SourceLocation Loc,
196
                                                    const IdentifierInfo *,
197
                                                    StringRef) {
198
  parseToLocation(Loc);
199
}
200
void ExpandModularHeadersPPCallbacks::PragmaDetectMismatch(SourceLocation Loc,
201
                                                           StringRef,
202
                                                           StringRef) {
203
  parseToLocation(Loc);
204
}
205
void ExpandModularHeadersPPCallbacks::PragmaDebug(SourceLocation Loc,
206
                                                  StringRef) {
207
  parseToLocation(Loc);
208
}
209
void ExpandModularHeadersPPCallbacks::PragmaMessage(SourceLocation Loc,
210
                                                    StringRef,
211
                                                    PragmaMessageKind,
212
                                                    StringRef) {
213
  parseToLocation(Loc);
214
}
215
void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPush(SourceLocation Loc,
216
                                                           StringRef) {
217
  parseToLocation(Loc);
218
}
219
void ExpandModularHeadersPPCallbacks::PragmaDiagnosticPop(SourceLocation Loc,
220
                                                          StringRef) {
221
  parseToLocation(Loc);
222
}
223
void ExpandModularHeadersPPCallbacks::PragmaDiagnostic(SourceLocation Loc,
224
                                                       StringRef,
225
                                                       diag::Severity,
226
                                                       StringRef) {
227
  parseToLocation(Loc);
228
}
229
void ExpandModularHeadersPPCallbacks::HasInclude(SourceLocation Loc, StringRef,
230
                                                 bool, OptionalFileEntryRef,
231
                                                 SrcMgr::CharacteristicKind) {
232
  parseToLocation(Loc);
233
}
234
void ExpandModularHeadersPPCallbacks::PragmaOpenCLExtension(
235
    SourceLocation NameLoc, const IdentifierInfo *, SourceLocation StateLoc,
236
    unsigned) {
237
  // FIXME: Figure out whether it's the right location to parse to.
238
  parseToLocation(NameLoc);
239
}
240
void ExpandModularHeadersPPCallbacks::PragmaWarning(SourceLocation Loc,
241
                                                    PragmaWarningSpecifier,
242
                                                    ArrayRef<int>) {
243
  parseToLocation(Loc);
244
}
245
void ExpandModularHeadersPPCallbacks::PragmaWarningPush(SourceLocation Loc,
246
                                                        int) {
247
  parseToLocation(Loc);
248
}
249
void ExpandModularHeadersPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
250
  parseToLocation(Loc);
251
}
252
void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullBegin(
253
    SourceLocation Loc) {
254
  parseToLocation(Loc);
255
}
256
void ExpandModularHeadersPPCallbacks::PragmaAssumeNonNullEnd(
257
    SourceLocation Loc) {
258
  parseToLocation(Loc);
259
}
260
void ExpandModularHeadersPPCallbacks::MacroExpands(const Token &MacroNameTok,
261
                                                   const MacroDefinition &,
262
                                                   SourceRange Range,
263
                                                   const MacroArgs *) {
264
  // FIXME: Figure out whether it's the right location to parse to.
265
  parseToLocation(Range.getBegin());
266
}
267
void ExpandModularHeadersPPCallbacks::MacroDefined(const Token &MacroNameTok,
268
                                                   const MacroDirective *MD) {
269
  parseToLocation(MD->getLocation());
270
}
271
void ExpandModularHeadersPPCallbacks::MacroUndefined(
272
    const Token &, const MacroDefinition &, const MacroDirective *Undef) {
273
  if (Undef)
274
    parseToLocation(Undef->getLocation());
275
}
276
void ExpandModularHeadersPPCallbacks::Defined(const Token &MacroNameTok,
277
                                              const MacroDefinition &,
278
                                              SourceRange Range) {
279
  // FIXME: Figure out whether it's the right location to parse to.
280
  parseToLocation(Range.getBegin());
281
}
282
void ExpandModularHeadersPPCallbacks::SourceRangeSkipped(
283
    SourceRange Range, SourceLocation EndifLoc) {
284
  // FIXME: Figure out whether it's the right location to parse to.
285
  parseToLocation(EndifLoc);
286
}
287
void ExpandModularHeadersPPCallbacks::If(SourceLocation Loc, SourceRange,
288
                                         ConditionValueKind) {
289
  parseToLocation(Loc);
290
}
291
void ExpandModularHeadersPPCallbacks::Elif(SourceLocation Loc, SourceRange,
292
                                           ConditionValueKind, SourceLocation) {
293
  parseToLocation(Loc);
294
}
295
void ExpandModularHeadersPPCallbacks::Ifdef(SourceLocation Loc, const Token &,
296
                                            const MacroDefinition &) {
297
  parseToLocation(Loc);
298
}
299
void ExpandModularHeadersPPCallbacks::Ifndef(SourceLocation Loc, const Token &,
300
                                             const MacroDefinition &) {
301
  parseToLocation(Loc);
302
}
303
void ExpandModularHeadersPPCallbacks::Else(SourceLocation Loc, SourceLocation) {
304
  parseToLocation(Loc);
305
}
306
void ExpandModularHeadersPPCallbacks::Endif(SourceLocation Loc,
307
                                            SourceLocation) {
308
  parseToLocation(Loc);
309
}
310

311
} // namespace clang::tooling
312

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.