Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- ClangModulesDeclVendor.cpp ----------------------------------------===//
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 "clang/Basic/TargetInfo.h"
10
#include "clang/Frontend/CompilerInstance.h"
11
#include "clang/Frontend/FrontendActions.h"
12
#include "clang/Frontend/TextDiagnosticPrinter.h"
13
#include "clang/Lex/Preprocessor.h"
14
#include "clang/Lex/PreprocessorOptions.h"
15
#include "clang/Parse/Parser.h"
16
#include "clang/Sema/Lookup.h"
17
#include "clang/Serialization/ASTReader.h"
18
#include "llvm/Support/FileSystem.h"
19
#include "llvm/Support/Path.h"
20
#include "llvm/Support/Threading.h"
21
22
#include "ClangHost.h"
23
#include "ClangModulesDeclVendor.h"
24
#include "ModuleDependencyCollector.h"
25
26
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
27
#include "lldb/Core/ModuleList.h"
28
#include "lldb/Host/Host.h"
29
#include "lldb/Host/HostInfo.h"
30
#include "lldb/Symbol/CompileUnit.h"
31
#include "lldb/Symbol/SourceModule.h"
32
#include "lldb/Target/Target.h"
33
#include "lldb/Utility/FileSpec.h"
34
#include "lldb/Utility/LLDBAssert.h"
35
#include "lldb/Utility/Log.h"
36
#include "lldb/Utility/ReproducerProvider.h"
37
#include "lldb/Utility/StreamString.h"
38
39
#include <memory>
40
#include <mutex>
41
42
using namespace lldb_private;
43
44
namespace {
45
/// Any Clang compiler requires a consumer for diagnostics.  This one stores
46
/// them as strings so we can provide them to the user in case a module failed
47
/// to load.
48
class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
49
public:
50
  StoringDiagnosticConsumer();
51
52
  void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
53
                        const clang::Diagnostic &info) override;
54
55
  void ClearDiagnostics();
56
57
  void DumpDiagnostics(Stream &error_stream);
58
59
  void BeginSourceFile(const clang::LangOptions &LangOpts,
60
                       const clang::Preprocessor *PP = nullptr) override;
61
  void EndSourceFile() override;
62
63
private:
64
  typedef std::pair<clang::DiagnosticsEngine::Level, std::string>
65
      IDAndDiagnostic;
66
  std::vector<IDAndDiagnostic> m_diagnostics;
67
  /// The DiagnosticPrinter used for creating the full diagnostic messages
68
  /// that are stored in m_diagnostics.
69
  std::shared_ptr<clang::TextDiagnosticPrinter> m_diag_printer;
70
  /// Output stream of m_diag_printer.
71
  std::shared_ptr<llvm::raw_string_ostream> m_os;
72
  /// Output string filled by m_os. Will be reused for different diagnostics.
73
  std::string m_output;
74
  Log *m_log;
75
};
76
77
/// The private implementation of our ClangModulesDeclVendor.  Contains all the
78
/// Clang state required to load modules.
79
class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
80
public:
81
  ClangModulesDeclVendorImpl(
82
      llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
83
      std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
84
      std::unique_ptr<clang::CompilerInstance> compiler_instance,
85
      std::unique_ptr<clang::Parser> parser);
86
87
1.34k
  ~ClangModulesDeclVendorImpl() override = default;
88
89
  bool AddModule(const SourceModule &module, ModuleVector *exported_modules,
90
                 Stream &error_stream) override;
91
92
  bool AddModulesForCompileUnit(CompileUnit &cu, ModuleVector &exported_modules,
93
                                Stream &error_stream) override;
94
95
  uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
96
                     std::vector<CompilerDecl> &decls) override;
97
98
  void ForEachMacro(
99
      const ModuleVector &modules,
100
      std::function<bool(llvm::StringRef, llvm::StringRef)> handler) override;
101
102
private:
103
  typedef llvm::DenseSet<ModuleID> ExportedModuleSet;
104
  void ReportModuleExportsHelper(ExportedModuleSet &exports,
105
                                 clang::Module *module);
106
107
  void ReportModuleExports(ModuleVector &exports, clang::Module *module);
108
109
  clang::ModuleLoadResult DoGetModule(clang::ModuleIdPath path,
110
                                      bool make_visible);
111
112
  bool m_enabled = false;
113
114
  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
115
  std::shared_ptr<clang::CompilerInvocation> m_compiler_invocation;
