22#if defined(__has_feature)
23#if __has_feature(memory_sanitizer) && LLVM_VERSION_MAJOR <= 22
24#include <sanitizer/msan_interface.h>
25#define CPPINTEROP_MSAN_UNPOISON_VALUE(v) __msan_unpoison(&(v), sizeof(v))
27#define CPPINTEROP_MSAN_UNPOISON_VALUE(v) ((void)0)
30#define CPPINTEROP_MSAN_UNPOISON_VALUE(v) ((void)0)
33#include "clang/AST/Attrs.inc"
34#include "clang/AST/CXXInheritance.h"
35#include "clang/AST/Comment.h"
36#include "clang/AST/Decl.h"
37#include "clang/AST/DeclAccessPair.h"
38#include "clang/AST/DeclBase.h"
39#include "clang/AST/DeclCXX.h"
40#include "clang/AST/DeclTemplate.h"
41#include "clang/AST/DeclarationName.h"
42#include "clang/AST/Expr.h"
43#include "clang/AST/ExprCXX.h"
44#include "clang/AST/GlobalDecl.h"
45#include "clang/AST/Mangle.h"
46#include "clang/AST/NestedNameSpecifier.h"
47#include "clang/AST/QualTypeNames.h"
48#include "clang/AST/RawCommentList.h"
49#include "clang/AST/RecordLayout.h"
50#include "clang/AST/Stmt.h"
51#include "clang/AST/Type.h"
52#include "clang/AST/VTableBuilder.h"
53#include "clang/Basic/Diagnostic.h"
54#include "clang/Basic/DiagnosticSema.h"
55#include "clang/Basic/LangStandard.h"
56#include "clang/Basic/Linkage.h"
57#include "clang/Basic/OperatorKinds.h"
58#include "clang/Basic/SourceLocation.h"
59#include "clang/Basic/SourceManager.h"
60#include "clang/Basic/Specifiers.h"
61#include "clang/Basic/Version.h"
62#include "clang/Frontend/CompilerInstance.h"
63#include "clang/Interpreter/Interpreter.h"
64#include "clang/Sema/Lookup.h"
65#include "clang/Sema/Overload.h"
66#include "clang/Sema/Ownership.h"
67#include "clang/Sema/Redeclaration.h"
68#include "clang/Sema/Sema.h"
69#include "clang/Sema/TemplateDeduction.h"
71#include "llvm/ADT/SmallString.h"
72#include "llvm/ADT/SmallVector.h"
73#include "llvm/ADT/StringRef.h"
74#include "llvm/Demangle/Demangle.h"
75#include "llvm/ExecutionEngine/JITSymbol.h"
76#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
77#include "llvm/ExecutionEngine/Orc/Core.h"
78#include "llvm/ExecutionEngine/Orc/CoreContainers.h"
79#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
80#include "llvm/IR/GlobalValue.h"
81#include "llvm/Support/Casting.h"
82#include "llvm/Support/CommandLine.h"
83#include "llvm/Support/Debug.h"
84#include "llvm/Support/Error.h"
85#include "llvm/Support/FileSystem.h"
86#include "llvm/Support/ManagedStatic.h"
87#include "llvm/Support/Path.h"
88#include "llvm/Support/Process.h"
89#include "llvm/Support/Signals.h"
90#include "llvm/Support/TargetSelect.h"
91#include "llvm/Support/raw_ostream.h"
92#include "llvm/TargetParser/Host.h"
93#include "llvm/TargetParser/Triple.h"
112#include <sys/types.h>
121#define STDOUT_FILENO 1
122#define STDERR_FILENO 2
125#define popen(x, y) (_popen(x, y))
126#define pclose (_pclose)
136#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
139#if CLANG_VERSION_MAJOR > 21
148 void* OpaqueType, ...);
155#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && \
156 (defined(__SANITIZE_ADDRESS__) || \
157 (defined(__has_feature) && __has_feature(address_sanitizer)))
158#define CPPINTEROP_ASAN_BUILD 1
163using namespace clang;
183 other.isOwned =
false;
186 if (
this != &other) {
194 other.Interpreter =
nullptr;
195 other.isOwned =
false;
228#if LLVM_VERSION_MAJOR > 22
229 llvm::llvm_shutdown();
236static std::deque<InterpreterInfo>&
238 static llvm::ManagedStatic<std::deque<InterpreterInfo>> sInterpreters;
239 static std::once_flag ProcessInitialized;
240 std::call_once(ProcessInitialized, [SetCrashHandler]() {
242 llvm::sys::PrintStackTraceOnErrorSignal(
"CppInterOp");
244 if (getenv(
"CPPINTEROP_LOG") !=
nullptr)
248 llvm::InitializeAllTargetInfos();
249 llvm::InitializeAllTargets();
250 llvm::InitializeAllTargetMCs();
251 llvm::InitializeAllAsmParsers();
252 llvm::InitializeAllAsmPrinters();
256 if (SetCrashHandler) {
257 llvm::sys::SetOneShotPipeSignalFunction(
258 llvm::sys::DefaultOneShotPipeSignalHandler);
261 llvm::install_out_of_memory_new_handler();
269 return *sInterpreters;
277 llvm::errs() <<
"\n**************************************************\n";
278 llvm::errs() <<
" CppInterOp CRASH DETECTED\n";
282 llvm::errs() <<
" Reproducer saved to: " << Path <<
"\n";
284 llvm::errs() <<
" Failed to write reproducer file.\n";
286 llvm::errs() <<
" Re-run with CPPINTEROP_LOG=1 for a crash reproducer\n";
289 if (!Interps.empty()) {
290 llvm::errs() <<
" Active Interpreters:\n";
291 for (
const auto& Info : Interps) {
292 if (Info.Interpreter)
293 llvm::errs() <<
" - " << Info.Interpreter <<
"\n";
297 llvm::errs() <<
"**************************************************\n";
298 llvm::errs().flush();
301 llvm::sys::PrintStackTrace(llvm::errs());
303 llvm::errs() <<
"**************************************************\n";
304 llvm::errs().flush();
308 llvm::sys::Process::Exit(1,
false);
313 Interps.emplace_back(I, Owned);
318 assert(!Interps.empty() &&
319 "Interpreter instance must be set before calling this!");
321 for (
auto& Info : Interps)
322 if (Info.Interpreter == I)
325 return Interps.back();
330 return *unwrap<compat::Interpreter>(I);
344 assert(
GetInterpreters(
false).empty() &&
"sInterpreter already in use!");
356 auto* Interp = unwrap<compat::Interpreter>(I);
358 std::find_if(Interps.begin(), Interps.end(), [Interp](
const auto& Info) {
359 return Info.Interpreter == Interp;
361 if (found == Interps.end())
364 if (std::next(found) != Interps.end())
365 std::rotate(found, found + 1, Interps.end());
381 auto* Interp = unwrap<compat::Interpreter>(I);
383 std::find_if(Interps.begin(), Interps.end(), [Interp](
const auto& Info) {
384 return Info.Interpreter == Interp;
386 if (found == Interps.end())
389 Interps.erase(found);
401 ASTContext& C = I.
getSema().getASTContext();
403 D->addAttr(UsedAttr::CreateImplicit(C));
404#ifdef CPPINTEROP_USE_CLING
405 cling::Interpreter::PushTransactionRAII RAII(&I);
406 I.
getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D));
408 I.
getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D));
410 auto GeneratedPTU = I.
Parse(
"");
412 llvm::logAllUnhandledErrors(GeneratedPTU.takeError(), llvm::errs(),
413 "[ForceCodeGen] Failed to generate PTU:");
417 for (
auto& GV : GeneratedPTU->TheModule->globals()) {
418 llvm::GlobalValue::LinkageTypes LT = GV.getLinkage();
419 if (GV.isDeclaration() || !GV.hasName() ||
420 GV.getName().starts_with(
".str") ||
421 !llvm::GlobalVariable::isDiscardableIfUnused(LT) ||
422 LT != llvm::GlobalValue::InternalLinkage)
424 GV.setLinkage(llvm::GlobalValue::WeakAnyLinkage);
426 if (
auto Err = I.
Execute(*GeneratedPTU))
427 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
428 "[ForceCodeGen] Failed to execute PTU:");
432#define DEBUG_TYPE "jitcall"
433bool JitCall::AreArgumentsValid(
void* result, ArgList args,
void* self,
437 assert(result &&
"Must pass the location of the created object!");
438 Valid &= (bool)result;
441 assert(0 &&
"Must pass at least the minimal number of args!");
444 if (args.m_ArgSize) {
445 assert(args.m_Args !=
nullptr &&
"Must pass an argument list!");
446 Valid &= (bool)args.m_Args;
450 assert(self &&
"Must pass the pointer to object");
453 const auto* FD = cast<FunctionDecl>(unwrap<Decl>(m_FD));
454 if (!FD->getReturnType()->isVoidType() && !result) {
455 assert(0 &&
"We are discarding the return TyRef of the function!");
459 assert(0 &&
"Number of objects to construct should be atleast 1");
463 const auto* CD = cast<CXXConstructorDecl>(unwrap<Decl>(m_FD));
464 if (CD->getMinRequiredArguments() != 0 && nary > 1) {
466 "Cannot pass initialization parameters to array new construction");
470 assert(m_Kind != kDestructorCall &&
"Wrong overload!");
471 Valid &= m_Kind != kDestructorCall;
478 void** args, std::size_t nargs,
484 llvm::raw_string_ostream OS(Name);
485 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
486 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
488 LLVM_DEBUG(dbgs() <<
"Run '" << Name <<
"', compiled at: "
489 << (
void*)JC->m_GenericCall <<
" with result at: " << result
490 <<
" , args at: " << args <<
" , arg count: " << nargs
491 <<
" , self at: " << self <<
"\n";);
492 std::string SelfPart = self ? TI->lookupHandle(self) :
"";
493 TI->appendToLog(llvm::formatv(
" // JitCall::Invoke {0}(nargs={1}, self={2})",
495 SelfPart.empty() ?
"nullptr" : SelfPart));
505 llvm::raw_string_ostream OS(Name);
506 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
507 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
509 LLVM_DEBUG(dbgs() <<
"Finish '" << Name
510 <<
"', compiled at: " << (
void*)JC->m_DestructorCall);
511 std::string ObjPart =
object ? TI->lookupHandle(
object) :
"nullptr";
513 llvm::formatv(
" // JitCall::InvokeDestructor {0}(object={1}, nary={2}, "
515 Name, ObjPart, nary, withFree));
526 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
527 bool RegisterPtr = isa<CXXConstructorDecl>(FD);
529 QualType RT = FD->getReturnType();
530 RegisterPtr = RT->isPointerType() || RT->isReferenceType();
534 if (
void* p = *
static_cast<void* const*
>(result))
535 TI->getOrRegisterHandle(p);
542 const char*
const VERSION = CPPINTEROP_VERSION;
543 std::string fullVersion =
"CppInterOp version";
544 fullVersion += VERSION;
545 fullVersion +=
"\n (based on "
546#ifdef CPPINTEROP_USE_CLING
551 return INTEROP_RETURN(fullVersion +
"[" + clang::getClangFullVersion() +
563#include "CppInterOp/BuildInfo.inc"
568std::string
Demangle(
const std::string& mangled_name) {
574 char* Raw = microsoftDemangle(mangled_name,
nullptr,
nullptr);
576 char* Raw = llvm::itaniumDemangle(mangled_name);
578 std::string demangle = Raw ? Raw :
"";
585 llvm::DebugFlag = value;
596 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
597 getSema().InstantiateFunctionDefinition(SourceLocation(), FD,
601 clang::DiagnosticsEngine& Diags =
getSema().getDiagnostics();
602 if (!FD->isDefined() && Diags.hasErrorOccurred()) {
605 Diags.getClient()->clear();
612 const auto* D = unwrap<Decl>(DRef);
615 if (
const auto* ValD = dyn_cast<ValueDecl>(D))
616 if (ValD->getType()->isArrayType())
620 if (
const auto* CXXRD = dyn_cast<CXXRecordDecl>(D))
628 const auto* D = unwrap<Decl>(DRef);
634 const auto* D = unwrap<Decl>(DRef);
640 const auto* D = unwrap<Decl>(DRef);
646 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
652 const auto* D = unwrap<Decl>(DRef);
653 if (
const auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(D))
654 if (
const auto* CXXRDD = CXXRD->getDefinition())
660 auto& SM = semaRef.getSourceManager();
661 return SM.getLocForStartOfFile(SM.getMainFileID());
670 const auto* D = unwrap<Decl>(DRef);
672 if (isa<ClassTemplateSpecializationDecl>(D)) {
680 if (
const auto* CXXRD = dyn_cast<CXXRecordDecl>(D))
682 else if (
const auto* TD = dyn_cast<TagDecl>(D))
695 if (
const auto* RD = dyn_cast<RecordDecl>(unwrap<Decl>(DRef))) {
696 ASTContext& Context = RD->getASTContext();
697 const ASTRecordLayout& Layout = Context.getASTRecordLayout(RD);
706 QualType Ty = QualType::getFromOpaquePtr(TyRef.data);
707 if (Ty->isBuiltinType() || Ty->isAnyComplexType())
710 if (
const auto* RD = Ty->getAsCXXRecordDecl()) {
711 if (
const auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
712 IdentifierInfo* II = CTSD->getSpecializedTemplate()->getIdentifier();
713 if (II && II->isStr(
"complex") &&
714 CTSD->getDeclContext()->isStdNamespace())
723 const auto* D = unwrap<clang::Decl>(DRef);
724 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::TemplateDecl>(D));
729 const auto* D = unwrap<clang::Decl>(DRef);
731 llvm::isa_and_nonnull<clang::ClassTemplateSpecializationDecl>(D));
736 const auto* D = unwrap<clang::Decl>(DRef);
737 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::TypedefNameDecl>(D));
742 const auto* D = unwrap<clang::Decl>(DRef);
743 if (
const auto* CXXRD = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(D))
751 const auto* D = unwrap<clang::Decl>(DRef);
757 const auto* D = unwrap<clang::Decl>(DRef);
758 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::EnumConstantDecl>(D));
763 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
768 auto IsUseCountPresent = [](
const RecordDecl* Record) {
769 ASTContext& C = Record->getASTContext();
770 return !Record->lookup(&C.Idents.get(
"use_count")).empty();
772 auto IsOverloadedOperatorPresent = [](
const RecordDecl* Record,
773 OverloadedOperatorKind Op) {
774 ASTContext& C = Record->getASTContext();
775 DeclContextLookupResult Result =
776 Record->lookup(C.DeclarationNames.getCXXOperatorName(Op));
777 return !Result.empty();
780 const RecordDecl* Record = RT->getDecl();
781 if (IsUseCountPresent(Record))
784 bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
785 bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
786 if (foundStarOperator && foundArrowOperator)
789 const auto* CXXRecord = dyn_cast<CXXRecordDecl>(Record);
793 auto FindOverloadedOperators = [&](
const CXXRecordDecl* Base) {
795 if (IsUseCountPresent(Base))
797 if (!foundStarOperator)
798 foundStarOperator = IsOverloadedOperatorPresent(Base, OO_Star);
799 if (!foundArrowOperator)
800 foundArrowOperator = IsOverloadedOperatorPresent(Base, OO_Arrow);
801 if (foundStarOperator && foundArrowOperator)
806 return !CXXRecord->forallBases(FindOverloadedOperators);
811 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
812 if (
const RecordType* RT = QT->getAs<RecordType>()) {
815 llvm::StringRef tsRef(typeString);
816 if (tsRef.starts_with(
"std::unique_ptr") ||
817 tsRef.starts_with(
"std::shared_ptr") ||
818 tsRef.starts_with(
"std::weak_ptr"))
827 const auto* D = unwrap<clang::Decl>(DRef);
828 if (
const auto* ED = llvm::dyn_cast_or_null<clang::EnumDecl>(D)) {
840 QualType QT = QualType::getFromOpaquePtr(enum_type.data);
841 if (
const auto* ET = QT->getAs<EnumType>())
842 return INTEROP_RETURN(ET->getDecl()->getIntegerType().getAsOpaquePtr());
849 const auto* D = unwrap<clang::Decl>(DRef);
851 if (
const auto* ED = llvm::dyn_cast_or_null<clang::EnumDecl>(D)) {
852 std::vector<DeclRef> enum_constants;
853 for (
auto* ECD : ED->enumerators()) {
854 enum_constants.push_back(ECD);
868 const auto* D = unwrap<clang::Decl>(DRef);
869 if (
const auto* ECD = llvm::dyn_cast<clang::EnumConstantDecl>(D))
877 const auto* D = unwrap<clang::Decl>(DRef);
878 if (
const auto* ECD = llvm::dyn_cast_or_null<clang::EnumConstantDecl>(D)) {
879 const llvm::APSInt& Val = ECD->getInitVal();
887 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
888 if (
const TagType* TT = QT->getAs<TagType>())
892 auto TI =
getSema().getASTContext().getTypeInfo(QT);
893 size_t TypeSize = TI.Width;
899 const auto* D = unwrap<clang::Decl>(DRef);
905 const auto* D = unwrap<clang::NamedDecl>(DRef);
907 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
911 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
919 auto& C =
getSema().getASTContext();
920 const auto* D = unwrap<Decl>(DRef);
922 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
923 PrintingPolicy Policy = C.getPrintingPolicy();
924 Policy.SuppressUnwrittenScope =
true;
926 Policy.FullyQualifiedName =
true;
927 Policy.Suppress_Elab =
true;
929 Policy.SuppressScope =
true;
930 Policy.AnonymousTagLocations =
false;
931 Policy.SuppressTemplateArgsInCXXConstructors =
false;
932 Policy.SuppressDefaultTemplateArgs =
false;
933 Policy.AlwaysIncludeTypeForTemplateArgument =
true;
936 if (
const auto* TD = llvm::dyn_cast<TagDecl>(ND)) {
937 std::string type_name;
938 QualType QT = C.Get_Tag_Type(TD);
939 QT.getAsStringInternal(type_name, Policy);
942 if (
const auto* FD = llvm::dyn_cast<FunctionDecl>(ND)) {
943 std::string func_name;
944 llvm::raw_string_ostream name_stream(func_name);
945 FD->getNameForDiagnostic(name_stream, Policy, qualified);
950 return qualified ? ND->getQualifiedNameAsString() : ND->getNameAsString();
953 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
967 const auto* D = unwrap<Decl>(DRef);
968 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
972 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
986 const auto* D = unwrap<Decl>(DRef);
990 D = D->getCanonicalDecl();
991 ASTContext& C = D->getASTContext();
993 const RawComment* RC = C.getRawCommentForAnyRedecl(D);
997 (void)C.getCommentForDecl(D,
nullptr);
999 const SourceManager& SM = C.getSourceManager();
1001 if (!strip_comment_markers)
1004 return INTEROP_RETURN(RC->getFormattedText(SM, C.getDiagnostics()));
1009 const auto* D = unwrap<clang::Decl>(DRef);
1011 if (
const auto* DC = llvm::dyn_cast_or_null<clang::DeclContext>(D)) {
1012 std::vector<DeclRef> namespaces;
1013 for (
auto UD : DC->using_directives()) {
1014 namespaces.push_back(UD->getNominatedNamespace());
1029 if (
auto* Type = QT.getCanonicalType().getTypePtrOrNull()) {
1030 Type = Type->getPointeeOrArrayElementType();
1031 Type = Type->getUnqualifiedDesugaredType();
1032 if (
auto* ET = llvm::dyn_cast<EnumType>(Type))
1033 return ET->getDecl();
1034 CXXRecordDecl* CXXRD = Type->getAsCXXRecordDecl();
1036 return CXXRD->getCanonicalDecl();
1043 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
1048 if (
const auto* TND = dyn_cast_or_null<TypedefNameDecl>(D)) {
1051 }
else if (
const auto* USS = dyn_cast_or_null<UsingShadowDecl>(D)) {
1052 if (
const auto* Scope = USS->getTargetDecl())
1056 return D->getCanonicalDecl();
1070DeclRef
GetScope(
const std::string& name, ConstDeclRef parent) {
1079 auto* ND = unwrap<NamedDecl>(
GetNamed(name, parent));
1081 if (!ND || ND == (NamedDecl*)-1)
1084 if (llvm::isa<NamespaceDecl>(ND) || llvm::isa<RecordDecl>(ND) ||
1085 llvm::isa<ClassTemplateDecl>(ND) || llvm::isa<TypedefNameDecl>(ND) ||
1086 llvm::isa<TypeAliasTemplateDecl>(ND) || llvm::isa<TypeAliasDecl>(ND))
1094 std::string delim =
"::";
1096 size_t end = name.find(delim);
1097 DeclRef curr_scope =
nullptr;
1098 while (end != std::string::npos) {
1099 curr_scope =
GetScope(name.substr(start, end - start), curr_scope);
1100 start = end + delim.length();
1101 end = name.find(delim, start);
1119clang::Scope* BuildSyntheticScopeChain(clang::Sema& S, clang::DeclContext* DC) {
1120 if (!DC || DC->isTranslationUnit())
1122 auto* Parent = BuildSyntheticScopeChain(S, DC->getParent());
1123 auto* Mine =
new clang::Scope(Parent, clang::Scope::DeclScope, S.Diags);
1124 Mine->setEntity(DC);
1135class SyntheticScopeChain {
1137 SyntheticScopeChain(clang::Sema& Sema, clang::DeclContext* Within)
1138 : S(Sema), Innermost(BuildSyntheticScopeChain(Sema, Within)),
1139 Saved(
ACCESS(Sema, CurScope)) {
1140 ACCESS(S, CurScope) = Innermost;
1142 ~SyntheticScopeChain() {
1143 ACCESS(S, CurScope) = Saved;
1144 while (Innermost && Innermost != S.TUScope) {
1145 auto* Next = Innermost->getParent();
1150 SyntheticScopeChain(
const SyntheticScopeChain&) =
delete;
1151 SyntheticScopeChain& operator=(
const SyntheticScopeChain&) =
delete;
1153 clang::Scope* get()
const {
return Innermost; }
1157 clang::Scope* Innermost;
1158 clang::Scope* Saved;
1170clang::NamedDecl* LookupUnqualified(clang::Sema& S,
1171 const clang::DeclarationName& Name,
1172 clang::DeclContext* Within) {
1173 SyntheticScopeChain Chain(S, Within);
1179 clang::LookupResult R(S, Name, clang::SourceLocation(),
1180 clang::Sema::LookupOrdinaryName,
1181 RedeclarationKind::NotForRedeclaration);
1182 R.suppressDiagnostics();
1183 S.LookupName(R, Chain.get());
1191 if (R.isSingleResult())
1192 return llvm::dyn_cast<clang::NamedDecl>(R.getFoundDecl());
1193 return (clang::NamedDecl*)-1;
1200bool HasReachableUsingDirective(
const clang::DeclContext* DC) {
1201 for (; DC && !DC->isTranslationUnit(); DC = DC->getParent()) {
1202 if (
const auto* NS = llvm::dyn_cast<clang::NamespaceDecl>(DC)) {
1203 auto UDs = NS->using_directives();
1204 if (UDs.begin() != UDs.end())
1212DeclRef
GetNamed(
const std::string& name, ConstDeclRef parent ) {
1214 clang::DeclContext* Within = 0;
1217 Within = llvm::dyn_cast<clang::DeclContext>(D);
1219#ifdef CPPINTEROP_USE_CLING
1221 Within->getPrimaryContext()->buildLookup();
1230 if (ND && ND != (clang::NamedDecl*)-1)
1237 if (!Within || !llvm::isa<clang::NamespaceDecl>(Within) ||
1238 !HasReachableUsingDirective(Within))
1240 clang::DeclarationName DName = &
getSema().Context.Idents.get(name);
1241 ND = LookupUnqualified(
getSema(), DName, Within);
1242 if (ND && ND != (clang::NamedDecl*)-1)
1253 auto* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1255 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
1258 auto* ParentDC = D->getDeclContext();
1263 auto* P = clang::Decl::castFromDeclContext(ParentDC)->getCanonicalDecl();
1265 if (
auto* TU = llvm::dyn_cast_or_null<TranslationUnitDecl>(P))
1273 const auto* D = unwrap<Decl>(DRef);
1275 if (
const auto* CTSD =
1276 llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(D))
1277 if (!CTSD->hasDefinition())
1279 getInterp(),
const_cast<ClassTemplateSpecializationDecl*
>(CTSD));
1280 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1281 if (CXXRD->hasDefinition())
1290 const auto* D = unwrap<Decl>(DRef);
1291 const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D);
1292 if (!CXXRD || CXXRD->getNumBases() <= ibase)
1295 auto TyRef = (CXXRD->bases_begin() + ibase)->getType();
1296 if (
const auto* RT = TyRef->getAs<RecordType>())
1306 if (derived == base)
1309 if (!derived || !base)
1312 const auto* derived_D = unwrap<clang::Decl>(derived);
1313 const auto* base_D = unwrap<clang::Decl>(base);
1315 if (!isa<CXXRecordDecl>(derived_D) || !isa<CXXRecordDecl>(base_D))
1318 const auto* Derived = cast<CXXRecordDecl>(derived_D);
1319 const auto* Base = cast<CXXRecordDecl>(base_D);
1329 const CXXRecordDecl* DerivedRD,
1330 const CXXBasePath& Path) {
1331 CharUnits NonVirtualOffset = CharUnits::Zero();
1333 unsigned NonVirtualStart = 0;
1334 const CXXRecordDecl* VirtualBase =
nullptr;
1337 for (
int I = Path.size(), E = 0; I != E; --I) {
1338 const CXXBasePathElement& Element = Path[I - 1];
1340 if (Element.Base->isVirtual()) {
1341 NonVirtualStart = I;
1342 QualType VBaseType = Element.Base->getType();
1343 VirtualBase = VBaseType->getAsCXXRecordDecl();
1349 for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
1350 const CXXBasePathElement& Element = Path[I];
1353 const ASTRecordLayout& Layout = Context.getASTRecordLayout(Element.Class);
1355 const CXXRecordDecl* Base = Element.Base->getType()->getAsCXXRecordDecl();
1357 NonVirtualOffset += Layout.getBaseClassOffset(Base);
1365 const ASTRecordLayout& Layout = Context.getASTRecordLayout(DerivedRD);
1366 CharUnits VirtualOffset = Layout.getVBaseClassOffset(VirtualBase);
1367 return (NonVirtualOffset + VirtualOffset).getQuantity();
1369 return NonVirtualOffset.getQuantity();
1374 if (base == derived)
1377 assert(derived || base);
1379 const auto* DD = unwrap<Decl>(derived);
1380 const auto* BD = unwrap<Decl>(base);
1381 if (!isa<CXXRecordDecl>(DD) || !isa<CXXRecordDecl>(BD))
1383 const auto* DCXXRD = cast<CXXRecordDecl>(DD);
1384 const auto* BCXXRD = cast<CXXRecordDecl>(BD);
1392#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
1393#pragma GCC diagnostic push
1394#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1396 CXXBasePaths Paths(
false,
true,
1398#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
1399#pragma GCC diagnostic pop
1401 DCXXRD->isDerivedFrom(BCXXRD, Paths);
1408template <
typename DeclType,
typename HandleType>
1415 Decl* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1417 if (
auto* TD = dyn_cast<TypedefNameDecl>(D)) {
1419 D = unwrap<clang::Decl>(Scope);
1422 if (!D || !isa<CXXRecordDecl>(D))
1425 auto* CXXRD = dyn_cast<CXXRecordDecl>(D);
1427 if (
auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
1429#if CLANG_VERSION_MAJOR < 22
1430 QT = QualType(CTSD->getTypeForDecl(), 0);
1432 QT =
getSema().getASTContext().getCanonicalTagType(CTSD);
1434 if (!
getSema().isCompleteType(CTSD->getLocation(), QT))
1438 if (CXXRD->hasDefinition())
1439 CXXRD = CXXRD->getDefinition();
1440 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1441 for (Decl* DI : CXXRD->decls()) {
1442 if (
auto* MD = dyn_cast<DeclType>(DI))
1443 methods.push_back(MD);
1444 else if (
auto* USD = dyn_cast<UsingShadowDecl>(DI)) {
1445 auto* MD = dyn_cast<DeclType>(USD->getTargetDecl());
1449 auto* CUSD = dyn_cast<ConstructorUsingShadowDecl>(DI);
1451 methods.push_back(MD);
1455 auto* CXXCD = dyn_cast_or_null<CXXConstructorDecl>(CUSD->getTargetDecl());
1457 methods.push_back(MD);
1460 if (CXXCD->isDeleted())
1466 getSema().findInheritingConstructor(SourceLocation(), CXXCD, CUSD);
1473 GetClassDecls<CXXMethodDecl>(DRef, methods);
1478 std::vector<FuncRef>& methods) {
1480 GetClassDecls<FunctionTemplateDecl>(DRef, methods);
1486 const auto* D = unwrap<clang::Decl>(DRef);
1488 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D))
1498 auto* CXXRD = unwrap<clang::CXXRecordDecl>(DRef);
1500 return interp.
getCI()->getSema().LookupDefaultConstructor(CXXRD);
1511 auto* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1513 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1514 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1523 const auto* D = unwrap<clang::Decl>(DRef);
1529 const std::string& name) {
1532 if (!DRef || name.empty())
1537 std::vector<FuncRef> funcs;
1538 llvm::StringRef Name(name);
1541 clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
1542 RedeclarationKind::ForVisibleRedeclaration);
1551 for (
auto* Found : R) {
1552 if (llvm::isa<FunctionDecl>(Found))
1553 funcs.push_back(Found);
1554 else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(Found)) {
1555 if (
auto* FTD = llvm::dyn_cast<FunctionDecl>(USD->getTargetDecl()))
1556 funcs.push_back(FTD);
1565 const auto* D = unwrap<clang::Decl>(func);
1566 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
1567 QualType Type = FD->getReturnType();
1568 if (Type->isUndeducedAutoType()) {
1569 bool needInstantiation =
false;
1571 needInstantiation =
true;
1572 if (
const auto* MD = llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
1574 needInstantiation =
true;
1577 if (needInstantiation) {
1580 const_cast<Decl*
>(
static_cast<const Decl*
>(FD)));
1582 Type = FD->getReturnType();
1587 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1589 (FD->getTemplatedDecl())->getReturnType().getAsOpaquePtr());
1596 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
1597 const auto* T = QT.getTypePtr();
1598 return llvm::isa_and_nonnull<clang::FunctionProtoType>(T);
1603 QualType QT = QualType::getFromOpaquePtr(fn_type.data);
1604 const auto* FPT = QT->getAs<clang::FunctionProtoType>();
1607 sig.push_back(FPT->getReturnType().getAsOpaquePtr());
1608 for (
size_t i = 0; i < FPT->getNumParams(); i++)
1609 sig.push_back(FPT->getParamType(i).getAsOpaquePtr());
1615 const auto* D = unwrap<clang::Decl>(func);
1616 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1619 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1627 const auto* D = unwrap<clang::Decl>(func);
1628 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1631 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1632 return INTEROP_RETURN((FD->getTemplatedDecl())->getMinRequiredArguments());
1639 const auto* D = unwrap<clang::Decl>(func);
1641 if (
const auto* FTD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1642 D = FTD->getTemplatedDecl();
1644 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
1645 if (iarg < FD->getNumParams()) {
1646 const auto* PVD = FD->getParamDecl(iarg);
1656 clang::QualType QT = clang::QualType::getFromOpaquePtr(TyRef.data);
1665 const auto* D = unwrap<clang::Decl>(func);
1666 const clang::FunctionDecl* FD;
1668 if (llvm::dyn_cast<FunctionDecl>(D))
1669 FD = llvm::dyn_cast<FunctionDecl>(D);
1670 else if (
const auto* FTD = llvm::dyn_cast<clang::FunctionTemplateDecl>(D))
1671 FD = FTD->getTemplatedDecl();
1675 std::string Signature;
1676 raw_string_ostream SS(Signature);
1677 PrintingPolicy Policy =
getASTContext().getPrintingPolicy();
1679 Policy.TerseOutput =
true;
1680 Policy.FullyQualifiedName =
true;
1681 Policy.SuppressDefaultTemplateArgs =
false;
1682 FD->print(SS, Policy);
1691 return llvm::isa_and_nonnull<FunctionTemplateDecl>(D);
1694bool IsTemplateInstantiationOrSpecialization(
const Decl* D) {
1695 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
1696 auto TK = FD->getTemplatedKind();
1698 FunctionDecl::TemplatedKind::TK_FunctionTemplateSpecialization ||
1699 TK == FunctionDecl::TemplatedKind::
1700 TK_DependentFunctionTemplateSpecialization ||
1701 TK == FunctionDecl::TemplatedKind::TK_FunctionTemplate;
1710 const auto* FD = cast<FunctionDecl>(unwrap<clang::Decl>(function));
1716 const auto* D = unwrap<Decl>(func);
1718 IsTemplateInstantiationOrSpecialization(D));
1726 const DeclContext* Within =
nullptr;
1728 const auto* D = unwrap<Decl>(parent);
1729 Within = llvm::dyn_cast<DeclContext>(D);
1734 if ((intptr_t)ND == (intptr_t)0)
1737 if ((intptr_t)ND != (intptr_t)-1)
1739 IsTemplateInstantiationOrSpecialization(ND));
1747 std::vector<FuncRef>& funcs) {
1750 auto* D =
const_cast<Decl*
>(unwrap<Decl>(parent));
1752 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1753 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1754 DeclContextLookupResult Result =
getSema().LookupConstructors(CXXRD);
1758 for (
auto* i : Result)
1759 if (
GetName(DeclRef(i)) == name)
1766 std::vector<FuncRef>& funcs) {
1768 const auto* D = unwrap<Decl>(parent);
1769 if (!D && name.empty())
1776 llvm::StringRef Name(name);
1778 clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
1779 RedeclarationKind::ForVisibleRedeclaration);
1780 auto* DC = clang::Decl::castToDeclContext(DU);
1789 funcs.push_back(R.getFoundDecl());
1793 for (
auto* Found : R) {
1795 funcs.push_back(Found);
1796 else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(Found)) {
1798 llvm::dyn_cast<FunctionTemplateDecl>(USD->getTargetDecl()))
1799 funcs.push_back(FTD);
1817 const std::vector<TemplateArgInfo>& explicit_types,
1818 const std::vector<TemplateArgInfo>& arg_types) {
1821 auto& C = S.getASTContext();
1830 struct WrapperExpr :
public OpaqueValueExpr {
1831 WrapperExpr() : OpaqueValueExpr(clang::Stmt::EmptyShell()) {}
1833 auto* Exprs =
new WrapperExpr[arg_types.size()];
1834 llvm::SmallVector<Expr*> Args;
1835 Args.reserve(arg_types.size());
1837 for (
auto i : arg_types) {
1838 QualType Type = QualType::getFromOpaquePtr(i.m_Type);
1841 ExprValueKind ExprKind = ExprValueKind::VK_XValue;
1842 if (Type->isLValueReferenceType())
1843 ExprKind = ExprValueKind::VK_LValue;
1845 new (&Exprs[idx]) OpaqueValueExpr(SourceLocation::getFromRawEncoding(1),
1846 Type.getNonReferenceType(), ExprKind);
1847 Args.push_back(&Exprs[idx]);
1852 llvm::SmallVector<TemplateArgument> TemplateArgs;
1853 TemplateArgs.reserve(explicit_types.size());
1854 for (
auto explicit_type : explicit_types) {
1855 QualType ArgTy = QualType::getFromOpaquePtr(explicit_type.m_Type);
1856 if (explicit_type.m_IntegralValue) {
1859 auto Res = llvm::APSInt(explicit_type.m_IntegralValue);
1860 Res = Res.extOrTrunc(C.getIntWidth(ArgTy));
1861 TemplateArgs.push_back(TemplateArgument(C, Res, ArgTy));
1863 TemplateArgs.push_back(ArgTy);
1867 TemplateArgumentListInfo ExplicitTemplateArgs{};
1868 for (
auto TA : TemplateArgs)
1869 ExplicitTemplateArgs.addArgument(
1870 S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation()));
1872 OverloadCandidateSet Overloads(
1873 SourceLocation(), OverloadCandidateSet::CandidateSetKind::CSK_Normal);
1875 for (
auto i : candidates) {
1876 auto* D =
const_cast<Decl*
>(unwrap<Decl>(i));
1877 if (
auto* FD = dyn_cast<FunctionDecl>(D)) {
1878 S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
1880 }
else if (
auto* FTD = dyn_cast<FunctionTemplateDecl>(D)) {
1886 S.AddTemplateOverloadCandidate(
1887 FTD, DeclAccessPair::make(FTD, FTD->getAccess()),
1888 &ExplicitTemplateArgs, Args, Overloads);
1892 OverloadCandidateSet::iterator Best;
1893 Overloads.BestViableFunction(S, SourceLocation(), Best);
1895 FunctionDecl* Result = Best != Overloads.end() ? Best->Function :
nullptr;
1903 const auto* D = unwrap<Decl>(method);
1904 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
1905 return CXXMD->getAccess() == AS;
1913 const auto* D = unwrap<clang::Decl>(method);
1914 if (
const auto* FTD = dyn_cast_or_null<FunctionTemplateDecl>(D))
1915 D = FTD->getTemplatedDecl();
1937 const auto* D = unwrap<Decl>(method);
1938 if (
const auto* FTD = dyn_cast<FunctionTemplateDecl>(D))
1940 return INTEROP_RETURN(llvm::isa_and_nonnull<CXXConstructorDecl>(D));
1945 const auto* D = unwrap<Decl>(method);
1946 return INTEROP_RETURN(llvm::isa_and_nonnull<CXXDestructorDecl>(D));
1951 const auto* D = unwrap<Decl>(method);
1952 if (
const auto* FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D))
1953 D = FTD->getTemplatedDecl();
1955 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
1967 const auto* D = unwrap<Decl>(method);
1969 if (
const auto* FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D))
1970 D = FTD->getTemplatedDecl();
1972 if (
const auto* CD = llvm::dyn_cast_or_null<CXXConstructorDecl>(D))
1975 if (
const auto* CD = llvm::dyn_cast_or_null<CXXConversionDecl>(D))
1978 if (
const auto* DGD = llvm::dyn_cast_or_null<CXXDeductionGuideDecl>(D))
1988 if (llvm::Error Err = FDAorErr.takeError())
1989 llvm::consumeError(std::move(Err));
1991 return INTEROP_RETURN(llvm::jitTargetAddressToPointer<void*>(*FDAorErr));
1997 const auto get_mangled_name = [](
const FunctionDecl* FD) {
2000 if (!MangleCtxt->shouldMangleDeclName(FD)) {
2001 return FD->getNameInfo().getName().getAsString();
2004 std::string mangled_name;
2005 llvm::raw_string_ostream ostream(mangled_name);
2007 MangleCtxt->mangleName(FD, ostream);
2012 return mangled_name;
2016 if (!llvm::isa<CXXConstructorDecl>(FD) && !llvm::isa<CXXDestructorDecl>(FD))
2024 auto* D = unwrap<Decl>(method);
2025 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
2026 if ((IsTemplateInstantiationOrSpecialization(FD) ||
2027 FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) &&
2028 !FD->getDefinition())
2031 if (isDiscardableGVALinkage(C.GetGVALinkageForFunction(FD)))
2040 const auto* D = unwrap<Decl>(method);
2041 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
2053 const auto* MD = llvm::dyn_cast_or_null<CXXMethodDecl>(unwrap<Decl>(method));
2054 if (!MD || !MD->isVirtual())
2058 if (C.getTargetInfo().getCXXABI().isMicrosoft()) {
2059 auto* VTC = llvm::cast<MicrosoftVTableContext>(C.getVTableContext());
2060 return (
int)VTC->getMethodVFTableLocation(GlobalDecl(MD)).Index;
2062 auto* VTC = llvm::cast<ItaniumVTableContext>(C.getVTableContext());
2063 return (
int)VTC->getMethodVTableIndex(GlobalDecl(MD));
2070 const auto* RD = llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(DRef));
2072 RD = RD->getDefinition();
2073 if (!RD || !RD->isPolymorphic())
2077 if (C.getTargetInfo().getCXXABI().isMicrosoft()) {
2078 auto* VTC = llvm::cast<MicrosoftVTableContext>(C.getVTableContext());
2079 const VTableLayout& L = VTC->getVFTableLayout(RD, CharUnits::Zero());
2080 return (
int)L.vtable_components().size();
2082 auto* VTC = llvm::cast<ItaniumVTableContext>(C.getVTableContext());
2083 const VTableLayout& L = VTC->getVTableLayout(RD);
2084 unsigned AddrPoint = L.getAddressPointIndices()[0];
2085 return (
int)(L.vtable_components().size() - AddrPoint);
2098 if (RD->getNumVBases() > 0)
2100 unsigned polymorphic_direct_bases = 0;
2101 for (
const auto& B : RD->bases()) {
2102 const auto* BD = B.getType()->getAsCXXRecordDecl();
2105 BD = BD->getDefinition();
2106 if (BD && BD->isPolymorphic() && ++polymorphic_direct_bases > 1)
2121 "public prefix size must equal ABI prefix + 1 hidden slot");
2147 std::size_t n_extra)
2173 template <
class To,
class From>
static To
BitCastFn(From f)
noexcept {
2174 static_assert(
sizeof(To) ==
sizeof(From));
2176 std::memcpy(&to, &f,
sizeof(to));
2181 return *
reinterpret_cast<void***
>(
inst);
2184 *
reinterpret_cast<void***
>(
inst) = new_vptr;
2224 const int* slots,
void*
const* fns,
2226 std::size_t n_extra_prefix_slots) {
2229 for (std::size_t i = 0; i < n; ++i) {
2230 if (slots[i] < 0 || slots[i] >= total_method_slots)
2238 const std::size_t total = n_extra_prefix_slots + kPrefix + total_method_slots;
2245 void** block =
new void*[total]();
2246 std::memcpy(block + n_extra_prefix_slots + 1, orig_vptr -
kABIPrefixSize,
2249 for (std::size_t i = 0; i < n; ++i)
2250 block[n_extra_prefix_slots + kPrefix + slots[i]] = fns[i];
2255 return new VTableOverlay(block, orig_vptr, inst, n_extra_prefix_slots);
2271 void*
const* overlay_fns, std::size_t n_overlays,
2272 std::size_t n_extra_prefix_slots,
2273 VTableOverlayDtorHook on_destroy,
void* cleanup_data) {
2275 n_extra_prefix_slots, on_destroy, cleanup_data);
2282 const auto* RD = llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(base));
2284 RD = RD->getDefinition();
2292 llvm::SmallVector<int, 8> slots;
2293 slots.reserve(n_overlays);
2294 for (std::size_t i = 0; i < n_overlays; ++i) {
2298 slots.push_back(slot);
2301 overlay_fns, n_overlays,
2302 n_extra_prefix_slots);
2312 void** vptr = ov->address_point();
2315 ov->cleanup = on_destroy;
2316 ov->cleanup_data = cleanup_data;
2332 auto* D = unwrap<Decl>(DRef);
2334 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
2335 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
2336 if (CXXRD->hasDefinition())
2337 CXXRD = CXXRD->getDefinition();
2339 llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_begin;
2340 llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_end;
2341 stack_begin.push_back(CXXRD->decls_begin());
2342 stack_end.push_back(CXXRD->decls_end());
2343 while (!stack_begin.empty()) {
2344 if (stack_begin.back() == stack_end.back()) {
2345 stack_begin.pop_back();
2346 stack_end.pop_back();
2349 Decl* D = *(stack_begin.back());
2350 if (
auto* FD = llvm::dyn_cast<FieldDecl>(D)) {
2351 if (FD->isAnonymousStructOrUnion()) {
2352 if (
const auto* RT = FD->getType()->getAs<RecordType>()) {
2353 if (
auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(RT->getDecl())) {
2354 stack_begin.back()++;
2355 stack_begin.push_back(CXXRD->decls_begin());
2356 stack_end.push_back(CXXRD->decls_end());
2361 datamembers.push_back(D);
2363 }
else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(D)) {
2364 if (llvm::isa<FieldDecl>(USD->getTargetDecl()))
2365 datamembers.push_back(USD);
2367 stack_begin.back()++;
2374 std::vector<DeclRef>& datamembers) {
2376 GetClassDecls<VarDecl>(DRef, datamembers);
2381 std::vector<DeclRef>& datamembers,
2382 bool include_enum_class) {
2384 std::vector<DeclRef> EDs;
2385 GetClassDecls<EnumDecl>(DRef, EDs);
2386 for (DeclRef i : EDs) {
2387 auto* ED = unwrap<EnumDecl>(i);
2389 bool is_class_tagged = ED->isScopedUsingClassTag();
2390 if (is_class_tagged && !include_enum_class)
2393 std::copy(ED->enumerator_begin(), ED->enumerator_end(),
2394 std::back_inserter(datamembers));
2401 const clang::DeclContext* Within =
nullptr;
2403 const auto* D = unwrap<clang::Decl>(parent);
2404 Within = llvm::dyn_cast<clang::DeclContext>(D);
2408 if (ND && ND != (clang::NamedDecl*)-1) {
2409 if (llvm::isa_and_nonnull<clang::FieldDecl>(ND)) {
2419 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2420 if (
auto* CXXRD = QT->getAsCXXRecordDecl()) {
2428 const auto* D = unwrap<Decl>(var);
2430 if (
const auto* DD = llvm::dyn_cast_or_null<DeclaratorDecl>(D)) {
2431 QualType QT = DD->getType();
2434 if (QT->isTypedefNameType()) {
2439 QT = QT.getCanonicalType();
2443 if (
const auto* ECD = llvm::dyn_cast_or_null<EnumConstantDecl>(D))
2450 CXXRecordDecl* BaseCXXRD) {
2454 auto& C = I.
getSema().getASTContext();
2456 if (
auto* FD = llvm::dyn_cast<FieldDecl>(D)) {
2457 clang::RecordDecl* FieldParentRecordDecl = FD->getParent();
2458 intptr_t offset = C.toCharUnitsFromBits(C.getFieldOffset(FD)).getQuantity();
2459 while (FieldParentRecordDecl->isAnonymousStructOrUnion()) {
2460 clang::RecordDecl* anon = FieldParentRecordDecl;
2461 FieldParentRecordDecl = llvm::dyn_cast<RecordDecl>(anon->getParent());
2462 for (
auto F = FieldParentRecordDecl->field_begin();
2463 F != FieldParentRecordDecl->field_end(); ++F) {
2464 const auto* RT = F->getType()->getAs<RecordType>();
2467 if (anon == RT->getDecl()) {
2472 offset += C.toCharUnitsFromBits(C.getFieldOffset(FD)).getQuantity();
2474 if (BaseCXXRD && BaseCXXRD != FieldParentRecordDecl->getCanonicalDecl()) {
2481 std::vector<CXXRecordDecl*> stack;
2482 std::map<CXXRecordDecl*, CXXRecordDecl*> direction;
2483 stack.push_back(BaseCXXRD);
2484 while (!stack.empty()) {
2485 CXXRecordDecl* RD = stack.back();
2489 for (
size_t i = 0; i < num_bases; i++) {
2490 auto* CRD = unwrap<CXXRecordDecl>(
GetBaseClass(RD, i));
2491 direction[CRD] = RD;
2492 if (CRD == FieldParentRecordDecl) {
2496 stack.push_back(CRD);
2501 if (
auto* RD = llvm::dyn_cast<CXXRecordDecl>(FieldParentRecordDecl)) {
2503 RD = RD->getCanonicalDecl();
2504 while (BaseCXXRD != RD) {
2505 CXXRecordDecl* Parent = direction.at(RD);
2507 C.getASTRecordLayout(Parent).getBaseClassOffset(RD).getQuantity();
2511 assert(
false &&
"Unreachable");
2517 if (
auto* VD = llvm::dyn_cast<VarDecl>(D)) {
2518 auto GD = GlobalDecl(VD);
2519 std::string mangledName;
2521 void* address = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
2522 mangledName.c_str());
2527 if (!VD->hasInit()) {
2529 getSema().InstantiateVariableDefinition(SourceLocation(), VD);
2530 VD = VD->getDefinition();
2532 if (VD->hasInit() &&
2533 (VD->isConstexpr() || VD->getType().isConstQualified())) {
2534 if (
const APValue* val = VD->evaluateValue()) {
2535 if (VD->getType()->isIntegralType(C)) {
2536 return (intptr_t)val->getInt().getRawData();
2542 auto Linkage = C.GetGVALinkageForVariable(VD);
2543 if (isDiscardableGVALinkage(Linkage))
2548 llvm::logAllUnhandledErrors(VDAorErr.takeError(), llvm::errs(),
2549 "Failed to GetVariableOffset:");
2552 return (intptr_t)jitTargetAddressToPointer<void*>(VDAorErr.get());
2561 auto* D =
const_cast<Decl*
>(unwrap<Decl>(var));
2562 auto* RD =
const_cast<CXXRecordDecl*
>(
2563 llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(parent)));
2569 const auto* D = unwrap<Decl>(var);
2570 return D->getAccess() == AS;
2591 const auto* D = unwrap<Decl>(var);
2592 if (llvm::isa_and_nonnull<VarDecl>(D)) {
2601 const auto* D = unwrap<clang::Decl>(var);
2603 if (
const auto* VD = llvm::dyn_cast_or_null<ValueDecl>(D)) {
2612 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2618 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2630 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2631 if (!QT->hasIntegerRepresentation())
2634 *s = QT->hasSignedIntegerRepresentation() ? Signedness::kSigned
2635 : Signedness::kUnsigned;
2644 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2650 if (!type_a || !type_b)
2652 QualType QT1 = QualType::getFromOpaquePtr(type_a.data);
2653 QualType QT2 = QualType::getFromOpaquePtr(type_b.data);
2659 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2667 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2675 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2681 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2687 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2688 if (QT->isRValueReferenceType())
2690 if (QT->isLValueReferenceType())
2697 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2703 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2706 getASTContext().getRValueReferenceType(QT).getAsOpaquePtr());
2708 getASTContext().getLValueReferenceType(QT).getAsOpaquePtr());
2715 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2716 return INTEROP_RETURN(QT.getNonReferenceType().getAsOpaquePtr());
2723 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2724 QT = QT->getCanonicalTypeUnqualified();
2727 while (QT->isArrayType())
2728 QT = QualType(QT->getArrayElementTypeNoTypeQual(), 0);
2732 for (
auto PT = QT->getPointeeType(); !PT.isNull();
2733 PT = QT->getPointeeType()) {
2736 QT = QT->getCanonicalTypeUnqualified();
2742 QualType QT = QualType::getFromOpaquePtr(var.data);
2745 Policy.SuppressTagKeyword =
true;
2746 Policy.Suppress_Elab =
true;
2747 Policy.FullyQualifiedName =
true;
2755 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2764 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2765 if (qual & QualKind::Const) {
2766 if (!QT.isConstQualified())
2769 if (qual & QualKind::Volatile) {
2770 if (!QT.isVolatileQualified())
2773 if (qual & QualKind::Restrict) {
2774 if (!QT.isRestrictQualified())
2785 auto QT = QualType(QualType::getFromOpaquePtr(TyRef.data));
2786 if (qual & QualKind::Const)
2787 QT.removeLocalConst();
2788 if (qual & QualKind::Volatile)
2789 QT.removeLocalVolatile();
2790 if (qual & QualKind::Restrict)
2791 QT.removeLocalRestrict();
2800 auto QT = QualType(QualType::getFromOpaquePtr(TyRef.data));
2801 if (qual & QualKind::Const) {
2802 if (!QT.isConstQualified())
2805 if (qual & QualKind::Volatile) {
2806 if (!QT.isVolatileQualified())
2809 if (qual & QualKind::Restrict) {
2810 if (!QT.isRestrictQualified())
2818 llvm::SmallVectorImpl<llvm::StringRef>& Words) {
2819 std::sort(Words.begin(), Words.end());
2822 for (
size_t i = 0; i < Words.size(); ++i) {
2825 Key += Words[i].str();
2828 }
while (std::next_permutation(Words.begin(), Words.end()));
2832 const PrintingPolicy Policy(Context.getLangOpts());
2834 const auto& Types =
ACCESS(Context, Types);
2836 for (clang::Type* T : Types) {
2837 auto* BT = llvm::dyn_cast<BuiltinType>(T);
2838 if (!BT || BT->isPlaceholderType())
2842 std::string Name = QT.getAsString(Policy);
2843 if (Name.empty() || Name[0] ==
'<')
2847 BuiltinMap[Name] = QT;
2849 llvm::SmallVector<llvm::StringRef, 4> Words;
2850 llvm::StringRef(Name).split(Words,
' ', -1,
false);
2852 bool hasInt =
false;
2853 bool hasSigned =
false;
2854 bool hasUnsigned =
false;
2855 bool hasChar =
false;
2856 bool isModifiable =
false;
2858 for (
auto W : Words) {
2861 else if (W ==
"signed")
2863 else if (W ==
"unsigned")
2865 else if (W ==
"char")
2868 if (W ==
"long" || W ==
"short" || hasInt)
2869 isModifiable =
true;
2873 if (!isModifiable && !hasUnsigned && !hasSigned)
2877 if (Words.size() > 1)
2881 if (!hasInt && !hasChar) {
2882 auto WithInt = Words;
2883 WithInt.push_back(
"int");
2888 if (!hasSigned && !hasUnsigned) {
2889 auto WithBoth = WithInt;
2890 WithBoth.push_back(
"signed");
2897 if (!hasSigned && !hasUnsigned) {
2898 auto WithSigned = Words;
2899 WithSigned.push_back(
"signed");
2905 BuiltinMap[
"signed"] = Context.IntTy;
2906 BuiltinMap[
"unsigned"] = Context.UnsignedIntTy;
2909 llvm::StringMap<QualType>& BuiltinMap =
GetInterpreters().back().BuiltinMap;
2910 if (BuiltinMap.empty())
2914 auto It = BuiltinMap.find(typeName);
2915 if (It != BuiltinMap.end())
2925 if (
const auto* TND = llvm::dyn_cast_or_null<TypedefNameDecl>(D))
2926 return TND->getUnderlyingType();
2928 if (
const auto* VD = dyn_cast<ValueDecl>(D))
2929 return VD->getType();
2931 if (
const auto* TD = llvm::dyn_cast_or_null<TypeDecl>(D))
2932#if CLANG_VERSION_MAJOR < 22
2933 return QualType(TD->getTypeForDecl(), 0);
2941TypeRef
GetType(
const std::string& name, ConstDeclRef parent ) {
2944 if (!builtin.isNull())
2952 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2971static unsigned long long gWrapperSerial = 0LL;
2973enum EReferenceType { kNotReference, kLValueReference, kRValueReference };
2977#define DEBUG_TYPE "jitcall"
2981inline void indent(std::ostringstream& buf,
int indent_level) {
2982 static const std::string kIndentString(
" ");
2983 for (
int i = 0; i < indent_level; ++i)
2984 buf << kIndentString;
2988 const std::string& wrapper,
2989 bool withAccessControl =
true) {
2990 LLVM_DEBUG(dbgs() <<
"Compiling '" << wrapper_name <<
"'\n");
2995void get_type_as_string(QualType QT, std::string& type_name, ASTContext& C,
2996 PrintingPolicy Policy) {
2999 if (!QT->isTypedefNameType() || QT->isBuiltinType())
3000 QT = QT.getDesugaredType(C);
3001 Policy.Suppress_Elab =
true;
3002 Policy.SuppressTagKeyword = !QT->isEnumeralType();
3003 Policy.FullyQualifiedName =
true;
3004 Policy.UsePreferredNames =
false;
3005 QT.getAsStringInternal(type_name, Policy);
3008static void GetDeclName(
const clang::Decl* D, ASTContext& Context,
3009 std::string& name) {
3011 PrintingPolicy Policy(Context.getPrintingPolicy());
3012 Policy.SuppressTagKeyword =
true;
3013 Policy.SuppressUnwrittenScope =
true;
3014 Policy.Print_Canonical_Types =
true;
3015 if (
const auto* TD = dyn_cast<TypeDecl>(D)) {
3018 if (
const auto* Typedef = dyn_cast<const TypedefDecl>(TD)) {
3020 QT = Typedef->getTypeSourceInfo()->getType();
3022#if CLANG_VERSION_MAJOR < 22
3023 QT = {TD->getTypeForDecl(), 0};
3025 QT = TD->getASTContext().getTypeDeclType(TD);
3027 get_type_as_string(QT, name, Context, Policy);
3028 }
else if (
const auto* ND = dyn_cast<NamedDecl>(D)) {
3030 raw_string_ostream stream(name);
3031 ND->getNameForDiagnostic(stream, Policy,
true);
3036void collect_type_info(
const FunctionDecl* FD, QualType& QT,
3037 std::ostringstream& typedefbuf,
3038 std::ostringstream& callbuf, std::string& type_name,
3039 EReferenceType& refType,
bool& isPointer,
3040 int indent_level,
bool forArgument) {
3045 ASTContext& C = FD->getASTContext();
3046 PrintingPolicy Policy(C.getPrintingPolicy());
3047 Policy.Suppress_Elab =
true;
3048 refType = kNotReference;
3049 if (QT->isRecordType()) {
3051 get_type_as_string(QT, type_name, C, Policy);
3054 if (
auto* CXXRD = QT->getAsCXXRecordDecl()) {
3055 if (CXXRD->isLambda()) {
3056 std::string fn_name;
3057 llvm::raw_string_ostream stream(fn_name);
3058 Policy.FullyQualifiedName =
true;
3059 Policy.SuppressUnwrittenScope =
true;
3060 FD->getNameForDiagnostic(stream, Policy,
3062 type_name =
"__internal_CppInterOp::function<decltype(" + fn_name +
3068 if (QT.getNonReferenceType()->isFunctionPointerType() ||
3069 QT.getNonReferenceType()->isFunctionProtoType()) {
3070 clang::QualType NRQT = QT.getNonReferenceType();
3071 std::string fp_typedef_name;
3073 std::ostringstream nm;
3074 nm <<
"FP" << gWrapperSerial++;
3075 type_name = nm.str();
3076 raw_string_ostream OS(fp_typedef_name);
3077 NRQT.print(OS, Policy, type_name);
3081 indent(typedefbuf, indent_level);
3083 typedefbuf <<
"typedef " << fp_typedef_name <<
";\n";
3085 if (QT->isRValueReferenceType())
3086 refType = kRValueReference;
3088 refType = kLValueReference;
3090 }
else if (QT->isMemberPointerType()) {
3091 std::string mp_typedef_name;
3093 std::ostringstream nm;
3094 nm <<
"MP" << gWrapperSerial++;
3095 type_name = nm.str();
3096 raw_string_ostream OS(mp_typedef_name);
3097 QT.print(OS, Policy, type_name);
3101 indent(typedefbuf, indent_level);
3103 typedefbuf <<
"typedef " << mp_typedef_name <<
";\n";
3105 }
else if (QT->isPointerType()) {
3107 QT = cast<clang::PointerType>(QT.getCanonicalType())->getPointeeType();
3108 }
else if (QT->isReferenceType()) {
3109 if (QT->isRValueReferenceType())
3110 refType = kRValueReference;
3112 refType = kLValueReference;
3113 QT = cast<ReferenceType>(QT.getCanonicalType())->getPointeeType();
3117 if (QT->isArrayType()) {
3118 std::string ar_typedef_name;
3120 std::ostringstream ar;
3121 ar <<
"AR" << gWrapperSerial++;
3122 type_name = ar.str();
3123 raw_string_ostream OS(ar_typedef_name);
3124 QT.print(OS, Policy, type_name);
3127 indent(typedefbuf, indent_level);
3128 typedefbuf <<
"typedef " << ar_typedef_name <<
";\n";
3131 get_type_as_string(QT, type_name, C, Policy);
3134void make_narg_ctor(
const FunctionDecl* FD,
const unsigned N,
3135 std::ostringstream& typedefbuf, std::ostringstream& callbuf,
3136 const std::string& class_name,
int indent_level,
3137 bool array =
false) {
3146 callbuf << class_name <<
"[nary]";
3148 callbuf << class_name;
3153 for (
unsigned i = 0U; i < N; ++i) {
3154 const ParmVarDecl* PVD = FD->getParamDecl(i);
3155 QualType Ty = PVD->getType();
3156 QualType QT = Ty.getCanonicalType();
3157 std::string type_name;
3158 EReferenceType refType = kNotReference;
3159 bool isPointer =
false;
3160 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3161 isPointer, indent_level,
true);
3168 indent(callbuf, indent_level);
3171 if (refType != kNotReference) {
3172 callbuf <<
"(" << type_name.c_str()
3173 << (refType == kLValueReference ?
"&" :
"&&") <<
")*("
3174 << type_name.c_str() <<
"*)args[" << i <<
"]";
3175 }
else if (isPointer) {
3176 callbuf <<
"*(" << type_name.c_str() <<
"**)args[" << i <<
"]";
3178 callbuf <<
"*(" << type_name.c_str() <<
"*)args[" << i <<
"]";
3184 else if (
const auto* CD = dyn_cast<CXXConstructorDecl>(FD);
3185 CD && CD->isDefaultConstructor() && !array) {
3190const DeclContext* get_non_transparent_decl_context(
const FunctionDecl* FD) {
3191 const auto* DC = FD->getDeclContext();
3192 while (DC->isTransparentContext()) {
3193 DC = DC->getParent();
3194 assert(DC &&
"All transparent contexts should have a parent!");
3199void make_narg_call(
const FunctionDecl* FD,
const std::string& return_type,
3200 const unsigned N, std::ostringstream& typedefbuf,
3201 std::ostringstream& callbuf,
const std::string& class_name,
3222 bool op_flag = !FD->isOverloadedOperator() ||
3223 FD->getOverloadedOperator() == clang::OO_Call;
3225 bool ShouldCastFunction = !isa<CXXMethodDecl>(FD) &&
3226 N == FD->getNumParams() && op_flag &&
3227 !FD->isTemplateInstantiation();
3228 if (ShouldCastFunction) {
3231 callbuf << return_type <<
" (&)";
3234 for (
unsigned i = 0U; i < N; ++i) {
3241 indent(callbuf, indent_level + 1);
3244 const ParmVarDecl* PVD = FD->getParamDecl(i);
3245 QualType Ty = PVD->getType();
3246 QualType QT = Ty.getCanonicalType();
3247 std::string arg_type;
3248 ASTContext& C = FD->getASTContext();
3249 get_type_as_string(QT, arg_type, C, C.getPrintingPolicy());
3250 callbuf << arg_type;
3252 if (FD->isVariadic())
3260 if (
const auto* MD = dyn_cast<CXXMethodDecl>(FD)) {
3263 callbuf <<
"((const " << class_name <<
"*)obj)->";
3265 callbuf <<
"((" << class_name <<
"*)obj)->";
3268 callbuf << class_name <<
"::";
3269 }
else if (isa<NamedDecl>(get_non_transparent_decl_context(FD))) {
3271 if (op_flag || N <= 1)
3272 callbuf << class_name <<
"::";
3278 std::string complete_name;
3279 llvm::raw_string_ostream stream(complete_name);
3280 PrintingPolicy PP = FD->getASTContext().getPrintingPolicy();
3281 PP.FullyQualifiedName =
true;
3282 PP.SuppressUnwrittenScope =
true;
3283 PP.Suppress_Elab =
true;
3284 FD->getNameForDiagnostic(stream, PP,
3286 name = complete_name;
3293 std::string simple_name = FD->getNameAsString();
3294 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
3295 const auto* FTDecl =
3296 llvm::dyn_cast<FunctionTemplateDecl>(FD->getPrimaryTemplate());
3298 auto* templateParms = FTDecl->getTemplateParameters();
3300 for (
size_t iParam = 0, nParams = templateParms->size();
3301 iParam < nParams; ++iParam) {
3302 if (templateParms->getParam(iParam)->isTemplateParameterPack())
3312 if (FD->isOverloadedOperator())
3315 if (op_flag || N <= 1)
3318 if (ShouldCastFunction)
3322 for (
unsigned i = 0U; i < N; ++i) {
3323 const ParmVarDecl* PVD = FD->getParamDecl(i);
3324 QualType Ty = PVD->getType();
3325 QualType QT = Ty.getCanonicalType();
3326 std::string type_name;
3327 EReferenceType refType = kNotReference;
3328 bool isPointer =
false;
3329 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3330 isPointer, indent_level,
true);
3337 << clang::getOperatorSpelling(FD->getOverloadedOperator())
3342 CXXRecordDecl* rtdecl = QT->getAsCXXRecordDecl();
3343 if (refType != kNotReference) {
3344 callbuf <<
"(" << type_name.c_str()
3345 << (refType == kLValueReference ?
"&" :
"&&") <<
")*("
3346 << type_name.c_str() <<
"*)args[" << i <<
"]";
3347 }
else if (isPointer) {
3348 callbuf <<
"*(" << type_name.c_str() <<
"**)args[" << i <<
"]";
3349 }
else if (rtdecl &&
3350 (rtdecl->hasTrivialCopyConstructor() &&
3351 !rtdecl->hasSimpleCopyConstructor()) &&
3352 rtdecl->hasMoveConstructor()) {
3369 callbuf <<
"static_cast<" << type_name.c_str() <<
"&&>(*("
3370 << type_name.c_str() <<
"*)args[" << i <<
"])";
3374 callbuf <<
"*(" << type_name.c_str() <<
"*)args[" << i <<
"]";
3380void make_narg_ctor_with_return(
const FunctionDecl* FD,
const unsigned N,
3381 const std::string& class_name,
3382 std::ostringstream& buf,
int indent_level) {
3395 std::ostringstream typedefbuf;
3396 std::ostringstream callbuf;
3400 indent(callbuf, indent_level);
3401 const auto* CD = dyn_cast<CXXConstructorDecl>(FD);
3409 if (CD->isDefaultConstructor()) {
3410 callbuf <<
"if (nary > 1) {\n";
3411 indent(callbuf, indent_level);
3412 callbuf <<
"(*(" << class_name <<
"**)ret) = ";
3413 callbuf <<
"(is_arena) ? new (*(" << class_name <<
"**)ret) ";
3414 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
3417 callbuf <<
": new ";
3421 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
3427 indent(callbuf, indent_level);
3429 callbuf <<
"else {\n";
3435 indent(callbuf, indent_level);
3436 callbuf <<
"(*(" << class_name <<
"**)ret) = ";
3437 callbuf <<
"(is_arena) ? new (*(" << class_name <<
"**)ret) ";
3438 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
3440 callbuf <<
": new ";
3444 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
3449 indent(callbuf, --indent_level);
3450 if (CD->isDefaultConstructor())
3452#if __has_feature(memory_sanitizer)
3455 indent(callbuf, indent_level);
3456 callbuf <<
"__msan_unpoison(*(void**)ret, sizeof(" << class_name
3457 <<
") * (nary > 1 ? nary : 1));\n";
3463 buf << typedefbuf.str() << callbuf.str();
3468 const unsigned N,
const std::string& class_name,
3469 std::ostringstream& buf,
int indent_level) {
3479 if (
const auto* CD = dyn_cast<CXXConstructorDecl>(FD)) {
3480 if (N <= 1 && llvm::isa<UsingShadowDecl>(FD)) {
3481 auto SpecMemKind = I.
getCI()->getSema().getSpecialMember(CD);
3482 if ((N == 0 && SpecMemKind == CXXSpecialMemberKind::DefaultConstructor) ||
3483 (N == 1 && (SpecMemKind == CXXSpecialMemberKind::CopyConstructor ||
3484 SpecMemKind == CXXSpecialMemberKind::MoveConstructor))) {
3492 make_narg_ctor_with_return(FD, N, class_name, buf, indent_level);
3495 QualType QT = FD->getReturnType();
3496 if (QT->isVoidType()) {
3497 std::ostringstream typedefbuf;
3498 std::ostringstream callbuf;
3499 indent(callbuf, indent_level);
3500 make_narg_call(FD,
"void", N, typedefbuf, callbuf, class_name,
3503 indent(callbuf, indent_level);
3504 callbuf <<
"return;\n";
3505 buf << typedefbuf.str() << callbuf.str();
3507 indent(buf, indent_level);
3509 std::string type_name;
3510 EReferenceType refType = kNotReference;
3511 bool isPointer =
false;
3513 std::ostringstream typedefbuf;
3514 std::ostringstream callbuf;
3516 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3517 isPointer, indent_level,
false);
3519 buf << typedefbuf.str();
3521 buf <<
"if (ret) {\n";
3527 indent(callbuf, indent_level);
3528 callbuf <<
"new (ret) ";
3532 callbuf <<
"(" << type_name.c_str();
3533 if (refType != kNotReference) {
3536 }
else if (isPointer) {
3545 make_narg_call(FD, type_name, N, typedefbuf, callbuf, class_name,
3551#if __has_feature(memory_sanitizer)
3552 indent(callbuf, indent_level);
3553 callbuf <<
"__msan_unpoison(ret, sizeof(" << type_name <<
"));\n";
3555 indent(callbuf, indent_level);
3556 callbuf <<
"return;\n";
3560 buf << typedefbuf.str() << callbuf.str();
3563 indent(buf, indent_level);
3565 indent(buf, indent_level);
3569 std::ostringstream typedefbuf;
3570 std::ostringstream callbuf;
3571 indent(callbuf, indent_level);
3572 callbuf <<
"(void)(";
3573 make_narg_call(FD, type_name, N, typedefbuf, callbuf, class_name,
3576 indent(callbuf, indent_level);
3577 callbuf <<
"return;\n";
3578 buf << typedefbuf.str() << callbuf.str();
3581 indent(buf, indent_level);
3587 std::string& wrapper_name, std::string& wrapper) {
3588 assert(FD &&
"generate_wrapper called without a function decl!");
3589 ASTContext& Context = FD->getASTContext();
3593 std::string class_name;
3594 const clang::DeclContext* DC = get_non_transparent_decl_context(FD);
3595 GetDeclName(cast<Decl>(DC), Context, class_name);
3600 bool needInstantiation =
false;
3601 const FunctionDecl* Definition = 0;
3603 if (!FD->isDefined(Definition)) {
3604 FunctionDecl::TemplatedKind TK = FD->getTemplatedKind();
3606 case FunctionDecl::TK_NonTemplate: {
3616 case FunctionDecl::TK_FunctionTemplate: {
3619 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3621 <<
"Cannot make wrapper for a function template!";
3624 case FunctionDecl::TK_MemberSpecialization: {
3631 if (!FD->isTemplateInstantiation()) {
3644 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3646 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3648 <<
"Cannot make wrapper for a member function "
3649 "instantiation with no pattern!";
3652 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3653 TemplateSpecializationKind PTSK =
3654 Pattern->getTemplateSpecializationKind();
3657 (PTK == FunctionDecl::TK_NonTemplate) ||
3660 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3661 ((PTSK == TSK_Undeclared) ||
3662 (PTSK == TSK_ExplicitSpecialization)))) {
3667 }
else if (!Pattern->hasBody()) {
3668 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3670 <<
"Cannot make wrapper for a member function "
3671 "instantiation with no body!";
3674 if (FD->isImplicitlyInstantiable()) {
3675 needInstantiation =
true;
3678 case FunctionDecl::TK_FunctionTemplateSpecialization: {
3683 if (!FD->isTemplateInstantiation()) {
3696 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3698 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3700 <<
"Cannot make wrapper for a function template"
3701 "instantiation with no pattern!";
3704 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3705 TemplateSpecializationKind PTSK =
3706 Pattern->getTemplateSpecializationKind();
3709 (PTK == FunctionDecl::TK_NonTemplate) ||
3712 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3713 ((PTSK == TSK_Undeclared) ||
3714 (PTSK == TSK_ExplicitSpecialization)))) {
3721 if (!Pattern->hasBody()) {
3722 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3724 <<
"Cannot make wrapper for a function template "
3725 <<
"instantiation with no body!";
3728 if (FD->isImplicitlyInstantiable()) {
3729 needInstantiation =
true;
3733 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
3741 if (!FD->isTemplateInstantiation()) {
3754 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3756 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3758 <<
"Cannot make wrapper for a dependent function template"
3759 "instantiation with no pattern!";
3762 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3763 TemplateSpecializationKind PTSK =
3764 Pattern->getTemplateSpecializationKind();
3767 (PTK == FunctionDecl::TK_NonTemplate) ||
3770 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3771 ((PTSK == TSK_Undeclared) ||
3772 (PTSK == TSK_ExplicitSpecialization)))) {
3778 if (!Pattern->hasBody()) {
3779 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3781 <<
"Cannot make wrapper for a dependent function template"
3782 "instantiation with no body!";
3785 if (FD->isImplicitlyInstantiable()) {
3786 needInstantiation =
true;
3792 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3794 <<
"Unhandled template kind!";
3816 if (needInstantiation) {
3817 clang::FunctionDecl* FDmod =
const_cast<clang::FunctionDecl*
>(FD);
3820 if (!FD->isDefined(Definition)) {
3821 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3823 <<
"Failed to force template instantiation!";
3828 FunctionDecl::TemplatedKind TK = Definition->getTemplatedKind();
3830 case FunctionDecl::TK_NonTemplate: {
3832 if (Definition->isDeleted()) {
3833 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3835 <<
"Cannot make wrapper for a deleted function!";
3837 }
else if (Definition->isLateTemplateParsed()) {
3838 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3840 <<
"Cannot make wrapper for a late template parsed "
3851 case FunctionDecl::TK_FunctionTemplate: {
3854 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3856 <<
"Cannot make wrapper for a function template!";
3859 case FunctionDecl::TK_MemberSpecialization: {
3863 if (Definition->isDeleted()) {
3864 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3866 <<
"Cannot make wrapper for a deleted member function "
3867 "of a specialization!";
3869 }
else if (Definition->isLateTemplateParsed()) {
3870 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3872 <<
"Cannot make wrapper for a late template parsed "
3873 "member function of a specialization!";
3883 case FunctionDecl::TK_FunctionTemplateSpecialization: {
3888 if (Definition->isDeleted()) {
3889 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3891 <<
"Cannot make wrapper for a deleted function "
3892 "template specialization!";
3894 }
else if (Definition->isLateTemplateParsed()) {
3895 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3897 <<
"Cannot make wrapper for a late template parsed "
3898 "function template specialization!";
3908 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
3916 if (Definition->isDeleted()) {
3917 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3919 <<
"Cannot make wrapper for a deleted dependent function "
3920 "template specialization!";
3922 }
else if (Definition->isLateTemplateParsed()) {
3923 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3925 <<
"Cannot make wrapper for a late template parsed "
3926 "dependent function template specialization!";
3939 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3941 <<
"Unhandled template kind!";
3946 unsigned min_args = FD->getMinRequiredArguments();
3947 unsigned num_params = FD->getNumParams();
3952 std::ostringstream buf;
3958 buf <<
'_' << gWrapperSerial++;
3959 wrapper_name = buf.str();
3965 int indent_level = 0;
3966 std::ostringstream buf;
3967 buf <<
"#pragma clang diagnostic push\n"
3968 "#pragma clang diagnostic ignored \"-Wformat-security\"\n";
3969#if __has_feature(memory_sanitizer)
3972 buf <<
"extern \"C\" void __msan_unpoison(const volatile void*, "
3973 "unsigned long);\n";
3975 buf <<
"__attribute__((used)) "
3976 "__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
3977 "extern \"C\" void ";
3978 buf << wrapper_name;
3980 buf <<
"(void* ret, unsigned long nary, unsigned long nargs, void** args, "
3984 buf <<
"(void* obj, unsigned long nargs, void** args, void* ret)\n"
3988 if (min_args == num_params) {
3990 make_narg_call_with_return(I, FD, num_params, class_name, buf,
3995 for (
unsigned N = min_args; N <= num_params; ++N) {
3996 indent(buf, indent_level);
3997 buf <<
"if (nargs == " << N <<
") {\n";
3999 make_narg_call_with_return(I, FD, N, class_name, buf, indent_level);
4001 indent(buf, indent_level);
4007 "#pragma clang diagnostic pop";
4008 wrapper = buf.str();
4013 const FunctionDecl* FD) {
4016 auto R = WrapperStore.find(FD);
4017 if (R != WrapperStore.end())
4018 return (JitCall::GenericCall)R->second;
4020 std::string wrapper_name;
4021 std::string wrapper_code;
4023 if (get_wrapper_code(I, FD, wrapper_name, wrapper_code) == 0)
4028 std::string FuncName;
4029 llvm::raw_string_ostream FNS(FuncName);
4030 FD->getNameForDiagnostic(FNS, FD->getASTContext().getPrintingPolicy(),
4032 TI->appendToLog(
" // === Wrapper for " + FuncName +
" ===");
4034 llvm::StringRef WC(wrapper_code);
4035 while (!WC.empty()) {
4036 auto [Line, Rest] = WC.split(
'\n');
4038 TI->appendToLog((
" // " + Line).str());
4041 TI->appendToLog(
" // === End wrapper ===");
4047 bool withAccessControl =
true;
4049 if (
auto Ctor = dyn_cast<CXXConstructorDecl>(FD))
4050 withAccessControl = !Ctor->isDefaultConstructor();
4052 compile_wrapper(I, wrapper_name, wrapper_code, withAccessControl);
4054 WrapperStore.insert(std::make_pair(FD, wrapper));
4056 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4058 <<
"Failed to compile\n"
4059 <<
"==== SOURCE BEGIN ====\n"
4060 << wrapper_code <<
"\n"
4061 <<
"==== SOURCE END ====\n";
4063 LLVM_DEBUG(dbgs() <<
"Compiled '" << (wrapper ?
"" :
"un")
4064 <<
"successfully:\n"
4065 << wrapper_code <<
"'\n");
4066 return (JitCall::GenericCall)wrapper;
4070static std::string PrepareStructorWrapper(
const Decl* D,
4071 const char* wrapper_prefix,
4072 std::string& class_name) {
4073 ASTContext& Context = D->getASTContext();
4074 GetDeclName(D, Context, class_name);
4079 std::string wrapper_name;
4081 std::ostringstream buf;
4082 buf << wrapper_prefix;
4087 buf <<
'_' << gWrapperSerial++;
4088 wrapper_name = buf.str();
4091 return wrapper_name;
4126 auto I = DtorWrapperStore.find(D);
4127 if (I != DtorWrapperStore.end())
4128 return (JitCall::DestructorCall)I->second;
4133 std::string class_name;
4134 std::string wrapper_name = PrepareStructorWrapper(D,
"__dtor", class_name);
4138 int indent_level = 0;
4139 std::ostringstream buf;
4140#if CPPINTEROP_ASAN_BUILD
4150 buf <<
"extern \"C\" void __lsan_ignore_object(const void*);\n";
4152 buf <<
"__attribute__((used)) ";
4153 buf <<
"extern \"C\" void ";
4154 buf << wrapper_name;
4155 buf <<
"(void* obj, unsigned long nary, int withFree)\n";
4167 indent(buf, indent_level);
4168 buf <<
"if (withFree) {\n";
4170#if CPPINTEROP_ASAN_BUILD
4171 indent(buf, indent_level);
4172 buf <<
"__lsan_ignore_object(obj);\n";
4174 indent(buf, indent_level);
4175 buf <<
"if (!nary) {\n";
4177 indent(buf, indent_level);
4178 buf <<
"delete (" << class_name <<
"*) obj;\n";
4180 indent(buf, indent_level);
4182 indent(buf, indent_level);
4185 indent(buf, indent_level);
4186 buf <<
"delete[] (" << class_name <<
"*) obj;\n";
4188 indent(buf, indent_level);
4191 indent(buf, indent_level);
4204 indent(buf, indent_level);
4207 indent(buf, indent_level);
4208 buf <<
"typedef " << class_name <<
" Nm;\n";
4209 buf <<
"if (!nary) {\n";
4211 indent(buf, indent_level);
4212 buf <<
"((Nm*)obj)->~Nm();\n";
4214 indent(buf, indent_level);
4216 indent(buf, indent_level);
4219 indent(buf, indent_level);
4222 indent(buf, indent_level);
4223 buf <<
"(((Nm*)obj)+(--nary))->~Nm();\n";
4225 indent(buf, indent_level);
4226 buf <<
"} while (nary);\n";
4228 indent(buf, indent_level);
4231 indent(buf, indent_level);
4237 std::string wrapper(buf.str());
4242 void* F = compile_wrapper(interp, wrapper_name, wrapper,
4245 DtorWrapperStore.insert(std::make_pair(D, F));
4247 llvm::errs() <<
"make_dtor_wrapper"
4248 <<
"Failed to compile\n"
4249 <<
"==== SOURCE BEGIN ====\n"
4250 << wrapper <<
"\n ==== SOURCE END ====";
4252 LLVM_DEBUG(dbgs() <<
"Compiled '" << (F ?
"" :
"un") <<
"successfully:\n"
4253 << wrapper <<
"'\n");
4254 return (JitCall::DestructorCall)F;
4262 const auto* D = unwrap<clang::Decl>(func);
4266 auto* interp = unwrap<compat::Interpreter>(I);
4269 if (
const auto* Dtor = dyn_cast<CXXDestructorDecl>(D)) {
4270 if (
auto Wrapper = make_dtor_wrapper(*interp, Dtor->getParent()))
4272 JitCall(JitCall::kDestructorCall, Wrapper, wrap<ConstFuncRef>(Dtor)));
4277 if (
const auto* Ctor = dyn_cast<CXXConstructorDecl>(D)) {
4278 if (
auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D)))
4279 return INTEROP_RETURN(JitCall(JitCall::kConstructorCall, Wrapper,
4280 wrap<ConstFuncRef>(Ctor)));
4285 if (
auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D))) {
4287 wrap<ConstFuncRef>(cast<FunctionDecl>(D))));
4299#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
4302 using namespace llvm;
4303 using namespace llvm::orc;
4306 JITDylib& DyLib = *Jit.getProcessSymbolsJITDylib().get();
4313 llvm::orc::SymbolMap InjectedSymbols{
4314 {Jit.mangleAndIntern(unmangled_name),
4315 ExecutorSymbolDef(ExecutorAddr(address), JITSymbolFlags::Exported)}};
4317 if (Error Err = DyLib.define(absoluteSymbols(InjectedSymbols))) {
4318 logAllUnhandledErrors(std::move(Err), errs(),
4319 "DefineAbsoluteSymbol error: ");
4326static std::string MakeResourcesPath() {
4328#ifdef LLVM_BINARY_DIR
4329 Dir = LLVM_BINARY_DIR;
4336 StringRef Dir = sys::path::parent_path(BinaryPath);
4338 Dir = sys::path::parent_path(Dir);
4339 Dir = sys::path::parent_path(Dir);
4340 Dir = sys::path::parent_path(Dir);
4341 Dir = sys::path::parent_path(Dir);
4344 llvm::SmallString<128> P(Dir);
4345 llvm::sys::path::append(P, CLANG_INSTALL_LIBDIR_BASENAME,
"clang",
4346 CLANG_VERSION_MAJOR_STRING);
4347 return std::string(P.str());
4350void AddLibrarySearchPaths(
const std::string& ResourceDir,
4359 std::string path1 = ResourceDir +
"/lib";
4361 size_t pos = ResourceDir.rfind(
"/llvm-");
4362 if (pos != std::string::npos) {
4366 pos = ResourceDir.rfind(
"/clang");
4367 if (pos != std::string::npos) {
4372std::string ExtractArgument(
const std::vector<const char*>& Args,
4373 const std::string& Arg) {
4375 for (
auto i = Args.begin(); i != Args.end(); i++)
4376 if ((++I < Args.size()) && (*i == Arg))
4383 const std::vector<const char*>& GpuArgs ) {
4385 std::string MainExecutableName = sys::fs::getMainExecutable(
nullptr,
nullptr);
4392 std::string ResourceDir = ExtractArgument(Args,
"-resource-dir");
4393 if (ResourceDir.empty())
4394 ResourceDir = MakeResourcesPath();
4395 llvm::Triple T(llvm::sys::getProcessTriple());
4396 if ((!sys::fs::is_directory(ResourceDir)) &&
4397 (T.isOSDarwin() || T.isOSLinux()))
4400 std::vector<const char*> ClingArgv = {
"-resource-dir", ResourceDir.c_str(),
4402 ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str());
4405 ClingArgv.push_back(
"-fno-delayed-template-parsing");
4407#if __has_feature(memory_sanitizer)
4412 ClingArgv.push_back(
"-stdlib=libc++");
4420 std::string LibcxxIncDir;
4421 if (!ResourceDir.empty()) {
4422 SmallString<256> P(ResourceDir);
4423 sys::path::remove_filename(P);
4424 sys::path::remove_filename(P);
4425 sys::path::remove_filename(P);
4426 sys::path::append(P,
"include",
"c++",
"v1");
4427 if (sys::fs::is_directory(P)) {
4428 LibcxxIncDir = P.str().str();
4429 ClingArgv.push_back(
"-cxx-isystem");
4430 ClingArgv.push_back(LibcxxIncDir.c_str());
4434 ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
4438 if (!GpuArgs.empty()) {
4439 llvm::StringRef Arg0 = GpuArgs[0];
4440 Arg0 = Arg0.trim().ltrim(
'-');
4441 if (Arg0 !=
"cuda") {
4442 llvm::errs() <<
"[CreateInterpreter]: Make sure --cuda is passed as the"
4443 <<
" first argument of the GpuArgs\n";
4447 ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
4450 std::vector<std::string> ExtraArgs;
4451 auto EnvOpt = llvm::sys::Process::GetEnv(
"CPPINTEROP_EXTRA_INTERPRETER_ARGS");
4453 StringRef Env(*EnvOpt);
4454 while (!Env.empty()) {
4456 std::tie(Arg, Env) = Env.split(
' ');
4457 ExtraArgs.push_back(Arg.str());
4460 std::transform(ExtraArgs.begin(), ExtraArgs.end(),
4461 std::back_inserter(ClingArgv),
4462 [&](
const std::string& str) { return str.c_str(); });
4467#ifdef CPPINTEROP_USE_CLING
4472 ClingArgv.data(),
nullptr, {},
nullptr,
true);
4475 auto* I = Interp.release();
4482 const CompilerInstance* Clang = I->getCI();
4483 if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
4484 unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
4485 auto Args = std::make_unique<const char*[]>(NumArgs + 2);
4486 Args[0] =
"clang (LLVM option parsing)";
4487 for (
unsigned i = 0; i != NumArgs; ++i)
4488 Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
4489 Args[NumArgs + 1] =
nullptr;
4490 llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
4494 AddLibrarySearchPaths(ResourceDir, I);
4498 namespace __internal_CppInterOp {
4499 template <typename Signature>
4501 template <typename Res, typename... ArgTypes>
4502 struct function<Res(ArgTypes...)> {
4503 typedef Res result_type;
4505 } // namespace __internal_CppInterOp
4512#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
4513 DefineAbsoluteSymbol(*I,
"__ci_newtag",
4516#if CLANG_VERSION_MAJOR >= 21
4517 DefineAbsoluteSymbol(
4518 *I,
"__clang_Interpreter_SetValueWithAlloc",
4523 unwrap<Decl>(
Cpp::GetNamed(
"__clang_Interpreter_SetValueWithAlloc"));
4524 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
4525 auto GD = GlobalDecl(FD);
4526 std::string mangledName;
4528 DefineAbsoluteSymbol(
4529 *I, mangledName.c_str(),
4534 DefineAbsoluteSymbol(
4535 *I,
"__clang_Interpreter_SetValueNoAlloc",
4544 const auto& LO = interp->
getCI()->getLangOpts();
4552 auto standard = clang::LangStandard::getLangStandardForKind(LO.LangStd);
4553 auto lang =
static_cast<InterpreterLanguage
>(standard.getLanguage());
4554 assert(lang != InterpreterLanguage::Unknown &&
"Unknown language");
4555 assert(
static_cast<unsigned char>(lang) <=
4556 static_cast<unsigned char>(InterpreterLanguage::HLSL) &&
4557 "Unhandled Language");
4564 const auto& LO = interp->
getCI()->getLangOpts();
4565 auto langStandard =
static_cast<InterpreterLanguageStandard
>(LO.LangStd);
4566 assert(langStandard != InterpreterLanguageStandard::lang_unspecified &&
4567 "Unspecified language standard");
4568 assert(
static_cast<unsigned char>(langStandard) <=
4569 static_cast<unsigned char>(
4570 InterpreterLanguageStandard::lang_unspecified) &&
4571 "Unhandled language standard.");
4584 getInterp().getCI()->getHeaderSearchOpts().ResourceDir.c_str());
4588static bool exec(
const char* cmd, std::vector<std::string>& outputs) {
4589#define DEBUG_TYPE "exec"
4591 std::array<char, 256> buffer;
4592 struct file_deleter {
4593 void operator()(FILE* fp) { pclose(fp); }
4595 std::unique_ptr<FILE, file_deleter> pipe{popen(cmd,
"r")};
4596 LLVM_DEBUG(dbgs() <<
"Executing command '" << cmd <<
"'\n");
4599 LLVM_DEBUG(dbgs() <<
"Execute failed!\n");
4604 LLVM_DEBUG(dbgs() <<
"Execute returned:\n");
4605 while (fgets(buffer.data(),
static_cast<int>(buffer.size()), pipe.get())) {
4606 LLVM_DEBUG(dbgs() << buffer.data());
4607 llvm::StringRef trimmed = buffer.data();
4608 outputs.push_back(trimmed.trim().str());
4618 std::string cmd = std::string(ClangBinaryName) +
" -print-resource-dir";
4619 std::vector<std::string> outs;
4620 exec(cmd.c_str(), outs);
4621 if (outs.empty() || outs.size() > 1)
4624 std::string detected_resource_dir = outs.back();
4626 std::string version = CLANG_VERSION_MAJOR_STRING;
4628 if (llvm::sys::path::filename(detected_resource_dir) != version)
4635 const char* CompilerName ) {
4637 std::string cmd =
"LC_ALL=C ";
4638 cmd += CompilerName;
4639 cmd +=
" -xc++ -E -v /dev/null 2>&1 | sed -n -e '/^.include/,${' -e '/^ "
4641 std::vector<std::string> outs;
4642 exec(cmd.c_str(), Paths);
4655 llvm::SmallVector<std::string> paths(1);
4657 for (
auto& i : paths)
4658 IncludePaths.push_back(i);
4665 clangSilent(clang::DiagnosticsEngine& diag) :
fDiagEngine(diag) {
4670 ~clangSilent() {
fDiagEngine.setSuppressAllDiagnostics(fOldDiagValue); }
4682 clang::DiagnosticsEngine& Diag = I.
getSema().getDiagnostics();
4683 clang::DiagnosticErrorTrap Trap(Diag);
4685 clangSilent diagSuppr(Diag);
4686 auto result = I.
declare(code);
4687 if (Trap.hasErrorOccurred())
4691 auto result = I.
declare(code);
4692 if (Trap.hasErrorOccurred())
4715 if (
const auto* BT = QT->getAs<clang::BuiltinType>()) {
4716 switch (BT->getKind()) {
4717 case clang::BuiltinType::Bool:
4719 case clang::BuiltinType::Char_S:
4721 case clang::BuiltinType::Char_U:
4725 case clang::BuiltinType::SChar:
4727 case clang::BuiltinType::UChar:
4729 case clang::BuiltinType::Short:
4731 case clang::BuiltinType::UShort:
4733 case clang::BuiltinType::Int:
4735 case clang::BuiltinType::UInt:
4737 case clang::BuiltinType::Long:
4739 case clang::BuiltinType::ULong:
4741 case clang::BuiltinType::LongLong:
4743 case clang::BuiltinType::ULongLong:
4745 case clang::BuiltinType::Float:
4747 case clang::BuiltinType::Double:
4749 case clang::BuiltinType::LongDouble:
4753 "clang::Value asserts on builtins outside the X-macro set");
4764 if (res != 0 || !V.hasValue())
4767 clang::QualType QT = V.getType();
4768 void* qt = QT.getAsOpaquePtr();
4770#define X(TyRef, name) \
4771 case Cpp::Box::K_##name: \
4772 return INTEROP_RETURN( \
4773 Cpp::Box::Create<TyRef>(compat::convertTo<TyRef>(V), qt));
4783 llvm_unreachable(
"Box::Kind not produced by classifyByQualType");
4785 llvm_unreachable(
"classifyByQualType returned an unhandled Kind");
4791 getInterp().getDynamicLibraryManager()->lookupLibrary(lib_name));
4809 bool search_system ) {
4813 DLM->searchLibrariesForSymbol(mangled_name, search_system));
4817 const char* linker_mangled_name,
4841 using namespace llvm;
4842 using namespace llvm::orc;
4846 llvm::orc::ExecutionSession& ES = Jit.getExecutionSession();
4847 JITDylib& DyLib = *Jit.getProcessSymbolsJITDylib().get();
4849 if (Error Err = Symbol.takeError()) {
4850 logAllUnhandledErrors(std::move(Err), errs(),
4851 "[InsertOrReplaceJitSymbol] error: ");
4852#define DEBUG_TYPE "orc"
4853 LLVM_DEBUG(ES.dump(dbgs()));
4859 if (*Symbol && *Symbol == address) {
4860 errs() <<
"[InsertOrReplaceJitSymbol] warning: redefining '"
4861 << linker_mangled_name <<
"' with the same address\n";
4866 llvm::orc::SymbolMap InjectedSymbols;
4868 char GlobalPrefix = DL.getGlobalPrefix();
4869 std::string tmp(linker_mangled_name);
4870 if (GlobalPrefix !=
'\0') {
4871 tmp = std::string(1, GlobalPrefix) + tmp;
4873 auto Name = ES.intern(tmp);
4874 InjectedSymbols[Name] =
4875 ExecutorSymbolDef(ExecutorAddr(address), JITSymbolFlags::Exported);
4878 if (Symbol && address)
4880 if (
auto Err = DyLib.remove({Name})) {
4881 logAllUnhandledErrors(std::move(Err), errs(),
4882 "[InsertOrReplaceJitSymbol] error: ");
4886 if (Error Err = DyLib.define(absoluteSymbols(InjectedSymbols))) {
4887 logAllUnhandledErrors(std::move(Err), errs(),
4888 "[InsertOrReplaceJitSymbol] error: ");
4908 TemplateArgumentListInfo& TLI, Sema& S,
4909 bool instantiate_body) {
4913 if (
auto* FunctionTemplate = dyn_cast<FunctionTemplateDecl>(TemplateD)) {
4914 FunctionDecl* Specialization =
nullptr;
4915 clang::sema::TemplateDeductionInfo Info(fakeLoc);
4916 TemplateDeductionResult Result =
4917 S.DeduceTemplateArguments(FunctionTemplate, &TLI, Specialization, Info,
4919 if (Result != TemplateDeductionResult::Success) {
4923 if (instantiate_body)
4925 return Specialization;
4928 if (
auto* VarTemplate = dyn_cast<VarTemplateDecl>(TemplateD)) {
4929#if CLANG_VERSION_MAJOR < 22
4930 DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI);
4932 DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI,
4935 if (R.isInvalid()) {
4942 SourceLocation noLoc;
4943#if CLANG_VERSION_MAJOR < 22
4944 QualType TT = S.CheckTemplateIdType(TemplateName(TemplateD), noLoc, TLI);
4946 QualType TT = S.CheckTemplateIdType(
4947 ElaboratedTypeKeyword::None, TemplateName(TemplateD), noLoc, TLI,
4954 S.RequireCompleteType(fakeLoc, TT, diag::err_tentative_def_incomplete_type);
4969 ArrayRef<TemplateArgument> TemplateArgs, Sema& S,
4970 bool instantiate_body) {
4972 TemplateArgumentListInfo TLI{};
4973 for (
auto TA : TemplateArgs)
4975 S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation()));
4982 size_t template_args_size,
bool instantiate_body) {
4984 auto& C = S.getASTContext();
4986 llvm::SmallVector<TemplateArgument> TemplateArgs;
4987 TemplateArgs.reserve(template_args_size);
4988 for (
size_t i = 0; i < template_args_size; ++i) {
4989 QualType ArgTy = QualType::getFromOpaquePtr(template_args[i].m_Type);
4990 if (template_args[i].m_IntegralValue) {
4993 auto Res = llvm::APSInt(template_args[i].m_IntegralValue);
4994 Res = Res.extOrTrunc(C.getIntWidth(ArgTy));
4995 TemplateArgs.push_back(TemplateArgument(C, Res, ArgTy));
4997 TemplateArgs.push_back(ArgTy);
5001 auto* TmplD = unwrap<TemplateDecl>(tmpl);
5008 size_t template_args_size,
bool instantiate_body) {
5009 INTEROP_TRACE(tmpl, template_args, template_args_size, instantiate_body);
5011 getInterp(), tmpl, template_args, template_args_size, instantiate_body));
5015 const std::vector<TemplateArgInfo>& template_args,
5016 bool instantiate_body) {
5022 template_args.size(), instantiate_body));
5026 std::vector<TemplateArgInfo>& args) {
5028 const auto* CTSD = unwrap<ClassTemplateSpecializationDecl>(templ_instance);
5029 for (
const auto& TA : CTSD->getTemplateArgs().asArray()) {
5031 args.push_back({TA.getAsType().getAsOpaquePtr()});
5037 std::vector<TemplateArgInfo>& args) {
5039 const auto* CTSD = unwrap<ClassTemplateSpecializationDecl>(templ_instance);
5040 for (
const auto& TA : CTSD->getTemplateInstantiationArgs().asArray()) {
5041 switch (TA.getKind()) {
5043 assert(0 &&
"Not yet supported!");
5045 case TemplateArgument::Pack:
5046 for (
auto SubTA : TA.pack_elements())
5047 args.push_back({SubTA.getAsType().getAsOpaquePtr()});
5049 case TemplateArgument::Integral:
5055 case TemplateArgument::Type:
5056 args.push_back({TA.getAsType().getAsOpaquePtr()});
5068 static unsigned long long var_count = 0;
5069 std::string
id =
"__Cppyy_GetMethTmpl_" + std::to_string(var_count++);
5070 std::string instance =
"auto " +
id +
" = " + function_template +
";\n";
5074 DeclRefExpr* DRE = (DeclRefExpr*)VD->getInit()->IgnoreImpCasts();
5082 const auto* D = unwrap<clang::Decl>(DRef);
5083 clang::DeclContext* DC;
5084 clang::DeclContext::decl_iterator decl;
5088 if (
const auto* TD = dyn_cast_or_null<TagDecl>(D)) {
5089 DC = clang::TagDecl::castToDeclContext(TD);
5090 decl = DC->decls_begin();
5092 }
else if (
const auto* ND = dyn_cast_or_null<NamespaceDecl>(D)) {
5093 DC = clang::NamespaceDecl::castToDeclContext(ND);
5094 decl = DC->decls_begin();
5095 }
else if (
const auto* TUD = dyn_cast_or_null<TranslationUnitDecl>(D)) {
5096 DC = clang::TranslationUnitDecl::castToDeclContext(TUD);
5097 decl = DC->decls_begin();
5102 for (; decl != DC->decls_end(); decl++) {
5103 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(*decl)) {
5104 names.insert(ND->getNameAsString());
5110void GetEnums(ConstDeclRef DRef, std::vector<std::string>& Result) {
5113 auto* D =
const_cast<clang::Decl*
>(unwrap<clang::Decl>(DRef));
5115 if (!llvm::isa_and_nonnull<clang::DeclContext>(D))
5118 auto* DC = llvm::dyn_cast<clang::DeclContext>(D);
5120 llvm::SmallVector<clang::DeclContext*, 4> DCs;
5121 DC->collectAllContexts(DCs);
5124 for (
auto* DC : DCs) {
5125 for (
auto decl = DC->decls_begin(); decl != DC->decls_end(); decl++) {
5126 if (
auto* ND = llvm::dyn_cast_or_null<EnumDecl>(*decl)) {
5127 Result.push_back(ND->getNameAsString());
5138 QualType Qual = QualType::getFromOpaquePtr(TyRef.data);
5141 Qual = Qual.getCanonicalType();
5142 std::vector<long int> dims;
5143 if (Qual->isArrayType()) {
5144 const auto* ArrayType = dyn_cast<clang::ArrayType>(Qual.getTypePtr());
5146 if (
const auto* CAT = dyn_cast_or_null<ConstantArrayType>(ArrayType)) {
5147 llvm::APSInt Size(CAT->getSize());
5148 long int ArraySize = Size.getLimitedValue();
5149 dims.push_back(ArraySize);
5153 dims.push_back(DimensionValue::UNKNOWN_SIZE);
5155 ArrayType = ArrayType->getElementType()->getAsArrayTypeUnsafe();
5166 auto derivedType = clang::QualType::getFromOpaquePtr(derived.data);
5167 auto baseType = clang::QualType::getFromOpaquePtr(base.data);
5170 return INTEROP_RETURN(S.IsDerivedFrom(fakeLoc, derivedType, baseType));
5175 const auto* D = unwrap<clang::Decl>(func);
5176 const clang::ParmVarDecl* PI =
nullptr;
5178 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
5179 PI = FD->getParamDecl(param_index);
5181 else if (
const auto* FD =
5182 llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
5183 PI = (FD->getTemplatedDecl())->getParamDecl(param_index);
5185 if (PI->hasDefaultArg()) {
5187 llvm::raw_string_ostream OS(Result);
5188 const Expr* DefaultArgExpr =
nullptr;
5190 if (PI->hasUninstantiatedDefaultArg())
5191 DefaultArgExpr = PI->getUninstantiatedDefaultArg();
5193 DefaultArgExpr = PI->getDefaultArg();
5194 DefaultArgExpr->printPretty(OS,
nullptr, PrintingPolicy(LangOptions()));
5200 if (PI->getType()->isFloatingType()) {
5201 if (!Result.empty() && Result.back() ==
'.')
5203 auto DefaultArgValue = std::stod(Result);
5204 std::ostringstream oss;
5205 oss << DefaultArgValue;
5218 const auto* D = unwrap<clang::Decl>(method);
5219 if (
const auto* func = dyn_cast<CXXMethodDecl>(D))
5227 const auto* D = unwrap<clang::Decl>(func);
5228 const clang::ParmVarDecl* PI =
nullptr;
5230 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
5231 PI = FD->getParamDecl(param_index);
5232 else if (
const auto* FD =
5233 llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
5234 PI = (FD->getTemplatedDecl())->getParamDecl(param_index);
5242 clang::getOperatorSpelling((clang::OverloadedOperatorKind)Operator));
5247#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5248 if ((Spelling) == op) { \
5249 return INTEROP_RETURN((Operator)OO_##Name); \
5251#include "clang/Basic/OperatorKinds.def"
5257 const auto* D = unwrap<Decl>(op);
5258 if (
const auto* FD = llvm::dyn_cast<FunctionDecl>(D)) {
5259 if (FD->isOverloadedOperator()) {
5260 switch (FD->getOverloadedOperator()) {
5261#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5263 if ((Unary) && (Binary)) \
5264 return INTEROP_RETURN(kBoth); \
5266 return INTEROP_RETURN(kUnary); \
5268 return INTEROP_RETURN(kBinary); \
5270#include "clang/Basic/OperatorKinds.def"
5280 std::vector<FuncRef>& operators, OperatorArity kind) {
5282 const auto* D = unwrap<Decl>(DRef);
5284 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
5285 auto fn = [&operators, kind, op](
const RecordDecl* RD) {
5286 ASTContext& C = RD->getASTContext();
5287 DeclContextLookupResult Result =
5288 RD->lookup(C.DeclarationNames.getCXXOperatorName(
5289 (clang::OverloadedOperatorKind)op));
5290 for (
auto* i : Result) {
5292 operators.push_back(i);
5297 CXXRD->forallBases(fn);
5298 }
else if (
const auto* DC = llvm::dyn_cast_or_null<DeclContext>(D)) {
5299 ASTContext& C =
getSema().getASTContext();
5300 DeclContextLookupResult Result =
5301 DC->lookup(C.DeclarationNames.getCXXOperatorName(
5302 (clang::OverloadedOperatorKind)op));
5304 for (
auto* i : Result) {
5306 operators.push_back(i);
5320 ::operator
delete(address.data, bytes);
5326 void* arena ,
size_t count ) {
5329 FuncRef ctorAsFunc = wrap<FuncRef>(DRef.data);
5335 FuncRef ctor =
nullptr;
5344 void* is_arena = arena ?
reinterpret_cast<void*
>(1) :
nullptr;
5345 void* result = arena;
5346 JC.InvokeConstructor(&result, count, {}, is_arena);
5359 bool withFree,
size_t nary) {
5360 if (
auto wrapper = make_dtor_wrapper(interp, Class)) {
5361 (*wrapper)(This.data, nary, withFree);
5368bool Destruct(ObjectRef This, DeclRef DRef,
bool withFree ,
5371 const auto* Class = unwrap<Decl>(DRef);
5376 FILE* m_TempFile =
nullptr;
5379 bool m_OwnsFile =
true;
5385 FILE* stream =
nullptr;
5387 err = tmpfile_s(&stream);
5389 printf(
"Cannot create temporary file!\n");
5395#if !defined(CPPINTEROP_USE_CLING) && !defined(_WIN32)
5397 if (I.isOutOfProcess()) {
5403 FILE* redirected = I.getRedirectionFileForOutOfProcess(FD);
5405 m_TempFile = redirected;
5407 if (ftruncate(fileno(m_TempFile), 0) != 0)
5408 perror(
"ftruncate");
5409 if (lseek(fileno(m_TempFile), 0, SEEK_SET) == -1)
5413 m_TempFile = tmpfile();
5416 m_TempFile = tmpfile();
5421 perror(
"StreamCaptureInfo: Unable to create temp file");
5430 ::fflush(FD == STDOUT_FILENO ? stdout : stderr);
5431 if (dup2(fileno(m_TempFile), FD) < 0)
5432 perror(
"StreamCaptureInfo:");
5440 assert(m_DupFD == -1 &&
"Captured output not used?");
5442 if (m_OwnsFile && m_TempFile)
5447 assert(m_DupFD != -1 &&
"Multiple calls to GetCapturedString");
5450 if (dup2(m_DupFD, m_FD) < 0)
5451 perror(
"StreamCaptureInfo:");
5453 if (fseek(m_TempFile, 0L, SEEK_END) != 0)
5454 perror(
"StreamCaptureInfo:");
5457 long bufsize = ftell(m_TempFile);
5458 if (bufsize == -1) {
5459 perror(
"StreamCaptureInfo:");
5466 std::unique_ptr<char[]> content(
new char[bufsize + 1]);
5469 if (fseek(m_TempFile, 0L, SEEK_SET) != 0)
5470 perror(
"StreamCaptureInfo:");
5473 size_t newLen = fread(content.get(),
sizeof(
char), bufsize, m_TempFile);
5474 if (ferror(m_TempFile) != 0)
5475 fputs(
"Error reading file", stderr);
5477 content[newLen++] =
'\0';
5479 std::string result = content.get();
5482#if !defined(_WIN32) && !defined(CPPINTEROP_USE_CLING)
5484 if (I.isOutOfProcess()) {
5485 int fd = fileno(m_TempFile);
5486 if (ftruncate(fd, 0) != 0)
5487 perror(
"ftruncate");
5488 if (lseek(fd, 0, SEEK_SET) == -1)
5497 static std::stack<StreamCaptureInfo> sRedirectionStack;
5498 return sRedirectionStack;
5517 unsigned complete_line ,
5518 unsigned complete_column ) {
5525int Undo(
unsigned N) {
5528#ifdef CPPINTEROP_USE_CLING
#define CPP_BOX_BUILTIN_TYPES
#define clang_LookupResult_Found_Overloaded
#define clang_LookupResult_Not_Found
#define clang_LookupResult_Found
struct __clang_Interpreter_NewTag __ci_newtag
#define CPPINTEROP_MSAN_UNPOISON_VALUE(v)
clang::DiagnosticsEngine & fDiagEngine
void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,...)
void * __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, void *OpaqueType)
#define ACCESS(OBJECT, MEMBER)
#define ALLOW_ACCESS(CLASS, MEMBER,...)
#define INTEROP_TRACE(...)
#define INTEROP_RETURN(Val)
#define INTEROP_VOID_RETURN()
std::string writeToFile(const std::string &Version="")
Write the accumulated reproducer log to a file.
void unloadLibrary(llvm::StringRef libStem)
void addSearchPath(llvm::StringRef dir, bool isUser=true, bool prepend=false)
llvm::Expected< clang::PartialTranslationUnit & > Parse(llvm::StringRef Code)
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)
llvm::Error Execute(clang::PartialTranslationUnit &T)
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
void AddIncludePath(llvm::StringRef PathsStr)
Adds a single include path (-I).
const clang::CompilerInstance * getCI() const
void * getAddressOfGlobal(const clang::GlobalDecl &GD) const
CompilationResult
Describes the return result of the different routines that do the incremental compilation.
CompilationResult evaluate(const std::string &input, clang::Value &V)
clang::Sema & getSema() const
void GetIncludePaths(llvm::SmallVectorImpl< std::string > &incpaths, bool withSystem, bool withFlags) const
Get the current include paths that are used.
void * compileFunction(llvm::StringRef name, llvm::StringRef code, bool ifUnique, bool withAccessControl)
StreamCaptureInfo(const StreamCaptureInfo &)=delete
StreamCaptureInfo & operator=(const StreamCaptureInfo &)=delete
StreamCaptureInfo & operator=(StreamCaptureInfo &&)=delete
std::string GetCapturedString()
StreamCaptureInfo(int FD)
StreamCaptureInfo(StreamCaptureInfo &&)=delete
void InitTracing()
Activate tracing.
TraceInfo * TheTraceInfo
Process-global tracer pointer.
void Named(clang::Sema *S, clang::LookupResult &R, const clang::DeclContext *Within=nullptr)
std::string GetExecutablePath()
static constexpr int kVTableOverlayPrefixSize
bool IsPODType(ConstTypeRef TyRef)
void BeginStdStreamCapture(CaptureStreamKind fd_kind)
bool IsSameType(ConstTypeRef type_a, ConstTypeRef type_b)
DeclRef GetUnderlyingScope(ConstDeclRef DRef)
bool DeleteInterpreter(InterpRef I)
void GetEnums(ConstDeclRef DRef, std::vector< std::string > &Result)
TypeRef GetCanonicalType(ConstTypeRef TyRef)
static bool isSmartPointer(const RecordType *RT)
bool IsComplete(ConstDeclRef DRef)
void UseExternalInterpreter(InterpRef I)
InterpreterLanguageStandard GetLanguageStandard(InterpRef I)
std::vector< FuncRef > GetFunctionsUsingName(ConstDeclRef DRef, const std::string &name)
void CppInterOpTraceJitCallInvokeImpl(const JitCall *JC, void *result, void **args, std::size_t nargs, void *self)
std::string GetTypeAsString(ConstTypeRef var)
bool IsProtectedMethod(ConstFuncRef method)
DeclRef GetScope(const std::string &name, ConstDeclRef parent)
TypeRef RemoveTypeQualifier(ConstTypeRef TyRef, QualKind qual)
static Decl * GetScopeFromType(QualType QT)
int64_t GetBaseClassOffset(ConstDeclRef derived, ConstDeclRef base)
void GetAllCppNames(ConstDeclRef DRef, std::set< std::string > &names)
bool IsRecordType(ConstTypeRef TyRef)
static VTableOverlay * applyVTableOverlay(void *inst, int total_method_slots, const int *slots, void *const *fns, std::size_t n, std::size_t n_extra_prefix_slots)
bool CheckVariableAccess(ConstDeclRef var, AccessSpecifier AS)
ValueKind GetValueKind(ConstTypeRef TyRef)
std::string GetFunctionArgDefault(ConstFuncRef func, size_t param_index)
std::string ObjToString(const char *TyRef, void *obj)
Operator GetOperatorFromSpelling(const std::string &op)
TypeRef GetTypeFromScope(ConstDeclRef DRef)
std::vector< DeclRef > GetEnumConstants(ConstDeclRef DRef)
bool IsVoidPointerType(ConstTypeRef TyRef)
FuncRef GetDestructor(ConstDeclRef DRef)
bool IsDestructor(ConstFuncRef method)
std::string GetSpellingFromOperator(Operator Operator)
TypeRef GetIntegerTypeFromEnumType(ConstTypeRef enum_type)
bool IsEnumType(ConstTypeRef TyRef)
FuncRef InstantiateTemplateFunctionFromString(const char *function_template)
bool IsLambdaClass(ConstTypeRef TyRef)
void DetectSystemCompilerIncludePaths(std::vector< std::string > &Paths, const char *CompilerName)
DeclRef GetParentScope(ConstDeclRef DRef)
bool HasTypeQualifier(ConstTypeRef TyRef, QualKind qual)
std::vector< DeclRef > GetUsingNamespaces(ConstDeclRef DRef)
TypeRef GetPointeeType(ConstTypeRef TyRef)
InterpRef CreateInterpreter(const std::vector< const char * > &Args, const std::vector< const char * > &GpuArgs)
void CodeComplete(std::vector< std::string > &Results, const char *code, unsigned complete_line, unsigned complete_column)
size_t GetFunctionRequiredArgs(ConstFuncRef func)
DeclRef GetScopeFromCompleteName(const std::string &name)
std::string GetQualifiedName(ConstDeclRef DRef)
bool IsPrivateVariable(ConstDeclRef var)
ObjectRef Construct(compat::Interpreter &interp, DeclRef DRef, void *arena, size_t count)
bool IsTemplateSpecialization(ConstDeclRef DRef)
bool ActivateInterpreter(InterpRef I)
bool IsEnumConstant(ConstDeclRef DRef)
bool InsertOrReplaceJitSymbol(compat::Interpreter &I, const char *linker_mangled_name, uint64_t address)
bool Destruct(compat::Interpreter &interp, ObjectRef This, const Decl *Class, bool withFree, size_t nary)
OperatorArity GetOperatorArity(ConstFuncRef op)
bool IsVariable(ConstDeclRef DRef)
bool HasDefaultConstructor(ConstDeclRef DRef)
size_t GetSizeOfType(ConstTypeRef TyRef)
bool IsConstructor(ConstFuncRef method)
std::string Demangle(const std::string &mangled_name)
TypeRef GetFunctionReturnType(ConstFuncRef func)
void GetIncludePaths(std::vector< std::string > &IncludePaths, bool withSystem, bool withFlags)
size_t SizeOf(ConstDeclRef DRef)
static Decl * InstantiateTemplate(TemplateDecl *TemplateD, TemplateArgumentListInfo &TLI, Sema &S, bool instantiate_body)
bool ExistsFunctionTemplate(const std::string &name, ConstDeclRef parent)
constexpr int kMinVTableMethodSlots
void EnableDebugOutput(bool value)
std::string EndStdStreamCapture()
static void RegisterInterpreter(compat::Interpreter *I, bool Owned)
bool GetClassTemplatedMethods(const std::string &name, ConstDeclRef parent, std::vector< FuncRef > &funcs)
static QualType findBuiltinType(llvm::StringRef typeName, ASTContext &Context)
Box Evaluate(const char *code)
void AddIncludePath(const char *dir)
static void GetClassDecls(ConstDeclRef DRef, std::vector< HandleType > &methods)
bool IsVirtualMethod(ConstFuncRef method)
constexpr int kABIPrefixSize
std::string DetectResourceDir(const char *ClangBinaryName)
static void RegisterPerms(llvm::StringMap< QualType > &Map, QualType QT, llvm::SmallVectorImpl< llvm::StringRef > &Words)
bool IsStaticVariable(ConstDeclRef var)
std::string GetFunctionSignature(ConstFuncRef func)
const char * GetResourceDir()
bool IsPublicVariable(ConstDeclRef var)
TypeRef AddTypeQualifier(ConstTypeRef TyRef, QualKind qual)
void * GetFunctionAddress(const char *mangled_name)
DeclRef GetNamed(const std::string &name, ConstDeclRef parent)
static InterpreterInfo & getInterpInfo(compat::Interpreter *I=nullptr)
std::string GetName(ConstDeclRef DRef)
void DestroyVTableOverlay(VTableOverlay *overlay)
static void DefaultProcessCrashHandler(void *)
constexpr int kDeletingDtorSlot
void GetClassTemplateArgs(ConstDeclRef templ_instance, std::vector< TemplateArgInfo > &args)
std::string GetCompleteName(ConstDeclRef DRef)
TypeRef GetVariableType(ConstDeclRef var)
std::string GetDoxygenComment(ConstDeclRef DRef, bool strip_comment_markers)
bool IsReferenceType(ConstTypeRef TyRef)
static void ForceCodeGen(Decl *D, compat::Interpreter &I)
static std::deque< InterpreterInfo > & GetInterpreters(bool SetCrashHandler=true)
TypeRef GetEnumConstantType(ConstDeclRef DRef)
DeclRef GetBaseClass(ConstDeclRef DRef, size_t ibase)
static void InstantiateFunctionDefinition(Decl *D)
bool IsFunction(ConstDeclRef DRef)
bool IsConstMethod(ConstFuncRef method)
TypeRef GetNonReferenceType(ConstTypeRef TyRef)
DeclRef LookupDatamember(const std::string &name, ConstDeclRef parent)
static bool exec(const char *cmd, std::vector< std::string > &outputs)
std::string GetFunctionArgName(ConstFuncRef func, size_t param_index)
int Declare(compat::Interpreter &I, const char *code, bool silent)
void UnloadLibrary(const char *lib_stem)
bool IsStaticMethod(ConstFuncRef method)
void Deallocate(DeclRef DRef, ObjectRef address, size_t count)
bool IsNamespace(ConstDeclRef DRef)
InterpreterLanguage GetLanguage(InterpRef I)
bool IsTemplatedFunction(ConstFuncRef func)
bool IsClassPolymorphic(ConstDeclRef DRef)
void GetClassTemplateInstantiationArgs(ConstDeclRef templ_instance, std::vector< TemplateArgInfo > &args)
static const clang::Decl * GetUnderlyingScopeImpl(const clang::Decl *D)
static std::optional< QualType > GetTypeInternal(const Decl *D)
bool CheckMethodAccess(ConstFuncRef method, AccessSpecifier AS)
void GetClassMethods(ConstDeclRef DRef, std::vector< FuncRef > &methods)
bool IsFunctionDeleted(ConstFuncRef function)
static clang::Sema & getSema()
bool IsTemplate(ConstDeclRef DRef)
void DumpScope(ConstDeclRef DRef)
TypeRef GetComplexType(ConstTypeRef TyRef)
void CppInterOpTraceJitCallInvokeReturnImpl(const JitCall *JC, void *result)
bool IsPrivateMethod(ConstFuncRef method)
std::string GetBuildInfo()
static int virtualMethodSlot(ConstFuncRef method)
static bool hasComplexVTableLayout(const CXXRecordDecl *RD)
TypeRef GetIntegerTypeFromEnumScope(ConstDeclRef DRef)
static Cpp::Box::Kind classifyByQualType(clang::QualType QT)
static clang::ASTContext & getASTContext()
bool IsEnumScope(ConstDeclRef DRef)
TypeRef GetType(const std::string &name, ConstDeclRef parent)
bool IsTemplateParmType(ConstTypeRef TyRef)
JitCall MakeFunctionCallable(InterpRef I, ConstFuncRef func)
bool IsMethod(ConstFuncRef method)
static SourceLocation GetValidSLoc(Sema &semaRef)
int Process(const char *code)
bool IsTypeDerivedFrom(ConstTypeRef derived, ConstTypeRef base)
void GetDatamembers(DeclRef DRef, std::vector< DeclRef > &datamembers)
void GetFnTypeSignature(ConstTypeRef fn_type, std::vector< TypeRef > &sig)
bool IsAggregate(ConstDeclRef DRef)
ObjectRef Allocate(DeclRef DRef, size_t count)
bool IsFunctionPointerType(ConstTypeRef TyRef)
TypeRef GetFunctionArgType(ConstFuncRef func, size_t iarg)
intptr_t GetVariableOffset(compat::Interpreter &I, Decl *D, CXXRecordDecl *BaseCXXRD)
TypeRef GetUnderlyingType(ConstTypeRef TyRef)
static int vtableMethodSlotCount(ConstDeclRef DRef)
bool IsSmartPtrType(ConstTypeRef TyRef)
std::string GetQualifiedCompleteName(ConstDeclRef DRef)
void AddSearchPath(const char *dir, bool isUser, bool prepend)
TypeRef GetPointerType(ConstTypeRef TyRef)
size_t GetFunctionNumArgs(ConstFuncRef func)
static void PopulateBuiltinMap(ASTContext &Context)
bool IsDebugOutputEnabled()
bool IsFloatingType(ConstTypeRef TyRef)
TypeRef GetReferencedType(ConstTypeRef TyRef, bool rvalue)
bool IsBuiltin(ConstTypeRef TyRef)
size_t GetNumBases(ConstDeclRef DRef)
static std::string GetCompleteNameImpl(ConstDeclRef DRef, bool qualified)
bool IsClass(ConstDeclRef DRef)
std::vector< long int > GetDimensions(ConstTypeRef TyRef)
bool IsPublicMethod(ConstFuncRef method)
void LookupConstructors(const std::string &name, ConstDeclRef parent, std::vector< FuncRef > &funcs)
FuncRef GetDefaultConstructor(compat::Interpreter &interp, DeclRef DRef)
bool IsIntegerType(ConstTypeRef TyRef, Signedness *s)
bool IsAbstract(ConstDeclRef DRef)
void cppinteropVTableOverlayDtorWrapper(void *self)
void CppInterOpTraceJitCallInvokeDestructorImpl(const JitCall *JC, void *object, unsigned long nary, int withFree)
void GetStaticDatamembers(ConstDeclRef DRef, std::vector< DeclRef > &datamembers)
bool IsPointerType(ConstTypeRef TyRef)
std::string SearchLibrariesForSymbol(const char *mangled_name, bool search_system)
FuncRef BestOverloadFunctionMatch(const std::vector< FuncRef > &candidates, const std::vector< TemplateArgInfo > &explicit_types, const std::vector< TemplateArgInfo > &arg_types)
void GetOperator(ConstDeclRef DRef, Operator op, std::vector< FuncRef > &operators, OperatorArity kind)
bool LoadLibrary(const char *lib_stem, bool lookup)
bool IsSubclass(ConstDeclRef derived, ConstDeclRef base)
void GetEnumConstantDatamembers(ConstDeclRef DRef, std::vector< DeclRef > &datamembers, bool include_enum_class)
static bool SkipShutDown
Set by UseExternalInterpreter to suppress llvm_shutdown at process exit – the client owns LLVM in tha...
VTableOverlay * MakeVTableOverlay(void *inst, ConstDeclRef base, const ConstFuncRef *methods, void *const *overlay_fns, std::size_t n_overlays, std::size_t n_extra_prefix_slots, VTableOverlayDtorHook on_destroy, void *cleanup_data)
static unsigned ComputeBaseOffset(const ASTContext &Context, const CXXRecordDecl *DerivedRD, const CXXBasePath &Path)
InterpRef GetInterpreter()
static std::stack< StreamCaptureInfo > & GetRedirectionStack()
bool IsExplicit(ConstFuncRef method)
size_t GetEnumConstantValue(ConstDeclRef DRef)
static compat::Interpreter & getInterp(InterpRef I=nullptr)
std::string LookupLibrary(const char *lib_name)
bool IsProtectedVariable(ConstDeclRef var)
bool IsConstVariable(ConstDeclRef var)
void GetFunctionTemplatedDecls(ConstDeclRef DRef, std::vector< FuncRef > &methods)
bool IsFunctionProtoType(ConstTypeRef TyRef)
bool IsTypedefed(ConstDeclRef DRef)
void InstantiateClassTemplateSpecialization(Interpreter &interp, clang::ClassTemplateSpecializationDecl *CTSD)
void maybeMangleDeclName(const clang::GlobalDecl &GD, std::string &mangledName)
CppInternal::Interpreter Interpreter
void codeComplete(std::vector< std::string > &Results, clang::Interpreter &I, const char *code, unsigned complete_line=1U, unsigned complete_column=1U)
llvm::orc::LLJIT * getExecutionEngine(clang::Interpreter &I)
Cpp::Box MakeValueBox(const Value &V, void *qt) noexcept
Wrap a compat::Value into a refcount-shared K_PtrOrObj Cpp::Box.
llvm::Expected< llvm::JITTargetAddress > getSymbolAddress(clang::Interpreter &I, llvm::StringRef IRName)
llvm::StringMap< QualType > BuiltinMap
std::map< const Decl *, void * > DtorWrapperStore
InterpreterInfo(const InterpreterInfo &)=delete
InterpreterInfo(compat::Interpreter *I, bool Owned)
compat::Interpreter * Interpreter
InterpreterInfo & operator=(const InterpreterInfo &)=delete
InterpreterInfo & operator=(InterpreterInfo &&other) noexcept
InterpreterInfo(InterpreterInfo &&other) noexcept
std::map< const FunctionDecl *, void * > WrapperStore
RAII guard whose dtor calls llvm_shutdown for the owned-interpreter case.
VTableOverlay & operator=(const VTableOverlay &)=delete
static void ** ReadVPtr(void *inst)
VTableOverlay ** hidden_slot() const
VTableOverlayDtorHook cleanup
static void WriteVPtr(void *inst, void **new_vptr)
void(* orig_dtor)(void *)
std::size_t n_extra_prefix_slots
VTableOverlay(void **block, void **orig_vptr, void *inst, std::size_t n_extra)
static To BitCastFn(From f) noexcept
void ** address_point() const
VTableOverlay(const VTableOverlay &)=delete
Holds information for instantiating a template.