]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Expression/ClangModulesDeclVendor.cpp
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Expression / ClangModulesDeclVendor.cpp
1 //===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Core/StreamString.h"
11 #include "lldb/Expression/ClangModulesDeclVendor.h"
12 #include "lldb/Host/FileSpec.h"
13 #include "lldb/Host/Host.h"
14 #include "lldb/Host/HostInfo.h"
15 #include "lldb/Target/Target.h"
16
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Frontend/CompilerInstance.h"
19 #include "clang/Frontend/FrontendActions.h"
20 #include "clang/Lex/Preprocessor.h"
21 #include "clang/Parse/Parser.h"
22 #include "clang/Sema/Lookup.h"
23 #include "clang/Serialization/ASTReader.h"
24
25 #include <mutex>
26
27 using namespace lldb_private;
28
29 namespace {
30     // Any Clang compiler requires a consumer for diagnostics.  This one stores them as strings
31     // so we can provide them to the user in case a module failed to load.
32     class StoringDiagnosticConsumer : public clang::DiagnosticConsumer
33     {
34     public:
35         StoringDiagnosticConsumer ();
36         void
37         HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info);
38         
39         void
40         ClearDiagnostics ();
41         
42         void
43         DumpDiagnostics (Stream &error_stream);
44     private:
45         typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic;
46         std::vector<IDAndDiagnostic> m_diagnostics;
47         Log * m_log;
48     };
49     
50     // The private implementation of our ClangModulesDeclVendor.  Contains all the Clang state required
51     // to load modules.
52     class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor
53     {
54     public:
55         ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
56                                    llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
57                                    std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
58                                    std::unique_ptr<clang::Parser> &&parser);
59         
60         virtual bool
61         AddModule(std::vector<llvm::StringRef> &path,
62                   Stream &error_stream);
63         
64         virtual uint32_t
65         FindDecls (const ConstString &name,
66                    bool append,
67                    uint32_t max_matches,
68                    std::vector <clang::NamedDecl*> &decls);
69         
70         ~ClangModulesDeclVendorImpl();
71         
72     private:
73         clang::ModuleLoadResult
74         DoGetModule(clang::ModuleIdPath path, bool make_visible);
75         
76         llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine>  m_diagnostics_engine;
77         llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation;
78         std::unique_ptr<clang::CompilerInstance>            m_compiler_instance;
79         std::unique_ptr<clang::Parser>                      m_parser;
80     };
81 }
82
83 StoringDiagnosticConsumer::StoringDiagnosticConsumer ()
84 {
85     m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
86 }
87
88 void
89 StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info)
90 {
91     llvm::SmallVector<char, 256> diagnostic_string;
92     
93     info.FormatDiagnostic(diagnostic_string);
94     
95     m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size())));
96 }
97
98 void
99 StoringDiagnosticConsumer::ClearDiagnostics ()
100 {
101     m_diagnostics.clear();
102 }
103
104 void
105 StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream)
106 {
107     for (IDAndDiagnostic &diag : m_diagnostics)
108     {
109         switch (diag.first)
110         {
111             default:
112                 error_stream.PutCString(diag.second.c_str());
113                 error_stream.PutChar('\n');
114                 break;
115             case clang::DiagnosticsEngine::Level::Ignored:
116                 break;
117         }
118     }
119 }
120
121 static FileSpec
122 GetResourceDir ()
123 {
124     static FileSpec g_cached_resource_dir;
125     
126     static std::once_flag g_once_flag;
127     
128     std::call_once(g_once_flag, [](){
129         HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir);
130     });
131     
132     return g_cached_resource_dir;
133 }
134
135
136 ClangModulesDeclVendor::ClangModulesDeclVendor()
137 {
138 }
139
140 ClangModulesDeclVendor::~ClangModulesDeclVendor()
141 {
142 }
143
144 ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
145                                                        llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
146                                                        std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
147                                                        std::unique_ptr<clang::Parser> &&parser) :
148     ClangModulesDeclVendor(),
149     m_diagnostics_engine(diagnostics_engine),
150     m_compiler_invocation(compiler_invocation),
151     m_compiler_instance(std::move(compiler_instance)),
152     m_parser(std::move(parser))
153 {
154 }
155
156 bool
157 ClangModulesDeclVendorImpl::AddModule(std::vector<llvm::StringRef> &path,
158                                       Stream &error_stream)
159 {
160     // Fail early.
161     
162     if (m_compiler_instance->hadModuleLoaderFatalFailure())
163     {
164         error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n");
165         return false;
166     }
167     
168     if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0]))
169     {
170         error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].str().c_str());
171         return false;
172     }
173     
174     llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, 4> clang_path;
175     
176     {
177         size_t source_loc_counter = 0;
178         clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager();
179         
180         for (llvm::StringRef &component : path)
181         {
182             clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(component),
183                                                 source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(source_loc_counter++)));
184         }
185     }
186     
187     StoringDiagnosticConsumer *diagnostic_consumer = static_cast<StoringDiagnosticConsumer *>(m_compiler_instance->getDiagnostics().getClient());
188     
189     diagnostic_consumer->ClearDiagnostics();
190     
191     clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
192     
193     if (!top_level_module)
194     {
195         diagnostic_consumer->DumpDiagnostics(error_stream);
196         error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].str().c_str());
197         return false;
198     }
199     
200     clang::Module *submodule = top_level_module;
201     
202     for (size_t ci = 1; ci < path.size(); ++ci)
203     {
204         llvm::StringRef &component = path[ci];
205         submodule = submodule->findSubmodule(component.str());
206         if (!submodule)
207         {
208             diagnostic_consumer->DumpDiagnostics(error_stream);
209             error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str());
210             return false;
211         }
212     }
213     
214     clang::Module *requested_module = DoGetModule(clang_path, true);
215     
216     return (requested_module != nullptr);
217 }
218
219 // ClangImporter::lookupValue
220
221 uint32_t
222 ClangModulesDeclVendorImpl::FindDecls (const ConstString &name,
223                                        bool append,
224                                        uint32_t max_matches,
225                                        std::vector <clang::NamedDecl*> &decls)
226 {
227     if (!append)
228         decls.clear();
229     
230     clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
231     
232     clang::LookupResult lookup_result(m_compiler_instance->getSema(),
233                                       clang::DeclarationName(&ident),
234                                       clang::SourceLocation(),
235                                       clang::Sema::LookupOrdinaryName);
236     
237     m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl()));
238     
239     uint32_t num_matches = 0;
240     
241     for (clang::NamedDecl *named_decl : lookup_result)
242     {
243         if (num_matches >= max_matches)
244             return num_matches;
245         
246         decls.push_back(named_decl);
247         ++num_matches;
248     }
249     
250     return num_matches;
251 }
252
253 ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl()
254 {
255 }
256
257 clang::ModuleLoadResult
258 ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
259                                         bool make_visible)
260 {
261     clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden;
262     
263     const bool is_inclusion_directive = false;
264     
265     return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive);
266 }
267
268 static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
269
270 lldb_private::ClangModulesDeclVendor *
271 ClangModulesDeclVendor::Create(Target &target)
272 {
273     // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's
274     // compiler are both initialized in the same way – preferably by the same code.
275     
276     if (!target.GetPlatform()->SupportsModules())
277         return nullptr;
278     
279     const ArchSpec &arch = target.GetArchitecture();
280     
281     std::vector<std::string> compiler_invocation_arguments =
282     {
283         "-fmodules",
284         "-fcxx-modules",
285         "-fsyntax-only",
286         "-femit-all-decls",
287         "-target", arch.GetTriple().str(),
288         "-fmodules-validate-system-headers",
289         "-Werror=non-modular-include-in-framework-module"
290     };
291     
292     target.GetPlatform()->AddClangModuleCompilationOptions(compiler_invocation_arguments);
293
294     compiler_invocation_arguments.push_back(ModuleImportBufferName);
295
296     // Add additional search paths with { "-I", path } or { "-F", path } here.
297    
298     {
299         llvm::SmallString<128> DefaultModuleCache;
300         const bool erased_on_reboot = false;
301         llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache);
302         llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
303         llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
304         std::string module_cache_argument("-fmodules-cache-path=");
305         module_cache_argument.append(DefaultModuleCache.str().str());
306         compiler_invocation_arguments.push_back(module_cache_argument);
307     }
308     
309     {
310         FileSpec clang_resource_dir = GetResourceDir();
311         
312         if (clang_resource_dir.IsDirectory())
313         {
314             compiler_invocation_arguments.push_back("-resource-dir");
315             compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
316         }
317     }
318     
319     llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
320                                                                                                                        new StoringDiagnosticConsumer);
321     
322     std::vector<const char *> compiler_invocation_argument_cstrs;
323     
324     for (const std::string &arg : compiler_invocation_arguments) {
325         compiler_invocation_argument_cstrs.push_back(arg.c_str());
326     }
327     
328     llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine));
329     
330     if (!invocation)
331         return nullptr;
332     
333     std::unique_ptr<llvm::MemoryBuffer> source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));",
334                                                                                          ModuleImportBufferName);
335     
336     invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release());
337     
338     std::unique_ptr<clang::CompilerInstance> instance(new clang::CompilerInstance);
339     
340     instance->setDiagnostics(diagnostics_engine.get());
341     instance->setInvocation(invocation.get());
342     
343     std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
344     
345     instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts));
346     
347     if (!instance->hasTarget())
348         return nullptr;
349     
350     instance->getTarget().adjust(instance->getLangOpts());
351     
352     if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0]))
353         return nullptr;
354     
355     instance->getPreprocessor().enableIncrementalProcessing();
356     
357     instance->createModuleManager();
358     
359     instance->createSema(action->getTranslationUnitKind(), nullptr);
360     
361     const bool skipFunctionBodies = false;
362     std::unique_ptr<clang::Parser> parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
363     
364     instance->getPreprocessor().EnterMainSourceFile();
365     parser->Initialize();
366     
367     clang::Parser::DeclGroupPtrTy parsed;
368     
369     while (!parser->ParseTopLevelDecl(parsed));
370     
371     return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser));
372 }