116
  std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
117
  std::unique_ptr<clang::Parser> m_parser;
118
  size_t m_source_location_index =
119
      0; // used to give name components fake SourceLocations
120
121
  typedef std::vector<ConstString> ImportedModule;
122
  typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
123
  typedef llvm::DenseSet<ModuleID> ImportedModuleSet;
124
  ImportedModuleMap m_imported_modules;
125
  ImportedModuleSet m_user_imported_modules;
126
  // We assume that every ASTContext has an TypeSystemClang, so we also store
127
  // a custom TypeSystemClang for our internal ASTContext.
128
  std::unique_ptr<TypeSystemClang> m_ast_context;
129
};
130
} // anonymous namespace
131
132
1.42k
StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
133
1.42k
  m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
134
135
1.42k
  clang::DiagnosticOptions *m_options = new clang::DiagnosticOptions();
136
1.42k
  m_os = std::make_shared<llvm::raw_string_ostream>(m_output);
137
1.42k
  m_diag_printer =
138
1.42k
      std::make_shared<clang::TextDiagnosticPrinter>(*m_os, m_options);
139
1.42k
}
140
141
void StoringDiagnosticConsumer::HandleDiagnostic(
142
1.75k
    clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) {
143
  // Print the diagnostic to m_output.
144
1.75k
  m_output.clear();
145
1.75k
  m_diag_printer->HandleDiagnostic(DiagLevel, info);
146
1.75k
  m_os->flush();
147
148
  // Store the diagnostic for later.
149
1.75k
  m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, m_output));
150
1.75k
}
151
152
158
void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
153
154
3
void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
155
9
  for (IDAndDiagnostic &diag : m_diagnostics) {
156
9
    switch (diag.first) {
157
9
    default:
158
9
      error_stream.PutCString(diag.second);
159
9
      error_stream.PutChar('\n');
160
9
      break;
161
0
    case clang::DiagnosticsEngine::Level::Ignored:
162
0
      break;
163
9
    }
164
9
  }
165
3
}
166
167
void StoringDiagnosticConsumer::BeginSourceFile(
168
1.38k
    const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) {
169
1.38k
  m_diag_printer->BeginSourceFile(LangOpts, PP);
170
1.38k
}
171
172
0
void StoringDiagnosticConsumer::EndSourceFile() {
173
0
  m_diag_printer->EndSourceFile();
174
0
}
175
176
ClangModulesDeclVendor::ClangModulesDeclVendor()
177
1.38k
    : ClangDeclVendor(eClangModuleDeclVendor) {}
178
179
1.34k
ClangModulesDeclVendor::~ClangModulesDeclVendor() = default;
180
181
ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
182
    llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
183
    std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
184
    std::unique_ptr<clang::CompilerInstance> compiler_instance,
185
    std::unique_ptr<clang::Parser> parser)
186
    : m_diagnostics_engine(std::move(diagnostics_engine)),
187
      m_compiler_invocation(std::move(compiler_invocation)),
188
      m_compiler_instance(std::move(compiler_instance)),
189
1.38k
      m_parser(std::move(parser)) {
190
191
  // Initialize our TypeSystemClang.
192
1.38k
  m_ast_context =
193
1.38k
      std::make_unique<TypeSystemClang>("ClangModulesDeclVendor ASTContext",
194
1.38k
                                        m_compiler_instance->getASTContext());
195
1.38k
}
196
197
void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
198
2.07M
    ExportedModuleSet &exports, clang::Module *module) {
199
2.07M
  if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
200
1.58M
    return;
201
202
493k
  exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
203
204
493k
  llvm::SmallVector<clang::Module *, 2> sub_exports;
205
206
493k
  module->getExportedModules(sub_exports);
207
208
493k
  for (clang::Module *module : sub_exports)
209
2.07M
    ReportModuleExportsHelper(exports, module);
210
493k
}
211
212
void ClangModulesDeclVendorImpl::ReportModuleExports(
213
829
    ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) {
214
829
  ExportedModuleSet exports_set;
215
216
829
  ReportModuleExportsHelper(exports_set, module);
217
218
829
  for (ModuleID module : exports_set)
219
493k
    exports.push_back(module);
220
829
}
221
222
bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
223
                                           ModuleVector *exported_modules,
