25#if defined(__has_feature)
26#if __has_feature(memory_sanitizer) && LLVM_VERSION_MAJOR <= 22
27#include <sanitizer/msan_interface.h>
28#define CPPINTEROP_MSAN_UNPOISON_VALUE(v) __msan_unpoison(&(v), sizeof(v))
30#define CPPINTEROP_MSAN_UNPOISON_VALUE(v) ((void)0)
33#define CPPINTEROP_MSAN_UNPOISON_VALUE(v) ((void)0)
36#include "clang/AST/Attrs.inc"
37#include "clang/AST/CXXInheritance.h"
38#include "clang/AST/Comment.h"
39#include "clang/AST/Decl.h"
40#include "clang/AST/DeclAccessPair.h"
41#include "clang/AST/DeclBase.h"
42#include "clang/AST/DeclCXX.h"
43#include "clang/AST/DeclTemplate.h"
44#include "clang/AST/DeclarationName.h"
45#include "clang/AST/Expr.h"
46#include "clang/AST/ExprCXX.h"
47#include "clang/AST/GlobalDecl.h"
48#include "clang/AST/Mangle.h"
49#include "clang/AST/NestedNameSpecifier.h"
50#include "clang/AST/QualTypeNames.h"
51#include "clang/AST/RawCommentList.h"
52#include "clang/AST/RecordLayout.h"
53#include "clang/AST/Stmt.h"
54#include "clang/AST/Type.h"
55#include "clang/AST/VTableBuilder.h"
56#include "clang/Basic/CharInfo.h"
57#include "clang/Basic/Diagnostic.h"
58#include "clang/Basic/DiagnosticSema.h"
59#include "clang/Basic/LangStandard.h"
60#include "clang/Basic/Linkage.h"
61#include "clang/Basic/OperatorKinds.h"
62#include "clang/Basic/SourceLocation.h"
63#include "clang/Basic/SourceManager.h"
64#include "clang/Basic/Specifiers.h"
65#include "clang/Basic/Version.h"
66#include "clang/Frontend/CompilerInstance.h"
67#include "clang/Interpreter/Interpreter.h"
68#include "clang/Sema/Lookup.h"
69#include "clang/Sema/Overload.h"
70#include "clang/Sema/Ownership.h"
71#include "clang/Sema/Redeclaration.h"
72#include "clang/Sema/Sema.h"
73#include "clang/Sema/TemplateDeduction.h"
75#include "llvm/ADT/SmallString.h"
76#include "llvm/ADT/SmallVector.h"
77#include "llvm/ADT/StringRef.h"
78#include "llvm/Demangle/Demangle.h"
79#include "llvm/ExecutionEngine/JITSymbol.h"
80#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
81#include "llvm/ExecutionEngine/Orc/Core.h"
82#include "llvm/ExecutionEngine/Orc/CoreContainers.h"
83#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
84#include "llvm/IR/GlobalValue.h"
85#include "llvm/Support/Casting.h"
86#include "llvm/Support/CommandLine.h"
87#include "llvm/Support/Debug.h"
88#include "llvm/Support/Error.h"
89#include "llvm/Support/FileSystem.h"
90#include "llvm/Support/ManagedStatic.h"
91#include "llvm/Support/Path.h"
92#include "llvm/Support/Process.h"
93#include "llvm/Support/Signals.h"
94#include "llvm/Support/TargetSelect.h"
95#include "llvm/Support/raw_ostream.h"
96#include "llvm/TargetParser/Host.h"
97#include "llvm/TargetParser/Triple.h"
116#include <sys/types.h>
125#define STDOUT_FILENO 1
126#define STDERR_FILENO 2
129#define popen(x, y) (_popen(x, y))
130#define pclose (_pclose)
140#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
143#if CLANG_VERSION_MAJOR > 21
152 void* OpaqueType, ...);
159#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && \
160 (defined(__SANITIZE_ADDRESS__) || \
161 (defined(__has_feature) && __has_feature(address_sanitizer)))
162#define CPPINTEROP_ASAN_BUILD 1
167using namespace clang;
188#if LLVM_VERSION_MAJOR > 22
189 llvm::llvm_shutdown();
196static std::deque<InterpreterInfo>&
198 static llvm::ManagedStatic<std::deque<InterpreterInfo>> sInterpreters;
199 static std::once_flag ProcessInitialized;
200 std::call_once(ProcessInitialized, [SetCrashHandler]() {
202 llvm::sys::PrintStackTraceOnErrorSignal(
"CppInterOp");
204 if (getenv(
"CPPINTEROP_LOG") !=
nullptr)
208 llvm::InitializeAllTargetInfos();
209 llvm::InitializeAllTargets();
210 llvm::InitializeAllTargetMCs();
211 llvm::InitializeAllAsmParsers();
212 llvm::InitializeAllAsmPrinters();
216 if (SetCrashHandler) {
217 llvm::sys::SetOneShotPipeSignalFunction(
218 llvm::sys::DefaultOneShotPipeSignalHandler);
221 llvm::install_out_of_memory_new_handler();
229 return *sInterpreters;
237 llvm::errs() <<
"\n**************************************************\n";
238 llvm::errs() <<
" CppInterOp CRASH DETECTED\n";
242 llvm::errs() <<
" Reproducer saved to: " << Path <<
"\n";
244 llvm::errs() <<
" Failed to write reproducer file.\n";
246 llvm::errs() <<
" Re-run with CPPINTEROP_LOG=1 for a crash reproducer\n";
249 if (!Interps.empty()) {
250 llvm::errs() <<
" Active Interpreters:\n";
251 for (
const auto& Info : Interps) {
252 if (Info.Interpreter)
253 llvm::errs() <<
" - " << Info.Interpreter <<
"\n";
257 llvm::errs() <<
"**************************************************\n";
258 llvm::errs().flush();
261 llvm::sys::PrintStackTrace(llvm::errs());
263 llvm::errs() <<
"**************************************************\n";
264 llvm::errs().flush();
268 llvm::sys::Process::Exit(1,
false);
273 Interps.emplace_back(I, Owned);
279 assert(!Interps.empty() &&
280 "Interpreter instance must be set before calling this!");
282 for (
auto& Info : Interps)
283 if (Info.Interpreter == I)
286 return Interps.back();
291 return *unwrap<compat::Interpreter>(I);
296 return &
getInterpInfo(I ? unwrap<compat::Interpreter>(I) :
nullptr);
309 assert(
GetInterpreters(
false).empty() &&
"sInterpreter already in use!");
321 auto* Interp = unwrap<compat::Interpreter>(I);
323 std::find_if(Interps.begin(), Interps.end(), [Interp](
const auto& Info) {
324 return Info.Interpreter == Interp;
326 if (found == Interps.end())
329 if (std::next(found) != Interps.end())
330 std::rotate(found, found + 1, Interps.end());
346 auto* Interp = unwrap<compat::Interpreter>(I);
348 std::find_if(Interps.begin(), Interps.end(), [Interp](
const auto& Info) {
349 return Info.Interpreter == Interp;
351 if (found == Interps.end())
354 Interps.erase(found);
366 ASTContext& C = I.
getSema().getASTContext();
368 D->addAttr(UsedAttr::CreateImplicit(C));
369#ifdef CPPINTEROP_USE_CLING
370 cling::Interpreter::PushTransactionRAII RAII(&I);
371 I.
getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D));
373 I.
getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D));
375 auto GeneratedPTU = I.
Parse(
"");
377 llvm::logAllUnhandledErrors(GeneratedPTU.takeError(), llvm::errs(),
378 "[ForceCodeGen] Failed to generate PTU:");
382 for (
auto& GV : GeneratedPTU->TheModule->globals()) {
383 llvm::GlobalValue::LinkageTypes LT = GV.getLinkage();
384 if (GV.isDeclaration() || !GV.hasName() ||
385 GV.getName().starts_with(
".str") ||
386 !llvm::GlobalVariable::isDiscardableIfUnused(LT) ||
387 LT != llvm::GlobalValue::InternalLinkage)
389 GV.setLinkage(llvm::GlobalValue::WeakAnyLinkage);
391 if (
auto Err = I.
Execute(*GeneratedPTU))
392 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
393 "[ForceCodeGen] Failed to execute PTU:");
397#define DEBUG_TYPE "jitcall"
398bool JitCall::AreArgumentsValid(
void* result, ArgList args,
void* self,
402 assert(result &&
"Must pass the location of the created object!");
403 Valid &= (bool)result;
406 assert(0 &&
"Must pass at least the minimal number of args!");
409 if (args.m_ArgSize) {
410 assert(args.m_Args !=
nullptr &&
"Must pass an argument list!");
411 Valid &= (bool)args.m_Args;
415 assert(self &&
"Must pass the pointer to object");
418 const auto* FD = cast<FunctionDecl>(unwrap<Decl>(m_FD));
419 if (!FD->getReturnType()->isVoidType() && !result) {
420 assert(0 &&
"We are discarding the return TyRef of the function!");
424 assert(0 &&
"Number of objects to construct should be atleast 1");
428 const auto* CD = cast<CXXConstructorDecl>(unwrap<Decl>(m_FD));
429 if (CD->getMinRequiredArguments() != 0 && nary > 1) {
431 "Cannot pass initialization parameters to array new construction");
435 assert(m_Kind != kDestructorCall &&
"Wrong overload!");
436 Valid &= m_Kind != kDestructorCall;
443 void** args, std::size_t nargs,
449 llvm::raw_string_ostream OS(Name);
450 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
451 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
453 LLVM_DEBUG(dbgs() <<
"Run '" << Name <<
"', compiled at: "
454 << (
void*)JC->m_GenericCall <<
" with result at: " << result
455 <<
" , args at: " << args <<
" , arg count: " << nargs
456 <<
" , self at: " << self <<
"\n";);
457 std::string SelfPart = self ? TI->lookupHandle(self) :
"";
458 TI->appendToLog(llvm::formatv(
" // JitCall::Invoke {0}(nargs={1}, self={2})",
460 SelfPart.empty() ?
"nullptr" : SelfPart));
470 llvm::raw_string_ostream OS(Name);
471 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
472 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
474 LLVM_DEBUG(dbgs() <<
"Finish '" << Name
475 <<
"', compiled at: " << (
void*)JC->m_DestructorCall);
476 std::string ObjPart =
object ? TI->lookupHandle(
object) :
"nullptr";
478 llvm::formatv(
" // JitCall::InvokeDestructor {0}(object={1}, nary={2}, "
480 Name, ObjPart, nary, withFree));
491 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
492 bool RegisterPtr = isa<CXXConstructorDecl>(FD);
494 QualType RT = FD->getReturnType();
495 RegisterPtr = RT->isPointerType() || RT->isReferenceType();
499 if (
void* p = *
static_cast<void* const*
>(result))
500 TI->getOrRegisterHandle(p);
507 const char*
const VERSION = CPPINTEROP_VERSION;
508 std::string fullVersion =
"CppInterOp version";
509 fullVersion += VERSION;
510 fullVersion +=
"\n (based on "
511#ifdef CPPINTEROP_USE_CLING
516 return INTEROP_RETURN(fullVersion +
"[" + clang::getClangFullVersion() +
528#include "CppInterOp/BuildInfo.inc"
533std::string
Demangle(
const std::string& mangled_name) {
539 char* Raw = microsoftDemangle(mangled_name,
nullptr,
nullptr);
541 char* Raw = llvm::itaniumDemangle(mangled_name);
543 std::string demangle = Raw ? Raw :
"";
550 llvm::DebugFlag = value;
561 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
562 getSema().InstantiateFunctionDefinition(SourceLocation(), FD,
566 clang::DiagnosticsEngine& Diags =
getSema().getDiagnostics();
567 if (!FD->isDefined() && Diags.hasErrorOccurred()) {
570 Diags.getClient()->clear();
577 const auto* D = unwrap<Decl>(DRef);
580 if (
const auto* ValD = dyn_cast<ValueDecl>(D))
581 if (ValD->getType()->isArrayType())
585 if (
const auto* CXXRD = dyn_cast<CXXRecordDecl>(D))
593 const auto* D = unwrap<Decl>(DRef);
599 const auto* D = unwrap<Decl>(DRef);
605 const auto* D = unwrap<Decl>(DRef);
611 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
617 const auto* D = unwrap<Decl>(DRef);
618 if (
const auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(D))
619 if (
const auto* CXXRDD = CXXRD->getDefinition())
625 auto& SM = semaRef.getSourceManager();
626 return SM.getLocForStartOfFile(SM.getMainFileID());
635 const auto* D = unwrap<Decl>(DRef);
637 if (isa<ClassTemplateSpecializationDecl>(D)) {
645 if (
const auto* CXXRD = dyn_cast<CXXRecordDecl>(D))
647 else if (
const auto* TD = dyn_cast<TagDecl>(D))
660 if (
const auto* RD = dyn_cast<RecordDecl>(unwrap<Decl>(DRef))) {
661 ASTContext& Context = RD->getASTContext();
662 const ASTRecordLayout& Layout = Context.getASTRecordLayout(RD);
671 QualType Ty = QualType::getFromOpaquePtr(TyRef.data);
672 if (Ty->isBuiltinType() || Ty->isAnyComplexType())
675 if (
const auto* RD = Ty->getAsCXXRecordDecl()) {
676 if (
const auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
677 IdentifierInfo* II = CTSD->getSpecializedTemplate()->getIdentifier();
678 if (II && II->isStr(
"complex") &&
679 CTSD->getDeclContext()->isStdNamespace())
688 const auto* D = unwrap<clang::Decl>(DRef);
689 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::TemplateDecl>(D));
694 const auto* D = unwrap<clang::Decl>(DRef);
696 llvm::isa_and_nonnull<clang::ClassTemplateSpecializationDecl>(D));
701 const auto* D = unwrap<clang::Decl>(DRef);
702 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::TypedefNameDecl>(D));
707 const auto* D = unwrap<clang::Decl>(DRef);
708 if (
const auto* CXXRD = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(D))
716 const auto* D = unwrap<clang::Decl>(DRef);
722 const auto* D = unwrap<clang::Decl>(DRef);
723 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::EnumConstantDecl>(D));
728 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
733 auto IsUseCountPresent = [](
const RecordDecl* Record) {
734 ASTContext& C = Record->getASTContext();
735 return !Record->lookup(&C.Idents.get(
"use_count")).empty();
737 auto IsOverloadedOperatorPresent = [](
const RecordDecl* Record,
738 OverloadedOperatorKind Op) {
739 ASTContext& C = Record->getASTContext();
740 DeclContextLookupResult Result =
741 Record->lookup(C.DeclarationNames.getCXXOperatorName(Op));
742 return !Result.empty();
745 const RecordDecl* Record = RT->getDecl();
746 if (IsUseCountPresent(Record))
749 bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
750 bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
751 if (foundStarOperator && foundArrowOperator)
754 const auto* CXXRecord = dyn_cast<CXXRecordDecl>(Record);
758 auto FindOverloadedOperators = [&](
const CXXRecordDecl* Base) {
760 if (IsUseCountPresent(Base))
762 if (!foundStarOperator)
763 foundStarOperator = IsOverloadedOperatorPresent(Base, OO_Star);
764 if (!foundArrowOperator)
765 foundArrowOperator = IsOverloadedOperatorPresent(Base, OO_Arrow);
766 if (foundStarOperator && foundArrowOperator)
771 return !CXXRecord->forallBases(FindOverloadedOperators);
776 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
777 if (
const RecordType* RT = QT->getAs<RecordType>()) {
780 llvm::StringRef tsRef(typeString);
781 if (tsRef.starts_with(
"std::unique_ptr") ||
782 tsRef.starts_with(
"std::shared_ptr") ||
783 tsRef.starts_with(
"std::weak_ptr"))
792 const auto* D = unwrap<clang::Decl>(DRef);
793 if (
const auto* ED = llvm::dyn_cast_or_null<clang::EnumDecl>(D)) {
805 QualType QT = QualType::getFromOpaquePtr(enum_type.data);
806 if (
const auto* ET = QT->getAs<EnumType>())
807 return INTEROP_RETURN(ET->getDecl()->getIntegerType().getAsOpaquePtr());
814 const auto* D = unwrap<clang::Decl>(DRef);
816 if (
const auto* ED = llvm::dyn_cast_or_null<clang::EnumDecl>(D)) {
817 std::vector<DeclRef> enum_constants;
818 for (
auto* ECD : ED->enumerators()) {
819 enum_constants.push_back(ECD);
833 const auto* D = unwrap<clang::Decl>(DRef);
834 if (
const auto* ECD = llvm::dyn_cast<clang::EnumConstantDecl>(D))
842 const auto* D = unwrap<clang::Decl>(DRef);
843 if (
const auto* ECD = llvm::dyn_cast_or_null<clang::EnumConstantDecl>(D)) {
844 const llvm::APSInt& Val = ECD->getInitVal();
852 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
853 if (
const TagType* TT = QT->getAs<TagType>())
857 auto TI =
getSema().getASTContext().getTypeInfo(QT);
858 size_t TypeSize = TI.Width;
864 const auto* D = unwrap<clang::Decl>(DRef);
870 const auto* D = unwrap<clang::NamedDecl>(DRef);
872 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
876 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
884 auto& C =
getSema().getASTContext();
885 const auto* D = unwrap<Decl>(DRef);
887 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
888 PrintingPolicy Policy = C.getPrintingPolicy();
889 Policy.SuppressUnwrittenScope =
true;
891 Policy.FullyQualifiedName =
true;
892 Policy.Suppress_Elab =
true;
894 Policy.SuppressScope =
true;
895 Policy.AnonymousTagLocations =
false;
896 Policy.SuppressTemplateArgsInCXXConstructors =
false;
897 Policy.SuppressDefaultTemplateArgs =
false;
898 Policy.AlwaysIncludeTypeForTemplateArgument =
true;
901 if (
const auto* TD = llvm::dyn_cast<TagDecl>(ND)) {
902 std::string type_name;
904 QT.getAsStringInternal(type_name, Policy);
907 if (
const auto* FD = llvm::dyn_cast<FunctionDecl>(ND)) {
908 std::string func_name;
909 llvm::raw_string_ostream name_stream(func_name);
910 FD->getNameForDiagnostic(name_stream, Policy, qualified);
915 return qualified ? ND->getQualifiedNameAsString() : ND->getNameAsString();
918 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
932 const auto* D = unwrap<Decl>(DRef);
933 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
937 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
951 const auto* D = unwrap<Decl>(DRef);
955 D = D->getCanonicalDecl();
956 ASTContext& C = D->getASTContext();
958 const RawComment* RC = C.getRawCommentForAnyRedecl(D);
962 (void)C.getCommentForDecl(D,
nullptr);
964 const SourceManager& SM = C.getSourceManager();
966 if (!strip_comment_markers)
969 return INTEROP_RETURN(RC->getFormattedText(SM, C.getDiagnostics()));
974 const auto* D = unwrap<clang::Decl>(DRef);
976 if (
const auto* DC = llvm::dyn_cast_or_null<clang::DeclContext>(D)) {
977 std::vector<DeclRef> namespaces;
978 for (
auto UD : DC->using_directives()) {
979 namespaces.push_back(UD->getNominatedNamespace());
994 if (
auto* Type = QT.getCanonicalType().getTypePtrOrNull()) {
995 Type = Type->getPointeeOrArrayElementType();
996 Type = Type->getUnqualifiedDesugaredType();
997 if (
auto* ET = llvm::dyn_cast<EnumType>(Type))
998 return ET->getDecl();
999 CXXRecordDecl* CXXRD = Type->getAsCXXRecordDecl();
1001 return CXXRD->getCanonicalDecl();
1008 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
1013 if (
const auto* TND = dyn_cast_or_null<TypedefNameDecl>(D)) {
1016 }
else if (
const auto* USS = dyn_cast_or_null<UsingShadowDecl>(D)) {
1017 if (
const auto* Scope = USS->getTargetDecl())
1021 return D->getCanonicalDecl();
1035DeclRef
GetScope(
const std::string& name, ConstDeclRef parent) {
1044 auto* ND = unwrap<NamedDecl>(
GetNamed(name, parent));
1046 if (!ND || ND == (NamedDecl*)-1)
1049 if (llvm::isa<NamespaceDecl>(ND) || llvm::isa<RecordDecl>(ND) ||
1050 llvm::isa<ClassTemplateDecl>(ND) || llvm::isa<TypedefNameDecl>(ND) ||
1051 llvm::isa<TypeAliasTemplateDecl>(ND) || llvm::isa<TypeAliasDecl>(ND))
1059 std::string delim =
"::";
1061 size_t end = name.find(delim);
1062 DeclRef curr_scope =
nullptr;
1063 while (end != std::string::npos) {
1064 curr_scope =
GetScope(name.substr(start, end - start), curr_scope);
1065 start = end + delim.length();
1066 end = name.find(delim, start);
1084clang::Scope* BuildSyntheticScopeChain(clang::Sema& S, clang::DeclContext* DC) {
1085 if (!DC || DC->isTranslationUnit())
1087 auto* Parent = BuildSyntheticScopeChain(S, DC->getParent());
1088 auto* Mine =
new clang::Scope(Parent, clang::Scope::DeclScope, S.Diags);
1089 Mine->setEntity(DC);
1100class SyntheticScopeChain {
1102 SyntheticScopeChain(clang::Sema& Sema, clang::DeclContext* Within)
1103 : S(Sema), Innermost(BuildSyntheticScopeChain(Sema, Within)),
1104 Saved(
ACCESS(Sema, CurScope)) {
1105 ACCESS(S, CurScope) = Innermost;
1107 ~SyntheticScopeChain() {
1108 ACCESS(S, CurScope) = Saved;
1109 while (Innermost && Innermost != S.TUScope) {
1110 auto* Next = Innermost->getParent();
1115 SyntheticScopeChain(
const SyntheticScopeChain&) =
delete;
1116 SyntheticScopeChain& operator=(
const SyntheticScopeChain&) =
delete;
1118 clang::Scope* get()
const {
return Innermost; }
1122 clang::Scope* Innermost;
1123 clang::Scope* Saved;
1135clang::NamedDecl* LookupUnqualified(clang::Sema& S,
1136 const clang::DeclarationName& Name,
1137 clang::DeclContext* Within) {
1138 SyntheticScopeChain Chain(S, Within);
1144 clang::LookupResult R(S, Name, clang::SourceLocation(),
1145 clang::Sema::LookupOrdinaryName,
1146 RedeclarationKind::NotForRedeclaration);
1147 R.suppressDiagnostics();
1148 S.LookupName(R, Chain.get());
1156 if (R.isSingleResult())
1157 return llvm::dyn_cast<clang::NamedDecl>(R.getFoundDecl());
1158 return (clang::NamedDecl*)-1;
1165bool HasReachableUsingDirective(
const clang::DeclContext* DC) {
1166 for (; DC && !DC->isTranslationUnit(); DC = DC->getParent()) {
1167 if (
const auto* NS = llvm::dyn_cast<clang::NamespaceDecl>(DC)) {
1168 auto UDs = NS->using_directives();
1169 if (UDs.begin() != UDs.end())
1177DeclRef
GetNamed(
const std::string& name, ConstDeclRef parent ) {
1179 clang::DeclContext* Within = 0;
1182 Within = llvm::dyn_cast<clang::DeclContext>(D);
1184#ifdef CPPINTEROP_USE_CLING
1186 Within->getPrimaryContext()->buildLookup();
1195 if (ND && ND != (clang::NamedDecl*)-1)
1202 if (!Within || !llvm::isa<clang::NamespaceDecl>(Within) ||
1203 !HasReachableUsingDirective(Within))
1205 clang::DeclarationName DName = &
getSema().Context.Idents.get(name);
1206 ND = LookupUnqualified(
getSema(), DName, Within);
1207 if (ND && ND != (clang::NamedDecl*)-1)
1218 auto* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1220 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
1223 auto* ParentDC = D->getDeclContext();
1228 auto* P = clang::Decl::castFromDeclContext(ParentDC)->getCanonicalDecl();
1230 if (
auto* TU = llvm::dyn_cast_or_null<TranslationUnitDecl>(P))
1238 const auto* D = unwrap<Decl>(DRef);
1240 if (
const auto* CTSD =
1241 llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(D))
1242 if (!CTSD->hasDefinition())
1244 getInterp(),
const_cast<ClassTemplateSpecializationDecl*
>(CTSD));
1245 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1246 if (CXXRD->hasDefinition())
1255 const auto* D = unwrap<Decl>(DRef);
1256 const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D);
1257 if (!CXXRD || CXXRD->getNumBases() <= ibase)
1260 auto TyRef = (CXXRD->bases_begin() + ibase)->getType();
1261 if (
const auto* RT = TyRef->getAs<RecordType>())
1271 if (derived == base)
1274 if (!derived || !base)
1277 const auto* derived_D = unwrap<clang::Decl>(derived);
1278 const auto* base_D = unwrap<clang::Decl>(base);
1280 if (!isa<CXXRecordDecl>(derived_D) || !isa<CXXRecordDecl>(base_D))
1283 const auto* Derived = cast<CXXRecordDecl>(derived_D);
1284 const auto* Base = cast<CXXRecordDecl>(base_D);
1294 const CXXRecordDecl* DerivedRD,
1295 const CXXBasePath& Path) {
1296 CharUnits NonVirtualOffset = CharUnits::Zero();
1298 unsigned NonVirtualStart = 0;
1299 const CXXRecordDecl* VirtualBase =
nullptr;
1302 for (
int I = Path.size(), E = 0; I != E; --I) {
1303 const CXXBasePathElement& Element = Path[I - 1];
1305 if (Element.Base->isVirtual()) {
1306 NonVirtualStart = I;
1307 QualType VBaseType = Element.Base->getType();
1308 VirtualBase = VBaseType->getAsCXXRecordDecl();
1314 for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
1315 const CXXBasePathElement& Element = Path[I];
1318 const ASTRecordLayout& Layout = Context.getASTRecordLayout(Element.Class);
1320 const CXXRecordDecl* Base = Element.Base->getType()->getAsCXXRecordDecl();
1322 NonVirtualOffset += Layout.getBaseClassOffset(Base);
1330 const ASTRecordLayout& Layout = Context.getASTRecordLayout(DerivedRD);
1331 CharUnits VirtualOffset = Layout.getVBaseClassOffset(VirtualBase);
1332 return (NonVirtualOffset + VirtualOffset).getQuantity();
1334 return NonVirtualOffset.getQuantity();
1339 if (base == derived)
1342 assert(derived || base);
1344 const auto* DD = unwrap<Decl>(derived);
1345 const auto* BD = unwrap<Decl>(base);
1346 if (!isa<CXXRecordDecl>(DD) || !isa<CXXRecordDecl>(BD))
1348 const auto* DCXXRD = cast<CXXRecordDecl>(DD);
1349 const auto* BCXXRD = cast<CXXRecordDecl>(BD);
1357#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
1358#pragma GCC diagnostic push
1359#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1361 CXXBasePaths Paths(
false,
true,
1363#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
1364#pragma GCC diagnostic pop
1366 DCXXRD->isDerivedFrom(BCXXRD, Paths);
1373template <
typename DeclType,
typename HandleType>
1380 Decl* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1382 if (
auto* TD = dyn_cast<TypedefNameDecl>(D)) {
1384 D = unwrap<clang::Decl>(Scope);
1387 if (!D || !isa<CXXRecordDecl>(D))
1390 auto* CXXRD = dyn_cast<CXXRecordDecl>(D);
1392 if (
auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
1394 if (!
getSema().isCompleteType(CTSD->getLocation(), QT))
1398 if (CXXRD->hasDefinition())
1399 CXXRD = CXXRD->getDefinition();
1400 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1401 for (Decl* DI : CXXRD->decls()) {
1402 if (
auto* MD = dyn_cast<DeclType>(DI))
1403 methods.push_back(MD);
1404 else if (
auto* USD = dyn_cast<UsingShadowDecl>(DI)) {
1405 auto* MD = dyn_cast<DeclType>(USD->getTargetDecl());
1409 auto* CUSD = dyn_cast<ConstructorUsingShadowDecl>(DI);
1411 methods.push_back(MD);
1415 auto* CXXCD = dyn_cast_or_null<CXXConstructorDecl>(CUSD->getTargetDecl());
1417 methods.push_back(MD);
1420 if (CXXCD->isDeleted())
1426 getSema().findInheritingConstructor(SourceLocation(), CXXCD, CUSD);
1433 GetClassDecls<CXXMethodDecl>(DRef, methods);
1438 std::vector<FuncRef>& methods) {
1440 GetClassDecls<FunctionTemplateDecl>(DRef, methods);
1446 const auto* D = unwrap<clang::Decl>(DRef);
1448 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D))
1458 auto* CXXRD = unwrap<clang::CXXRecordDecl>(DRef);
1460 return interp.
getCI()->getSema().LookupDefaultConstructor(CXXRD);
1471 auto* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1473 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1474 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1483 const auto* D = unwrap<clang::Decl>(DRef);
1494 llvm::StringRef name) {
1495 static constexpr llvm::StringRef OperatorPrefix(
"operator");
1496 if (!name.consume_front(OperatorPrefix) || name.empty() ||
1497 clang::isAsciiIdentifierContinue(
1498 static_cast<unsigned char>(name.front())))
1499 return DeclarationName();
1501 llvm::StringRef Spelling = name.trim();
1502#define OVERLOADED_OPERATOR(OpName, OpSpelling, Token, Unary, Binary, \
1504 if (Spelling == (OpSpelling)) \
1505 return Ctx.DeclarationNames.getCXXOperatorName(clang::OO_##OpName);
1506#include "clang/Basic/OperatorKinds.def"
1507#undef OVERLOADED_OPERATOR
1508 return DeclarationName();
1512 const std::string& name) {
1515 if (!DRef || name.empty())
1520 std::vector<FuncRef> funcs;
1526 DName = &Ctx.Idents.get(name);
1528 clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
1529 RedeclarationKind::ForVisibleRedeclaration);
1538 for (
auto* Found : R) {
1539 if (llvm::isa<FunctionDecl>(Found))
1540 funcs.push_back(Found);
1541 else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(Found)) {
1542 if (
auto* FTD = llvm::dyn_cast<FunctionDecl>(USD->getTargetDecl()))
1543 funcs.push_back(FTD);
1552 const auto* D = unwrap<clang::Decl>(func);
1553 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
1554 QualType Type = FD->getReturnType();
1555 if (Type->isUndeducedAutoType()) {
1556 bool needInstantiation =
false;
1558 needInstantiation =
true;
1559 if (
const auto* MD = llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
1561 needInstantiation =
true;
1564 if (needInstantiation) {
1567 const_cast<Decl*
>(
static_cast<const Decl*
>(FD)));
1569 Type = FD->getReturnType();
1574 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1576 (FD->getTemplatedDecl())->getReturnType().getAsOpaquePtr());
1583 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
1584 const auto* T = QT.getTypePtr();
1585 return llvm::isa_and_nonnull<clang::FunctionProtoType>(T);
1590 QualType QT = QualType::getFromOpaquePtr(fn_type.data);
1591 const auto* FPT = QT->getAs<clang::FunctionProtoType>();
1594 sig.push_back(FPT->getReturnType().getAsOpaquePtr());
1595 for (
size_t i = 0; i < FPT->getNumParams(); i++)
1596 sig.push_back(FPT->getParamType(i).getAsOpaquePtr());
1607 const auto* D = unwrap<clang::Decl>(func);
1608 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1611 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1612 return INTEROP_RETURN(FD->getTemplatedDecl()->getNumNonObjectParams());
1619 const auto* D = unwrap<clang::Decl>(func);
1620 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1623 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1625 FD->getTemplatedDecl()->getMinRequiredExplicitArguments());
1632 const auto* D = unwrap<clang::Decl>(func);
1634 if (
const auto* FTD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1635 D = FTD->getTemplatedDecl();
1637 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
1638 if (iarg < FD->getNumNonObjectParams()) {
1639 const auto* PVD = FD->getNonObjectParameter(iarg);
1649 clang::QualType QT = clang::QualType::getFromOpaquePtr(TyRef.data);
1658 const auto* D = unwrap<clang::Decl>(func);
1659 const clang::FunctionDecl* FD;
1661 if (llvm::dyn_cast<FunctionDecl>(D))
1662 FD = llvm::dyn_cast<FunctionDecl>(D);
1663 else if (
const auto* FTD = llvm::dyn_cast<clang::FunctionTemplateDecl>(D))
1664 FD = FTD->getTemplatedDecl();
1668 std::string Signature;
1669 raw_string_ostream SS(Signature);
1670 PrintingPolicy Policy =
getASTContext().getPrintingPolicy();
1672 Policy.TerseOutput =
true;
1673 Policy.FullyQualifiedName =
true;
1674 Policy.SuppressDefaultTemplateArgs =
false;
1675 FD->print(SS, Policy);
1684 return llvm::isa_and_nonnull<FunctionTemplateDecl>(D);
1687bool IsTemplateInstantiationOrSpecialization(
const Decl* D) {
1688 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
1689 auto TK = FD->getTemplatedKind();
1691 FunctionDecl::TemplatedKind::TK_FunctionTemplateSpecialization ||
1692 TK == FunctionDecl::TemplatedKind::
1693 TK_DependentFunctionTemplateSpecialization ||
1694 TK == FunctionDecl::TemplatedKind::TK_FunctionTemplate;
1703 const auto* FD = cast<FunctionDecl>(unwrap<clang::Decl>(function));
1709 const auto* D = unwrap<Decl>(func);
1711 IsTemplateInstantiationOrSpecialization(D));
1719 const DeclContext* Within =
nullptr;
1721 const auto* D = unwrap<Decl>(parent);
1722 Within = llvm::dyn_cast<DeclContext>(D);
1727 if ((intptr_t)ND == (intptr_t)0)
1730 if ((intptr_t)ND != (intptr_t)-1)
1732 IsTemplateInstantiationOrSpecialization(ND));
1740 std::vector<FuncRef>& funcs) {
1743 auto* D =
const_cast<Decl*
>(unwrap<Decl>(parent));
1745 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1746 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1747 DeclContextLookupResult Result =
getSema().LookupConstructors(CXXRD);
1751 for (
auto* i : Result)
1752 if (
GetName(DeclRef(i)) == name)
1759 std::vector<FuncRef>& funcs) {
1761 const auto* D = unwrap<Decl>(parent);
1762 if (!D && name.empty())
1769 llvm::StringRef Name(name);
1771 clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
1772 RedeclarationKind::ForVisibleRedeclaration);
1773 auto* DC = clang::Decl::castToDeclContext(DU);
1782 funcs.push_back(R.getFoundDecl());
1786 for (
auto* Found : R) {
1788 funcs.push_back(Found);
1789 else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(Found)) {
1791 llvm::dyn_cast<FunctionTemplateDecl>(USD->getTargetDecl()))
1792 funcs.push_back(FTD);
1810 const std::vector<TemplateArgInfo>& explicit_types,
1811 const std::vector<TemplateArgInfo>& arg_types) {
1814 auto& C = S.getASTContext();
1823 struct WrapperExpr :
public OpaqueValueExpr {
1824 WrapperExpr() : OpaqueValueExpr(clang::Stmt::EmptyShell()) {}
1826 auto* Exprs =
new WrapperExpr[arg_types.size()];
1827 llvm::SmallVector<Expr*> Args;
1828 Args.reserve(arg_types.size());
1830 for (
auto i : arg_types) {
1831 QualType Type = QualType::getFromOpaquePtr(i.m_Type);
1834 ExprValueKind ExprKind = ExprValueKind::VK_XValue;
1835 if (Type->isLValueReferenceType())
1836 ExprKind = ExprValueKind::VK_LValue;
1838 new (&Exprs[idx]) OpaqueValueExpr(SourceLocation::getFromRawEncoding(1),
1839 Type.getNonReferenceType(), ExprKind);
1840 Args.push_back(&Exprs[idx]);
1845 llvm::SmallVector<TemplateArgument> TemplateArgs;
1846 TemplateArgs.reserve(explicit_types.size());
1847 for (
auto explicit_type : explicit_types) {
1848 QualType ArgTy = QualType::getFromOpaquePtr(explicit_type.m_Type);
1849 if (explicit_type.m_IntegralValue) {
1852 auto Res = llvm::APSInt(explicit_type.m_IntegralValue);
1853 Res = Res.extOrTrunc(C.getIntWidth(ArgTy));
1854 TemplateArgs.push_back(TemplateArgument(C, Res, ArgTy));
1856 TemplateArgs.push_back(ArgTy);
1860 TemplateArgumentListInfo ExplicitTemplateArgs{};
1861 for (
auto TA : TemplateArgs)
1862 ExplicitTemplateArgs.addArgument(
1863 S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation()));
1866 SourceLocation Loc = SourceLocation::getFromRawEncoding(1);
1867 Sema::SFINAETrap Trap(S,
true);
1869 OverloadCandidateSet Overloads(
1870 Loc, OverloadCandidateSet::CandidateSetKind::CSK_Normal);
1872 for (
auto i : candidates) {
1873 auto* D =
const_cast<Decl*
>(unwrap<Decl>(i));
1874 if (
auto* FD = dyn_cast<FunctionDecl>(D)) {
1875 S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
1877 }
else if (
auto* FTD = dyn_cast<FunctionTemplateDecl>(D)) {
1878 auto* MD = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl());
1879 if (MD && MD->isExplicitObjectMemberFunction()) {
1882 CXXRecordDecl* RD = MD->getParent();
1884 OpaqueValueExpr ObjectExpr(SourceLocation::getFromRawEncoding(1),
1885 ObjectType, ExprValueKind::VK_LValue);
1886 S.AddMethodTemplateCandidate(
1887 FTD, DeclAccessPair::make(FTD, FTD->getAccess()), RD,
1888 &ExplicitTemplateArgs, ObjectType, ObjectExpr.Classify(C), Args,
1896 S.AddTemplateOverloadCandidate(
1897 FTD, DeclAccessPair::make(FTD, FTD->getAccess()),
1898 &ExplicitTemplateArgs, Args, Overloads);
1903 OverloadCandidateSet::iterator Best;
1904 Overloads.BestViableFunction(S, Loc, Best);
1906 FunctionDecl* Result = Best != Overloads.end() ? Best->Function :
nullptr;
1914 const auto* D = unwrap<Decl>(method);
1915 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
1916 return CXXMD->getAccess() == AS;
1924 const auto* D = unwrap<clang::Decl>(method);
1925 if (
const auto* FTD = dyn_cast_or_null<FunctionTemplateDecl>(D))
1926 D = FTD->getTemplatedDecl();
1948 const auto* D = unwrap<Decl>(method);
1949 if (
const auto* FTD = dyn_cast<FunctionTemplateDecl>(D))
1951 return INTEROP_RETURN(llvm::isa_and_nonnull<CXXConstructorDecl>(D));
1956 const auto* D = unwrap<Decl>(method);
1957 return INTEROP_RETURN(llvm::isa_and_nonnull<CXXDestructorDecl>(D));
1962 const auto* D = unwrap<Decl>(method);
1963 if (
const auto* FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D))
1964 D = FTD->getTemplatedDecl();
1966 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
1978 const auto* D = unwrap<Decl>(method);
1980 if (
const auto* FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D))
1981 D = FTD->getTemplatedDecl();
1983 if (
const auto* CD = llvm::dyn_cast_or_null<CXXConstructorDecl>(D))
1986 if (
const auto* CD = llvm::dyn_cast_or_null<CXXConversionDecl>(D))
1989 if (
const auto* DGD = llvm::dyn_cast_or_null<CXXDeductionGuideDecl>(D))
1999 if (llvm::Error Err = FDAorErr.takeError())
2000 llvm::consumeError(std::move(Err));
2002 return INTEROP_RETURN(llvm::jitTargetAddressToPointer<void*>(*FDAorErr));
2008 const auto get_mangled_name = [](
const FunctionDecl* FD) {
2011 if (!MangleCtxt->shouldMangleDeclName(FD)) {
2012 return FD->getNameInfo().getName().getAsString();
2015 std::string mangled_name;
2016 llvm::raw_string_ostream ostream(mangled_name);
2018 MangleCtxt->mangleName(FD, ostream);
2023 return mangled_name;
2027 if (!llvm::isa<CXXConstructorDecl>(FD) && !llvm::isa<CXXDestructorDecl>(FD))
2035 auto* D = unwrap<Decl>(method);
2036 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
2037 if ((IsTemplateInstantiationOrSpecialization(FD) ||
2038 FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) &&
2039 !FD->getDefinition())
2042 if (isDiscardableGVALinkage(C.GetGVALinkageForFunction(FD)))
2051 const auto* D = unwrap<Decl>(method);
2052 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
2064 const auto* MD = llvm::dyn_cast_or_null<CXXMethodDecl>(unwrap<Decl>(method));
2065 if (!MD || !MD->isVirtual())
2069 if (C.getTargetInfo().getCXXABI().isMicrosoft()) {
2070 auto* VTC = llvm::cast<MicrosoftVTableContext>(C.getVTableContext());
2071 return (
int)VTC->getMethodVFTableLocation(GlobalDecl(MD)).Index;
2073 auto* VTC = llvm::cast<ItaniumVTableContext>(C.getVTableContext());
2074 return (
int)VTC->getMethodVTableIndex(GlobalDecl(MD));
2081 const auto* RD = llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(DRef));
2083 RD = RD->getDefinition();
2084 if (!RD || !RD->isPolymorphic())
2088 if (C.getTargetInfo().getCXXABI().isMicrosoft()) {
2089 auto* VTC = llvm::cast<MicrosoftVTableContext>(C.getVTableContext());
2090 const VTableLayout& L = VTC->getVFTableLayout(RD, CharUnits::Zero());
2091 return (
int)L.vtable_components().size();
2093 auto* VTC = llvm::cast<ItaniumVTableContext>(C.getVTableContext());
2094 const VTableLayout& L = VTC->getVTableLayout(RD);
2095 unsigned AddrPoint = L.getAddressPointIndices()[0];
2096 return (
int)(L.vtable_components().size() - AddrPoint);
2109 if (RD->getNumVBases() > 0)
2111 unsigned polymorphic_direct_bases = 0;
2112 for (
const auto& B : RD->bases()) {
2113 const auto* BD = B.getType()->getAsCXXRecordDecl();
2116 BD = BD->getDefinition();
2117 if (BD && BD->isPolymorphic() && ++polymorphic_direct_bases > 1)
2132 "public prefix size must equal ABI prefix + 1 hidden slot");
2158 std::size_t n_extra)
2184 template <
class To,
class From>
static To
BitCastFn(From f)
noexcept {
2185 static_assert(
sizeof(To) ==
sizeof(From));
2187 std::memcpy(&to, &f,
sizeof(to));
2192 return *
reinterpret_cast<void***
>(
inst);
2195 *
reinterpret_cast<void***
>(
inst) = new_vptr;
2235 const int* slots,
void*
const* fns,
2237 std::size_t n_extra_prefix_slots) {
2240 for (std::size_t i = 0; i < n; ++i) {
2241 if (slots[i] < 0 || slots[i] >= total_method_slots)
2249 const std::size_t total = n_extra_prefix_slots + kPrefix + total_method_slots;
2256 void** block =
new void*[total]();
2257 std::memcpy(block + n_extra_prefix_slots + 1, orig_vptr -
kABIPrefixSize,
2260 for (std::size_t i = 0; i < n; ++i)
2261 block[n_extra_prefix_slots + kPrefix + slots[i]] = fns[i];
2266 return new VTableOverlay(block, orig_vptr, inst, n_extra_prefix_slots);
2282 void*
const* overlay_fns, std::size_t n_overlays,
2283 std::size_t n_extra_prefix_slots,
2284 VTableOverlayDtorHook on_destroy,
void* cleanup_data) {
2286 n_extra_prefix_slots, on_destroy, cleanup_data);
2293 const auto* RD = llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(base));
2295 RD = RD->getDefinition();
2303 llvm::SmallVector<int, 8> slots;
2304 slots.reserve(n_overlays);
2305 for (std::size_t i = 0; i < n_overlays; ++i) {
2309 slots.push_back(slot);
2312 overlay_fns, n_overlays,
2313 n_extra_prefix_slots);
2323 void** vptr = ov->address_point();
2326 ov->cleanup = on_destroy;
2327 ov->cleanup_data = cleanup_data;
2343 auto* D = unwrap<Decl>(DRef);
2345 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
2346 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
2347 if (CXXRD->hasDefinition())
2348 CXXRD = CXXRD->getDefinition();
2350 llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_begin;
2351 llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_end;
2352 stack_begin.push_back(CXXRD->decls_begin());
2353 stack_end.push_back(CXXRD->decls_end());
2354 while (!stack_begin.empty()) {
2355 if (stack_begin.back() == stack_end.back()) {
2356 stack_begin.pop_back();
2357 stack_end.pop_back();
2360 Decl* D = *(stack_begin.back());
2361 if (
auto* FD = llvm::dyn_cast<FieldDecl>(D)) {
2362 if (FD->isAnonymousStructOrUnion()) {
2363 if (
const auto* RT = FD->getType()->getAs<RecordType>()) {
2364 if (
auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(RT->getDecl())) {
2365 stack_begin.back()++;
2366 stack_begin.push_back(CXXRD->decls_begin());
2367 stack_end.push_back(CXXRD->decls_end());
2372 datamembers.push_back(D);
2374 }
else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(D)) {
2375 if (llvm::isa<FieldDecl>(USD->getTargetDecl()))
2376 datamembers.push_back(USD);
2378 stack_begin.back()++;
2385 std::vector<DeclRef>& datamembers) {
2387 GetClassDecls<VarDecl>(DRef, datamembers);
2392 std::vector<DeclRef>& datamembers,
2393 bool include_enum_class) {
2395 std::vector<DeclRef> EDs;
2396 GetClassDecls<EnumDecl>(DRef, EDs);
2397 for (DeclRef i : EDs) {
2398 auto* ED = unwrap<EnumDecl>(i);
2400 bool is_class_tagged = ED->isScopedUsingClassTag();
2401 if (is_class_tagged && !include_enum_class)
2404 std::copy(ED->enumerator_begin(), ED->enumerator_end(),
2405 std::back_inserter(datamembers));
2412 const clang::DeclContext* Within =
nullptr;
2414 const auto* D = unwrap<clang::Decl>(parent);
2415 Within = llvm::dyn_cast<clang::DeclContext>(D);
2419 if (ND && ND != (clang::NamedDecl*)-1) {
2420 if (llvm::isa_and_nonnull<clang::FieldDecl>(ND)) {
2430 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2431 if (
auto* CXXRD = QT->getAsCXXRecordDecl()) {
2439 const auto* D = unwrap<Decl>(var);
2441 if (
const auto* DD = llvm::dyn_cast_or_null<DeclaratorDecl>(D)) {
2442 QualType QT = DD->getType();
2445 if (QT->isTypedefNameType()) {
2450 QT = QT.getCanonicalType();
2454 if (
const auto* ECD = llvm::dyn_cast_or_null<EnumConstantDecl>(D))
2461 CXXRecordDecl* BaseCXXRD) {
2465 auto& C = I.
getSema().getASTContext();
2467 if (
auto* FD = llvm::dyn_cast<FieldDecl>(D)) {
2468 clang::RecordDecl* FieldParentRecordDecl = FD->getParent();
2469 intptr_t offset = C.toCharUnitsFromBits(C.getFieldOffset(FD)).getQuantity();
2470 while (FieldParentRecordDecl->isAnonymousStructOrUnion()) {
2471 clang::RecordDecl* anon = FieldParentRecordDecl;
2472 FieldParentRecordDecl = llvm::dyn_cast<RecordDecl>(anon->getParent());
2473 for (
auto F = FieldParentRecordDecl->field_begin();
2474 F != FieldParentRecordDecl->field_end(); ++F) {
2475 const auto* RT = F->getType()->getAs<RecordType>();
2478 if (anon == RT->getDecl()) {
2483 offset += C.toCharUnitsFromBits(C.getFieldOffset(FD)).getQuantity();
2485 if (BaseCXXRD && BaseCXXRD != FieldParentRecordDecl->getCanonicalDecl()) {
2492 std::vector<CXXRecordDecl*> stack;
2493 std::map<CXXRecordDecl*, CXXRecordDecl*> direction;
2494 stack.push_back(BaseCXXRD);
2495 while (!stack.empty()) {
2496 CXXRecordDecl* RD = stack.back();
2500 for (
size_t i = 0; i < num_bases; i++) {
2501 auto* CRD = unwrap<CXXRecordDecl>(
GetBaseClass(RD, i));
2502 direction[CRD] = RD;
2503 if (CRD == FieldParentRecordDecl) {
2507 stack.push_back(CRD);
2512 if (
auto* RD = llvm::dyn_cast<CXXRecordDecl>(FieldParentRecordDecl)) {
2514 RD = RD->getCanonicalDecl();
2515 while (BaseCXXRD != RD) {
2516 CXXRecordDecl* Parent = direction.at(RD);
2518 C.getASTRecordLayout(Parent).getBaseClassOffset(RD).getQuantity();
2522 assert(
false &&
"Unreachable");
2528 if (
auto* VD = llvm::dyn_cast<VarDecl>(D)) {
2529 auto GD = GlobalDecl(VD);
2530 std::string mangledName;
2532 void* address = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
2533 mangledName.c_str());
2538 if (!VD->hasInit()) {
2540 getSema().InstantiateVariableDefinition(SourceLocation(), VD);
2541 VD = VD->getDefinition();
2543 if (VD->hasInit() &&
2544 (VD->isConstexpr() || VD->getType().isConstQualified())) {
2545 if (
const APValue* val = VD->evaluateValue()) {
2546 if (VD->getType()->isIntegralType(C)) {
2547 return (intptr_t)val->getInt().getRawData();
2553 auto Linkage = C.GetGVALinkageForVariable(VD);
2554 if (isDiscardableGVALinkage(Linkage))
2559 llvm::logAllUnhandledErrors(VDAorErr.takeError(), llvm::errs(),
2560 "Failed to GetVariableOffset:");
2563 return (intptr_t)jitTargetAddressToPointer<void*>(VDAorErr.get());
2572 auto* D =
const_cast<Decl*
>(unwrap<Decl>(var));
2573 auto* RD =
const_cast<CXXRecordDecl*
>(
2574 llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(parent)));
2580 const auto* D = unwrap<Decl>(var);
2581 return D->getAccess() == AS;
2602 const auto* D = unwrap<Decl>(var);
2603 if (llvm::isa_and_nonnull<VarDecl>(D)) {
2612 const auto* D = unwrap<clang::Decl>(var);
2614 if (
const auto* VD = llvm::dyn_cast_or_null<ValueDecl>(D)) {
2623 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2629 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2641 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2642 if (!QT->hasIntegerRepresentation())
2645 *s = QT->hasSignedIntegerRepresentation() ? Signedness::kSigned
2646 : Signedness::kUnsigned;
2655 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2661 if (!type_a || !type_b)
2663 QualType QT1 = QualType::getFromOpaquePtr(type_a.data);
2664 QualType QT2 = QualType::getFromOpaquePtr(type_b.data);
2670 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2678 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2686 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2692 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2698 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2699 if (QT->isRValueReferenceType())
2701 if (QT->isLValueReferenceType())
2708 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2714 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2717 getASTContext().getRValueReferenceType(QT).getAsOpaquePtr());
2719 getASTContext().getLValueReferenceType(QT).getAsOpaquePtr());
2726 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2727 return INTEROP_RETURN(QT.getNonReferenceType().getAsOpaquePtr());
2734 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2735 QT = QT->getCanonicalTypeUnqualified();
2738 while (QT->isArrayType())
2739 QT = QualType(QT->getArrayElementTypeNoTypeQual(), 0);
2743 for (
auto PT = QT->getPointeeType(); !PT.isNull();
2744 PT = QT->getPointeeType()) {
2747 QT = QT->getCanonicalTypeUnqualified();
2753 QualType QT = QualType::getFromOpaquePtr(var.data);
2756 Policy.SuppressTagKeyword =
true;
2757 Policy.Suppress_Elab =
true;
2758 Policy.FullyQualifiedName =
true;
2766 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2775 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2776 if (qual & QualKind::Const) {
2777 if (!QT.isConstQualified())
2780 if (qual & QualKind::Volatile) {
2781 if (!QT.isVolatileQualified())
2784 if (qual & QualKind::Restrict) {
2785 if (!QT.isRestrictQualified())
2796 auto QT = QualType(QualType::getFromOpaquePtr(TyRef.data));
2797 if (qual & QualKind::Const)
2798 QT.removeLocalConst();
2799 if (qual & QualKind::Volatile)
2800 QT.removeLocalVolatile();
2801 if (qual & QualKind::Restrict)
2802 QT.removeLocalRestrict();
2811 auto QT = QualType(QualType::getFromOpaquePtr(TyRef.data));
2812 if (qual & QualKind::Const) {
2813 if (!QT.isConstQualified())
2816 if (qual & QualKind::Volatile) {
2817 if (!QT.isVolatileQualified())
2820 if (qual & QualKind::Restrict) {
2821 if (!QT.isRestrictQualified())
2829 llvm::SmallVectorImpl<llvm::StringRef>& Words) {
2830 std::sort(Words.begin(), Words.end());
2833 for (
size_t i = 0; i < Words.size(); ++i) {
2836 Key += Words[i].str();
2839 }
while (std::next_permutation(Words.begin(), Words.end()));
2843 const PrintingPolicy Policy(Context.getLangOpts());
2845 const auto& Types =
ACCESS(Context, Types);
2847 for (clang::Type* T : Types) {
2848 auto* BT = llvm::dyn_cast<BuiltinType>(T);
2849 if (!BT || BT->isPlaceholderType())
2853 std::string Name = QT.getAsString(Policy);
2854 if (Name.empty() || Name[0] ==
'<')
2858 BuiltinMap[Name] = QT;
2860 llvm::SmallVector<llvm::StringRef, 4> Words;
2861 llvm::StringRef(Name).split(Words,
' ', -1,
false);
2863 bool hasInt =
false;
2864 bool hasSigned =
false;
2865 bool hasUnsigned =
false;
2866 bool hasChar =
false;
2867 bool isModifiable =
false;
2869 for (
auto W : Words) {
2872 else if (W ==
"signed")
2874 else if (W ==
"unsigned")
2876 else if (W ==
"char")
2879 if (W ==
"long" || W ==
"short" || hasInt)
2880 isModifiable =
true;
2884 if (!isModifiable && !hasUnsigned && !hasSigned)
2888 if (Words.size() > 1)
2892 if (!hasInt && !hasChar) {
2893 auto WithInt = Words;
2894 WithInt.push_back(
"int");
2899 if (!hasSigned && !hasUnsigned) {
2900 auto WithBoth = WithInt;
2901 WithBoth.push_back(
"signed");
2908 if (!hasSigned && !hasUnsigned) {
2909 auto WithSigned = Words;
2910 WithSigned.push_back(
"signed");
2916 BuiltinMap[
"signed"] = Context.IntTy;
2917 BuiltinMap[
"unsigned"] = Context.UnsignedIntTy;
2920 llvm::StringMap<QualType>& BuiltinMap =
GetInterpreters().back().BuiltinMap;
2921 if (BuiltinMap.empty())
2925 auto It = BuiltinMap.find(typeName);
2926 if (It != BuiltinMap.end())
2936 if (
const auto* TND = llvm::dyn_cast_or_null<TypedefNameDecl>(D))
2937 return TND->getUnderlyingType();
2939 if (
const auto* VD = dyn_cast<ValueDecl>(D))
2940 return VD->getType();
2942 if (
const auto* TD = llvm::dyn_cast_or_null<TypeDecl>(D))
2948TypeRef
GetType(
const std::string& name, ConstDeclRef parent ) {
2951 if (!builtin.isNull())
2959 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2978static unsigned long long gWrapperSerial = 0LL;
2980enum EReferenceType { kNotReference, kLValueReference, kRValueReference };
2984#define DEBUG_TYPE "jitcall"
2988inline void indent(std::ostringstream& buf,
int indent_level) {
2989 static const std::string kIndentString(
" ");
2990 for (
int i = 0; i < indent_level; ++i)
2991 buf << kIndentString;
2995 const std::string& wrapper,
2996 bool withAccessControl =
true) {
2997 LLVM_DEBUG(dbgs() <<
"Compiling '" << wrapper_name <<
"'\n");
3002void get_type_as_string(QualType QT, std::string& type_name, ASTContext& C,
3003 PrintingPolicy Policy) {
3013 while (
const auto* TST = QT->getAs<TemplateSpecializationType>()) {
3014 if (!TST->isTypeAlias())
3016 QT = TST->desugar();
3018 if (!QT->isTypedefNameType() || QT->isBuiltinType())
3019 QT = QT.getDesugaredType(C);
3020 Policy.Suppress_Elab =
true;
3021 Policy.SuppressTagKeyword = !QT->isEnumeralType();
3022 Policy.FullyQualifiedName =
true;
3023 Policy.UsePreferredNames =
false;
3024 QT.getAsStringInternal(type_name, Policy);
3027static void GetDeclName(
const clang::Decl* D, ASTContext& Context,
3028 std::string& name) {
3030 PrintingPolicy Policy(Context.getPrintingPolicy());
3031 Policy.SuppressTagKeyword =
true;
3032 Policy.SuppressUnwrittenScope =
true;
3033 Policy.Print_Canonical_Types =
true;
3034 if (
const auto* TD = dyn_cast<TypeDecl>(D)) {
3037 if (
const auto* Typedef = dyn_cast<const TypedefDecl>(TD)) {
3039 QT = Typedef->getTypeSourceInfo()->getType();
3042 get_type_as_string(QT, name, Context, Policy);
3043 }
else if (
const auto* ND = dyn_cast<NamedDecl>(D)) {
3045 raw_string_ostream stream(name);
3046 ND->getNameForDiagnostic(stream, Policy,
true);
3051void collect_type_info(
const FunctionDecl* FD, QualType& QT,
3052 std::ostringstream& typedefbuf,
3053 std::ostringstream& callbuf, std::string& type_name,
3054 EReferenceType& refType,
bool& isPointer,
3055 int indent_level,
bool forArgument) {
3060 ASTContext& C = FD->getASTContext();
3061 PrintingPolicy Policy(C.getPrintingPolicy());
3062 Policy.Suppress_Elab =
true;
3063 refType = kNotReference;
3064 if (QT->isRecordType()) {
3066 get_type_as_string(QT, type_name, C, Policy);
3069 if (
auto* CXXRD = QT->getAsCXXRecordDecl()) {
3070 if (CXXRD->isLambda()) {
3071 std::string fn_name;
3072 llvm::raw_string_ostream stream(fn_name);
3073 Policy.FullyQualifiedName =
true;
3074 Policy.SuppressUnwrittenScope =
true;
3075 FD->getNameForDiagnostic(stream, Policy,
3077 type_name =
"__internal_CppInterOp::function<decltype(" + fn_name +
3083 if (QT.getNonReferenceType()->isFunctionPointerType() ||
3084 QT.getNonReferenceType()->isFunctionProtoType()) {
3085 clang::QualType NRQT = QT.getNonReferenceType();
3086 std::string fp_typedef_name;
3088 std::ostringstream nm;
3089 nm <<
"FP" << gWrapperSerial++;
3090 type_name = nm.str();
3091 raw_string_ostream OS(fp_typedef_name);
3092 NRQT.print(OS, Policy, type_name);
3096 indent(typedefbuf, indent_level);
3098 typedefbuf <<
"typedef " << fp_typedef_name <<
";\n";
3100 if (QT->isRValueReferenceType())
3101 refType = kRValueReference;
3103 refType = kLValueReference;
3105 }
else if (QT->isMemberPointerType()) {
3106 std::string mp_typedef_name;
3108 std::ostringstream nm;
3109 nm <<
"MP" << gWrapperSerial++;
3110 type_name = nm.str();
3111 raw_string_ostream OS(mp_typedef_name);
3112 QT.print(OS, Policy, type_name);
3116 indent(typedefbuf, indent_level);
3118 typedefbuf <<
"typedef " << mp_typedef_name <<
";\n";
3120 }
else if (QT->isPointerType()) {
3122 QT = cast<clang::PointerType>(QT.getCanonicalType())->getPointeeType();
3123 }
else if (QT->isReferenceType()) {
3124 if (QT->isRValueReferenceType())
3125 refType = kRValueReference;
3127 refType = kLValueReference;
3128 QT = cast<ReferenceType>(QT.getCanonicalType())->getPointeeType();
3132 if (QT->isArrayType()) {
3133 std::string ar_typedef_name;
3135 std::ostringstream ar;
3136 ar <<
"AR" << gWrapperSerial++;
3137 type_name = ar.str();
3138 raw_string_ostream OS(ar_typedef_name);
3139 QT.print(OS, Policy, type_name);
3142 indent(typedefbuf, indent_level);
3143 typedefbuf <<
"typedef " << ar_typedef_name <<
";\n";
3146 get_type_as_string(QT, type_name, C, Policy);
3149void make_narg_ctor(
const FunctionDecl* FD,
const unsigned N,
3150 std::ostringstream& typedefbuf, std::ostringstream& callbuf,
3151 const std::string& class_name,
int indent_level,
3152 bool array =
false) {
3161 callbuf << class_name <<
"[nary]";
3163 callbuf << class_name;
3168 for (
unsigned i = 0U; i < N; ++i) {
3169 const ParmVarDecl* PVD = FD->getParamDecl(i);
3170 QualType Ty = PVD->getType();
3171 QualType QT = Ty.getCanonicalType();
3172 std::string type_name;
3173 EReferenceType refType = kNotReference;
3174 bool isPointer =
false;
3175 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3176 isPointer, indent_level,
true);
3183 indent(callbuf, indent_level);
3186 if (refType != kNotReference) {
3187 callbuf <<
"(" << type_name.c_str()
3188 << (refType == kLValueReference ?
"&" :
"&&") <<
")*("
3189 << type_name.c_str() <<
"*)args[" << i <<
"]";
3190 }
else if (isPointer) {
3191 callbuf <<
"*(" << type_name.c_str() <<
"**)args[" << i <<
"]";
3193 callbuf <<
"*(" << type_name.c_str() <<
"*)args[" << i <<
"]";
3199 else if (
const auto* CD = dyn_cast<CXXConstructorDecl>(FD);
3200 CD && CD->isDefaultConstructor() && !array) {
3205const DeclContext* get_non_transparent_decl_context(
const FunctionDecl* FD) {
3206 const auto* DC = FD->getDeclContext();
3207 while (DC->isTransparentContext()) {
3208 DC = DC->getParent();
3209 assert(DC &&
"All transparent contexts should have a parent!");
3214void make_narg_call(
const FunctionDecl* FD,
const std::string& return_type,
3215 const unsigned N, std::ostringstream& typedefbuf,
3216 std::ostringstream& callbuf,
const std::string& class_name,
3237 bool op_flag = !FD->isOverloadedOperator() ||
3238 FD->getOverloadedOperator() == clang::OO_Call;
3240 bool ShouldCastFunction = !isa<CXXMethodDecl>(FD) &&
3241 N == FD->getNumParams() && op_flag &&
3242 !FD->isTemplateInstantiation();
3243 if (ShouldCastFunction) {
3246 callbuf << return_type <<
" (&)";
3249 for (
unsigned i = 0U; i < N; ++i) {
3256 indent(callbuf, indent_level + 1);
3259 const ParmVarDecl* PVD = FD->getNonObjectParameter(i);
3260 QualType Ty = PVD->getType();
3261 QualType QT = Ty.getCanonicalType();
3262 std::string arg_type;
3263 ASTContext& C = FD->getASTContext();
3264 get_type_as_string(QT, arg_type, C, C.getPrintingPolicy());
3265 callbuf << arg_type;
3267 if (FD->isVariadic())
3275 if (
const auto* MD = dyn_cast<CXXMethodDecl>(FD)) {
3280 bool rvalue_ref = MD->getRefQualifier() == clang::RQ_RValue ||
3281 (MD->hasCXXExplicitFunctionObjectParameter() &&
3282 MD->getParamDecl(0)->getType()->isRValueReferenceType());
3284 callbuf <<
"static_cast<" << class_name <<
"&&>(*(" << class_name
3286 else if (MD->isConst())
3287 callbuf <<
"((const " << class_name <<
"*)obj)->";
3289 callbuf <<
"((" << class_name <<
"*)obj)->";
3292 callbuf << class_name <<
"::";
3293 }
else if (isa<NamedDecl>(get_non_transparent_decl_context(FD))) {
3295 if (op_flag || N <= 1)
3296 callbuf << class_name <<
"::";
3302 std::string complete_name;
3303 llvm::raw_string_ostream stream(complete_name);
3304 PrintingPolicy PP = FD->getASTContext().getPrintingPolicy();
3305 PP.FullyQualifiedName =
true;
3306 PP.SuppressUnwrittenScope =
true;
3307 PP.Suppress_Elab =
true;
3308 FD->getNameForDiagnostic(stream, PP,
3310 name = complete_name;
3317 std::string simple_name = FD->getNameAsString();
3318 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
3319 const auto* FTDecl =
3320 llvm::dyn_cast<FunctionTemplateDecl>(FD->getPrimaryTemplate());
3322 auto* templateParms = FTDecl->getTemplateParameters();
3324 for (
size_t iParam = 0, nParams = templateParms->size();
3325 iParam < nParams; ++iParam) {
3326 if (templateParms->getParam(iParam)->isTemplateParameterPack())
3336 if (FD->isOverloadedOperator())
3339 if (op_flag || N <= 1)
3342 if (ShouldCastFunction)
3346 for (
unsigned i = 0U; i < N; ++i) {
3347 const ParmVarDecl* PVD = FD->getNonObjectParameter(i);
3348 QualType Ty = PVD->getType();
3349 QualType QT = Ty.getCanonicalType();
3350 std::string type_name;
3351 EReferenceType refType = kNotReference;
3352 bool isPointer =
false;
3353 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3354 isPointer, indent_level,
true);
3361 << clang::getOperatorSpelling(FD->getOverloadedOperator())
3366 CXXRecordDecl* rtdecl = QT->getAsCXXRecordDecl();
3367 if (refType != kNotReference) {
3368 callbuf <<
"(" << type_name.c_str()
3369 << (refType == kLValueReference ?
"&" :
"&&") <<
")*("
3370 << type_name.c_str() <<
"*)args[" << i <<
"]";
3371 }
else if (isPointer) {
3372 callbuf <<
"*(" << type_name.c_str() <<
"**)args[" << i <<
"]";
3373 }
else if (rtdecl &&
3374 (rtdecl->hasTrivialCopyConstructor() &&
3375 !rtdecl->hasSimpleCopyConstructor()) &&
3376 rtdecl->hasMoveConstructor()) {
3393 callbuf <<
"static_cast<" << type_name.c_str() <<
"&&>(*("
3394 << type_name.c_str() <<
"*)args[" << i <<
"])";
3398 callbuf <<
"*(" << type_name.c_str() <<
"*)args[" << i <<
"]";
3404void make_narg_ctor_with_return(
const FunctionDecl* FD,
const unsigned N,
3405 const std::string& class_name,
3406 std::ostringstream& buf,
int indent_level) {
3419 std::ostringstream typedefbuf;
3420 std::ostringstream callbuf;
3424 indent(callbuf, indent_level);
3425 const auto* CD = dyn_cast<CXXConstructorDecl>(FD);
3433 if (CD->isDefaultConstructor()) {
3434 callbuf <<
"if (nary > 1) {\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,
3441 callbuf <<
": new ";
3445 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
3451 indent(callbuf, indent_level);
3453 callbuf <<
"else {\n";
3459 indent(callbuf, indent_level);
3460 callbuf <<
"(*(" << class_name <<
"**)ret) = ";
3461 callbuf <<
"(is_arena) ? new (*(" << class_name <<
"**)ret) ";
3462 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
3464 callbuf <<
": new ";
3468 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
3473 indent(callbuf, --indent_level);
3474 if (CD->isDefaultConstructor())
3476#if __has_feature(memory_sanitizer)
3479 indent(callbuf, indent_level);
3480 callbuf <<
"__msan_unpoison(*(void**)ret, sizeof(" << class_name
3481 <<
") * (nary > 1 ? nary : 1));\n";
3487 buf << typedefbuf.str() << callbuf.str();
3492 const unsigned N,
const std::string& class_name,
3493 std::ostringstream& buf,
int indent_level) {
3503 if (
const auto* CD = dyn_cast<CXXConstructorDecl>(FD)) {
3504 if (N <= 1 && llvm::isa<UsingShadowDecl>(FD)) {
3505 auto SpecMemKind = I.
getCI()->getSema().getSpecialMember(CD);
3506 if ((N == 0 && SpecMemKind == CXXSpecialMemberKind::DefaultConstructor) ||
3507 (N == 1 && (SpecMemKind == CXXSpecialMemberKind::CopyConstructor ||
3508 SpecMemKind == CXXSpecialMemberKind::MoveConstructor))) {
3516 make_narg_ctor_with_return(FD, N, class_name, buf, indent_level);
3519 QualType QT = FD->getReturnType();
3520 if (QT->isVoidType()) {
3521 std::ostringstream typedefbuf;
3522 std::ostringstream callbuf;
3523 indent(callbuf, indent_level);
3524 make_narg_call(FD,
"void", N, typedefbuf, callbuf, class_name,
3527 indent(callbuf, indent_level);
3528 callbuf <<
"return;\n";
3529 buf << typedefbuf.str() << callbuf.str();
3531 indent(buf, indent_level);
3533 std::string type_name;
3534 EReferenceType refType = kNotReference;
3535 bool isPointer =
false;
3537 std::ostringstream typedefbuf;
3538 std::ostringstream callbuf;
3540 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3541 isPointer, indent_level,
false);
3543 buf << typedefbuf.str();
3545 buf <<
"if (ret) {\n";
3551 indent(callbuf, indent_level);
3552 callbuf <<
"new (ret) ";
3556 callbuf <<
"(" << type_name.c_str();
3557 if (refType != kNotReference) {
3560 }
else if (isPointer) {
3569 make_narg_call(FD, type_name, N, typedefbuf, callbuf, class_name,
3575#if __has_feature(memory_sanitizer)
3576 indent(callbuf, indent_level);
3577 callbuf <<
"__msan_unpoison(ret, sizeof(" << type_name <<
"));\n";
3579 indent(callbuf, indent_level);
3580 callbuf <<
"return;\n";
3584 buf << typedefbuf.str() << callbuf.str();
3587 indent(buf, indent_level);
3589 indent(buf, indent_level);
3593 std::ostringstream typedefbuf;
3594 std::ostringstream callbuf;
3595 indent(callbuf, indent_level);
3596 callbuf <<
"(void)(";
3597 make_narg_call(FD, type_name, N, typedefbuf, callbuf, class_name,
3600 indent(callbuf, indent_level);
3601 callbuf <<
"return;\n";
3602 buf << typedefbuf.str() << callbuf.str();
3605 indent(buf, indent_level);
3611 std::string& wrapper_name, std::string& wrapper) {
3612 assert(FD &&
"generate_wrapper called without a function decl!");
3613 ASTContext& Context = FD->getASTContext();
3617 std::string class_name;
3618 const clang::DeclContext* DC = get_non_transparent_decl_context(FD);
3619 GetDeclName(cast<Decl>(DC), Context, class_name);
3624 bool needInstantiation =
false;
3625 const FunctionDecl* Definition = 0;
3627 if (!FD->isDefined(Definition)) {
3628 FunctionDecl::TemplatedKind TK = FD->getTemplatedKind();
3630 case FunctionDecl::TK_NonTemplate: {
3640 case FunctionDecl::TK_FunctionTemplate: {
3643 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3645 <<
"Cannot make wrapper for a function template!";
3648 case FunctionDecl::TK_MemberSpecialization: {
3655 if (!FD->isTemplateInstantiation()) {
3668 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3670 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3672 <<
"Cannot make wrapper for a member function "
3673 "instantiation with no pattern!";
3676 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3677 TemplateSpecializationKind PTSK =
3678 Pattern->getTemplateSpecializationKind();
3681 (PTK == FunctionDecl::TK_NonTemplate) ||
3684 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3685 ((PTSK == TSK_Undeclared) ||
3686 (PTSK == TSK_ExplicitSpecialization)))) {
3691 }
else if (!Pattern->hasBody()) {
3692 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3694 <<
"Cannot make wrapper for a member function "
3695 "instantiation with no body!";
3698 if (FD->isImplicitlyInstantiable()) {
3699 needInstantiation =
true;
3702 case FunctionDecl::TK_FunctionTemplateSpecialization: {
3707 if (!FD->isTemplateInstantiation()) {
3720 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3722 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3724 <<
"Cannot make wrapper for a function template"
3725 "instantiation with no pattern!";
3728 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3729 TemplateSpecializationKind PTSK =
3730 Pattern->getTemplateSpecializationKind();
3733 (PTK == FunctionDecl::TK_NonTemplate) ||
3736 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3737 ((PTSK == TSK_Undeclared) ||
3738 (PTSK == TSK_ExplicitSpecialization)))) {
3745 if (!Pattern->hasBody()) {
3746 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3748 <<
"Cannot make wrapper for a function template "
3749 <<
"instantiation with no body!";
3752 if (FD->isImplicitlyInstantiable()) {
3753 needInstantiation =
true;
3757 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
3765 if (!FD->isTemplateInstantiation()) {
3778 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3780 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3782 <<
"Cannot make wrapper for a dependent function template"
3783 "instantiation with no pattern!";
3786 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3787 TemplateSpecializationKind PTSK =
3788 Pattern->getTemplateSpecializationKind();
3791 (PTK == FunctionDecl::TK_NonTemplate) ||
3794 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3795 ((PTSK == TSK_Undeclared) ||
3796 (PTSK == TSK_ExplicitSpecialization)))) {
3802 if (!Pattern->hasBody()) {
3803 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3805 <<
"Cannot make wrapper for a dependent function template"
3806 "instantiation with no body!";
3809 if (FD->isImplicitlyInstantiable()) {
3810 needInstantiation =
true;
3816 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3818 <<
"Unhandled template kind!";
3840 if (needInstantiation) {
3841 clang::FunctionDecl* FDmod =
const_cast<clang::FunctionDecl*
>(FD);
3844 if (!FD->isDefined(Definition)) {
3845 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3847 <<
"Failed to force template instantiation!";
3852 FunctionDecl::TemplatedKind TK = Definition->getTemplatedKind();
3854 case FunctionDecl::TK_NonTemplate: {
3856 if (Definition->isDeleted()) {
3857 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3859 <<
"Cannot make wrapper for a deleted function!";
3861 }
else if (Definition->isLateTemplateParsed()) {
3862 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3864 <<
"Cannot make wrapper for a late template parsed "
3875 case FunctionDecl::TK_FunctionTemplate: {
3878 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3880 <<
"Cannot make wrapper for a function template!";
3883 case FunctionDecl::TK_MemberSpecialization: {
3887 if (Definition->isDeleted()) {
3888 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3890 <<
"Cannot make wrapper for a deleted member function "
3891 "of a specialization!";
3893 }
else if (Definition->isLateTemplateParsed()) {
3894 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3896 <<
"Cannot make wrapper for a late template parsed "
3897 "member function of a specialization!";
3907 case FunctionDecl::TK_FunctionTemplateSpecialization: {
3912 if (Definition->isDeleted()) {
3913 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3915 <<
"Cannot make wrapper for a deleted function "
3916 "template specialization!";
3918 }
else if (Definition->isLateTemplateParsed()) {
3919 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3921 <<
"Cannot make wrapper for a late template parsed "
3922 "function template specialization!";
3932 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
3940 if (Definition->isDeleted()) {
3941 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3943 <<
"Cannot make wrapper for a deleted dependent function "
3944 "template specialization!";
3946 }
else if (Definition->isLateTemplateParsed()) {
3947 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3949 <<
"Cannot make wrapper for a late template parsed "
3950 "dependent function template specialization!";
3963 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3965 <<
"Unhandled template kind!";
3973 unsigned min_args = FD->getMinRequiredExplicitArguments();
3974 unsigned num_params = FD->getNumNonObjectParams();
3979 std::ostringstream buf;
3985 buf <<
'_' << gWrapperSerial++;
3986 wrapper_name = buf.str();
3992 int indent_level = 0;
3993 std::ostringstream buf;
3994 buf <<
"#pragma clang diagnostic push\n"
3995 "#pragma clang diagnostic ignored \"-Wformat-security\"\n";
3996#if __has_feature(memory_sanitizer)
3999 buf <<
"extern \"C\" void __msan_unpoison(const volatile void*, "
4000 "unsigned long);\n";
4002 buf <<
"__attribute__((used)) "
4003 "__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
4004 "extern \"C\" void ";
4005 buf << wrapper_name;
4007 buf <<
"(void* ret, unsigned long nary, unsigned long nargs, void** args, "
4011 buf <<
"(void* obj, unsigned long nargs, void** args, void* ret)\n"
4015 if (min_args == num_params) {
4017 make_narg_call_with_return(I, FD, num_params, class_name, buf,
4022 for (
unsigned N = min_args; N <= num_params; ++N) {
4023 indent(buf, indent_level);
4024 buf <<
"if (nargs == " << N <<
") {\n";
4026 make_narg_call_with_return(I, FD, N, class_name, buf, indent_level);
4028 indent(buf, indent_level);
4034 "#pragma clang diagnostic pop";
4035 wrapper = buf.str();
4040 const FunctionDecl* FD) {
4043 auto R = WrapperStore.find(FD);
4044 if (R != WrapperStore.end())
4045 return (JitCall::GenericCall)R->second;
4047 std::string wrapper_name;
4048 std::string wrapper_code;
4050 if (get_wrapper_code(I, FD, wrapper_name, wrapper_code) == 0)
4055 std::string FuncName;
4056 llvm::raw_string_ostream FNS(FuncName);
4057 FD->getNameForDiagnostic(FNS, FD->getASTContext().getPrintingPolicy(),
4059 TI->appendToLog(
" // === Wrapper for " + FuncName +
" ===");
4061 llvm::StringRef WC(wrapper_code);
4062 while (!WC.empty()) {
4063 auto [Line, Rest] = WC.split(
'\n');
4065 TI->appendToLog((
" // " + Line).str());
4068 TI->appendToLog(
" // === End wrapper ===");
4074 bool withAccessControl =
true;
4076 if (
auto Ctor = dyn_cast<CXXConstructorDecl>(FD))
4077 withAccessControl = !Ctor->isDefaultConstructor();
4079 compile_wrapper(I, wrapper_name, wrapper_code, withAccessControl);
4081 WrapperStore.insert(std::make_pair(FD, wrapper));
4083 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4085 <<
"Failed to compile\n"
4086 <<
"==== SOURCE BEGIN ====\n"
4087 << wrapper_code <<
"\n"
4088 <<
"==== SOURCE END ====\n";
4090 LLVM_DEBUG(dbgs() <<
"Compiled '" << (wrapper ?
"" :
"un")
4091 <<
"successfully:\n"
4092 << wrapper_code <<
"'\n");
4093 return (JitCall::GenericCall)wrapper;
4097static std::string PrepareStructorWrapper(
const Decl* D,
4098 const char* wrapper_prefix,
4099 std::string& class_name) {
4100 ASTContext& Context = D->getASTContext();
4101 GetDeclName(D, Context, class_name);
4106 std::string wrapper_name;
4108 std::ostringstream buf;
4109 buf << wrapper_prefix;
4114 buf <<
'_' << gWrapperSerial++;
4115 wrapper_name = buf.str();
4118 return wrapper_name;
4153 auto I = DtorWrapperStore.find(D);
4154 if (I != DtorWrapperStore.end())
4155 return (JitCall::DestructorCall)I->second;
4160 std::string class_name;
4161 std::string wrapper_name = PrepareStructorWrapper(D,
"__dtor", class_name);
4165 int indent_level = 0;
4166 std::ostringstream buf;
4167#if CPPINTEROP_ASAN_BUILD
4177 buf <<
"extern \"C\" void __lsan_ignore_object(const void*);\n";
4179 buf <<
"__attribute__((used)) ";
4180 buf <<
"extern \"C\" void ";
4181 buf << wrapper_name;
4182 buf <<
"(void* obj, unsigned long nary, int withFree)\n";
4194 indent(buf, indent_level);
4195 buf <<
"if (withFree) {\n";
4197#if CPPINTEROP_ASAN_BUILD
4198 indent(buf, indent_level);
4199 buf <<
"__lsan_ignore_object(obj);\n";
4201 indent(buf, indent_level);
4202 buf <<
"if (!nary) {\n";
4204 indent(buf, indent_level);
4205 buf <<
"delete (" << class_name <<
"*) obj;\n";
4207 indent(buf, indent_level);
4209 indent(buf, indent_level);
4212 indent(buf, indent_level);
4213 buf <<
"delete[] (" << class_name <<
"*) obj;\n";
4215 indent(buf, indent_level);
4218 indent(buf, indent_level);
4231 indent(buf, indent_level);
4234 indent(buf, indent_level);
4235 buf <<
"typedef " << class_name <<
" Nm;\n";
4236 buf <<
"if (!nary) {\n";
4238 indent(buf, indent_level);
4239 buf <<
"((Nm*)obj)->~Nm();\n";
4241 indent(buf, indent_level);
4243 indent(buf, indent_level);
4246 indent(buf, indent_level);
4249 indent(buf, indent_level);
4250 buf <<
"(((Nm*)obj)+(--nary))->~Nm();\n";
4252 indent(buf, indent_level);
4253 buf <<
"} while (nary);\n";
4255 indent(buf, indent_level);
4258 indent(buf, indent_level);
4264 std::string wrapper(buf.str());
4269 void* F = compile_wrapper(interp, wrapper_name, wrapper,
4272 DtorWrapperStore.insert(std::make_pair(D, F));
4274 llvm::errs() <<
"make_dtor_wrapper"
4275 <<
"Failed to compile\n"
4276 <<
"==== SOURCE BEGIN ====\n"
4277 << wrapper <<
"\n ==== SOURCE END ====";
4279 LLVM_DEBUG(dbgs() <<
"Compiled '" << (F ?
"" :
"un") <<
"successfully:\n"
4280 << wrapper <<
"'\n");
4281 return (JitCall::DestructorCall)F;
4289 const auto* D = unwrap<clang::Decl>(func);
4293 auto* interp = unwrap<compat::Interpreter>(I);
4296 if (
const auto* Dtor = dyn_cast<CXXDestructorDecl>(D)) {
4297 if (
auto Wrapper = make_dtor_wrapper(*interp, Dtor->getParent()))
4299 JitCall(JitCall::kDestructorCall, Wrapper, wrap<ConstFuncRef>(Dtor)));
4304 if (
const auto* Ctor = dyn_cast<CXXConstructorDecl>(D)) {
4305 if (
auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D)))
4306 return INTEROP_RETURN(JitCall(JitCall::kConstructorCall, Wrapper,
4307 wrap<ConstFuncRef>(Ctor)));
4312 if (
auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D))) {
4314 wrap<ConstFuncRef>(cast<FunctionDecl>(D))));
4326#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
4329 using namespace llvm;
4330 using namespace llvm::orc;
4333 JITDylib& DyLib = *Jit.getProcessSymbolsJITDylib().get();
4340 llvm::orc::SymbolMap InjectedSymbols{
4341 {Jit.mangleAndIntern(unmangled_name),
4342 ExecutorSymbolDef(ExecutorAddr(address), JITSymbolFlags::Exported)}};
4344 if (Error Err = DyLib.define(absoluteSymbols(InjectedSymbols))) {
4345 logAllUnhandledErrors(std::move(Err), errs(),
4346 "DefineAbsoluteSymbol error: ");
4353static std::string MakeResourcesPath() {
4355#ifdef LLVM_BINARY_DIR
4356 Dir = LLVM_BINARY_DIR;
4363 StringRef Dir = sys::path::parent_path(BinaryPath);
4365 Dir = sys::path::parent_path(Dir);
4366 Dir = sys::path::parent_path(Dir);
4367 Dir = sys::path::parent_path(Dir);
4368 Dir = sys::path::parent_path(Dir);
4371 llvm::SmallString<128> P(Dir);
4372 llvm::sys::path::append(P, CLANG_INSTALL_LIBDIR_BASENAME,
"clang",
4373 CLANG_VERSION_MAJOR_STRING);
4374 return std::string(P.str());
4377void AddLibrarySearchPaths(
const std::string& ResourceDir,
4386 std::string path1 = ResourceDir +
"/lib";
4388 size_t pos = ResourceDir.rfind(
"/llvm-");
4389 if (pos != std::string::npos) {
4393 pos = ResourceDir.rfind(
"/clang");
4394 if (pos != std::string::npos) {
4399std::string ExtractArgument(
const std::vector<const char*>& Args,
4400 const std::string& Arg) {
4402 for (
auto i = Args.begin(); i != Args.end(); i++)
4403 if ((++I < Args.size()) && (*i == Arg))
4410 const std::vector<const char*>& GpuArgs ) {
4412 std::string MainExecutableName = sys::fs::getMainExecutable(
nullptr,
nullptr);
4419 std::string ResourceDir = ExtractArgument(Args,
"-resource-dir");
4420 if (ResourceDir.empty())
4421 ResourceDir = MakeResourcesPath();
4422 llvm::Triple T(llvm::sys::getProcessTriple());
4423 if ((!sys::fs::is_directory(ResourceDir)) &&
4424 (T.isOSDarwin() || T.isOSLinux()))
4427 std::vector<const char*> ClingArgv = {
"-std=c++14"};
4428 if (!ResourceDir.empty())
4429 ClingArgv.insert(ClingArgv.begin(), {
"-resource-dir", ResourceDir.c_str()});
4430 ClingArgv.insert(ClingArgv.begin(), MainExecutableName.c_str());
4433 ClingArgv.push_back(
"-fno-delayed-template-parsing");
4435#if __has_feature(memory_sanitizer)
4440 ClingArgv.push_back(
"-stdlib=libc++");
4448 std::string LibcxxIncDir;
4449 if (!ResourceDir.empty()) {
4450 SmallString<256> P(ResourceDir);
4451 sys::path::remove_filename(P);
4452 sys::path::remove_filename(P);
4453 sys::path::remove_filename(P);
4454 sys::path::append(P,
"include",
"c++",
"v1");
4455 if (sys::fs::is_directory(P)) {
4456 LibcxxIncDir = P.str().str();
4457 ClingArgv.push_back(
"-cxx-isystem");
4458 ClingArgv.push_back(LibcxxIncDir.c_str());
4462 ClingArgv.insert(ClingArgv.end(), Args.begin(), Args.end());
4466 if (!GpuArgs.empty()) {
4467 llvm::StringRef Arg0 = GpuArgs[0];
4468 Arg0 = Arg0.trim().ltrim(
'-');
4469 if (Arg0 !=
"cuda") {
4470 llvm::errs() <<
"[CreateInterpreter]: Make sure --cuda is passed as the"
4471 <<
" first argument of the GpuArgs\n";
4475 ClingArgv.insert(ClingArgv.end(), GpuArgs.begin(), GpuArgs.end());
4478 std::vector<std::string> ExtraArgs;
4479 auto EnvOpt = llvm::sys::Process::GetEnv(
"CPPINTEROP_EXTRA_INTERPRETER_ARGS");
4481 StringRef Env(*EnvOpt);
4482 while (!Env.empty()) {
4484 std::tie(Arg, Env) = Env.split(
' ');
4485 ExtraArgs.push_back(Arg.str());
4488 std::transform(ExtraArgs.begin(), ExtraArgs.end(),
4489 std::back_inserter(ClingArgv),
4490 [&](
const std::string& str) { return str.c_str(); });
4495#ifdef CPPINTEROP_USE_CLING
4500 ClingArgv.data(),
nullptr, {},
nullptr,
true);
4503 auto* I = Interp.release();
4510 const CompilerInstance* Clang = I->getCI();
4511 if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
4512 unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
4513 auto Args = std::make_unique<const char*[]>(NumArgs + 2);
4514 Args[0] =
"clang (LLVM option parsing)";
4515 for (
unsigned i = 0; i != NumArgs; ++i)
4516 Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
4517 Args[NumArgs + 1] =
nullptr;
4518 llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
4522 AddLibrarySearchPaths(ResourceDir, I);
4526 namespace __internal_CppInterOp {
4527 template <typename Signature>
4529 template <typename Res, typename... ArgTypes>
4530 struct function<Res(ArgTypes...)> {
4531 typedef Res result_type;
4533 } // namespace __internal_CppInterOp
4540#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
4541 DefineAbsoluteSymbol(*I,
"__ci_newtag",
4544#if CLANG_VERSION_MAJOR >= 21
4545 DefineAbsoluteSymbol(
4546 *I,
"__clang_Interpreter_SetValueWithAlloc",
4551 unwrap<Decl>(
Cpp::GetNamed(
"__clang_Interpreter_SetValueWithAlloc"));
4552 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
4553 auto GD = GlobalDecl(FD);
4554 std::string mangledName;
4556 DefineAbsoluteSymbol(
4557 *I, mangledName.c_str(),
4562 DefineAbsoluteSymbol(
4563 *I,
"__clang_Interpreter_SetValueNoAlloc",
4572 const auto& LO = interp->
getCI()->getLangOpts();
4580 auto standard = clang::LangStandard::getLangStandardForKind(LO.LangStd);
4581 auto lang =
static_cast<InterpreterLanguage
>(standard.getLanguage());
4582 assert(lang != InterpreterLanguage::Unknown &&
"Unknown language");
4583 assert(
static_cast<unsigned char>(lang) <=
4584 static_cast<unsigned char>(InterpreterLanguage::HLSL) &&
4585 "Unhandled Language");
4592 const auto& LO = interp->
getCI()->getLangOpts();
4593 auto langStandard =
static_cast<InterpreterLanguageStandard
>(LO.LangStd);
4594 assert(langStandard != InterpreterLanguageStandard::lang_unspecified &&
4595 "Unspecified language standard");
4596 assert(
static_cast<unsigned char>(langStandard) <=
4597 static_cast<unsigned char>(
4598 InterpreterLanguageStandard::lang_unspecified) &&
4599 "Unhandled language standard.");
4612 getInterp().getCI()->getHeaderSearchOpts().ResourceDir.c_str());
4616static bool exec(
const char* cmd, std::vector<std::string>& outputs) {
4617#define DEBUG_TYPE "exec"
4619 std::array<char, 256> buffer;
4620 struct file_deleter {
4621 void operator()(FILE* fp) { pclose(fp); }
4623 std::unique_ptr<FILE, file_deleter> pipe{popen(cmd,
"r")};
4624 LLVM_DEBUG(dbgs() <<
"Executing command '" << cmd <<
"'\n");
4627 LLVM_DEBUG(dbgs() <<
"Execute failed!\n");
4632 LLVM_DEBUG(dbgs() <<
"Execute returned:\n");
4633 while (fgets(buffer.data(),
static_cast<int>(buffer.size()), pipe.get())) {
4634 LLVM_DEBUG(dbgs() << buffer.data());
4635 llvm::StringRef trimmed = buffer.data();
4636 outputs.push_back(trimmed.trim().str());
4646 std::string cmd = std::string(ClangBinaryName) +
" -print-resource-dir";
4647 std::vector<std::string> outs;
4648 exec(cmd.c_str(), outs);
4649 if (outs.empty() || outs.size() > 1)
4652 std::string detected_resource_dir = outs.back();
4654 std::string version = CLANG_VERSION_MAJOR_STRING;
4656 if (llvm::sys::path::filename(detected_resource_dir) != version)
4663 const char* CompilerName ) {
4665 std::string cmd =
"LC_ALL=C ";
4666 cmd += CompilerName;
4667 cmd +=
" -xc++ -E -v /dev/null 2>&1 | sed -n -e '/^.include/,${' -e '/^ "
4669 std::vector<std::string> outs;
4670 exec(cmd.c_str(), Paths);
4683 llvm::SmallVector<std::string> paths(1);
4685 for (
auto& i : paths)
4686 IncludePaths.push_back(i);
4693 clangSilent(clang::DiagnosticsEngine& diag) :
fDiagEngine(diag) {
4698 ~clangSilent() {
fDiagEngine.setSuppressAllDiagnostics(fOldDiagValue); }
4710 clang::DiagnosticsEngine& Diag = I.
getSema().getDiagnostics();
4711 clang::DiagnosticErrorTrap Trap(Diag);
4713 clangSilent diagSuppr(Diag);
4714 auto result = I.
declare(code);
4715 if (Trap.hasErrorOccurred())
4719 auto result = I.
declare(code);
4720 if (Trap.hasErrorOccurred())
4743 if (
const auto* BT = QT->getAs<clang::BuiltinType>()) {
4744 switch (BT->getKind()) {
4745 case clang::BuiltinType::Bool:
4747 case clang::BuiltinType::Char_S:
4749 case clang::BuiltinType::Char_U:
4753 case clang::BuiltinType::SChar:
4755 case clang::BuiltinType::UChar:
4757 case clang::BuiltinType::Short:
4759 case clang::BuiltinType::UShort:
4761 case clang::BuiltinType::Int:
4763 case clang::BuiltinType::UInt:
4765 case clang::BuiltinType::Long:
4767 case clang::BuiltinType::ULong:
4769 case clang::BuiltinType::LongLong:
4771 case clang::BuiltinType::ULongLong:
4773 case clang::BuiltinType::Float:
4775 case clang::BuiltinType::Double:
4777 case clang::BuiltinType::LongDouble:
4781 "clang::Value asserts on builtins outside the X-macro set");
4792 if (res != 0 || !V.hasValue())
4795 clang::QualType QT = V.getType();
4796 void* qt = QT.getAsOpaquePtr();
4798#define X(TyRef, name) \
4799 case Cpp::Box::K_##name: \
4800 return INTEROP_RETURN( \
4801 Cpp::Box::Create<TyRef>(compat::convertTo<TyRef>(V), qt));
4811 llvm_unreachable(
"Box::Kind not produced by classifyByQualType");
4813 llvm_unreachable(
"classifyByQualType returned an unhandled Kind");
4819 getInterp().getDynamicLibraryManager()->lookupLibrary(lib_name));
4837 bool search_system ) {
4841 DLM->searchLibrariesForSymbol(mangled_name, search_system));
4845 const char* linker_mangled_name,
4869 using namespace llvm;
4870 using namespace llvm::orc;
4874 llvm::orc::ExecutionSession& ES = Jit.getExecutionSession();
4875 JITDylib& DyLib = *Jit.getProcessSymbolsJITDylib().get();
4877 if (Error Err = Symbol.takeError()) {
4878 logAllUnhandledErrors(std::move(Err), errs(),
4879 "[InsertOrReplaceJitSymbol] error: ");
4880#define DEBUG_TYPE "orc"
4881 LLVM_DEBUG(ES.dump(dbgs()));
4887 if (*Symbol && *Symbol == address) {
4888 errs() <<
"[InsertOrReplaceJitSymbol] warning: redefining '"
4889 << linker_mangled_name <<
"' with the same address\n";
4894 llvm::orc::SymbolMap InjectedSymbols;
4896 char GlobalPrefix = DL.getGlobalPrefix();
4897 std::string tmp(linker_mangled_name);
4898 if (GlobalPrefix !=
'\0') {
4899 tmp = std::string(1, GlobalPrefix) + tmp;
4901 auto Name = ES.intern(tmp);
4902 InjectedSymbols[Name] =
4903 ExecutorSymbolDef(ExecutorAddr(address), JITSymbolFlags::Exported);
4906 if (Symbol && address)
4908 if (
auto Err = DyLib.remove({Name})) {
4909 logAllUnhandledErrors(std::move(Err), errs(),
4910 "[InsertOrReplaceJitSymbol] error: ");
4914 if (Error Err = DyLib.define(absoluteSymbols(InjectedSymbols))) {
4915 logAllUnhandledErrors(std::move(Err), errs(),
4916 "[InsertOrReplaceJitSymbol] error: ");
4936 TemplateArgumentListInfo& TLI, Sema& S,
4937 bool instantiate_body) {
4941 if (
auto* FunctionTemplate = dyn_cast<FunctionTemplateDecl>(TemplateD)) {
4942 FunctionDecl* Specialization =
nullptr;
4943 clang::sema::TemplateDeductionInfo Info(fakeLoc);
4944 TemplateDeductionResult Result =
4945 S.DeduceTemplateArguments(FunctionTemplate, &TLI, Specialization, Info,
4947 if (Result != TemplateDeductionResult::Success) {
4951 if (instantiate_body)
4953 return Specialization;
4956 if (
auto* VarTemplate = dyn_cast<VarTemplateDecl>(TemplateD)) {
4957#if CLANG_VERSION_MAJOR < 22
4958 DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI);
4960 DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI,
4963 if (R.isInvalid()) {
4970 SourceLocation noLoc;
4971#if CLANG_VERSION_MAJOR < 22
4972 QualType TT = S.CheckTemplateIdType(TemplateName(TemplateD), noLoc, TLI);
4974 QualType TT = S.CheckTemplateIdType(
4975 ElaboratedTypeKeyword::None, TemplateName(TemplateD), noLoc, TLI,
4982 S.RequireCompleteType(fakeLoc, TT, diag::err_tentative_def_incomplete_type);
4997 ArrayRef<TemplateArgument> TemplateArgs, Sema& S,
4998 bool instantiate_body) {
5000 TemplateArgumentListInfo TLI{};
5001 for (
auto TA : TemplateArgs)
5003 S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation()));
5010 size_t template_args_size,
bool instantiate_body) {
5012 auto& C = S.getASTContext();
5014 llvm::SmallVector<TemplateArgument> TemplateArgs;
5015 TemplateArgs.reserve(template_args_size);
5016 for (
size_t i = 0; i < template_args_size; ++i) {
5017 QualType ArgTy = QualType::getFromOpaquePtr(template_args[i].m_Type);
5018 if (template_args[i].m_IntegralValue) {
5021 auto Res = llvm::APSInt(template_args[i].m_IntegralValue);
5022 Res = Res.extOrTrunc(C.getIntWidth(ArgTy));
5023 TemplateArgs.push_back(TemplateArgument(C, Res, ArgTy));
5025 TemplateArgs.push_back(ArgTy);
5029 auto* TmplD = unwrap<TemplateDecl>(tmpl);
5036 size_t template_args_size,
bool instantiate_body) {
5037 INTEROP_TRACE(tmpl, template_args, template_args_size, instantiate_body);
5039 getInterp(), tmpl, template_args, template_args_size, instantiate_body));
5043 const std::vector<TemplateArgInfo>& template_args,
5044 bool instantiate_body) {
5050 template_args.size(), instantiate_body));
5054 std::vector<TemplateArgInfo>& args) {
5056 const auto* CTSD = unwrap<ClassTemplateSpecializationDecl>(templ_instance);
5057 for (
const auto& TA : CTSD->getTemplateArgs().asArray()) {
5059 args.push_back({TA.getAsType().getAsOpaquePtr()});
5065 std::vector<TemplateArgInfo>& args) {
5067 const auto* CTSD = unwrap<ClassTemplateSpecializationDecl>(templ_instance);
5068 for (
const auto& TA : CTSD->getTemplateInstantiationArgs().asArray()) {
5069 switch (TA.getKind()) {
5071 assert(0 &&
"Not yet supported!");
5073 case TemplateArgument::Pack:
5074 for (
auto SubTA : TA.pack_elements())
5075 args.push_back({SubTA.getAsType().getAsOpaquePtr()});
5077 case TemplateArgument::Integral:
5083 case TemplateArgument::Type:
5084 args.push_back({TA.getAsType().getAsOpaquePtr()});
5096 static unsigned long long var_count = 0;
5097 std::string
id =
"__Cppyy_GetMethTmpl_" + std::to_string(var_count++);
5098 std::string instance =
"auto " +
id +
" = " + function_template +
";\n";
5102 DeclRefExpr* DRE = (DeclRefExpr*)VD->getInit()->IgnoreImpCasts();
5110 const auto* D = unwrap<clang::Decl>(DRef);
5111 clang::DeclContext* DC;
5112 clang::DeclContext::decl_iterator decl;
5116 if (
const auto* TD = dyn_cast_or_null<TagDecl>(D)) {
5117 DC = clang::TagDecl::castToDeclContext(TD);
5118 decl = DC->decls_begin();
5120 }
else if (
const auto* ND = dyn_cast_or_null<NamespaceDecl>(D)) {
5121 DC = clang::NamespaceDecl::castToDeclContext(ND);
5122 decl = DC->decls_begin();
5123 }
else if (
const auto* TUD = dyn_cast_or_null<TranslationUnitDecl>(D)) {
5124 DC = clang::TranslationUnitDecl::castToDeclContext(TUD);
5125 decl = DC->decls_begin();
5130 for (; decl != DC->decls_end(); decl++) {
5131 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(*decl)) {
5132 names.insert(ND->getNameAsString());
5138void GetEnums(ConstDeclRef DRef, std::vector<std::string>& Result) {
5141 auto* D =
const_cast<clang::Decl*
>(unwrap<clang::Decl>(DRef));
5143 if (!llvm::isa_and_nonnull<clang::DeclContext>(D))
5146 auto* DC = llvm::dyn_cast<clang::DeclContext>(D);
5148 llvm::SmallVector<clang::DeclContext*, 4> DCs;
5149 DC->collectAllContexts(DCs);
5152 for (
auto* DC : DCs) {
5153 for (
auto decl = DC->decls_begin(); decl != DC->decls_end(); decl++) {
5154 if (
auto* ND = llvm::dyn_cast_or_null<EnumDecl>(*decl)) {
5155 Result.push_back(ND->getNameAsString());
5166 QualType Qual = QualType::getFromOpaquePtr(TyRef.data);
5169 Qual = Qual.getCanonicalType();
5170 std::vector<long int> dims;
5171 if (Qual->isArrayType()) {
5172 const auto* ArrayType = dyn_cast<clang::ArrayType>(Qual.getTypePtr());
5174 if (
const auto* CAT = dyn_cast_or_null<ConstantArrayType>(ArrayType)) {
5175 llvm::APSInt Size(CAT->getSize());
5176 long int ArraySize = Size.getLimitedValue();
5177 dims.push_back(ArraySize);
5181 dims.push_back(DimensionValue::UNKNOWN_SIZE);
5183 ArrayType = ArrayType->getElementType()->getAsArrayTypeUnsafe();
5194 auto derivedType = clang::QualType::getFromOpaquePtr(derived.data);
5195 auto baseType = clang::QualType::getFromOpaquePtr(base.data);
5198 return INTEROP_RETURN(S.IsDerivedFrom(fakeLoc, derivedType, baseType));
5203 const auto* D = unwrap<clang::Decl>(func);
5204 const clang::ParmVarDecl* PI =
nullptr;
5206 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
5207 PI = FD->getNonObjectParameter(param_index);
5209 else if (
const auto* FD =
5210 llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
5211 PI = (FD->getTemplatedDecl())->getNonObjectParameter(param_index);
5213 if (PI->hasDefaultArg()) {
5215 llvm::raw_string_ostream OS(Result);
5216 const Expr* DefaultArgExpr =
nullptr;
5218 if (PI->hasUninstantiatedDefaultArg())
5219 DefaultArgExpr = PI->getUninstantiatedDefaultArg();
5221 DefaultArgExpr = PI->getDefaultArg();
5222 DefaultArgExpr->printPretty(OS,
nullptr, PrintingPolicy(LangOptions()));
5228 if (PI->getType()->isFloatingType()) {
5229 if (!Result.empty() && Result.back() ==
'.')
5231 auto DefaultArgValue = std::stod(Result);
5232 std::ostringstream oss;
5233 oss << DefaultArgValue;
5246 const auto* D = unwrap<clang::Decl>(method);
5247 if (
const auto* func = dyn_cast<CXXMethodDecl>(D))
5255 const auto* D = unwrap<clang::Decl>(func);
5256 const clang::ParmVarDecl* PI =
nullptr;
5258 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
5259 PI = FD->getNonObjectParameter(param_index);
5260 else if (
const auto* FD =
5261 llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
5262 PI = (FD->getTemplatedDecl())->getNonObjectParameter(param_index);
5270 clang::getOperatorSpelling((clang::OverloadedOperatorKind)Operator));
5275#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5276 if ((Spelling) == op) { \
5277 return INTEROP_RETURN((Operator)OO_##Name); \
5279#include "clang/Basic/OperatorKinds.def"
5285 const auto* D = unwrap<Decl>(op);
5286 if (
const auto* FD = llvm::dyn_cast<FunctionDecl>(D)) {
5287 if (FD->isOverloadedOperator()) {
5288 switch (FD->getOverloadedOperator()) {
5289#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5291 if ((Unary) && (Binary)) \
5292 return INTEROP_RETURN(kBoth); \
5294 return INTEROP_RETURN(kUnary); \
5296 return INTEROP_RETURN(kBinary); \
5298#include "clang/Basic/OperatorKinds.def"
5308 std::vector<FuncRef>& operators, OperatorArity kind) {
5310 const auto* D = unwrap<Decl>(DRef);
5312 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
5313 auto fn = [&operators, kind, op](
const RecordDecl* RD) {
5314 ASTContext& C = RD->getASTContext();
5315 DeclContextLookupResult Result =
5316 RD->lookup(C.DeclarationNames.getCXXOperatorName(
5317 (clang::OverloadedOperatorKind)op));
5318 for (
auto* i : Result) {
5320 operators.push_back(i);
5325 CXXRD->forallBases(fn);
5326 }
else if (
const auto* DC = llvm::dyn_cast_or_null<DeclContext>(D)) {
5327 ASTContext& C =
getSema().getASTContext();
5328 DeclContextLookupResult Result =
5329 DC->lookup(C.DeclarationNames.getCXXOperatorName(
5330 (clang::OverloadedOperatorKind)op));
5332 for (
auto* i : Result) {
5334 operators.push_back(i);
5348 ::operator
delete(address.data, bytes);
5354 void* arena ,
size_t count ) {
5357 FuncRef ctorAsFunc = wrap<FuncRef>(DRef.data);
5363 FuncRef ctor =
nullptr;
5372 void* is_arena = arena ?
reinterpret_cast<void*
>(1) :
nullptr;
5373 void* result = arena;
5374 JC.InvokeConstructor(&result, count, {}, is_arena);
5387 bool withFree,
size_t nary) {
5388 if (
auto wrapper = make_dtor_wrapper(interp, Class)) {
5389 (*wrapper)(This.data, nary, withFree);
5396bool Destruct(ObjectRef This, DeclRef DRef,
bool withFree ,
5399 const auto* Class = unwrap<Decl>(DRef);
5404 FILE* m_TempFile =
nullptr;
5407 bool m_OwnsFile =
true;
5413 FILE* stream =
nullptr;
5415 err = tmpfile_s(&stream);
5417 printf(
"Cannot create temporary file!\n");
5423#if !defined(CPPINTEROP_USE_CLING) && !defined(_WIN32)
5425 if (I.isOutOfProcess()) {
5431 FILE* redirected = I.getRedirectionFileForOutOfProcess(FD);
5433 m_TempFile = redirected;
5435 if (ftruncate(fileno(m_TempFile), 0) != 0)
5436 perror(
"ftruncate");
5437 if (lseek(fileno(m_TempFile), 0, SEEK_SET) == -1)
5441 m_TempFile = tmpfile();
5444 m_TempFile = tmpfile();
5449 perror(
"StreamCaptureInfo: Unable to create temp file");
5458 ::fflush(FD == STDOUT_FILENO ? stdout : stderr);
5459 if (dup2(fileno(m_TempFile), FD) < 0)
5460 perror(
"StreamCaptureInfo:");
5468 assert(m_DupFD == -1 &&
"Captured output not used?");
5470 if (m_OwnsFile && m_TempFile)
5475 assert(m_DupFD != -1 &&
"Multiple calls to GetCapturedString");
5478 if (dup2(m_DupFD, m_FD) < 0)
5479 perror(
"StreamCaptureInfo:");
5481 if (fseek(m_TempFile, 0L, SEEK_END) != 0)
5482 perror(
"StreamCaptureInfo:");
5485 long bufsize = ftell(m_TempFile);
5486 if (bufsize == -1) {
5487 perror(
"StreamCaptureInfo:");
5494 std::unique_ptr<char[]> content(
new char[bufsize + 1]);
5497 if (fseek(m_TempFile, 0L, SEEK_SET) != 0)
5498 perror(
"StreamCaptureInfo:");
5501 size_t newLen = fread(content.get(),
sizeof(
char), bufsize, m_TempFile);
5502 if (ferror(m_TempFile) != 0)
5503 fputs(
"Error reading file", stderr);
5505 content[newLen++] =
'\0';
5507 std::string result = content.get();
5510#if !defined(_WIN32) && !defined(CPPINTEROP_USE_CLING)
5512 if (I.isOutOfProcess()) {
5513 int fd = fileno(m_TempFile);
5514 if (ftruncate(fd, 0) != 0)
5515 perror(
"ftruncate");
5516 if (lseek(fd, 0, SEEK_SET) == -1)
5525 static std::stack<StreamCaptureInfo> sRedirectionStack;
5526 return sRedirectionStack;
5545 unsigned complete_line ,
5546 unsigned complete_column ) {
5553int Undo(
unsigned N) {
5556#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)
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)
void InstallDiagConsumer(InterpreterInfo *II)
Wire CppInterOp's DiagnosticConsumer into the interpreter's DiagnosticsEngine so parser/sema diagnost...
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)
InterpreterInfo * GetInterpInfo(InterpRef I)
Resolve an InterpRef to the impl-side struct.
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 DeclarationName getCXXOperatorDeclName(ASTContext &Ctx, llvm::StringRef name)
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)
clang::QualType GetTypeFromDecl(const clang::TypeDecl *TD)
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)
std::map< const clang::FunctionDecl *, void * > WrapperStore
compat::Interpreter * Interpreter
std::map< const clang::Decl *, void * > DtorWrapperStore
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.