blob: b08c4540fe2aae9dc05c0222b3f8f56d3617b8b4 [file] [log] [blame]
Sean Callanan9998acd2014-12-05 01:21:59 +00001//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Sean Callanan9998acd2014-12-05 01:21:59 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +00009#include <mutex>
Greg Claytonff48e4b2015-02-03 02:05:44 +000010
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000011#include "clang/Basic/TargetInfo.h"
12#include "clang/Frontend/CompilerInstance.h"
13#include "clang/Frontend/FrontendActions.h"
14#include "clang/Lex/Preprocessor.h"
Chaoren Lin926db722016-07-18 21:11:43 +000015#include "clang/Lex/PreprocessorOptions.h"
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000016#include "clang/Parse/Parser.h"
17#include "clang/Sema/Lookup.h"
18#include "clang/Serialization/ASTReader.h"
Zachary Turner7d86ee52017-03-08 17:56:08 +000019#include "llvm/Support/FileSystem.h"
Chaoren Lin926db722016-07-18 21:11:43 +000020#include "llvm/Support/Path.h"
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000021#include "llvm/Support/Threading.h"
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000022
Zachary Turnerbdf08922018-06-04 17:41:00 +000023#include "ClangHost.h"
Sean Callanan4dbb2712015-09-25 20:35:58 +000024#include "ClangModulesDeclVendor.h"
Jonas Devlieghere63e2e592019-02-13 01:30:41 +000025#include "ModuleDependencyCollector.h"
Greg Claytonff48e4b2015-02-03 02:05:44 +000026
Adrian Prantl235354be2018-03-02 22:42:44 +000027#include "lldb/Core/ModuleList.h"
Sean Callanan9998acd2014-12-05 01:21:59 +000028#include "lldb/Host/Host.h"
29#include "lldb/Host/HostInfo.h"
Sean Callananf0c5aeb2015-04-20 16:31:29 +000030#include "lldb/Symbol/CompileUnit.h"
Adrian Prantl0f30a3b2019-02-13 18:10:41 +000031#include "lldb/Symbol/SourceModule.h"
Sean Callanan9998acd2014-12-05 01:21:59 +000032#include "lldb/Target/Target.h"
Zachary Turner5713a052017-03-22 18:40:07 +000033#include "lldb/Utility/FileSpec.h"
Sean Callanan007135e2015-07-08 00:13:49 +000034#include "lldb/Utility/LLDBAssert.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000035#include "lldb/Utility/Log.h"
Jonas Devlieghere63e2e592019-02-13 01:30:41 +000036#include "lldb/Utility/Reproducer.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000037#include "lldb/Utility/StreamString.h"
Sean Callanan9998acd2014-12-05 01:21:59 +000038
Sean Callanan9998acd2014-12-05 01:21:59 +000039using namespace lldb_private;
40
41namespace {
Adrian Prantl05097242018-04-30 16:49:04 +000042// Any Clang compiler requires a consumer for diagnostics. This one stores
43// them as strings so we can provide them to the user in case a module failed
44// to load.
Kate Stoneb9c1b512016-09-06 20:57:50 +000045class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
46public:
47 StoringDiagnosticConsumer();
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000048
Kate Stoneb9c1b512016-09-06 20:57:50 +000049 void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
50 const clang::Diagnostic &info) override;
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 void ClearDiagnostics();
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000053
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 void DumpDiagnostics(Stream &error_stream);
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056private:
57 typedef std::pair<clang::DiagnosticsEngine::Level, std::string>
58 IDAndDiagnostic;
59 std::vector<IDAndDiagnostic> m_diagnostics;
60 Log *m_log;
61};
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063// The private implementation of our ClangModulesDeclVendor. Contains all the
Adrian Prantl05097242018-04-30 16:49:04 +000064// Clang state required to load modules.
Kate Stoneb9c1b512016-09-06 20:57:50 +000065class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
66public:
67 ClangModulesDeclVendorImpl(
David Blaikie8fda2b32017-01-06 19:49:05 +000068 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
69 std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
70 std::unique_ptr<clang::CompilerInstance> compiler_instance,
71 std::unique_ptr<clang::Parser> parser);
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +000072
Kate Stoneb9c1b512016-09-06 20:57:50 +000073 ~ClangModulesDeclVendorImpl() override = default;
Sean Callananf0c5aeb2015-04-20 16:31:29 +000074
Adrian Prantl0f30a3b2019-02-13 18:10:41 +000075 bool AddModule(const SourceModule &module, ModuleVector *exported_modules,
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 Stream &error_stream) override;
Sean Callananf0c5aeb2015-04-20 16:31:29 +000077
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 bool AddModulesForCompileUnit(CompileUnit &cu, ModuleVector &exported_modules,
79 Stream &error_stream) override;
Sean Callananf0c5aeb2015-04-20 16:31:29 +000080
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 uint32_t FindDecls(const ConstString &name, bool append, uint32_t max_matches,
82 std::vector<clang::NamedDecl *> &decls) override;
83
84 void ForEachMacro(const ModuleVector &modules,
85 std::function<bool(const std::string &)> handler) override;
86
Sean Callanan68e44232017-09-28 20:20:25 +000087 clang::ExternalASTMerger::ImporterSource GetImporterSource() override;
Kate Stoneb9c1b512016-09-06 20:57:50 +000088private:
89 void
90 ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports,
91 clang::Module *module);
92
93 void ReportModuleExports(ModuleVector &exports, clang::Module *module);
94
95 clang::ModuleLoadResult DoGetModule(clang::ModuleIdPath path,
96 bool make_visible);
97
98 bool m_enabled = false;
99
100 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
David Blaikie8fda2b32017-01-06 19:49:05 +0000101 std::shared_ptr<clang::CompilerInvocation> m_compiler_invocation;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
103 std::unique_ptr<clang::Parser> m_parser;
104 size_t m_source_location_index =
105 0; // used to give name components fake SourceLocations
106
107 typedef std::vector<ConstString> ImportedModule;
108 typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
109 typedef std::set<ModuleID> ImportedModuleSet;
110 ImportedModuleMap m_imported_modules;
111 ImportedModuleSet m_user_imported_modules;
Sean Callanan68e44232017-09-28 20:20:25 +0000112 const clang::ExternalASTMerger::OriginMap m_origin_map;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113};
Eugene Zelenko4c3f2b92015-10-21 01:03:30 +0000114} // anonymous namespace
Sean Callanan9998acd2014-12-05 01:21:59 +0000115
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
117 m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
Sean Callanan9998acd2014-12-05 01:21:59 +0000118}
119
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120void StoringDiagnosticConsumer::HandleDiagnostic(
121 clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) {
122 llvm::SmallVector<char, 256> diagnostic_string;
123
124 info.FormatDiagnostic(diagnostic_string);
125
126 m_diagnostics.push_back(
127 IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(),
128 diagnostic_string.size())));
Sean Callanan9998acd2014-12-05 01:21:59 +0000129}
130
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
Sean Callanan9998acd2014-12-05 01:21:59 +0000132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
134 for (IDAndDiagnostic &diag : m_diagnostics) {
135 switch (diag.first) {
Sean Callananf0c5aeb2015-04-20 16:31:29 +0000136 default:
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000137 error_stream.PutCString(diag.second);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 error_stream.PutChar('\n');
139 break;
140 case clang::DiagnosticsEngine::Level::Ignored:
141 break;
Sean Callananf0c5aeb2015-04-20 16:31:29 +0000142 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 }
Sean Callananf0c5aeb2015-04-20 16:31:29 +0000144}
145
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146ClangModulesDeclVendor::ClangModulesDeclVendor() {}
147
148ClangModulesDeclVendor::~ClangModulesDeclVendor() {}
149
150ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
David Blaikie8fda2b32017-01-06 19:49:05 +0000151 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
152 std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
153 std::unique_ptr<clang::CompilerInstance> compiler_instance,
154 std::unique_ptr<clang::Parser> parser)
155 : m_diagnostics_engine(std::move(diagnostics_engine)),
156 m_compiler_invocation(std::move(compiler_invocation)),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 m_compiler_instance(std::move(compiler_instance)),
Pavel Labathcd3cbd42018-03-13 09:46:10 +0000158 m_parser(std::move(parser)), m_origin_map() {}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000159
160void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
161 std::set<ClangModulesDeclVendor::ModuleID> &exports,
162 clang::Module *module) {
163 if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
164 return;
165
166 exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
167
168 llvm::SmallVector<clang::Module *, 2> sub_exports;
169
170 module->getExportedModules(sub_exports);
171
172 for (clang::Module *module : sub_exports) {
173 ReportModuleExportsHelper(exports, module);
174 }
175}
176
177void ClangModulesDeclVendorImpl::ReportModuleExports(
178 ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) {
179 std::set<ClangModulesDeclVendor::ModuleID> exports_set;
180
181 ReportModuleExportsHelper(exports_set, module);
182
183 for (ModuleID module : exports_set) {
184 exports.push_back(module);
185 }
186}
187
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000188bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000189 ModuleVector *exported_modules,
190 Stream &error_stream) {
191 // Fail early.
192
193 if (m_compiler_instance->hadModuleLoaderFatalFailure()) {
194 error_stream.PutCString("error: Couldn't load a module because the module "
195 "loader is in a fatal state.\n");
196 return false;
197 }
198
199 // Check if we've already imported this module.
200
201 std::vector<ConstString> imported_module;
202
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000203 for (ConstString path_component : module.path) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 imported_module.push_back(path_component);
205 }
206
207 {
208 ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
209
210 if (mi != m_imported_modules.end()) {
211 if (exported_modules) {
212 ReportModuleExports(*exported_modules, mi->second);
213 }
214 return true;
215 }
216 }
217
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000218 clang::HeaderSearch &HS =
219 m_compiler_instance->getPreprocessor().getHeaderSearchInfo();
220
221 if (module.search_path) {
222 auto path_begin = llvm::sys::path::begin(module.search_path.GetStringRef());
223 auto path_end = llvm::sys::path::end(module.search_path.GetStringRef());
224 auto sysroot_begin = llvm::sys::path::begin(module.sysroot.GetStringRef());
225 auto sysroot_end = llvm::sys::path::end(module.sysroot.GetStringRef());
226 // FIXME: Use C++14 std::equal(it, it, it, it) variant once it's available.
227 bool is_system_module = (std::distance(path_begin, path_end) >=
228 std::distance(sysroot_begin, sysroot_end)) &&
229 std::equal(sysroot_begin, sysroot_end, path_begin);
230 // No need to inject search paths to modules in the sysroot.
231 if (!is_system_module) {
232 bool is_system = true;
233 bool is_framework = false;
234 auto *dir =
235 HS.getFileMgr().getDirectory(module.search_path.GetStringRef());
236 auto *file = HS.lookupModuleMapFile(dir, is_framework);
237 if (!HS.loadModuleMapFile(file, is_system))
238 error_stream.Printf("error: No module map file in %s\n",
239 module.search_path.AsCString());
240 return false;
241 }
242 }
243 if (!HS.lookupModule(module.path.front().GetStringRef())) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244 error_stream.Printf("error: Header search couldn't locate module %s\n",
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000245 module.path.front().AsCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246 return false;
247 }
248
249 llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>,
250 4>
251 clang_path;
252
253 {
254 clang::SourceManager &source_manager =
255 m_compiler_instance->getASTContext().getSourceManager();
256
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000257 for (ConstString path_component : module.path) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 clang_path.push_back(std::make_pair(
259 &m_compiler_instance->getASTContext().Idents.get(
260 path_component.GetStringRef()),
261 source_manager.getLocForStartOfFile(source_manager.getMainFileID())
262 .getLocWithOffset(m_source_location_index++)));
263 }
264 }
265
266 StoringDiagnosticConsumer *diagnostic_consumer =
267 static_cast<StoringDiagnosticConsumer *>(
268 m_compiler_instance->getDiagnostics().getClient());
269
270 diagnostic_consumer->ClearDiagnostics();
271
272 clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
273
274 if (!top_level_module) {
275 diagnostic_consumer->DumpDiagnostics(error_stream);
276 error_stream.Printf("error: Couldn't load top-level module %s\n",
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000277 module.path.front().AsCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000278 return false;
279 }
280
281 clang::Module *submodule = top_level_module;
282
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000283 for (auto &component : llvm::ArrayRef<ConstString>(module.path).drop_front()) {
284 submodule = submodule->findSubmodule(component.GetStringRef());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000285 if (!submodule) {
286 diagnostic_consumer->DumpDiagnostics(error_stream);
287 error_stream.Printf("error: Couldn't load submodule %s\n",
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000288 component.GetCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 return false;
290 }
291 }
292
293 clang::Module *requested_module = DoGetModule(clang_path, true);
294
295 if (requested_module != nullptr) {
296 if (exported_modules) {
297 ReportModuleExports(*exported_modules, requested_module);
298 }
299
300 m_imported_modules[imported_module] = requested_module;
301
302 m_enabled = true;
303
304 return true;
305 }
306
307 return false;
308}
309
310bool ClangModulesDeclVendor::LanguageSupportsClangModules(
311 lldb::LanguageType language) {
312 switch (language) {
313 default:
314 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315 case lldb::LanguageType::eLanguageTypeC:
316 case lldb::LanguageType::eLanguageTypeC11:
317 case lldb::LanguageType::eLanguageTypeC89:
318 case lldb::LanguageType::eLanguageTypeC99:
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000319 case lldb::LanguageType::eLanguageTypeC_plus_plus:
320 case lldb::LanguageType::eLanguageTypeC_plus_plus_03:
321 case lldb::LanguageType::eLanguageTypeC_plus_plus_11:
322 case lldb::LanguageType::eLanguageTypeC_plus_plus_14:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000323 case lldb::LanguageType::eLanguageTypeObjC:
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000324 case lldb::LanguageType::eLanguageTypeObjC_plus_plus:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325 return true;
326 }
327}
328
329bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
330 CompileUnit &cu, ClangModulesDeclVendor::ModuleVector &exported_modules,
331 Stream &error_stream) {
332 if (LanguageSupportsClangModules(cu.GetLanguage())) {
Adrian Prantl0f30a3b2019-02-13 18:10:41 +0000333 for (auto &imported_module : cu.GetImportedModules())
334 if (!AddModule(imported_module, &exported_modules, error_stream))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000335 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000336 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337 return true;
Sean Callanan9998acd2014-12-05 01:21:59 +0000338}
339
340// ClangImporter::lookupValue
341
342uint32_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343ClangModulesDeclVendorImpl::FindDecls(const ConstString &name, bool append,
344 uint32_t max_matches,
345 std::vector<clang::NamedDecl *> &decls) {
346 if (!m_enabled) {
347 return 0;
348 }
Sean Callananf0c5aeb2015-04-20 16:31:29 +0000349
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350 if (!append)
351 decls.clear();
352
353 clang::IdentifierInfo &ident =
354 m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
355
356 clang::LookupResult lookup_result(
357 m_compiler_instance->getSema(), clang::DeclarationName(&ident),
358 clang::SourceLocation(), clang::Sema::LookupOrdinaryName);
359
360 m_compiler_instance->getSema().LookupName(
361 lookup_result,
362 m_compiler_instance->getSema().getScopeForContext(
363 m_compiler_instance->getASTContext().getTranslationUnitDecl()));
364
365 uint32_t num_matches = 0;
366
367 for (clang::NamedDecl *named_decl : lookup_result) {
368 if (num_matches >= max_matches)
369 return num_matches;
370
371 decls.push_back(named_decl);
372 ++num_matches;
373 }
374
375 return num_matches;
Sean Callanan9998acd2014-12-05 01:21:59 +0000376}
377
Kate Stoneb9c1b512016-09-06 20:57:50 +0000378void ClangModulesDeclVendorImpl::ForEachMacro(
379 const ClangModulesDeclVendor::ModuleVector &modules,
380 std::function<bool(const std::string &)> handler) {
381 if (!m_enabled) {
382 return;
383 }
Sean Callananb8bf6ef2015-04-14 18:36:17 +0000384
Kate Stoneb9c1b512016-09-06 20:57:50 +0000385 typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
386 ModulePriorityMap module_priorities;
387
388 ssize_t priority = 0;
389
390 for (ModuleID module : modules) {
391 module_priorities[module] = priority++;
392 }
393
394 if (m_compiler_instance->getPreprocessor().getExternalSource()) {
395 m_compiler_instance->getPreprocessor()
396 .getExternalSource()
397 ->ReadDefinedMacros();
398 }
399
400 for (clang::Preprocessor::macro_iterator
401 mi = m_compiler_instance->getPreprocessor().macro_begin(),
402 me = m_compiler_instance->getPreprocessor().macro_end();
403 mi != me; ++mi) {
404 const clang::IdentifierInfo *ii = nullptr;
405
406 {
407 if (clang::IdentifierInfoLookup *lookup =
408 m_compiler_instance->getPreprocessor()
409 .getIdentifierTable()
410 .getExternalIdentifierLookup()) {
411 lookup->get(mi->first->getName());
412 }
413 if (!ii) {
414 ii = mi->first;
415 }
Sean Callananb8bf6ef2015-04-14 18:36:17 +0000416 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000417
418 ssize_t found_priority = -1;
419 clang::MacroInfo *macro_info = nullptr;
420
421 for (clang::ModuleMacro *module_macro :
422 m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) {
423 clang::Module *module = module_macro->getOwningModule();
424
425 {
426 ModulePriorityMap::iterator pi =
427 module_priorities.find(reinterpret_cast<ModuleID>(module));
428
429 if (pi != module_priorities.end() && pi->second > found_priority) {
430 macro_info = module_macro->getMacroInfo();
431 found_priority = pi->second;
432 }
433 }
434
435 clang::Module *top_level_module = module->getTopLevelModule();
436
437 if (top_level_module != module) {
438 ModulePriorityMap::iterator pi = module_priorities.find(
439 reinterpret_cast<ModuleID>(top_level_module));
440
441 if ((pi != module_priorities.end()) && pi->second > found_priority) {
442 macro_info = module_macro->getMacroInfo();
443 found_priority = pi->second;
444 }
445 }
446 }
447
448 if (macro_info) {
449 std::string macro_expansion = "#define ";
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000450 macro_expansion.append(mi->first->getName().str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451
452 {
453 if (macro_info->isFunctionLike()) {
454 macro_expansion.append("(");
455
456 bool first_arg = true;
457
Eugene Zemtsov20d28a12017-07-17 20:50:21 +0000458 for (auto pi = macro_info->param_begin(),
459 pe = macro_info->param_end();
460 pi != pe; ++pi) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000461 if (!first_arg) {
462 macro_expansion.append(", ");
463 } else {
464 first_arg = false;
465 }
466
Eugene Zemtsov20d28a12017-07-17 20:50:21 +0000467 macro_expansion.append((*pi)->getName().str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468 }
469
470 if (macro_info->isC99Varargs()) {
471 if (first_arg) {
472 macro_expansion.append("...");
473 } else {
474 macro_expansion.append(", ...");
475 }
476 } else if (macro_info->isGNUVarargs()) {
477 macro_expansion.append("...");
478 }
479
480 macro_expansion.append(")");
481 }
482
483 macro_expansion.append(" ");
484
485 bool first_token = true;
486
487 for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(),
488 te = macro_info->tokens_end();
489 ti != te; ++ti) {
490 if (!first_token) {
491 macro_expansion.append(" ");
492 } else {
493 first_token = false;
494 }
495
496 if (ti->isLiteral()) {
497 if (const char *literal_data = ti->getLiteralData()) {
498 std::string token_str(literal_data, ti->getLength());
499 macro_expansion.append(token_str);
500 } else {
501 bool invalid = false;
502 const char *literal_source =
503 m_compiler_instance->getSourceManager().getCharacterData(
504 ti->getLocation(), &invalid);
505
506 if (invalid) {
Pavel Labathf31c9d22017-01-05 13:18:42 +0000507 lldbassert(0 && "Unhandled token kind");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000508 macro_expansion.append("<unknown literal value>");
509 } else {
510 macro_expansion.append(
511 std::string(literal_source, ti->getLength()));
512 }
513 }
514 } else if (const char *punctuator_spelling =
515 clang::tok::getPunctuatorSpelling(ti->getKind())) {
516 macro_expansion.append(punctuator_spelling);
517 } else if (const char *keyword_spelling =
518 clang::tok::getKeywordSpelling(ti->getKind())) {
519 macro_expansion.append(keyword_spelling);
520 } else {
521 switch (ti->getKind()) {
522 case clang::tok::TokenKind::identifier:
523 macro_expansion.append(ti->getIdentifierInfo()->getName().str());
524 break;
525 case clang::tok::TokenKind::raw_identifier:
526 macro_expansion.append(ti->getRawIdentifier().str());
527 break;
528 default:
529 macro_expansion.append(ti->getName());
530 break;
531 }
532 }
533 }
534
535 if (handler(macro_expansion)) {
536 return;
537 }
538 }
539 }
540 }
Sean Callananb8bf6ef2015-04-14 18:36:17 +0000541}
542
Sean Callanan9998acd2014-12-05 01:21:59 +0000543clang::ModuleLoadResult
544ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000545 bool make_visible) {
546 clang::Module::NameVisibilityKind visibility =
547 make_visible ? clang::Module::AllVisible : clang::Module::Hidden;
548
549 const bool is_inclusion_directive = false;
550
551 return m_compiler_instance->loadModule(path.front().second, path, visibility,
552 is_inclusion_directive);
Sean Callanan9998acd2014-12-05 01:21:59 +0000553}
554
Sean Callanan68e44232017-09-28 20:20:25 +0000555clang::ExternalASTMerger::ImporterSource
556ClangModulesDeclVendorImpl::GetImporterSource() {
557 return {m_compiler_instance->getASTContext(),
558 m_compiler_instance->getFileManager(), m_origin_map};
559}
560
Sean Callanan9998acd2014-12-05 01:21:59 +0000561static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
562
563lldb_private::ClangModulesDeclVendor *
Kate Stoneb9c1b512016-09-06 20:57:50 +0000564ClangModulesDeclVendor::Create(Target &target) {
565 // FIXME we should insure programmatically that the expression parser's
566 // compiler and the modules runtime's
567 // compiler are both initialized in the same way – preferably by the same
568 // code.
Sean Callanan9998acd2014-12-05 01:21:59 +0000569
Kate Stoneb9c1b512016-09-06 20:57:50 +0000570 if (!target.GetPlatform()->SupportsModules())
571 return nullptr;
Sean Callanan9998acd2014-12-05 01:21:59 +0000572
Kate Stoneb9c1b512016-09-06 20:57:50 +0000573 const ArchSpec &arch = target.GetArchitecture();
574
575 std::vector<std::string> compiler_invocation_arguments = {
576 "clang",
577 "-fmodules",
578 "-fimplicit-module-maps",
579 "-fcxx-modules",
580 "-fsyntax-only",
581 "-femit-all-decls",
582 "-target",
583 arch.GetTriple().str(),
584 "-fmodules-validate-system-headers",
585 "-Werror=non-modular-include-in-framework-module"};
586
587 target.GetPlatform()->AddClangModuleCompilationOptions(
588 &target, compiler_invocation_arguments);
589
590 compiler_invocation_arguments.push_back(ModuleImportBufferName);
591
592 // Add additional search paths with { "-I", path } or { "-F", path } here.
593
594 {
Adrian Prantl235354be2018-03-02 22:42:44 +0000595 llvm::SmallString<128> path;
596 auto props = ModuleList::GetGlobalModuleListProperties();
597 props.GetClangModulesCachePath().GetPath(path);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000598 std::string module_cache_argument("-fmodules-cache-path=");
Adrian Prantl235354be2018-03-02 22:42:44 +0000599 module_cache_argument.append(path.str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000600 compiler_invocation_arguments.push_back(module_cache_argument);
601 }
602
603 FileSpecList &module_search_paths = target.GetClangModuleSearchPaths();
604
605 for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) {
606 const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi);
607
608 std::string search_path_argument = "-I";
609 search_path_argument.append(search_path.GetPath());
610
611 compiler_invocation_arguments.push_back(search_path_argument);
612 }
613
614 {
Zachary Turnerbdf08922018-06-04 17:41:00 +0000615 FileSpec clang_resource_dir = GetClangResourceDir();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000616
Jonas Devlieghere3a58d892018-11-08 00:14:50 +0000617 if (FileSystem::Instance().IsDirectory(clang_resource_dir.GetPath())) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000618 compiler_invocation_arguments.push_back("-resource-dir");
619 compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
Adrian McCarthy3f989d42015-10-26 21:38:41 +0000620 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000621 }
622
623 llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine =
624 clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
625 new StoringDiagnosticConsumer);
626
627 std::vector<const char *> compiler_invocation_argument_cstrs;
Jonas Devlieghereaa2dc6b2018-12-21 22:16:10 +0000628 compiler_invocation_argument_cstrs.reserve(
629 compiler_invocation_arguments.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000630 for (const std::string &arg : compiler_invocation_arguments) {
631 compiler_invocation_argument_cstrs.push_back(arg.c_str());
632 }
633
David Blaikie8fda2b32017-01-06 19:49:05 +0000634 std::shared_ptr<clang::CompilerInvocation> invocation =
Kate Stoneb9c1b512016-09-06 20:57:50 +0000635 clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs,
David Blaikie8fda2b32017-01-06 19:49:05 +0000636 diagnostics_engine);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000637
638 if (!invocation)
639 return nullptr;
640
641 std::unique_ptr<llvm::MemoryBuffer> source_buffer =
642 llvm::MemoryBuffer::getMemBuffer(
643 "extern int __lldb __attribute__((unavailable));",
644 ModuleImportBufferName);
645
646 invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName,
647 source_buffer.release());
648
649 std::unique_ptr<clang::CompilerInstance> instance(
650 new clang::CompilerInstance);
651
Jonas Devlieghere63e2e592019-02-13 01:30:41 +0000652 // When capturing a reproducer, hook up the file collector with clang to
653 // collector modules and headers.
654 if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) {
655 repro::FileProvider &fp = g->GetOrCreate<repro::FileProvider>();
656 instance->setModuleDepCollector(
657 std::make_shared<ModuleDependencyCollectorAdaptor>(
658 fp.GetFileCollector()));
659 clang::DependencyOutputOptions &opts = instance->getDependencyOutputOpts();
660 opts.IncludeSystemHeaders = true;
661 opts.IncludeModuleFiles = true;
662 }
663
Kate Stoneb9c1b512016-09-06 20:57:50 +0000664 instance->setDiagnostics(diagnostics_engine.get());
David Blaikie8fda2b32017-01-06 19:49:05 +0000665 instance->setInvocation(invocation);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000666
667 std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
668
669 instance->setTarget(clang::TargetInfo::CreateTargetInfo(
670 *diagnostics_engine, instance->getInvocation().TargetOpts));
671
672 if (!instance->hasTarget())
673 return nullptr;
674
675 instance->getTarget().adjust(instance->getLangOpts());
676
677 if (!action->BeginSourceFile(*instance,
678 instance->getFrontendOpts().Inputs[0]))
679 return nullptr;
680
681 instance->getPreprocessor().enableIncrementalProcessing();
682
683 instance->createModuleManager();
684
685 instance->createSema(action->getTranslationUnitKind(), nullptr);
686
687 const bool skipFunctionBodies = false;
688 std::unique_ptr<clang::Parser> parser(new clang::Parser(
689 instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
690
691 instance->getPreprocessor().EnterMainSourceFile();
692 parser->Initialize();
693
694 clang::Parser::DeclGroupPtrTy parsed;
695
696 while (!parser->ParseTopLevelDecl(parsed))
697 ;
698
David Blaikie8fda2b32017-01-06 19:49:05 +0000699 return new ClangModulesDeclVendorImpl(std::move(diagnostics_engine),
700 std::move(invocation),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000701 std::move(instance), std::move(parser));
Sean Callanan9998acd2014-12-05 01:21:59 +0000702}