224
4.89k
                                           Stream &error_stream) {
225
  // Fail early.
226
227
4.89k
  if (m_compiler_instance->hadModuleLoaderFatalFailure()) {
228
0
    error_stream.PutCString("error: Couldn't load a module because the module "
229
0
                            "loader is in a fatal state.\n");
230
0
    return false;
231
0
  }
232
233
  // Check if we've already imported this module.
234
235
4.89k
  std::vector<ConstString> imported_module;
236
237
4.89k
  for (ConstString path_component : module.path)
238
10.2k
    imported_module.push_back(path_component);
239
240
4.89k
  {
241
4.89k
    ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
242
243
4.89k
    if (mi != m_imported_modules.end()) {
244
674
      if (exported_modules)
245
674
        ReportModuleExports(*exported_modules, mi->second);
246
674
      return true;
247
674
    }
248
4.89k
  }
249
250
4.21k
  clang::HeaderSearch &HS =
251
4.21k
    m_compiler_instance->getPreprocessor().getHeaderSearchInfo();
252
253
4.21k
  if (module.search_path) {
254
4.18k
    auto path_begin = llvm::sys::path::begin(module.search_path.GetStringRef());
255
4.18k
    auto path_end = llvm::sys::path::end(module.search_path.GetStringRef());
256
4.18k
    auto sysroot_begin = llvm::sys::path::begin(module.sysroot.GetStringRef());
257
4.18k
    auto sysroot_end = llvm::sys::path::end(module.sysroot.GetStringRef());
258
    // FIXME: Use C++14 std::equal(it, it, it, it) variant once it's available.
259
4.18k
    bool is_system_module = (std::distance(path_begin, path_end) >=
260
4.18k
                             std::distance(sysroot_begin, sysroot_end)) &&
261
4.18k
                            std::equal(sysroot_begin, sysroot_end, path_begin);
262
    // No need to inject search paths to modules in the sysroot.
263
4.18k
    if (!is_system_module) {
264
3.00k
      auto error = [&]() {
265
3.00k
        error_stream.Printf("error: No module map file in %s\n",
266
3.00k
                            module.search_path.AsCString());
267
3.00k
        return false;
268
3.00k
      };
269
270
3.00k
      bool is_system = true;
271
3.00k
      bool is_framework = false;
272
3.00k
      auto dir =
273
3.00k
          HS.getFileMgr().getDirectory(module.search_path.GetStringRef());
274
3.00k
      if (!dir)
275
14
        return error();
276
2.99k
      auto *file = HS.lookupModuleMapFile(*dir, is_framework);
277
2.99k
      if (!file)
278
0
        return error();
279
2.99k
      if (!HS.loadModuleMapFile(file, is_system))
280
2.99k
        return error();
281
2.99k
    }
282
4.18k
  }
283
1.21k
  if (!HS.lookupModule(module.path.front().GetStringRef())) {
284
1.05k
    error_stream.Printf("error: Header search couldn't locate module %s\n",
285
1.05k
                        module.path.front().AsCString());
286
1.05k
    return false;
287
1.05k
  }
288
289
158
  llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>,
290
158
                    4>
291
158
      clang_path;
292
293
158
  {
294
158
    clang::SourceManager &source_manager =
295
158
        m_compiler_instance->getASTContext().getSourceManager();
296
297
271
    for (ConstString path_component : module.path) {
298
271
      clang_path.push_back(std::make_pair(
299
271
          &m_compiler_instance->getASTContext().Idents.get(
300
271
              path_component.GetStringRef()),
301
271
          source_manager.getLocForStartOfFile(source_manager.getMainFileID())
302
271
              .getLocWithOffset(m_source_location_index++)));
303
271
    }
304
158
  }
305
306
158
  StoringDiagnosticConsumer *diagnostic_consumer =
307
158
      static_cast<StoringDiagnosticConsumer *>(
308
158
          m_compiler_instance->getDiagnostics().getClient());
309
310
158
  diagnostic_consumer->ClearDiagnostics();
311
312
158
  clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
313
314
158
  if (!top_level_module) {
315
3
    diagnostic_consumer->DumpDiagnostics(error_stream);
316
3
    error_stream.Printf("error: Couldn't load top-level module %s\n",
317
3
                        module.path.front().AsCString());
318
3
    return false;
319
3
  }
320
321
155
  clang::Module *submodule = top_level_module;
322
323
155
  for (auto &component : llvm::ArrayRef<ConstString>(module.path).drop_front()) {
324
113
    submodule = submodule->findSubmodule(component.GetStringRef());
325
113
    if (!submodule) {
326
0
      diagnostic_consumer->DumpDiagnostics(error_stream);
327
0
      error_stream.Printf("error: Couldn't load submodule %s\n",
328
0
                          component.GetCString());
329
0
      return false;
330
0
    }
331
113
  }
332
333
155
  clang::Module *requested_module = DoGetModule(clang_path, true);
334
335
155
  if (requested_module != nullptr) {
336
155
    if (exported_modules)
337
155
      ReportModuleExports(*exported_modules, requested_module);
338
339
155
    m_imported_modules[imported_module] = requested_module;
340
341
155
    m_enabled = true;
342
343
155
    return true;
344
155
  }
345
346
0
  return false;
347
155
}
348
349
bool ClangModulesDeclVendor::LanguageSupportsClangModules(
350
19.0k
    lldb::LanguageType language) {
351
19.0k
  switch (language) {
352
0
  default:
353
0
    return false;
354
0
  case lldb::LanguageType::eLanguageTypeC:
355
0
  case lldb::LanguageType::eLanguageTypeC11:
356
0
  case lldb::LanguageType::eLanguageTypeC89:
357
1.69k
  case lldb::LanguageType::eLanguageTypeC99:
358
1.69k
  case lldb::LanguageType::eLanguageTypeC_plus_plus:
359
1.69k
  case lldb::LanguageType::eLanguageTypeC_plus_plus_03:
360
17.3k
  case lldb::LanguageType::eLanguageTypeC_plus_plus_11:
361
17.3k
  case lldb::LanguageType::eLanguageTypeC_plus_plus_14:
362
18.8k
  case lldb::LanguageType::eLanguageTypeObjC:
363
19.0k
  case lldb::LanguageType::eLanguageTypeObjC_plus_plus:
364
19.0k
    return true;
365
19.0k
  }
366
19.0k
}
367
368
bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
369
    CompileUnit &cu, ClangModulesDeclVendor::ModuleVector &exported_modules,
