CppInterOp
C++ Language Interoperability Layer
Loading...
Searching...
No Matches
CppInterOpInterpreter.h
Go to the documentation of this file.
1//--------------------------------------------------------------------*- C++ -*-
2// CppInterOp Interpreter (clang-repl)
3// author: Alexander Penev <alexander_penev@yahoo.com>
4//------------------------------------------------------------------------------
5
6#ifndef CPPINTEROP_INTERPRETER_H
7#define CPPINTEROP_INTERPRETER_H
8
9#include "Compatibility.h"
11#include "Paths.h"
12
13#include "clang/Interpreter/Interpreter.h"
14#include "clang/Interpreter/PartialTranslationUnit.h"
15
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclarationName.h"
18#include "clang/AST/GlobalDecl.h"
19#include "clang/Basic/LangOptions.h"
20#include "clang/Basic/TargetOptions.h"
21#include "clang/Frontend/CompilerInstance.h"
22#include "clang/Frontend/FrontendOptions.h"
23#include "clang/Lex/Preprocessor.h"
24#include "clang/Sema/Lookup.h"
25#include "clang/Sema/Redeclaration.h"
26#include "clang/Sema/Sema.h"
27#include "clang/Serialization/ModuleFileExtension.h"
28
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/ExecutionEngine/Orc/LLJIT.h"
34#include "llvm/Support/Compiler.h"
35#include "llvm/Support/Error.h"
36#include "llvm/Support/TargetSelect.h"
37#include "llvm/Support/raw_ostream.h"
38#include "llvm/TargetParser/Triple.h"
39
40#ifndef _WIN32
41#include <sched.h>
42#include <unistd.h>
43#endif
44#include <algorithm>
45#include <cstdio>
46#include <memory>
47#include <mutex>
48#include <tuple>
49#include <utility>
50#include <vector>
51
52namespace clang {
53class CompilerInstance;
54}
55
56namespace {
57template <typename D> static D* LookupResult2Decl(clang::LookupResult& R) {
58 if (R.empty())
59 return nullptr;
60
61 R.resolveKind();
62
63 if (R.isSingleResult())
64 return llvm::dyn_cast<D>(R.getFoundDecl());
65 return (D*)-1;
66}
67} // namespace
68
69namespace CppInternal {
70namespace utils {
71namespace Lookup {
72
73inline clang::NamespaceDecl* Namespace(clang::Sema* S, const char* Name,
74 const clang::DeclContext* Within) {
75 clang::DeclarationName DName = &(S->Context.Idents.get(Name));
76 clang::LookupResult R(*S, DName, clang::SourceLocation(),
77 clang::Sema::LookupNestedNameSpecifierName);
78 R.suppressDiagnostics();
79 if (!Within)
80 S->LookupName(R, S->TUScope);
81 else {
82 if (const clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(Within)) {
83 if (!TD->getDefinition()) {
84 // No definition, no lookup result.
85 return nullptr;
86 }
87 }
88 S->LookupQualifiedName(R, const_cast<clang::DeclContext*>(Within));
89 }
90
91 if (R.empty())
92 return nullptr;
93
94 R.resolveKind();
95
96 return llvm::dyn_cast<clang::NamespaceDecl>(R.getFoundDecl());
97}
98
99inline void Named(clang::Sema* S, clang::LookupResult& R,
100 const clang::DeclContext* Within = nullptr) {
101 R.suppressDiagnostics();
102 if (!Within)
103 S->LookupName(R, S->TUScope);
104 else {
105 const clang::DeclContext* primaryWithin = nullptr;
106 if (const clang::TagDecl* TD = llvm::dyn_cast<clang::TagDecl>(Within)) {
107 primaryWithin =
108 llvm::dyn_cast_or_null<clang::DeclContext>(TD->getDefinition());
109 } else {
110 primaryWithin = Within->getPrimaryContext();
111 }
112 if (!primaryWithin) {
113 // No definition, no lookup result.
114 return;
115 }
116 S->LookupQualifiedName(R, const_cast<clang::DeclContext*>(primaryWithin));
117 }
118}
119
120inline clang::NamedDecl* Named(clang::Sema* S,
121 const clang::DeclarationName& Name,
122 const clang::DeclContext* Within = nullptr) {
123 clang::LookupResult R(*S, Name, clang::SourceLocation(),
124 clang::Sema::LookupOrdinaryName,
125 RedeclarationKind::ForVisibleRedeclaration);
126 Named(S, R, Within);
127 return LookupResult2Decl<clang::NamedDecl>(R);
128}
129
130inline clang::NamedDecl* Named(clang::Sema* S, llvm::StringRef Name,
131 const clang::DeclContext* Within = nullptr) {
132 clang::DeclarationName DName = &S->Context.Idents.get(Name);
133 return Named(S, DName, Within);
134}
135
136inline clang::NamedDecl* Named(clang::Sema* S, const char* Name,
137 const clang::DeclContext* Within = nullptr) {
138 return Named(S, llvm::StringRef(Name), Within);
139}
140
141} // namespace Lookup
142} // namespace utils
143} // namespace CppInternal
144
145namespace CppInternal {
146
147/// CppInterOp Interpreter
148///
150public:
151 struct FileDeleter {
152 void operator()(FILE* f /* owns */) {
153 if (f)
154 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
155 fclose(f);
156 }
157 };
158
159 struct IOContext {
160 std::unique_ptr<FILE, FileDeleter> stdin_file;
161 std::unique_ptr<FILE, FileDeleter> stdout_file;
162 std::unique_ptr<FILE, FileDeleter> stderr_file;
163
165 stdin_file.reset(tmpfile()); // NOLINT(cppcoreguidelines-owning-memory)
166 stdout_file.reset(tmpfile()); // NOLINT(cppcoreguidelines-owning-memory)
167 stderr_file.reset(tmpfile()); // NOLINT(cppcoreguidelines-owning-memory)
169 }
170 };
171
172private:
173 static std::tuple<int, int, int>
174 initAndGetFileDescriptors(std::vector<const char*>& vargs,
175 IOContext& io_ctx) {
176 int stdin_fd = 0;
177 int stdout_fd = 1;
178 int stderr_fd = 2;
179
180 // Only initialize temp files if not already initialized
181 if (!io_ctx.stdin_file || !io_ctx.stdout_file || !io_ctx.stderr_file) {
182 bool init = io_ctx.initializeTempFiles();
183 if (!init) {
184 llvm::errs() << "Can't start out-of-process JIT execution.\n";
185 stdin_fd = -1;
186 stdout_fd = -1;
187 stderr_fd = -1;
188 }
189 }
190 stdin_fd = fileno(io_ctx.stdin_file.get());
191 stdout_fd = fileno(io_ctx.stdout_file.get());
192 stderr_fd = fileno(io_ctx.stderr_file.get());
193
194 return std::make_tuple(stdin_fd, stdout_fd, stderr_fd);
195 }
196
197 std::unique_ptr<clang::Interpreter> inner;
198 std::unique_ptr<IOContext> io_context;
199 mutable std::unique_ptr<DynamicLibraryManager> sDLM;
200 mutable std::once_flag sDLMInit;
201 bool outOfProcess;
202
203public:
204 Interpreter(std::unique_ptr<clang::Interpreter> CI,
205 std::unique_ptr<IOContext> ctx = nullptr, bool oop = false)
206 : inner(std::move(CI)), io_context(std::move(ctx)), outOfProcess(oop) {}
207
208public:
209 static std::unique_ptr<Interpreter>
210 create(int argc, const char* const* argv, const char* llvmdir = nullptr,
211 const std::vector<std::shared_ptr<clang::ModuleFileExtension>>&
212 moduleExtensions = {},
213 void* extraLibHandle = nullptr, bool noRuntime = true) {
214 std::vector<const char*> vargs(argv + 1, argv + argc);
215
216 int stdin_fd = 0;
217 int stdout_fd = 1;
218 int stderr_fd = 2;
219 auto io_ctx = std::make_unique<IOContext>();
220 bool outOfProcess = false;
221
222#if LLVM_VERSION_MAJOR > 21 && !defined(_WIN32)
223 outOfProcess = std::any_of(vargs.begin(), vargs.end(), [](const char* arg) {
224 return llvm::StringRef(arg).trim() == "--use-oop-jit";
225 });
226#endif
227
228 if (outOfProcess) {
229 std::tie(stdin_fd, stdout_fd, stderr_fd) =
230 initAndGetFileDescriptors(vargs, *io_ctx);
231
232 if (stdin_fd == -1 || stdout_fd == -1 || stderr_fd == -1) {
233 llvm::errs()
234 << "Redirection files creation failed for Out-Of-Process JIT\n";
235 return nullptr;
236 }
237 }
238
239 // Currently, we can't pass IOContext in `createClangInterpreter`, that's
240 // why fd's are passed. This should be refactored later.
241 auto CI =
242 compat::createClangInterpreter(vargs, stdin_fd, stdout_fd, stderr_fd);
243 if (!CI) {
244 llvm::errs() << "Interpreter creation failed\n";
245 return nullptr;
246 }
247
248 return std::make_unique<Interpreter>(std::move(CI), std::move(io_ctx),
249 outOfProcess);
250 }
251
253
254 operator const clang::Interpreter&() const { return *inner; }
255 operator clang::Interpreter&() { return *inner; }
256
257 [[nodiscard]] bool isOutOfProcess() const { return outOfProcess; }
258
259// Since, we are using custom pipes instead of stdout, sterr,
260// it is kind of necessary to have this complication in StreamCaptureInfo.
261
262// TODO(issues/733): Refactor the stream redirection
263#ifndef _WIN32
265 if (!io_context)
266 return nullptr;
267 switch (FD) {
268 case (STDIN_FILENO):
269 return io_context->stdin_file.get();
270 case (STDOUT_FILENO):
271 return io_context->stdout_file.get();
272 case (STDERR_FILENO):
273 return io_context->stderr_file.get();
274 default:
275 llvm::errs() << "No temp file for the FD\n";
276 return nullptr;
277 }
278 }
279#endif
280
281 ///\brief Describes the return result of the different routines that do the
282 /// incremental compilation.
283 ///
285
286 const clang::CompilerInstance* getCompilerInstance() const {
287 return inner->getCompilerInstance();
288 }
289
290 llvm::orc::LLJIT* getExecutionEngine() const {
291 return compat::getExecutionEngine(*inner);
292 }
293
294 llvm::Expected<clang::PartialTranslationUnit&> Parse(llvm::StringRef Code) {
295 return inner->Parse(Code);
296 }
297
298 llvm::Error Execute(clang::PartialTranslationUnit& T) {
299 return inner->Execute(T);
300 }
301
302 llvm::Error ParseAndExecute(llvm::StringRef Code, clang::Value* V = nullptr) {
303 return inner->ParseAndExecute(Code, V);
304 }
305
306 llvm::Error Undo(unsigned N = 1) { return compat::Undo(*inner, N); }
307
308 void makeEngineOnce() const {
309 static bool make_engine_once = true;
310 if (make_engine_once) {
311 if (auto Err = inner->ParseAndExecute(""))
312 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "Error:");
313 make_engine_once = false;
314 }
315 }
316
317 /// \returns the \c ExecutorAddr of a \c GlobalDecl. This interface uses
318 /// the CodeGenModule's internal mangling cache to avoid recomputing the
319 /// mangled name.
320 llvm::Expected<llvm::orc::ExecutorAddr>
321 getSymbolAddress(clang::GlobalDecl GD) const {
323 auto AddrOrErr = compat::getSymbolAddress(*inner, GD);
324 if (llvm::Error Err = AddrOrErr.takeError())
325 return std::move(Err);
326 return llvm::orc::ExecutorAddr(*AddrOrErr);
327 }
328
329 /// \returns the \c ExecutorAddr of a given name as written in the IR.
330 llvm::Expected<llvm::orc::ExecutorAddr>
331 getSymbolAddress(llvm::StringRef IRName) const {
333 auto AddrOrErr = compat::getSymbolAddress(*inner, IRName);
334 if (llvm::Error Err = AddrOrErr.takeError())
335 return std::move(Err);
336 return llvm::orc::ExecutorAddr(*AddrOrErr);
337 }
338
339 /// \returns the \c ExecutorAddr of a given name as written in the object
340 /// file.
341 llvm::Expected<llvm::orc::ExecutorAddr>
342 getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const {
343 auto AddrOrErr = compat::getSymbolAddressFromLinkerName(*inner, LinkerName);
344 if (llvm::Error Err = AddrOrErr.takeError())
345 return std::move(Err);
346 return llvm::orc::ExecutorAddr(*AddrOrErr);
347 }
348
349 bool isInSyntaxOnlyMode() const {
350 return getCompilerInstance()->getFrontendOpts().ProgramAction ==
351 clang::frontend::ParseSyntaxOnly;
352 }
353
354 // FIXME: Mangle GD and call the other overload.
355 void* getAddressOfGlobal(const clang::GlobalDecl& GD) const {
356 auto addressOrErr = getSymbolAddress(GD);
357 if (addressOrErr)
358 return addressOrErr->toPtr<void*>();
359
360 llvm::consumeError(addressOrErr.takeError()); // okay to be missing
361 return nullptr;
362 }
363
364 void* getAddressOfGlobal(llvm::StringRef SymName) const {
365 if (isInSyntaxOnlyMode())
366 return nullptr;
367
368 auto addressOrErr =
369 getSymbolAddressFromLinkerName(SymName); // TODO: Or getSymbolAddress
370 if (addressOrErr)
371 return addressOrErr->toPtr<void*>();
372
373 llvm::consumeError(addressOrErr.takeError()); // okay to be missing
374 return nullptr;
375 }
376
377 CompilationResult declare(const std::string& input,
378 clang::PartialTranslationUnit** PTU = nullptr) {
379 return process(input, /*Value=*/nullptr, PTU);
380 }
381
382 ///\brief Maybe transform the input line to implement cint command line
383 /// semantics (declarations are global) and compile to produce a module.
384 ///
385 CompilationResult process(const std::string& input, clang::Value* V = 0,
386 clang::PartialTranslationUnit** PTU = nullptr,
387 bool disableValuePrinting = false) {
388 auto PTUOrErr = Parse(input);
389 if (!PTUOrErr) {
390 llvm::logAllUnhandledErrors(PTUOrErr.takeError(), llvm::errs(),
391 "Failed to parse via ::process:");
393 }
394
395 if (PTU)
396 *PTU = &*PTUOrErr;
397
398 if (auto Err = Execute(*PTUOrErr)) {
399 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
400 "Failed to execute via ::process:");
402 }
404 }
405
406 CompilationResult evaluate(const std::string& input, clang::Value& V) {
407 if (auto Err = ParseAndExecute(input, &V)) {
408 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
409 "Failed to execute via ::evaluate:");
411 }
413 }
414
415 void* compileFunction(llvm::StringRef name, llvm::StringRef code,
416 bool ifUnique, bool withAccessControl) {
417 //
418 // Compile the wrapper code.
419 //
420
421 if (isInSyntaxOnlyMode())
422 return nullptr;
423
424 if (ifUnique) {
425 if (void* Addr = (void*)getAddressOfGlobal(name)) {
426 return Addr;
427 }
428 }
429
430 clang::LangOptions& LO =
431 const_cast<clang::LangOptions&>(getCompilerInstance()->getLangOpts());
432 bool SavedAccessControl = LO.AccessControl;
433 LO.AccessControl = withAccessControl;
434
435 if (auto Err = ParseAndExecute(code)) {
436 LO.AccessControl = SavedAccessControl;
437 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
438 "Failed to compileFunction: ");
439 return nullptr;
440 }
441
442 LO.AccessControl = SavedAccessControl;
443
444 return getAddressOfGlobal(name);
445 }
446
447 const clang::CompilerInstance* getCI() const { return getCompilerInstance(); }
448
449 clang::Sema& getSema() const { return getCI()->getSema(); }
450
452 assert(compat::getExecutionEngine(*inner) && "We must have an executor");
453 // Replaces the C++11 magic-static thread-safe init the previous
454 // function-local DLM had for free.
455 std::call_once(sDLMInit, [this] {
456 sDLM = std::make_unique<DynamicLibraryManager>();
457 sDLM->initializeDyld([](llvm::StringRef) { /*ignore*/ return false; });
458 });
459 return sDLM.get();
460 }
461
463 return const_cast<DynamicLibraryManager*>(
464 const_cast<const Interpreter*>(this)->getDynamicLibraryManager());
465 }
466
467 ///\brief Adds multiple include paths separated by a delimiter.
468 ///
469 ///\param[in] PathsStr - Path(s)
470 ///\param[in] Delim - Delimiter to separate paths or NULL if a single path
471 ///
472 void AddIncludePaths(llvm::StringRef PathsStr, const char* Delim = ":") {
473 const clang::CompilerInstance* CI = getCompilerInstance();
474 clang::HeaderSearchOptions& HOpts =
475 const_cast<clang::HeaderSearchOptions&>(CI->getHeaderSearchOpts());
476
477 // Save the current number of entries
478 size_t Idx = HOpts.UserEntries.size();
479 CppInternal::utils::AddIncludePaths(PathsStr, HOpts, Delim);
480
481 clang::Preprocessor& PP = CI->getPreprocessor();
482 clang::SourceManager& SM = PP.getSourceManager();
483 clang::FileManager& FM = SM.getFileManager();
484 clang::HeaderSearch& HSearch = PP.getHeaderSearchInfo();
485 const bool isFramework = false;
486
487 // Add all the new entries into Preprocessor
488 for (const size_t N = HOpts.UserEntries.size(); Idx < N; ++Idx) {
489 const clang::HeaderSearchOptions::Entry& E = HOpts.UserEntries[Idx];
490 if (auto DE = FM.getOptionalDirectoryRef(E.Path))
491 HSearch.AddSearchPath(
492 clang::DirectoryLookup(*DE, clang::SrcMgr::C_User, isFramework),
493 E.Group == clang::frontend::Angled);
494 }
495 }
496
497 ///\brief Adds a single include path (-I).
498 ///
499 void AddIncludePath(llvm::StringRef PathsStr) {
500 return AddIncludePaths(PathsStr, nullptr);
501 }
502
503 ///\brief Get the current include paths that are used.
504 ///
505 ///\param[out] incpaths - Pass in a llvm::SmallVector<std::string, N> with
506 /// sufficiently sized N, to hold the result of the call.
507 ///\param[in] withSystem - if true, incpaths will also contain system
508 /// include paths (framework, STL etc).
509 ///\param[in] withFlags - if true, each element in incpaths will be prefixed
510 /// with a "-I" or similar, and some entries of incpaths will signal
511 /// a new include path region (e.g. "-cxx-isystem"). Also, flags
512 /// defining header search behavior will be included in incpaths, e.g.
513 /// "-nostdinc".
514 ///
515 void GetIncludePaths(llvm::SmallVectorImpl<std::string>& incpaths,
516 bool withSystem, bool withFlags) const {
517 CppInternal::utils::CopyIncludePaths(getCI()->getHeaderSearchOpts(),
518 incpaths, withSystem, withFlags);
519 }
520
521 CompilationResult loadLibrary(const std::string& filename, bool lookup) {
522 llvm::Triple triple(getCompilerInstance()->getTargetOpts().Triple);
523 if (triple.isWasm()) {
524 // On WASM, dlopen-style canonical lookup has no effect.
525 if (auto Err = inner->LoadDynamicLibrary(filename.c_str())) {
526 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
527 "loadLibrary: ");
528 return kFailure;
529 }
530 return kSuccess;
531 }
532
534 std::string canonicalLib;
535 if (lookup)
536 canonicalLib = DLM->lookupLibrary(filename);
537
538 const std::string& library = lookup ? canonicalLib : filename;
539 if (!library.empty()) {
540 switch (
541 DLM->loadLibrary(library, /*permanent*/ false, /*resolved*/ true)) {
542 case DynamicLibraryManager::kLoadLibSuccess: // Intentional fall through
544 return kSuccess;
546 assert(0 && "Cannot find library with existing canonical name!");
547 return kFailure;
548 default:
549 // Not a source file (canonical name is non-empty) but can't load.
550 return kFailure;
551 }
552 }
553 return kMoreInputExpected;
554 }
555
556 std::string toString(const char* type, void* obj) {
557 assert(0 && "toString is not implemented!");
558 std::string ret;
559 return ret; // TODO: Implement
560 }
561
562 CompilationResult undo(unsigned N = 1) {
563 if (llvm::Error Err = Undo(N)) {
564 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
565 "Failed to undo via ::undo");
566 return kFailure;
567 }
568 return kSuccess;
569 }
570
571}; // Interpreter
572} // namespace CppInternal
573
574#endif // CPPINTEROP_INTERPRETER_H
A helper class managing dynamic shared objects.
LoadLibResult loadLibrary(llvm::StringRef, bool permanent, bool resolved=false)
Loads a shared library.
@ kLoadLibAlreadyLoaded
library was already loaded
@ kLoadLibSuccess
library loaded successfully
std::string lookupLibrary(llvm::StringRef libStem, llvm::SmallVector< llvm::StringRef, 2 > RPath={}, llvm::SmallVector< llvm::StringRef, 2 > RunPath={}, llvm::StringRef libLoader="", bool variateLibStem=true) const
Looks up a library taking into account the current include paths and the system include paths.
CppInterOp Interpreter.
FILE * getRedirectionFileForOutOfProcess(int FD)
llvm::Expected< clang::PartialTranslationUnit & > Parse(llvm::StringRef Code)
DynamicLibraryManager * getDynamicLibraryManager()
Interpreter(std::unique_ptr< clang::Interpreter > CI, std::unique_ptr< IOContext > ctx=nullptr, bool oop=false)
CompilationResult declare(const std::string &input, clang::PartialTranslationUnit **PTU=nullptr)
CompilationResult loadLibrary(const std::string &filename, bool lookup)
CompilationResult undo(unsigned N=1)
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(clang::GlobalDecl GD) const
const clang::CompilerInstance * getCompilerInstance() const
llvm::Error Execute(clang::PartialTranslationUnit &T)
llvm::Error ParseAndExecute(llvm::StringRef Code, clang::Value *V=nullptr)
llvm::orc::LLJIT * getExecutionEngine() const
static std::unique_ptr< Interpreter > create(int argc, const char *const *argv, const char *llvmdir=nullptr, const std::vector< std::shared_ptr< clang::ModuleFileExtension > > &moduleExtensions={}, void *extraLibHandle=nullptr, bool noRuntime=true)
const DynamicLibraryManager * getDynamicLibraryManager() const
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddress(llvm::StringRef IRName) const
void AddIncludePath(llvm::StringRef PathsStr)
Adds a single include path (-I).
const clang::CompilerInstance * getCI() const
void * getAddressOfGlobal(const clang::GlobalDecl &GD) const
CompilationResult process(const std::string &input, clang::Value *V=0, clang::PartialTranslationUnit **PTU=nullptr, bool disableValuePrinting=false)
Maybe transform the input line to implement cint command line semantics (declarations are global) and...
llvm::Expected< llvm::orc::ExecutorAddr > getSymbolAddressFromLinkerName(llvm::StringRef LinkerName) const
CompilationResult
Describes the return result of the different routines that do the incremental compilation.
CompilationResult evaluate(const std::string &input, clang::Value &V)
std::string toString(const char *type, void *obj)
clang::Sema & getSema() const
void AddIncludePaths(llvm::StringRef PathsStr, const char *Delim=":")
Adds multiple include paths separated by a delimiter.
void GetIncludePaths(llvm::SmallVectorImpl< std::string > &incpaths, bool withSystem, bool withFlags) const
Get the current include paths that are used.
void * getAddressOfGlobal(llvm::StringRef SymName) const
void * compileFunction(llvm::StringRef name, llvm::StringRef code, bool ifUnique, bool withAccessControl)
llvm::Error Undo(unsigned N=1)
void Named(clang::Sema *S, clang::LookupResult &R, const clang::DeclContext *Within=nullptr)
clang::NamespaceDecl * Namespace(clang::Sema *S, const char *Name, const clang::DeclContext *Within)
void CopyIncludePaths(const clang::HeaderSearchOptions &Opts, llvm::SmallVectorImpl< std::string > &incpaths, bool withSystem, bool withFlags)
Copies the current include paths into the HeaderSearchOptions.
Definition Paths.cpp:150
void AddIncludePaths(llvm::StringRef PathStr, clang::HeaderSearchOptions &HOpts, const char *Delim)
Adds multiple include paths separated by a delimiter into the given HeaderSearchOptions.
Definition Paths.cpp:337
llvm::Expected< llvm::JITTargetAddress > getSymbolAddressFromLinkerName(clang::Interpreter &I, llvm::StringRef LinkerName)
llvm::Error Undo(clang::Interpreter &I, unsigned N=1)
std::unique_ptr< clang::Interpreter > createClangInterpreter(std::vector< const char * > &args, int stdin_fd=-1, int stdout_fd=-1, int stderr_fd=-1)
llvm::orc::LLJIT * getExecutionEngine(clang::Interpreter &I)
llvm::Expected< llvm::JITTargetAddress > getSymbolAddress(clang::Interpreter &I, llvm::StringRef IRName)
std::unique_ptr< FILE, FileDeleter > stdin_file
std::unique_ptr< FILE, FileDeleter > stderr_file
std::unique_ptr< FILE, FileDeleter > stdout_file