370
17.8k
    Stream &error_stream) {
371
17.8k
  if (LanguageSupportsClangModules(cu.GetLanguage())) {
372
17.8k
    for (auto &imported_module : cu.GetImportedModules())
373
4.85k
      if (!AddModule(imported_module, &exported_modules, error_stream))
374
4.05k
        return false;
375
17.8k
  }
376
13.7k
  return true;
377
17.8k
}
378
379
// ClangImporter::lookupValue
380
381
uint32_t
382
ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
383
                                      uint32_t max_matches,
384
20.3k
                                      std::vector<CompilerDecl> &decls) {
385
20.3k
  if (!m_enabled)
386
19.3k
    return 0;
387
388
994
  if (!append)
389
991
    decls.clear();
390
391
994
  clang::IdentifierInfo &ident =
392
994
      m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
393
394
994
  clang::LookupResult lookup_result(
395
994
      m_compiler_instance->getSema(), clang::DeclarationName(&ident),
396
994
      clang::SourceLocation(), clang::Sema::LookupOrdinaryName);
397
398
994
  m_compiler_instance->getSema().LookupName(
399
994
      lookup_result,
400
994
      m_compiler_instance->getSema().getScopeForContext(
401
994
          m_compiler_instance->getASTContext().getTranslationUnitDecl()));
402
403
994
  uint32_t num_matches = 0;
404
405
994
  for (clang::NamedDecl *named_decl : lookup_result) {
406
403
    if (num_matches >= max_matches)
407
0
      return num_matches;
408
409
403
    decls.push_back(m_ast_context->GetCompilerDecl(named_decl));
410
403
    ++num_matches;
411
403
  }
412
413
994
  return num_matches;
414
994
}
415
416
void ClangModulesDeclVendorImpl::ForEachMacro(
417
    const ClangModulesDeclVendor::ModuleVector &modules,
418
9.26k
    std::function<bool(llvm::StringRef, llvm::StringRef)> handler) {
419
9.26k
  if (!m_enabled)
420
8.92k
    return;
421
422
339
  typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
423
339
  ModulePriorityMap module_priorities;
424
425
339
  ssize_t priority = 0;
426
427
339
  for (ModuleID module : modules)
428
273k
    module_priorities[module] = priority++;
429
430
339
  if (m_compiler_instance->getPreprocessor().getExternalSource()) {
431
339
    m_compiler_instance->getPreprocessor()
432
339
        .getExternalSource()
433
339
        ->ReadDefinedMacros();
434
339
  }
435
436
339
  for (clang::Preprocessor::macro_iterator
437
339
           mi = m_compiler_instance->getPreprocessor().macro_begin(),
438
339
           me = m_compiler_instance->getPreprocessor().macro_end();
439
5.07M
       mi != me; 
++mi5.07M
) {
440
5.07M
    const clang::IdentifierInfo *ii = nullptr;
441
442
5.07M
    {
443
5.07M
      if (clang::IdentifierInfoLookup *lookup =
444
5.07M
              m_compiler_instance->getPreprocessor()
445
5.07M
                  .getIdentifierTable()
446
5.07M
                  .getExternalIdentifierLookup()) {
447
5.07M
        lookup->get(mi->first->getName());
448
5.07M
      }
449
5.07M
      if (!ii)
450
5.07M
        ii = mi->first;
451
5.07M
    }
452
453
5.07M
    ssize_t found_priority = -1;
454
5.07M
    clang::MacroInfo *macro_info = nullptr;
455
456
5.07M
    for (clang::ModuleMacro *module_macro :
457
5.07M
         m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) {
458
4.92M
      clang::Module *module = module_macro->getOwningModule();
459
460
4.92M
      {
461
4.92M
        ModulePriorityMap::iterator pi =
462
4.92M
            module_priorities.find(reinterpret_cast<ModuleID>(module));
463
464
4.92M
        if (pi != module_priorities.end() && 
pi->second > found_priority3.30M
) {
465
3.30M
          macro_info = module_macro->getMacroInfo();
466
3.30M
          found_priority = pi->second;
467
3.30M
        }
468
4.92M
      }
469
470
4.92M
      clang::Module *top_level_module = module->getTopLevelModule();
471
472
4.92M
      if (top_level_module != module) {
473
4.79M
        ModulePriorityMap::iterator pi = module_priorities.find(
474
4.79M
            reinterpret_cast<ModuleID>(top_level_module));
475
476
4.79M
        if ((pi != module_priorities.end()) && 
pi->second > found_priority2.77M
) {
477
1.13M
          macro_info = module_macro->getMacroInfo();
478
1.13M
          found_priority = pi->second;
479
1.13M
        }
480
4.79M
      }
481
4.92M
    }
482
483
5.07M
    if (macro_info) {
484
3.70M
      std::string macro_expansion = "#define ";
485
3.70M
      llvm::StringRef macro_identifier = mi->first->getName();
486
3.70M
      macro_expansion.append(macro_identifier.str());
487
488
3.70M
      {
489
3.70M
        if (macro_info->isFunctionLike()) {
490
488k
          macro_expansion.append("(");
491
492
488k
          bool first_arg = true;
493
494
488k
          for (auto pi = macro_info->param_begin(),
495
488k
                    pe = macro_info->param_end();
496
1.34M
               pi != pe; 
++pi860k
) {
497
860k
            if (!first_arg)
498
380k
              macro_expansion.append(", ");
499
479k
            else
500
479k
              first_arg = false;
501
502
860k
            macro_expansion.append((*pi)->getName().str());
503
860k
          }
504
505
488k
          if (macro_info->isC99Varargs()) {
506
26.2k
            if (first_arg)
507
0
              macro_expansion.append("...");
508
26.2k
            else
509
26.2k
              macro_expansion.append(", ...");
510
461k
          } else if (macro_info->isGNUVarargs())
511
201
            macro_expansion.append("...");
512
513
488k
          macro_expansion.append(")");
514
488k
        }
515
516
3.70M
        macro_expansion.append(" ");
517
518
3.70M
        bool first_token = true;
519
520
3.70M
        for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(),
521
3.70M
                                               te = macro_info->tokens_end();
522
21.9M
             ti != te; 
++ti18.2M
) {
523
18.2M
          if (!first_token)
524
14.8M
            macro_expansion.append(" ");
525
3.42M
          else
526
3.42M
            first_token = false;
527
528
18.2M
          if (ti->isLiteral()) {
529
3.72M
            if (const char *literal_data = ti->getLiteralData()) {
530
0
              std::string token_str(literal_data, ti->getLength());
531
0
              macro_expansion.append(token_str);
532
3.72M
            } else {
533
3.72M
              bool invalid = false;
534
3.72M
              const char *literal_source =
535
3.72M
                  m_compiler_instance->getSourceManager().getCharacterData(
536
3.72M
                      ti->getLocation(), &invalid);
537
538
3.72M
              if (invalid) {
539
0
                lldbassert(0 && "Unhandled token kind");
540
0
                macro_expansion.append("<unknown literal value>");
541
3.72M
              } else {
542
3.72M
                macro_expansion.append(
543
3.72M
                    std::string(literal_source, ti->getLength()));
544
3.72M
              }
545
3.72M
            }
546
14.5M
          } else if (const char *punctuator_spelling =
547
14.5M
                         clang::tok::getPunctuatorSpelling(ti->getKind())) {
548
9.65M
            macro_expansion.append(punctuator_spelling);
549
9.65M
          } else 
if (const char *4.90M
keyword_spelling4.90M
=
550
4.90M
                         clang::tok::getKeywordSpelling(ti->getKind())) {
551
610k
            macro_expansion.append(keyword_spelling);
552
4.29M
          } else {
553
4.29M
            switch (ti->getKind()) {
554
4.29M
            case clang::tok::TokenKind::identifier:
555
4.29M
              macro_expansion.append(ti->getIdentifierInfo()->getName().str());
556
4.29M
              break;
557
0
            case clang::tok::TokenKind::raw_identifier:
558
0
              macro_expansion.append(ti->getRawIdentifier().str());
559
0
              break;
560
0
            default:
561
0
              macro_expansion.append(ti->getName());
562
0
              break;
563
4.29M
            }
564
4.29M
          }
565
18.2M
        }
566
567
3.70M
        if (handler(macro_identifier, macro_expansion)) {
568
0
          return;
569
0
        }
570
3.70M
      }
571
3.70M
    }
572
5.07M
  }
573
339
}
574
575
clang::ModuleLoadResult
576
ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
577
313
                                        bool make_visible) {
578
313
  clang::Module::NameVisibilityKind visibility =
579
313
      make_visible ? 
clang::Module::AllVisible155
:
clang::Module::Hidden158
;
580
581
313
  const bool is_inclusion_directive = false;
582
583
313
  return m_compiler_instance->loadModule(path.front().second, path, visibility,
584
313
                                         is_inclusion_directive);
585
313
}
586
587
static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
588
589
lldb_private::ClangModulesDeclVendor *
590
1.42k
ClangModulesDeclVendor::Create(Target &target) {
591
  // FIXME we should insure programmatically that the expression parser's
592
  // compiler and the modules runtime's
593
  // compiler are both initialized in the same way – preferably by the same
594
  // code.
595
596
1.42k
  if (!target.GetPlatform()->SupportsModules())
597
4
    return nullptr;
598
599
1.42k
  const ArchSpec &arch = target.GetArchitecture();
600
601
1.42k
  std::vector<std::string> compiler_invocation_arguments = {
602
1.42k
      "clang",
603
1.42k
      "-fmodules",
604
1.42k
      "-fimplicit-module-maps",
605
1.42k
      "-fcxx-modules",
606
1.42k
      "-fsyntax-only",
607
1.42k
      "-femit-all-decls",
608
1.42k
      "-target",
609
1.42k
      arch.GetTriple().str(),
610
1.42k
      "-fmodules-validate-system-headers",
611
1.42k
      "-Werror=non-modular-include-in-framework-module"};
612
613
1.42k
  target.GetPlatform()->AddClangModuleCompilationOptions(
614
1.42k
      &target, compiler_invocation_arguments);
615
616
1.42k
  compiler_invocation_arguments.push_back(ModuleImportBufferName);
617
618
  // Add additional search paths with { "-I", path } or { "-F", path } here.
619
620
1.42k
  {
621
1.42k
    llvm::SmallString<128> path;
622
1.42k
    const auto &props = ModuleList::GetGlobalModuleListProperties();
623
1.42k
    props.GetClangModulesCachePath().GetPath(path);
624
1.42k
    std::string module_cache_argument("-fmodules-cache-path=");
625
1.42k
    module_cache_argument.append(std::string(path.str()));
626
1.42k
    compiler_invocation_arguments.push_back(module_cache_argument);
627
1.42k
  }
628
629
1.42k
  FileSpecList module_search_paths = target.GetClangModuleSearchPaths();
630
631
1.43k
  for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; 
++spi7
) {
632
7
    const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi);
633
634
7
    std::string search_path_argument = "-I";
635
7
    search_path_argument.append(search_path.GetPath());
636
637
7
    compiler_invocation_arguments.push_back(search_path_argument);
638
7
  }
639
640
1.42k
  {
641
1.42k
    FileSpec clang_resource_dir = GetClangResourceDir();
642
643
1.42k
    if (FileSystem::Instance().IsDirectory(clang_resource_dir.GetPath())) {
644
1.42k
      compiler_invocation_arguments.push_back("-resource-dir");
645
1.42k
      compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
646
1.42k
    }
647
1.42k
  }
648
649
1.42k
  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine =
650
1.42k
      clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
651
1.42k
                                                 new StoringDiagnosticConsumer);
652
653
1.42k
  std::vector<const char *> compiler_invocation_argument_cstrs;
654
1.42k
  compiler_invocation_argument_cstrs.reserve(
655
1.42k
      compiler_invocation_arguments.size());
656
1.42k
  for (const std::string &arg : compiler_invocation_arguments)
657
34.2k
    compiler_invocation_argument_cstrs.push_back(arg.c_str());
658
659
1.42k
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
660
1.42k
  LLDB_LOG(log, "ClangModulesDeclVendor's compiler flags {0:$[ ]}",
661
1.42k
           llvm::make_range(compiler_invocation_arguments.begin(),
662
1.42k
                            compiler_invocation_arguments.end()));
663
664
1.42k
  std::shared_ptr<clang::CompilerInvocation> invocation =
665
1.42k
      clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs,
666
1.42k
                                             diagnostics_engine);
667
668
1.42k
  if (!invocation)
669
41
    return nullptr;
670
671
1.38k
  std::unique_ptr<llvm::MemoryBuffer> source_buffer =
672
1.38k
      llvm::MemoryBuffer::getMemBuffer(
673
1.38k
          "extern int __lldb __attribute__((unavailable));",
674
1.38k
          ModuleImportBufferName);
675
676
1.38k
  invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName,
677
1.38k
                                                    source_buffer.release());
678
679
1.38k
  std::unique_ptr<clang::CompilerInstance> instance(
680
1.38k
      new clang::CompilerInstance);
681
682
  // When capturing a reproducer, hook up the file collector with clang to
683
  // collector modules and headers.
684
1.38k
  if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) {
685
2
    repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>();
686
2
    instance->setModuleDepCollector(
687
2
        std::make_shared<ModuleDependencyCollectorAdaptor>(
688
2
            fp.GetFileCollector()));
689
2
    clang::DependencyOutputOptions &opts = instance->getDependencyOutputOpts();
690
2
    opts.IncludeSystemHeaders = true;
691
2
    opts.IncludeModuleFiles = true;
692
2
  }
693
694
  // Make sure clang uses the same VFS as LLDB.
695
1.38k
  instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
696
1.38k
  instance->setDiagnostics(diagnostics_engine.get());
697
1.38k
  instance->setInvocation(invocation);
698
699
1.38k
  std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
700
701
1.38k
  instance->setTarget(clang::TargetInfo::CreateTargetInfo(
702
1.38k
      *diagnostics_engine, instance->getInvocation().TargetOpts));
703
704
1.38k
  if (!instance->hasTarget())
705
0
    return nullptr;
706
707
1.38k
  instance->getTarget().adjust(*diagnostics_engine, instance->getLangOpts());
708
709
1.38k
  if (!action->BeginSourceFile(*instance,
710
1.38k
                               instance->getFrontendOpts().Inputs[0]))
711
0
    return nullptr;
712
713
1.38k
  instance->getPreprocessor().enableIncrementalProcessing();
714
715
1.38k
  instance->createASTReader();
716
717
1.38k
  instance->createSema(action->getTranslationUnitKind(), nullptr);
718
719
1.38k
  const bool skipFunctionBodies = false;
720
1.38k
  std::unique_ptr<clang::Parser> parser(new clang::Parser(
721
1.38k
      instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
722
723
1.38k
  instance->getPreprocessor().EnterMainSourceFile();
724
1.38k
  parser->Initialize();
725
726
1.38k
  clang::Parser::DeclGroupPtrTy parsed;
727
728
2.76k
  while (!parser->ParseTopLevelDecl(parsed))
729
1.38k
    ;
730
731
1.38k
  return new ClangModulesDeclVendorImpl(std::move(diagnostics_engine),
732
1.38k
                                        std::move(invocation),
733
1.38k
                                        std::move(instance), std::move(parser));
734
1.38k
}