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/OperationKinds.h"
51#include "clang/AST/QualTypeNames.h"
52#include "clang/AST/RawCommentList.h"
53#include "clang/AST/RecordLayout.h"
54#include "clang/AST/RecursiveASTVisitor.h"
55#include "clang/AST/Stmt.h"
56#include "clang/AST/Type.h"
57#include "clang/AST/VTableBuilder.h"
58#include "clang/Basic/Builtins.h"
59#include "clang/Basic/CharInfo.h"
60#include "clang/Basic/Diagnostic.h"
61#include "clang/Basic/DiagnosticSema.h"
62#include "clang/Basic/LangStandard.h"
63#include "clang/Basic/Linkage.h"
64#include "clang/Basic/OperatorKinds.h"
65#include "clang/Basic/SourceLocation.h"
66#include "clang/Basic/SourceManager.h"
67#include "clang/Basic/Specifiers.h"
68#include "clang/Basic/Version.h"
69#include "clang/Frontend/CompilerInstance.h"
70#include "clang/Interpreter/Interpreter.h"
71#include "clang/Sema/Lookup.h"
72#include "clang/Sema/Overload.h"
73#include "clang/Sema/Ownership.h"
74#include "clang/Sema/Redeclaration.h"
75#include "clang/Sema/Sema.h"
76#include "clang/Sema/TemplateDeduction.h"
78#include "llvm/ADT/STLExtras.h"
79#include "llvm/ADT/SmallString.h"
80#include "llvm/ADT/SmallVector.h"
81#include "llvm/ADT/StringRef.h"
82#include "llvm/Demangle/Demangle.h"
83#include "llvm/ExecutionEngine/JITSymbol.h"
84#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
85#include "llvm/ExecutionEngine/Orc/Core.h"
86#include "llvm/ExecutionEngine/Orc/CoreContainers.h"
87#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
88#include "llvm/IR/GlobalValue.h"
89#include "llvm/Support/Casting.h"
90#include "llvm/Support/CommandLine.h"
91#include "llvm/Support/Debug.h"
92#include "llvm/Support/Error.h"
93#include "llvm/Support/FileSystem.h"
94#include "llvm/Support/ManagedStatic.h"
95#include "llvm/Support/Path.h"
96#include "llvm/Support/Process.h"
97#include "llvm/Support/Signals.h"
98#include "llvm/Support/TargetSelect.h"
99#include "llvm/Support/raw_ostream.h"
100#include "llvm/TargetParser/Host.h"
101#include "llvm/TargetParser/Triple.h"
122#include <sys/types.h>
126#include <unordered_map>
132#define STDOUT_FILENO 1
133#define STDERR_FILENO 2
136#define popen(x, y) (_popen(x, y))
137#define pclose (_pclose)
147#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
150#if CLANG_VERSION_MAJOR > 21
159 void* OpaqueType, ...);
166#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && \
167 (defined(__SANITIZE_ADDRESS__) || \
168 (defined(__has_feature) && __has_feature(address_sanitizer)))
169#define CPPINTEROP_ASAN_BUILD 1
174using namespace clang;
195#if LLVM_VERSION_MAJOR > 22
196 llvm::llvm_shutdown();
203static std::deque<InterpreterInfo>&
205 static llvm::ManagedStatic<std::deque<InterpreterInfo>> sInterpreters;
206 static std::once_flag ProcessInitialized;
207 std::call_once(ProcessInitialized, [SetCrashHandler]() {
209 llvm::sys::PrintStackTraceOnErrorSignal(
"CppInterOp");
211 if (getenv(
"CPPINTEROP_LOG") !=
nullptr)
215 llvm::InitializeAllTargetInfos();
216 llvm::InitializeAllTargets();
217 llvm::InitializeAllTargetMCs();
218 llvm::InitializeAllAsmParsers();
219 llvm::InitializeAllAsmPrinters();
223 if (SetCrashHandler) {
224 llvm::sys::SetOneShotPipeSignalFunction(
225 llvm::sys::DefaultOneShotPipeSignalHandler);
228 llvm::install_out_of_memory_new_handler();
236 return *sInterpreters;
244 llvm::errs() <<
"\n**************************************************\n";
245 llvm::errs() <<
" CppInterOp CRASH DETECTED\n";
249 llvm::errs() <<
" Reproducer saved to: " << Path <<
"\n";
251 llvm::errs() <<
" Failed to write reproducer file.\n";
253 llvm::errs() <<
" Re-run with CPPINTEROP_LOG=1 for a crash reproducer\n";
256 if (!Interps.empty()) {
257 llvm::errs() <<
" Active Interpreters:\n";
258 for (
const auto& Info : Interps) {
259 if (Info.Interpreter)
260 llvm::errs() <<
" - " << Info.Interpreter <<
"\n";
264 llvm::errs() <<
"**************************************************\n";
265 llvm::errs().flush();
268 llvm::sys::PrintStackTrace(llvm::errs());
270 llvm::errs() <<
"**************************************************\n";
271 llvm::errs().flush();
275 llvm::sys::Process::Exit(1,
false);
279 std::vector<std::string> ArgvStorage = {}) {
281 Interps.emplace_back(I, Owned, std::move(ArgvStorage));
287 assert(!Interps.empty() &&
288 "Interpreter instance must be set before calling this!");
290 for (
auto& Info : Interps)
291 if (Info.Interpreter == I)
294 return Interps.back();
299 return *unwrap<compat::Interpreter>(I);
304 return &
getInterpInfo(I ? unwrap<compat::Interpreter>(I) :
nullptr);
317 assert(
GetInterpreters(
false).empty() &&
"sInterpreter already in use!");
329 auto* Interp = unwrap<compat::Interpreter>(I);
331 std::find_if(Interps.begin(), Interps.end(), [Interp](
const auto& Info) {
332 return Info.Interpreter == Interp;
334 if (found == Interps.end())
337 if (std::next(found) != Interps.end())
338 std::rotate(found, found + 1, Interps.end());
354 auto* Interp = unwrap<compat::Interpreter>(I);
356 std::find_if(Interps.begin(), Interps.end(), [Interp](
const auto& Info) {
357 return Info.Interpreter == Interp;
359 if (found == Interps.end())
362 Interps.erase(found);
374 ASTContext& C = I.
getSema().getASTContext();
376 D->addAttr(UsedAttr::CreateImplicit(C));
377#ifdef CPPINTEROP_USE_CLING
378 cling::Interpreter::PushTransactionRAII RAII(&I);
379 I.
getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D));
381 I.
getCI()->getASTConsumer().HandleTopLevelDecl(DeclGroupRef(D));
383 auto GeneratedPTU = I.
Parse(
"");
385 llvm::logAllUnhandledErrors(GeneratedPTU.takeError(), llvm::errs(),
386 "[ForceCodeGen] Failed to generate PTU:");
390 for (
auto& GV : GeneratedPTU->TheModule->globals()) {
391 llvm::GlobalValue::LinkageTypes LT = GV.getLinkage();
392 if (GV.isDeclaration() || !GV.hasName() ||
393 GV.getName().starts_with(
".str") ||
394 !llvm::GlobalVariable::isDiscardableIfUnused(LT) ||
395 LT != llvm::GlobalValue::InternalLinkage)
397 GV.setLinkage(llvm::GlobalValue::WeakAnyLinkage);
399 if (
auto Err = I.
Execute(*GeneratedPTU))
400 llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
401 "[ForceCodeGen] Failed to execute PTU:");
405#define DEBUG_TYPE "jitcall"
406bool JitCall::AreArgumentsValid(
void*
result, ArgList args,
void* self,
410 assert(
result &&
"Must pass the location of the created object!");
414 assert(0 &&
"Must pass at least the minimal number of args!");
417 if (args.m_ArgSize) {
418 assert(args.m_Args !=
nullptr &&
"Must pass an argument list!");
419 Valid &= (bool)args.m_Args;
423 assert(self &&
"Must pass the pointer to object");
426 const auto* FD = cast<FunctionDecl>(unwrap<Decl>(m_FD));
427 if (!FD->getReturnType()->isVoidType() && !
result) {
428 assert(0 &&
"We are discarding the return TyRef of the function!");
432 assert(0 &&
"Number of objects to construct should be atleast 1");
436 const auto* CD = cast<CXXConstructorDecl>(unwrap<Decl>(m_FD));
437 if (CD->getMinRequiredArguments() != 0 && nary > 1) {
439 "Cannot pass initialization parameters to array new construction");
443 assert(m_Kind != kDestructorCall &&
"Wrong overload!");
444 Valid &= m_Kind != kDestructorCall;
451 void** args, std::size_t nargs,
457 llvm::raw_string_ostream OS(Name);
458 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
459 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
461 LLVM_DEBUG(dbgs() <<
"Run '" << Name <<
"', compiled at: "
462 << (
void*)JC->m_GenericCall <<
" with result at: " <<
result
463 <<
" , args at: " << args <<
" , arg count: " << nargs
464 <<
" , self at: " << self <<
"\n";);
465 std::string SelfPart = self ? TI->lookupHandle(self) :
"";
466 TI->appendToLog(llvm::formatv(
" // JitCall::Invoke {0}(nargs={1}, self={2})",
468 SelfPart.empty() ?
"nullptr" : SelfPart));
478 llvm::raw_string_ostream OS(Name);
479 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
480 FD->getNameForDiagnostic(OS, FD->getASTContext().getPrintingPolicy(),
482 LLVM_DEBUG(dbgs() <<
"Finish '" << Name
483 <<
"', compiled at: " << (
void*)JC->m_DestructorCall);
484 std::string ObjPart =
object ? TI->lookupHandle(
object) :
"nullptr";
486 llvm::formatv(
" // JitCall::InvokeDestructor {0}(object={1}, nary={2}, "
488 Name, ObjPart, nary, withFree));
499 const auto* FD = unwrap<FunctionDecl>(JC->m_FD);
500 bool RegisterPtr = isa<CXXConstructorDecl>(FD);
502 QualType RT = FD->getReturnType();
503 RegisterPtr = RT->isPointerType() || RT->isReferenceType();
507 if (
void* p = *
static_cast<void* const*
>(
result))
508 TI->getOrRegisterHandle(p);
515 const char*
const VERSION = CPPINTEROP_VERSION;
516 std::string fullVersion =
"CppInterOp version";
517 fullVersion += VERSION;
518 fullVersion +=
"\n (based on "
519#ifdef CPPINTEROP_USE_CLING
524 return INTEROP_RETURN(fullVersion +
"[" + clang::getClangFullVersion() +
536#include "CppInterOp/BuildInfo.inc"
541std::string
Demangle(
const std::string& mangled_name) {
547 char* Raw = microsoftDemangle(mangled_name,
nullptr,
nullptr);
549 char* Raw = llvm::itaniumDemangle(mangled_name);
551 std::string demangle = Raw ? Raw :
"";
558 llvm::DebugFlag = value;
569 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
570 getSema().InstantiateFunctionDefinition(SourceLocation(), FD,
574 clang::DiagnosticsEngine& Diags =
getSema().getDiagnostics();
575 if (!FD->isDefined() && Diags.hasErrorOccurred()) {
578 Diags.getClient()->clear();
585 const auto* D = unwrap<Decl>(DRef);
588 if (
const auto* ValD = dyn_cast<ValueDecl>(D))
589 if (ValD->getType()->isArrayType())
593 if (
const auto* CXXRD = dyn_cast<CXXRecordDecl>(D))
601 const auto* D = unwrap<Decl>(DRef);
607 const auto* D = unwrap<Decl>(DRef);
613 const auto* D = unwrap<Decl>(DRef);
619 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
625 const auto* D = unwrap<Decl>(DRef);
626 if (
const auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(D))
627 if (
const auto* CXXRDD = CXXRD->getDefinition())
633 auto& SM = semaRef.getSourceManager();
634 return SM.getLocForStartOfFile(SM.getMainFileID());
643 const auto* D = unwrap<Decl>(DRef);
645 if (isa<ClassTemplateSpecializationDecl>(D)) {
653 if (
const auto* CXXRD = dyn_cast<CXXRecordDecl>(D))
655 else if (
const auto* TD = dyn_cast<TagDecl>(D))
668 if (
const auto* RD = dyn_cast<RecordDecl>(unwrap<Decl>(DRef))) {
669 ASTContext& Context = RD->getASTContext();
670 const ASTRecordLayout& Layout = Context.getASTRecordLayout(RD);
679 QualType Ty = QualType::getFromOpaquePtr(TyRef.data);
680 if (Ty->isBuiltinType() || Ty->isAnyComplexType())
683 if (
const auto* RD = Ty->getAsCXXRecordDecl()) {
684 if (
const auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
685 IdentifierInfo* II = CTSD->getSpecializedTemplate()->getIdentifier();
686 if (II && II->isStr(
"complex") &&
687 CTSD->getDeclContext()->isStdNamespace())
696 const auto* D = unwrap<clang::Decl>(DRef);
697 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::TemplateDecl>(D));
702 const auto* D = unwrap<clang::Decl>(DRef);
704 llvm::isa_and_nonnull<clang::ClassTemplateSpecializationDecl>(D));
709 const auto* D = unwrap<clang::Decl>(DRef);
710 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::TypedefNameDecl>(D));
715 const auto* D = unwrap<clang::Decl>(DRef);
716 if (
const auto* CXXRD = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(D))
724 const auto* D = unwrap<clang::Decl>(DRef);
730 const auto* D = unwrap<clang::Decl>(DRef);
731 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::EnumConstantDecl>(D));
736 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
741 auto IsUseCountPresent = [](
const RecordDecl* Record) {
742 ASTContext& C = Record->getASTContext();
743 return !Record->lookup(&C.Idents.get(
"use_count")).empty();
745 auto IsOverloadedOperatorPresent = [](
const RecordDecl* Record,
746 OverloadedOperatorKind Op) {
747 ASTContext& C = Record->getASTContext();
748 DeclContextLookupResult Result =
749 Record->lookup(C.DeclarationNames.getCXXOperatorName(Op));
750 return !Result.empty();
753 const RecordDecl* Record = RT->getDecl();
754 if (IsUseCountPresent(Record))
757 bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
758 bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
759 if (foundStarOperator && foundArrowOperator)
762 const auto* CXXRecord = dyn_cast<CXXRecordDecl>(Record);
766 auto FindOverloadedOperators = [&](
const CXXRecordDecl* Base) {
768 if (IsUseCountPresent(Base))
770 if (!foundStarOperator)
771 foundStarOperator = IsOverloadedOperatorPresent(Base, OO_Star);
772 if (!foundArrowOperator)
773 foundArrowOperator = IsOverloadedOperatorPresent(Base, OO_Arrow);
774 if (foundStarOperator && foundArrowOperator)
779 return !CXXRecord->forallBases(FindOverloadedOperators);
784 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
785 if (
const RecordType* RT = QT->getAs<RecordType>()) {
788 llvm::StringRef tsRef(typeString);
789 if (tsRef.starts_with(
"std::unique_ptr") ||
790 tsRef.starts_with(
"std::shared_ptr") ||
791 tsRef.starts_with(
"std::weak_ptr"))
800 const auto* D = unwrap<clang::Decl>(DRef);
801 if (
const auto* ED = llvm::dyn_cast_or_null<clang::EnumDecl>(D)) {
813 QualType QT = QualType::getFromOpaquePtr(enum_type.data);
814 if (
const auto* ET = QT->getAs<EnumType>())
815 return INTEROP_RETURN(ET->getDecl()->getIntegerType().getAsOpaquePtr());
822 const auto* D = unwrap<clang::Decl>(DRef);
824 if (
const auto* ED = llvm::dyn_cast_or_null<clang::EnumDecl>(D)) {
825 std::vector<DeclRef> enum_constants;
826 for (
auto* ECD : ED->enumerators()) {
827 enum_constants.push_back(ECD);
841 const auto* D = unwrap<clang::Decl>(DRef);
842 if (
const auto* ECD = llvm::dyn_cast<clang::EnumConstantDecl>(D))
850 const auto* D = unwrap<clang::Decl>(DRef);
851 if (
const auto* ECD = llvm::dyn_cast_or_null<clang::EnumConstantDecl>(D)) {
852 const llvm::APSInt& Val = ECD->getInitVal();
860 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
861 if (
const TagType* TT = QT->getAs<TagType>())
865 auto TI =
getSema().getASTContext().getTypeInfo(QT);
866 size_t TypeSize = TI.Width;
872 const auto* D = unwrap<clang::Decl>(DRef);
878 const auto* D = unwrap<clang::NamedDecl>(DRef);
880 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
884 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
892 auto& C =
getSema().getASTContext();
893 const auto* D = unwrap<Decl>(DRef);
895 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
896 PrintingPolicy Policy = C.getPrintingPolicy();
897 Policy.SuppressUnwrittenScope =
true;
899 Policy.FullyQualifiedName =
true;
900 Policy.Suppress_Elab =
true;
902 Policy.SuppressScope =
true;
903 Policy.AnonymousTagLocations =
false;
904 Policy.SuppressTemplateArgsInCXXConstructors =
false;
905 Policy.SuppressDefaultTemplateArgs =
false;
906 Policy.AlwaysIncludeTypeForTemplateArgument =
true;
909 if (
const auto* TD = llvm::dyn_cast<TagDecl>(ND)) {
910 std::string type_name;
912 QT.getAsStringInternal(type_name, Policy);
915 if (
const auto* FD = llvm::dyn_cast<FunctionDecl>(ND)) {
916 std::string func_name;
917 llvm::raw_string_ostream name_stream(func_name);
918 FD->getNameForDiagnostic(name_stream, Policy, qualified);
923 return qualified ? ND->getQualifiedNameAsString() : ND->getNameAsString();
926 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
940 const auto* D = unwrap<Decl>(DRef);
941 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(D)) {
945 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
959 const auto* D = unwrap<Decl>(DRef);
963 D = D->getCanonicalDecl();
964 ASTContext& C = D->getASTContext();
966 const RawComment* RC = C.getRawCommentForAnyRedecl(D);
970 (void)C.getCommentForDecl(D,
nullptr);
972 const SourceManager& SM = C.getSourceManager();
974 if (!strip_comment_markers)
977 return INTEROP_RETURN(RC->getFormattedText(SM, C.getDiagnostics()));
982 const auto* D = unwrap<clang::Decl>(DRef);
984 if (
const auto* DC = llvm::dyn_cast_or_null<clang::DeclContext>(D)) {
985 std::vector<DeclRef> namespaces;
986 for (
auto UD : DC->using_directives()) {
987 namespaces.push_back(UD->getNominatedNamespace());
1002 if (
auto* Type = QT.getCanonicalType().getTypePtrOrNull()) {
1003 Type = Type->getPointeeOrArrayElementType();
1004 Type = Type->getUnqualifiedDesugaredType();
1005 if (
auto* ET = llvm::dyn_cast<EnumType>(Type))
1006 return ET->getDecl();
1007 CXXRecordDecl* CXXRD = Type->getAsCXXRecordDecl();
1009 return CXXRD->getCanonicalDecl();
1016 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
1021 if (
const auto* TND = dyn_cast_or_null<TypedefNameDecl>(D)) {
1024 }
else if (
const auto* USS = dyn_cast_or_null<UsingShadowDecl>(D)) {
1025 if (
const auto* Scope = USS->getTargetDecl())
1029 return D->getCanonicalDecl();
1043DeclRef
GetScope(
const std::string& name, ConstDeclRef parent) {
1052 auto* ND = unwrap<NamedDecl>(
GetNamed(name, parent));
1054 if (!ND || ND == (NamedDecl*)-1)
1057 if (llvm::isa<NamespaceDecl>(ND) || llvm::isa<RecordDecl>(ND) ||
1058 llvm::isa<ClassTemplateDecl>(ND) || llvm::isa<TypedefNameDecl>(ND) ||
1059 llvm::isa<TypeAliasTemplateDecl>(ND) || llvm::isa<TypeAliasDecl>(ND))
1067 std::string delim =
"::";
1069 size_t end = name.find(delim);
1070 DeclRef curr_scope =
nullptr;
1071 while (end != std::string::npos) {
1072 curr_scope =
GetScope(name.substr(start, end - start), curr_scope);
1073 start = end + delim.length();
1074 end = name.find(delim, start);
1092clang::Scope* BuildSyntheticScopeChain(clang::Sema& S, clang::DeclContext* DC) {
1093 if (!DC || DC->isTranslationUnit())
1095 auto* Parent = BuildSyntheticScopeChain(S, DC->getParent());
1096 auto* Mine =
new clang::Scope(Parent, clang::Scope::DeclScope, S.Diags);
1097 Mine->setEntity(DC);
1108class SyntheticScopeChain {
1110 SyntheticScopeChain(clang::Sema& Sema, clang::DeclContext* Within)
1111 : S(Sema), Innermost(BuildSyntheticScopeChain(Sema, Within)),
1112 Saved(
ACCESS(Sema, CurScope)) {
1113 ACCESS(S, CurScope) = Innermost;
1115 ~SyntheticScopeChain() {
1116 ACCESS(S, CurScope) = Saved;
1117 while (Innermost && Innermost != S.TUScope) {
1118 auto* Next = Innermost->getParent();
1123 SyntheticScopeChain(
const SyntheticScopeChain&) =
delete;
1124 SyntheticScopeChain& operator=(
const SyntheticScopeChain&) =
delete;
1126 clang::Scope* get()
const {
return Innermost; }
1130 clang::Scope* Innermost;
1131 clang::Scope* Saved;
1143clang::NamedDecl* LookupUnqualified(clang::Sema& S,
1144 const clang::DeclarationName& Name,
1145 clang::DeclContext* Within) {
1146 SyntheticScopeChain Chain(S, Within);
1152 clang::LookupResult R(S, Name, clang::SourceLocation(),
1153 clang::Sema::LookupOrdinaryName,
1154 RedeclarationKind::NotForRedeclaration);
1155 R.suppressDiagnostics();
1156 S.LookupName(R, Chain.get());
1164 if (R.isSingleResult())
1165 return llvm::dyn_cast<clang::NamedDecl>(R.getFoundDecl());
1166 return (clang::NamedDecl*)-1;
1173bool HasReachableUsingDirective(
const clang::DeclContext* DC) {
1174 for (; DC && !DC->isTranslationUnit(); DC = DC->getParent()) {
1175 if (
const auto* NS = llvm::dyn_cast<clang::NamespaceDecl>(DC)) {
1176 auto UDs = NS->using_directives();
1177 if (UDs.begin() != UDs.end())
1185DeclRef
GetNamed(
const std::string& name, ConstDeclRef parent ) {
1187 clang::DeclContext* Within = 0;
1190 Within = llvm::dyn_cast<clang::DeclContext>(D);
1192#ifdef CPPINTEROP_USE_CLING
1194 Within->getPrimaryContext()->buildLookup();
1203 if (ND && ND != (clang::NamedDecl*)-1)
1210 if (!Within || !llvm::isa<clang::NamespaceDecl>(Within) ||
1211 !HasReachableUsingDirective(Within))
1213 clang::DeclarationName DName = &
getSema().Context.Idents.get(name);
1214 ND = LookupUnqualified(
getSema(), DName, Within);
1215 if (ND && ND != (clang::NamedDecl*)-1)
1226 auto* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1228 if (llvm::isa_and_nonnull<TranslationUnitDecl>(D)) {
1231 auto* ParentDC = D->getDeclContext();
1236 auto* P = clang::Decl::castFromDeclContext(ParentDC)->getCanonicalDecl();
1238 if (
auto* TU = llvm::dyn_cast_or_null<TranslationUnitDecl>(P))
1246 const auto* D = unwrap<Decl>(DRef);
1248 if (
const auto* CTSD =
1249 llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(D))
1250 if (!CTSD->hasDefinition())
1252 getInterp(),
const_cast<ClassTemplateSpecializationDecl*
>(CTSD));
1253 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1254 if (CXXRD->hasDefinition())
1263 const auto* D = unwrap<Decl>(DRef);
1264 const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D);
1265 if (!CXXRD || CXXRD->getNumBases() <= ibase)
1268 auto TyRef = (CXXRD->bases_begin() + ibase)->getType();
1269 if (
const auto* RT = TyRef->getAs<RecordType>())
1279 if (derived == base)
1282 if (!derived || !base)
1285 const auto* derived_D = unwrap<clang::Decl>(derived);
1286 const auto* base_D = unwrap<clang::Decl>(base);
1288 if (!isa<CXXRecordDecl>(derived_D) || !isa<CXXRecordDecl>(base_D))
1291 const auto* Derived = cast<CXXRecordDecl>(derived_D);
1292 const auto* Base = cast<CXXRecordDecl>(base_D);
1302 const CXXRecordDecl* DerivedRD,
1303 const CXXBasePath& Path) {
1304 CharUnits NonVirtualOffset = CharUnits::Zero();
1306 unsigned NonVirtualStart = 0;
1307 const CXXRecordDecl* VirtualBase =
nullptr;
1310 for (
int I = Path.size(), E = 0; I != E; --I) {
1311 const CXXBasePathElement& Element = Path[I - 1];
1313 if (Element.Base->isVirtual()) {
1314 NonVirtualStart = I;
1315 QualType VBaseType = Element.Base->getType();
1316 VirtualBase = VBaseType->getAsCXXRecordDecl();
1322 for (
unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) {
1323 const CXXBasePathElement& Element = Path[I];
1326 const ASTRecordLayout& Layout = Context.getASTRecordLayout(Element.Class);
1328 const CXXRecordDecl* Base = Element.Base->getType()->getAsCXXRecordDecl();
1330 NonVirtualOffset += Layout.getBaseClassOffset(Base);
1338 const ASTRecordLayout& Layout = Context.getASTRecordLayout(DerivedRD);
1339 CharUnits VirtualOffset = Layout.getVBaseClassOffset(VirtualBase);
1340 return (NonVirtualOffset + VirtualOffset).getQuantity();
1342 return NonVirtualOffset.getQuantity();
1347 if (base == derived)
1350 assert(derived || base);
1352 const auto* DD = unwrap<Decl>(derived);
1353 const auto* BD = unwrap<Decl>(base);
1354 if (!isa<CXXRecordDecl>(DD) || !isa<CXXRecordDecl>(BD))
1356 const auto* DCXXRD = cast<CXXRecordDecl>(DD);
1357 const auto* BCXXRD = cast<CXXRecordDecl>(BD);
1365#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
1366#pragma GCC diagnostic push
1367#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1369 CXXBasePaths Paths(
false,
true,
1371#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
1372#pragma GCC diagnostic pop
1374 DCXXRD->isDerivedFrom(BCXXRD, Paths);
1381template <
typename DeclType,
typename HandleType>
1388 Decl* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1390 if (
auto* TD = dyn_cast<TypedefNameDecl>(D)) {
1392 D = unwrap<clang::Decl>(Scope);
1395 if (!D || !isa<CXXRecordDecl>(D))
1398 auto* CXXRD = dyn_cast<CXXRecordDecl>(D);
1400 if (
auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
1402 if (!
getSema().isCompleteType(CTSD->getLocation(), QT))
1406 if (CXXRD->hasDefinition())
1407 CXXRD = CXXRD->getDefinition();
1408 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1409 for (Decl* DI : CXXRD->decls()) {
1410 if (
auto* MD = dyn_cast<DeclType>(DI))
1411 methods.push_back(MD);
1412 else if (
auto* USD = dyn_cast<UsingShadowDecl>(DI)) {
1413 auto* MD = dyn_cast<DeclType>(USD->getTargetDecl());
1417 auto* CUSD = dyn_cast<ConstructorUsingShadowDecl>(DI);
1419 methods.push_back(MD);
1423 auto* CXXCD = dyn_cast_or_null<CXXConstructorDecl>(CUSD->getTargetDecl());
1425 methods.push_back(MD);
1428 if (CXXCD->isDeleted())
1434 getSema().findInheritingConstructor(SourceLocation(), CXXCD, CUSD);
1441 GetClassDecls<CXXMethodDecl>(DRef, methods);
1446 std::vector<FuncRef>& methods) {
1448 GetClassDecls<FunctionTemplateDecl>(DRef, methods);
1454 const auto* D = unwrap<clang::Decl>(DRef);
1456 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D))
1466 auto* CXXRD = unwrap<clang::CXXRecordDecl>(DRef);
1468 return interp.
getCI()->getSema().LookupDefaultConstructor(CXXRD);
1479 auto* D =
const_cast<Decl*
>(unwrap<clang::Decl>(DRef));
1481 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1482 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1491 const auto* D = unwrap<clang::Decl>(DRef);
1502 llvm::StringRef name) {
1503 static constexpr llvm::StringRef OperatorPrefix(
"operator");
1504 if (!name.consume_front(OperatorPrefix) || name.empty() ||
1505 clang::isAsciiIdentifierContinue(
1506 static_cast<unsigned char>(name.front())))
1507 return DeclarationName();
1509 llvm::StringRef Spelling = name.trim();
1510#define OVERLOADED_OPERATOR(OpName, OpSpelling, Token, Unary, Binary, \
1512 if (Spelling == (OpSpelling)) \
1513 return Ctx.DeclarationNames.getCXXOperatorName(clang::OO_##OpName);
1514#include "clang/Basic/OperatorKinds.def"
1515#undef OVERLOADED_OPERATOR
1516 return DeclarationName();
1520 const std::string& name) {
1523 if (!DRef || name.empty())
1528 std::vector<FuncRef> funcs;
1534 DName = &Ctx.Idents.get(name);
1536 clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
1537 RedeclarationKind::ForVisibleRedeclaration);
1546 for (
auto* Found : R) {
1547 if (llvm::isa<FunctionDecl>(Found))
1548 funcs.push_back(Found);
1549 else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(Found)) {
1550 if (
auto* FTD = llvm::dyn_cast<FunctionDecl>(USD->getTargetDecl()))
1551 funcs.push_back(FTD);
1560 const auto* D = unwrap<clang::Decl>(func);
1561 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
1562 QualType Type = FD->getReturnType();
1563 if (Type->isUndeducedAutoType()) {
1564 bool needInstantiation =
false;
1566 needInstantiation =
true;
1567 if (
const auto* MD = llvm::dyn_cast<clang::CXXMethodDecl>(FD)) {
1569 needInstantiation =
true;
1572 if (needInstantiation) {
1575 const_cast<Decl*
>(
static_cast<const Decl*
>(FD)));
1577 Type = FD->getReturnType();
1582 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1584 (FD->getTemplatedDecl())->getReturnType().getAsOpaquePtr());
1593 const auto* D = unwrap<clang::Decl>(Fn);
1594 if (
const auto* FD = dyn_cast<FunctionDecl>(D)) {
1595 if (FD->getBuiltinID() == Builtin::ID::BImalloc)
1597 if (
const auto* FDA = FD->getAttr<RestrictAttr>()) {
1598 if (FDA->getSemanticSpelling() != RestrictAttr::Declspec_restrict)
1602 if (
const auto* FDA = FD->getAttr<OwnershipAttr>()) {
1603 if (FDA->getOwnKind() == OwnershipAttr::Returns)
1607 if (FD->hasAttr<CFReturnsRetainedAttr>() ||
1608 FD->hasAttr<NSReturnsRetainedAttr>() ||
1609 FD->hasAttr<OSReturnsRetainedAttr>())
1620 const auto* D = unwrap<clang::Decl>(Fn);
1621 if (
const auto* FD = dyn_cast<FunctionDecl>(D)) {
1622 if (FD->getBuiltinID() == Builtin::ID::BIfree)
1624 if (
const auto* FDA = FD->getAttr<OwnershipAttr>()) {
1625 if (FDA->getOwnKind() == OwnershipAttr::Takes)
1635 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
1636 const auto* T = QT.getTypePtr();
1637 return INTEROP_RETURN(llvm::isa_and_nonnull<clang::FunctionProtoType>(T));
1640static std::optional<AllocType>
1642 std::unordered_map<
const clang::FunctionDecl*,
1646struct AllocationTraverser : RecursiveASTVisitor<AllocationTraverser> {
1647 std::unordered_map<const clang::VarDecl*, std::optional<AllocType>>
varMap;
1648 std::unordered_map<const clang::FunctionDecl*, std::optional<AllocType>>&
1654 AllocationTraverser(std::unordered_map<
const clang::FunctionDecl*,
1655 std::optional<AllocType>>& cache)
1659 bool TraverseLambdaExpr(clang::LambdaExpr*) {
return true; }
1662 bool TraverseDecl(clang::Decl* D) {
1663 if (llvm::isa_and_nonnull<clang::TagDecl>(D))
1665 return RecursiveASTVisitor::TraverseDecl(D);
1668 bool VisitVarDecl(VarDecl* VD) {
1669 Expr* expr = VD->getInit();
1671 varMap[VD] = handleExpr(expr);
1673 varMap[VD] = AllocType::None;
1677 bool VisitBinaryOperator(clang::BinaryOperator* BO) {
1678 if (BO->getOpcode() != BO_Assign)
1680 Expr* LHS = BO->getLHS();
1681 LHS = LHS->IgnoreParenCasts();
1682 if (
auto* DRE = dyn_cast<DeclRefExpr>(LHS)) {
1683 if (
auto* VD = dyn_cast<VarDecl>(DRE->getDecl())) {
1684 Expr* RHS = BO->getRHS();
1685 varMap[VD] = handleExpr(RHS);
1691 bool VisitReturnStmt(ReturnStmt* RS) {
1692 const clang::Expr* retExpr = RS->getRetValue();
1695 std::optional<AllocType> tmp = handleExpr(retExpr);
1696 if (!tmp.has_value())
1702 else if (*result != tmp) {
1703 result = AllocType::Unknown;
1709 std::optional<AllocType> handleCall(
const clang::CallExpr* CE) {
1710 if (
const auto* FD = CE->getDirectCallee()) {
1711 if (FD->getBuiltinID() == Builtin::ID::BImalloc)
1712 return AllocType::Malloc;
1721 return AllocType::Unknown;
1724 static AllocType handleNew(
const clang::CXXNewExpr* CNE) {
1725 if (CNE->getNumPlacementArgs() > 0)
1726 return AllocType::None;
1728 return AllocType::NewArr;
1729 return AllocType::New;
1732 std::optional<AllocType> handleExpr(
const clang::Expr* expr) {
1733 const clang::Expr* finExpr = expr->IgnoreParenCasts();
1735 if (
const auto* CNE = dyn_cast<CXXNewExpr>(finExpr))
1736 return handleNew(CNE);
1739 if (
const auto* DRE = dyn_cast<DeclRefExpr>(finExpr)) {
1740 if (
const auto* VD = dyn_cast<VarDecl>(DRE->getDecl())) {
1741 auto it =
varMap.find(VD);
1746 return AllocType::None;
1750 if (
const auto* CE = dyn_cast<CallExpr>(finExpr))
1751 return handleCall(CE);
1752 return AllocType::None;
1757static std::optional<AllocType>
1759 std::unordered_map<
const clang::FunctionDecl*,
1761 const clang::QualType QT = Fn->getReturnType();
1762 if (!QT->isPointerType())
1763 return AllocType::None;
1764 const Stmt* fnBody = Fn->getBody();
1766 return AllocType::Unknown;
1767 const auto* CmpStmt = dyn_cast<clang::CompoundStmt>(fnBody);
1770 return AllocType::Unknown;
1772 Traverser.TraverseStmt(
const_cast<clang::CompoundStmt*
>(CmpStmt));
1773 auto res = Traverser.result;
1781 const auto* D = unwrap<Decl>(Fn);
1782 if (
const auto* FD = dyn_cast<FunctionDecl>(D)) {
1783 std::unordered_map<const clang::FunctionDecl*, std::optional<AllocType>>
1795 QualType QT = QualType::getFromOpaquePtr(fn_type.data);
1796 const auto* FPT = QT->getAs<clang::FunctionProtoType>();
1799 sig.push_back(FPT->getReturnType().getAsOpaquePtr());
1800 for (
size_t i = 0; i < FPT->getNumParams(); i++)
1801 sig.push_back(FPT->getParamType(i).getAsOpaquePtr());
1812 const auto* D = unwrap<clang::Decl>(func);
1813 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1816 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1817 return INTEROP_RETURN(FD->getTemplatedDecl()->getNumNonObjectParams());
1824 const auto* D = unwrap<clang::Decl>(func);
1825 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D))
1828 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1830 FD->getTemplatedDecl()->getMinRequiredExplicitArguments());
1837 const auto* D = unwrap<clang::Decl>(func);
1839 if (
const auto* FTD = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
1840 D = FTD->getTemplatedDecl();
1842 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D)) {
1843 if (iarg < FD->getNumNonObjectParams()) {
1844 const auto* PVD = FD->getNonObjectParameter(iarg);
1854 clang::QualType QT = clang::QualType::getFromOpaquePtr(TyRef.data);
1863 const auto* D = unwrap<clang::Decl>(func);
1864 const clang::FunctionDecl* FD;
1866 if (llvm::dyn_cast<FunctionDecl>(D))
1867 FD = llvm::dyn_cast<FunctionDecl>(D);
1868 else if (
const auto* FTD = llvm::dyn_cast<clang::FunctionTemplateDecl>(D))
1869 FD = FTD->getTemplatedDecl();
1873 std::string Signature;
1874 raw_string_ostream SS(Signature);
1875 PrintingPolicy Policy =
getASTContext().getPrintingPolicy();
1877 Policy.TerseOutput =
true;
1878 Policy.FullyQualifiedName =
true;
1879 Policy.SuppressDefaultTemplateArgs =
false;
1880 FD->print(SS, Policy);
1889 return llvm::isa_and_nonnull<FunctionTemplateDecl>(D);
1892bool IsTemplateInstantiationOrSpecialization(
const Decl* D) {
1893 if (
const auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
1894 auto TK = FD->getTemplatedKind();
1896 FunctionDecl::TemplatedKind::TK_FunctionTemplateSpecialization ||
1897 TK == FunctionDecl::TemplatedKind::
1898 TK_DependentFunctionTemplateSpecialization ||
1899 TK == FunctionDecl::TemplatedKind::TK_FunctionTemplate;
1908 const auto* FD = cast<FunctionDecl>(unwrap<clang::Decl>(function));
1914 const auto* D = unwrap<Decl>(func);
1916 IsTemplateInstantiationOrSpecialization(D));
1924 const DeclContext* Within =
nullptr;
1926 const auto* D = unwrap<Decl>(parent);
1927 Within = llvm::dyn_cast<DeclContext>(D);
1932 if ((intptr_t)ND == (intptr_t)0)
1935 if ((intptr_t)ND != (intptr_t)-1)
1937 IsTemplateInstantiationOrSpecialization(ND));
1945 std::vector<FuncRef>& funcs) {
1948 auto* D =
const_cast<Decl*
>(unwrap<Decl>(parent));
1950 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1951 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
1952 DeclContextLookupResult Result =
getSema().LookupConstructors(CXXRD);
1956 for (
auto* i : Result)
1957 if (
GetName(DeclRef(i)) == name)
1964 std::vector<FuncRef>& funcs) {
1966 const auto* D = unwrap<Decl>(parent);
1967 if (!D && name.empty())
1974 llvm::StringRef Name(name);
1976 clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
1977 RedeclarationKind::ForVisibleRedeclaration);
1978 auto* DC = clang::Decl::castToDeclContext(DU);
1987 funcs.push_back(R.getFoundDecl());
1991 for (
auto* Found : R) {
1993 funcs.push_back(Found);
1994 else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(Found)) {
1996 llvm::dyn_cast<FunctionTemplateDecl>(USD->getTargetDecl()))
1997 funcs.push_back(FTD);
2015 const std::vector<TemplateArgInfo>& explicit_types,
2016 const std::vector<TemplateArgInfo>& arg_types) {
2019 auto& C = S.getASTContext();
2028 struct WrapperExpr :
public OpaqueValueExpr {
2029 WrapperExpr() : OpaqueValueExpr(clang::Stmt::EmptyShell()) {}
2031 auto* Exprs =
new WrapperExpr[arg_types.size()];
2032 llvm::SmallVector<Expr*> Args;
2033 Args.reserve(arg_types.size());
2035 for (
auto i : arg_types) {
2036 QualType Type = QualType::getFromOpaquePtr(i.m_Type);
2039 ExprValueKind ExprKind = ExprValueKind::VK_XValue;
2040 if (Type->isLValueReferenceType())
2041 ExprKind = ExprValueKind::VK_LValue;
2043 new (&Exprs[idx]) OpaqueValueExpr(SourceLocation::getFromRawEncoding(1),
2044 Type.getNonReferenceType(), ExprKind);
2045 Args.push_back(&Exprs[idx]);
2050 llvm::SmallVector<TemplateArgument> TemplateArgs;
2051 TemplateArgs.reserve(explicit_types.size());
2052 for (
auto explicit_type : explicit_types) {
2053 QualType ArgTy = QualType::getFromOpaquePtr(explicit_type.m_Type);
2054 if (explicit_type.m_IntegralValue) {
2057 auto Res = llvm::APSInt(explicit_type.m_IntegralValue);
2058 Res = Res.extOrTrunc(C.getIntWidth(ArgTy));
2059 TemplateArgs.push_back(TemplateArgument(C, Res, ArgTy));
2061 TemplateArgs.push_back(ArgTy);
2065 TemplateArgumentListInfo ExplicitTemplateArgs{};
2066 for (
auto TA : TemplateArgs)
2067 ExplicitTemplateArgs.addArgument(
2068 S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation()));
2071 SourceLocation Loc = SourceLocation::getFromRawEncoding(1);
2072 Sema::SFINAETrap Trap(S,
true);
2074 OverloadCandidateSet Overloads(
2075 Loc, OverloadCandidateSet::CandidateSetKind::CSK_Normal);
2077 for (
auto i : candidates) {
2078 auto* D =
const_cast<Decl*
>(unwrap<Decl>(i));
2079 if (
auto* FD = dyn_cast<FunctionDecl>(D)) {
2080 S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
2082 }
else if (
auto* FTD = dyn_cast<FunctionTemplateDecl>(D)) {
2083 auto* MD = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl());
2084 if (MD && MD->isExplicitObjectMemberFunction()) {
2087 CXXRecordDecl* RD = MD->getParent();
2089 OpaqueValueExpr ObjectExpr(SourceLocation::getFromRawEncoding(1),
2090 ObjectType, ExprValueKind::VK_LValue);
2091 S.AddMethodTemplateCandidate(
2092 FTD, DeclAccessPair::make(FTD, FTD->getAccess()), RD,
2093 &ExplicitTemplateArgs, ObjectType, ObjectExpr.Classify(C), Args,
2101 S.AddTemplateOverloadCandidate(
2102 FTD, DeclAccessPair::make(FTD, FTD->getAccess()),
2103 &ExplicitTemplateArgs, Args, Overloads);
2108 OverloadCandidateSet::iterator Best;
2109 Overloads.BestViableFunction(S, Loc, Best);
2111 FunctionDecl* Result = Best != Overloads.end() ? Best->Function :
nullptr;
2119 const auto* D = unwrap<Decl>(method);
2120 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
2121 return CXXMD->getAccess() == AS;
2129 const auto* D = unwrap<clang::Decl>(method);
2130 if (
const auto* FTD = dyn_cast_or_null<FunctionTemplateDecl>(D))
2131 D = FTD->getTemplatedDecl();
2153 const auto* D = unwrap<Decl>(method);
2154 if (
const auto* FTD = dyn_cast<FunctionTemplateDecl>(D))
2156 return INTEROP_RETURN(llvm::isa_and_nonnull<CXXConstructorDecl>(D));
2161 const auto* D = unwrap<Decl>(method);
2162 return INTEROP_RETURN(llvm::isa_and_nonnull<CXXDestructorDecl>(D));
2167 const auto* D = unwrap<Decl>(method);
2168 if (
const auto* FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D))
2169 D = FTD->getTemplatedDecl();
2171 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
2183 const auto* D = unwrap<Decl>(method);
2185 if (
const auto* FTD = llvm::dyn_cast_or_null<FunctionTemplateDecl>(D))
2186 D = FTD->getTemplatedDecl();
2188 if (
const auto* CD = llvm::dyn_cast_or_null<CXXConstructorDecl>(D))
2191 if (
const auto* CD = llvm::dyn_cast_or_null<CXXConversionDecl>(D))
2194 if (
const auto* DGD = llvm::dyn_cast_or_null<CXXDeductionGuideDecl>(D))
2204 if (llvm::Error Err = FDAorErr.takeError())
2205 llvm::consumeError(std::move(Err));
2207 return INTEROP_RETURN(llvm::jitTargetAddressToPointer<void*>(*FDAorErr));
2213 const auto get_mangled_name = [](
const FunctionDecl* FD) {
2216 if (!MangleCtxt->shouldMangleDeclName(FD)) {
2217 return FD->getNameInfo().getName().getAsString();
2220 std::string mangled_name;
2221 llvm::raw_string_ostream ostream(mangled_name);
2223 MangleCtxt->mangleName(FD, ostream);
2228 return mangled_name;
2232 if (!llvm::isa<CXXConstructorDecl>(FD) && !llvm::isa<CXXDestructorDecl>(FD))
2240 auto* D = unwrap<Decl>(method);
2241 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
2242 if ((IsTemplateInstantiationOrSpecialization(FD) ||
2243 FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization) &&
2244 !FD->getDefinition())
2247 if (isDiscardableGVALinkage(C.GetGVALinkageForFunction(FD)))
2256 const auto* D = unwrap<Decl>(method);
2257 if (
const auto* CXXMD = llvm::dyn_cast_or_null<CXXMethodDecl>(D)) {
2269 const auto* MD = llvm::dyn_cast_or_null<CXXMethodDecl>(unwrap<Decl>(method));
2270 if (!MD || !MD->isVirtual())
2274 if (C.getTargetInfo().getCXXABI().isMicrosoft()) {
2275 auto* VTC = llvm::cast<MicrosoftVTableContext>(C.getVTableContext());
2276 return (
int)VTC->getMethodVFTableLocation(GlobalDecl(MD)).Index;
2278 auto* VTC = llvm::cast<ItaniumVTableContext>(C.getVTableContext());
2279 return (
int)VTC->getMethodVTableIndex(GlobalDecl(MD));
2286 const auto* RD = llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(DRef));
2288 RD = RD->getDefinition();
2289 if (!RD || !RD->isPolymorphic())
2293 if (C.getTargetInfo().getCXXABI().isMicrosoft()) {
2294 auto* VTC = llvm::cast<MicrosoftVTableContext>(C.getVTableContext());
2295 const VTableLayout& L = VTC->getVFTableLayout(RD, CharUnits::Zero());
2296 return (
int)L.vtable_components().size();
2298 auto* VTC = llvm::cast<ItaniumVTableContext>(C.getVTableContext());
2299 const VTableLayout& L = VTC->getVTableLayout(RD);
2300 unsigned AddrPoint = L.getAddressPointIndices()[0];
2301 return (
int)(L.vtable_components().size() - AddrPoint);
2314 if (RD->getNumVBases() > 0)
2316 unsigned polymorphic_direct_bases = 0;
2317 for (
const auto& B : RD->bases()) {
2318 const auto* BD = B.getType()->getAsCXXRecordDecl();
2321 BD = BD->getDefinition();
2322 if (BD && BD->isPolymorphic() && ++polymorphic_direct_bases > 1)
2337 "public prefix size must equal ABI prefix + 1 hidden slot");
2362 std::memcpy(&fn,
static_cast<void*
>(&slot),
sizeof(slot));
2367 std::memcpy(
static_cast<void*
>(&slot), &fn,
sizeof(slot));
2395 std::size_t n_extra)
2421 template <
class To,
class From>
static To
BitCastFn(From f)
noexcept {
2422 static_assert(
sizeof(To) ==
sizeof(From));
2424 std::memcpy(&to, &f,
sizeof(to));
2429 return *
reinterpret_cast<void***
>(
inst);
2432 *
reinterpret_cast<void***
>(
inst) = new_vptr;
2457 (this->*orig_dtor)(flags);
2459 (this->*orig_dtor)();
2480 const int* slots,
void*
const* fns,
2482 std::size_t n_extra_prefix_slots) {
2485 for (std::size_t i = 0; i < n; ++i) {
2486 if (slots[i] < 0 || slots[i] >= total_method_slots)
2494 const std::size_t total = n_extra_prefix_slots + kPrefix + total_method_slots;
2501 void** block =
new void*[total]();
2502 std::memcpy(block + n_extra_prefix_slots + 1, orig_vptr -
kABIPrefixSize,
2505 for (std::size_t i = 0; i < n; ++i)
2506 block[n_extra_prefix_slots + kPrefix + slots[i]] = fns[i];
2511 return new VTableOverlay(block, orig_vptr, inst, n_extra_prefix_slots);
2527 void*
const* overlay_fns, std::size_t n_overlays,
2528 std::size_t n_extra_prefix_slots,
2529 VTableOverlayDtorHook on_destroy,
void* cleanup_data) {
2531 n_extra_prefix_slots, on_destroy, cleanup_data);
2538 const auto* RD = llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(base));
2540 RD = RD->getDefinition();
2548 llvm::SmallVector<int, 8> slots;
2549 slots.reserve(n_overlays);
2550 for (std::size_t i = 0; i < n_overlays; ++i) {
2554 slots.push_back(slot);
2557 overlay_fns, n_overlays,
2558 n_extra_prefix_slots);
2568 void** vptr = ov->address_point();
2570 ov->cleanup = on_destroy;
2571 ov->cleanup_data = cleanup_data;
2586 auto* D = unwrap<Decl>(DRef);
2588 if (
auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
2589 getSema().ForceDeclarationOfImplicitMembers(CXXRD);
2590 if (CXXRD->hasDefinition())
2591 CXXRD = CXXRD->getDefinition();
2593 llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_begin;
2594 llvm::SmallVector<RecordDecl::decl_iterator, 2> stack_end;
2595 stack_begin.push_back(CXXRD->decls_begin());
2596 stack_end.push_back(CXXRD->decls_end());
2597 while (!stack_begin.empty()) {
2598 if (stack_begin.back() == stack_end.back()) {
2599 stack_begin.pop_back();
2600 stack_end.pop_back();
2603 Decl* D = *(stack_begin.back());
2604 if (
auto* FD = llvm::dyn_cast<FieldDecl>(D)) {
2605 if (FD->isAnonymousStructOrUnion()) {
2606 if (
const auto* RT = FD->getType()->getAs<RecordType>()) {
2607 if (
auto* CXXRD = llvm::dyn_cast<CXXRecordDecl>(RT->getDecl())) {
2608 stack_begin.back()++;
2609 stack_begin.push_back(CXXRD->decls_begin());
2610 stack_end.push_back(CXXRD->decls_end());
2615 datamembers.push_back(D);
2617 }
else if (
auto* USD = llvm::dyn_cast<UsingShadowDecl>(D)) {
2618 if (llvm::isa<FieldDecl>(USD->getTargetDecl()))
2619 datamembers.push_back(USD);
2621 stack_begin.back()++;
2628 std::vector<DeclRef>& datamembers) {
2630 GetClassDecls<VarDecl>(DRef, datamembers);
2635 std::vector<DeclRef>& datamembers,
2636 bool include_enum_class) {
2638 std::vector<DeclRef> EDs;
2639 GetClassDecls<EnumDecl>(DRef, EDs);
2640 for (DeclRef i : EDs) {
2641 auto* ED = unwrap<EnumDecl>(i);
2643 bool is_class_tagged = ED->isScopedUsingClassTag();
2644 if (is_class_tagged && !include_enum_class)
2647 std::copy(ED->enumerator_begin(), ED->enumerator_end(),
2648 std::back_inserter(datamembers));
2655 const clang::DeclContext* Within =
nullptr;
2657 const auto* D = unwrap<clang::Decl>(parent);
2658 Within = llvm::dyn_cast<clang::DeclContext>(D);
2662 if (ND && ND != (clang::NamedDecl*)-1) {
2663 if (llvm::isa_and_nonnull<clang::FieldDecl>(ND)) {
2673 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2674 if (
auto* CXXRD = QT->getAsCXXRecordDecl()) {
2682 const auto* D = unwrap<Decl>(var);
2684 if (
const auto* DD = llvm::dyn_cast_or_null<DeclaratorDecl>(D)) {
2685 QualType QT = DD->getType();
2688 if (QT->isTypedefNameType()) {
2693 QT = QT.getCanonicalType();
2697 if (
const auto* ECD = llvm::dyn_cast_or_null<EnumConstantDecl>(D))
2704 CXXRecordDecl* BaseCXXRD) {
2708 auto& C = I.
getSema().getASTContext();
2710 if (
auto* FD = llvm::dyn_cast<FieldDecl>(D)) {
2711 clang::RecordDecl* FieldParentRecordDecl = FD->getParent();
2712 intptr_t offset = C.toCharUnitsFromBits(C.getFieldOffset(FD)).getQuantity();
2713 while (FieldParentRecordDecl->isAnonymousStructOrUnion()) {
2714 clang::RecordDecl* anon = FieldParentRecordDecl;
2715 FieldParentRecordDecl = llvm::dyn_cast<RecordDecl>(anon->getParent());
2716 for (
auto F = FieldParentRecordDecl->field_begin();
2717 F != FieldParentRecordDecl->field_end(); ++F) {
2718 const auto* RT = F->getType()->getAs<RecordType>();
2721 if (anon == RT->getDecl()) {
2726 offset += C.toCharUnitsFromBits(C.getFieldOffset(FD)).getQuantity();
2728 if (BaseCXXRD && BaseCXXRD != FieldParentRecordDecl->getCanonicalDecl()) {
2735 std::vector<CXXRecordDecl*> stack;
2736 std::map<CXXRecordDecl*, CXXRecordDecl*> direction;
2737 stack.push_back(BaseCXXRD);
2738 while (!stack.empty()) {
2739 CXXRecordDecl* RD = stack.back();
2743 for (
size_t i = 0; i < num_bases; i++) {
2744 auto* CRD = unwrap<CXXRecordDecl>(
GetBaseClass(RD, i));
2745 direction[CRD] = RD;
2746 if (CRD == FieldParentRecordDecl) {
2750 stack.push_back(CRD);
2755 if (
auto* RD = llvm::dyn_cast<CXXRecordDecl>(FieldParentRecordDecl)) {
2757 RD = RD->getCanonicalDecl();
2758 while (BaseCXXRD != RD) {
2759 CXXRecordDecl* Parent = direction.at(RD);
2761 C.getASTRecordLayout(Parent).getBaseClassOffset(RD).getQuantity();
2765 assert(
false &&
"Unreachable");
2771 if (
auto* VD = llvm::dyn_cast<VarDecl>(D)) {
2772 auto GD = GlobalDecl(VD);
2773 std::string mangledName;
2775 void* address = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
2776 mangledName.c_str());
2781 if (!VD->hasInit()) {
2789 if (VarDecl* Def = VD->getDefinition()) {
2791 }
else if (VD->getTemplateInstantiationPattern()) {
2793 getSema().InstantiateVariableDefinition(SourceLocation(), VD);
2794 if (VarDecl* Inst = VD->getDefinition())
2798 if (VD->hasInit() &&
2799 (VD->isConstexpr() || VD->getType().isConstQualified())) {
2800 if (
const APValue* val = VD->evaluateValue()) {
2801 if (VD->getType()->isIntegralType(C)) {
2802 return (intptr_t)val->getInt().getRawData();
2808 auto Linkage = C.GetGVALinkageForVariable(VD);
2809 if (isDiscardableGVALinkage(Linkage))
2814 llvm::logAllUnhandledErrors(VDAorErr.takeError(), llvm::errs(),
2815 "Failed to GetVariableOffset:");
2818 return (intptr_t)jitTargetAddressToPointer<void*>(VDAorErr.get());
2827 auto* D =
const_cast<Decl*
>(unwrap<Decl>(var));
2828 auto* RD =
const_cast<CXXRecordDecl*
>(
2829 llvm::dyn_cast_or_null<CXXRecordDecl>(unwrap<Decl>(parent)));
2835 const auto* D = unwrap<Decl>(var);
2836 return D->getAccess() == AS;
2857 const auto* D = unwrap<Decl>(var);
2858 if (llvm::isa_and_nonnull<VarDecl>(D)) {
2867 const auto* D = unwrap<clang::Decl>(var);
2869 if (
const auto* VD = llvm::dyn_cast_or_null<ValueDecl>(D)) {
2878 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2884 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2896 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2897 if (!QT->hasIntegerRepresentation())
2900 *s = QT->hasSignedIntegerRepresentation() ? Signedness::kSigned
2901 : Signedness::kUnsigned;
2910 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2916 if (!type_a || !type_b)
2918 QualType QT1 = QualType::getFromOpaquePtr(type_a.data);
2919 QualType QT2 = QualType::getFromOpaquePtr(type_b.data);
2925 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2933 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2941 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2947 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2953 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2954 if (QT->isRValueReferenceType())
2956 if (QT->isLValueReferenceType())
2963 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2969 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2972 getASTContext().getRValueReferenceType(QT).getAsOpaquePtr());
2974 getASTContext().getLValueReferenceType(QT).getAsOpaquePtr());
2981 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2982 return INTEROP_RETURN(QT.getNonReferenceType().getAsOpaquePtr());
2989 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
2990 QT = QT->getCanonicalTypeUnqualified();
2993 while (QT->isArrayType())
2994 QT = QualType(QT->getArrayElementTypeNoTypeQual(), 0);
2998 for (
auto PT = QT->getPointeeType(); !PT.isNull();
2999 PT = QT->getPointeeType()) {
3002 QT = QT->getCanonicalTypeUnqualified();
3008 QualType QT = QualType::getFromOpaquePtr(var.data);
3011 Policy.SuppressTagKeyword =
true;
3012 Policy.Suppress_Elab =
true;
3013 Policy.FullyQualifiedName =
true;
3021 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
3030 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
3031 if (qual & QualKind::Const) {
3032 if (!QT.isConstQualified())
3035 if (qual & QualKind::Volatile) {
3036 if (!QT.isVolatileQualified())
3039 if (qual & QualKind::Restrict) {
3040 if (!QT.isRestrictQualified())
3051 auto QT = QualType(QualType::getFromOpaquePtr(TyRef.data));
3052 if (qual & QualKind::Const)
3053 QT.removeLocalConst();
3054 if (qual & QualKind::Volatile)
3055 QT.removeLocalVolatile();
3056 if (qual & QualKind::Restrict)
3057 QT.removeLocalRestrict();
3066 auto QT = QualType(QualType::getFromOpaquePtr(TyRef.data));
3067 if (qual & QualKind::Const) {
3068 if (!QT.isConstQualified())
3071 if (qual & QualKind::Volatile) {
3072 if (!QT.isVolatileQualified())
3075 if (qual & QualKind::Restrict) {
3076 if (!QT.isRestrictQualified())
3084 llvm::SmallVectorImpl<llvm::StringRef>& Words) {
3085 std::sort(Words.begin(), Words.end());
3088 for (
size_t i = 0; i < Words.size(); ++i) {
3091 Key += Words[i].str();
3094 }
while (std::next_permutation(Words.begin(), Words.end()));
3098 const PrintingPolicy Policy(Context.getLangOpts());
3100 const auto& Types =
ACCESS(Context, Types);
3102 for (clang::Type* T : Types) {
3103 auto* BT = llvm::dyn_cast<BuiltinType>(T);
3104 if (!BT || BT->isPlaceholderType())
3108 std::string Name = QT.getAsString(Policy);
3109 if (Name.empty() || Name[0] ==
'<')
3113 BuiltinMap[Name] = QT;
3115 llvm::SmallVector<llvm::StringRef, 4> Words;
3116 llvm::StringRef(Name).split(Words,
' ', -1,
false);
3118 bool hasInt =
false;
3119 bool hasSigned =
false;
3120 bool hasUnsigned =
false;
3121 bool hasChar =
false;
3122 bool isModifiable =
false;
3124 for (
auto W : Words) {
3127 else if (W ==
"signed")
3129 else if (W ==
"unsigned")
3131 else if (W ==
"char")
3134 if (W ==
"long" || W ==
"short" || hasInt)
3135 isModifiable =
true;
3139 if (!isModifiable && !hasUnsigned && !hasSigned)
3143 if (Words.size() > 1)
3147 if (!hasInt && !hasChar) {
3148 auto WithInt = Words;
3149 WithInt.push_back(
"int");
3154 if (!hasSigned && !hasUnsigned) {
3155 auto WithBoth = WithInt;
3156 WithBoth.push_back(
"signed");
3163 if (!hasSigned && !hasUnsigned) {
3164 auto WithSigned = Words;
3165 WithSigned.push_back(
"signed");
3171 BuiltinMap[
"signed"] = Context.IntTy;
3172 BuiltinMap[
"unsigned"] = Context.UnsignedIntTy;
3175 llvm::StringMap<QualType>& BuiltinMap =
GetInterpreters().back().BuiltinMap;
3176 if (BuiltinMap.empty())
3180 auto It = BuiltinMap.find(typeName);
3181 if (It != BuiltinMap.end())
3191 if (
const auto* TND = llvm::dyn_cast_or_null<TypedefNameDecl>(D))
3192 return TND->getUnderlyingType();
3194 if (
const auto* VD = dyn_cast<ValueDecl>(D))
3195 return VD->getType();
3197 if (
const auto* TD = llvm::dyn_cast_or_null<TypeDecl>(D))
3203TypeRef
GetType(
const std::string& name, ConstDeclRef parent ) {
3206 if (!builtin.isNull())
3214 QualType QT = QualType::getFromOpaquePtr(TyRef.data);
3233static unsigned long long gWrapperSerial = 0LL;
3235enum EReferenceType { kNotReference, kLValueReference, kRValueReference };
3239#define DEBUG_TYPE "jitcall"
3243inline void indent(std::ostringstream& buf,
int indent_level) {
3244 static const std::string kIndentString(
" ");
3245 for (
int i = 0; i < indent_level; ++i)
3246 buf << kIndentString;
3250 const std::string& wrapper,
3251 bool withAccessControl =
true) {
3252 LLVM_DEBUG(dbgs() <<
"Compiling '" << wrapper_name <<
"'\n");
3257void get_type_as_string(QualType QT, std::string& type_name, ASTContext& C,
3258 PrintingPolicy Policy) {
3268 while (
const auto* TST = QT->getAs<TemplateSpecializationType>()) {
3269 if (!TST->isTypeAlias())
3271 QT = TST->desugar();
3273 if (!QT->isTypedefNameType() || QT->isBuiltinType())
3274 QT = QT.getDesugaredType(C);
3275 Policy.Suppress_Elab =
true;
3276 Policy.SuppressTagKeyword = !QT->isEnumeralType();
3277 Policy.FullyQualifiedName =
true;
3278 Policy.UsePreferredNames =
false;
3279 QT.getAsStringInternal(type_name, Policy);
3282static void GetDeclName(
const clang::Decl* D, ASTContext& Context,
3283 std::string& name) {
3285 PrintingPolicy Policy(Context.getPrintingPolicy());
3286 Policy.SuppressTagKeyword =
true;
3287 Policy.SuppressUnwrittenScope =
true;
3288 Policy.Print_Canonical_Types =
true;
3289 if (
const auto* TD = dyn_cast<TypeDecl>(D)) {
3292 if (
const auto* Typedef = dyn_cast<const TypedefDecl>(TD)) {
3294 QT = Typedef->getTypeSourceInfo()->getType();
3297 get_type_as_string(QT, name, Context, Policy);
3298 }
else if (
const auto* ND = dyn_cast<NamedDecl>(D)) {
3300 raw_string_ostream stream(name);
3301 ND->getNameForDiagnostic(stream, Policy,
true);
3306void collect_type_info(
const FunctionDecl* FD, QualType& QT,
3307 std::ostringstream& typedefbuf,
3308 std::ostringstream& callbuf, std::string& type_name,
3309 EReferenceType& refType,
bool& isPointer,
3310 int indent_level,
bool forArgument) {
3315 ASTContext& C = FD->getASTContext();
3316 PrintingPolicy Policy(C.getPrintingPolicy());
3317 Policy.Suppress_Elab =
true;
3318 refType = kNotReference;
3319 if (QT->isRecordType()) {
3321 get_type_as_string(QT, type_name, C, Policy);
3324 if (
auto* CXXRD = QT->getAsCXXRecordDecl()) {
3325 if (CXXRD->isLambda()) {
3326 std::string fn_name;
3327 llvm::raw_string_ostream stream(fn_name);
3328 Policy.FullyQualifiedName =
true;
3329 Policy.SuppressUnwrittenScope =
true;
3330 FD->getNameForDiagnostic(stream, Policy,
3332 type_name =
"__internal_CppInterOp::function<decltype(" + fn_name +
3338 if (QT.getNonReferenceType()->isFunctionPointerType() ||
3339 QT.getNonReferenceType()->isFunctionProtoType()) {
3340 clang::QualType NRQT = QT.getNonReferenceType();
3341 std::string fp_typedef_name;
3343 std::ostringstream nm;
3344 nm <<
"FP" << gWrapperSerial++;
3345 type_name = nm.str();
3346 raw_string_ostream OS(fp_typedef_name);
3347 NRQT.print(OS, Policy, type_name);
3351 indent(typedefbuf, indent_level);
3353 typedefbuf <<
"typedef " << fp_typedef_name <<
";\n";
3355 if (QT->isRValueReferenceType())
3356 refType = kRValueReference;
3358 refType = kLValueReference;
3360 }
else if (QT->isMemberPointerType()) {
3361 std::string mp_typedef_name;
3363 std::ostringstream nm;
3364 nm <<
"MP" << gWrapperSerial++;
3365 type_name = nm.str();
3366 raw_string_ostream OS(mp_typedef_name);
3367 QT.print(OS, Policy, type_name);
3371 indent(typedefbuf, indent_level);
3373 typedefbuf <<
"typedef " << mp_typedef_name <<
";\n";
3375 }
else if (QT->isPointerType()) {
3377 QT = cast<clang::PointerType>(QT.getCanonicalType())->getPointeeType();
3378 }
else if (QT->isReferenceType()) {
3379 if (QT->isRValueReferenceType())
3380 refType = kRValueReference;
3382 refType = kLValueReference;
3383 QT = cast<ReferenceType>(QT.getCanonicalType())->getPointeeType();
3387 if (QT->isArrayType()) {
3388 std::string ar_typedef_name;
3390 std::ostringstream ar;
3391 ar <<
"AR" << gWrapperSerial++;
3392 type_name = ar.str();
3393 raw_string_ostream OS(ar_typedef_name);
3394 QT.print(OS, Policy, type_name);
3397 indent(typedefbuf, indent_level);
3398 typedefbuf <<
"typedef " << ar_typedef_name <<
";\n";
3401 get_type_as_string(QT, type_name, C, Policy);
3404void make_narg_ctor(
const FunctionDecl* FD,
const unsigned N,
3405 std::ostringstream& typedefbuf, std::ostringstream& callbuf,
3406 const std::string& class_name,
int indent_level,
3407 bool array =
false) {
3416 callbuf << class_name <<
"[nary]";
3418 callbuf << class_name;
3423 for (
unsigned i = 0U; i < N; ++i) {
3424 const ParmVarDecl* PVD = FD->getParamDecl(i);
3425 QualType Ty = PVD->getType();
3426 QualType QT = Ty.getCanonicalType();
3427 std::string type_name;
3428 EReferenceType refType = kNotReference;
3429 bool isPointer =
false;
3430 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3431 isPointer, indent_level,
true);
3438 indent(callbuf, indent_level);
3441 if (refType != kNotReference) {
3442 callbuf <<
"(" << type_name.c_str()
3443 << (refType == kLValueReference ?
"&" :
"&&") <<
")*("
3444 << type_name.c_str() <<
"*)args[" << i <<
"]";
3445 }
else if (isPointer) {
3446 callbuf <<
"*(" << type_name.c_str() <<
"**)args[" << i <<
"]";
3448 callbuf <<
"*(" << type_name.c_str() <<
"*)args[" << i <<
"]";
3454 else if (
const auto* CD = dyn_cast<CXXConstructorDecl>(FD);
3455 CD && CD->isDefaultConstructor() && !array) {
3460const DeclContext* get_non_transparent_decl_context(
const FunctionDecl* FD) {
3461 const auto* DC = FD->getDeclContext();
3462 while (DC->isTransparentContext()) {
3463 DC = DC->getParent();
3464 assert(DC &&
"All transparent contexts should have a parent!");
3469void make_narg_call(
const FunctionDecl* FD,
const std::string& return_type,
3470 const unsigned N, std::ostringstream& typedefbuf,
3471 std::ostringstream& callbuf,
const std::string& class_name,
3492 bool op_flag = !FD->isOverloadedOperator() ||
3493 FD->getOverloadedOperator() == clang::OO_Call;
3495 bool ShouldCastFunction = !isa<CXXMethodDecl>(FD) &&
3496 N == FD->getNumParams() && op_flag &&
3497 !FD->isTemplateInstantiation();
3498 if (ShouldCastFunction) {
3501 callbuf << return_type <<
" (&)";
3504 for (
unsigned i = 0U; i < N; ++i) {
3511 indent(callbuf, indent_level + 1);
3514 const ParmVarDecl* PVD = FD->getNonObjectParameter(i);
3515 QualType Ty = PVD->getType();
3516 QualType QT = Ty.getCanonicalType();
3517 std::string arg_type;
3518 ASTContext& C = FD->getASTContext();
3519 get_type_as_string(QT, arg_type, C, C.getPrintingPolicy());
3520 callbuf << arg_type;
3522 if (FD->isVariadic())
3530 if (
const auto* MD = dyn_cast<CXXMethodDecl>(FD)) {
3535 bool rvalue_ref = MD->getRefQualifier() == clang::RQ_RValue ||
3536 (MD->hasCXXExplicitFunctionObjectParameter() &&
3537 MD->getParamDecl(0)->getType()->isRValueReferenceType());
3539 callbuf <<
"static_cast<" << class_name <<
"&&>(*(" << class_name
3541 else if (MD->isConst())
3542 callbuf <<
"((const " << class_name <<
"*)obj)->";
3544 callbuf <<
"((" << class_name <<
"*)obj)->";
3547 callbuf << class_name <<
"::";
3548 }
else if (isa<NamedDecl>(get_non_transparent_decl_context(FD))) {
3550 if (op_flag || N <= 1)
3551 callbuf << class_name <<
"::";
3557 std::string complete_name;
3558 llvm::raw_string_ostream stream(complete_name);
3559 PrintingPolicy PP = FD->getASTContext().getPrintingPolicy();
3560 PP.FullyQualifiedName =
true;
3561 PP.SuppressUnwrittenScope =
true;
3562 PP.Suppress_Elab =
true;
3563 FD->getNameForDiagnostic(stream, PP,
3565 name = complete_name;
3572 std::string simple_name = FD->getNameAsString();
3573 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
3574 const auto* FTDecl =
3575 llvm::dyn_cast<FunctionTemplateDecl>(FD->getPrimaryTemplate());
3577 auto* templateParms = FTDecl->getTemplateParameters();
3579 for (
size_t iParam = 0, nParams = templateParms->size();
3580 iParam < nParams; ++iParam) {
3581 if (templateParms->getParam(iParam)->isTemplateParameterPack())
3591 if (FD->isOverloadedOperator())
3594 if (op_flag || N <= 1)
3597 if (ShouldCastFunction)
3601 for (
unsigned i = 0U; i < N; ++i) {
3602 const ParmVarDecl* PVD = FD->getNonObjectParameter(i);
3603 QualType Ty = PVD->getType();
3604 QualType QT = Ty.getCanonicalType();
3605 std::string type_name;
3606 EReferenceType refType = kNotReference;
3607 bool isPointer =
false;
3608 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3609 isPointer, indent_level,
true);
3616 << clang::getOperatorSpelling(FD->getOverloadedOperator())
3621 CXXRecordDecl* rtdecl = QT->getAsCXXRecordDecl();
3622 if (refType != kNotReference) {
3623 callbuf <<
"(" << type_name.c_str()
3624 << (refType == kLValueReference ?
"&" :
"&&") <<
")*("
3625 << type_name.c_str() <<
"*)args[" << i <<
"]";
3626 }
else if (isPointer) {
3627 callbuf <<
"*(" << type_name.c_str() <<
"**)args[" << i <<
"]";
3628 }
else if (rtdecl &&
3629 (rtdecl->hasTrivialCopyConstructor() &&
3630 !rtdecl->hasSimpleCopyConstructor()) &&
3631 rtdecl->hasMoveConstructor()) {
3648 callbuf <<
"static_cast<" << type_name.c_str() <<
"&&>(*("
3649 << type_name.c_str() <<
"*)args[" << i <<
"])";
3653 callbuf <<
"*(" << type_name.c_str() <<
"*)args[" << i <<
"]";
3659void make_narg_ctor_with_return(
const FunctionDecl* FD,
const unsigned N,
3660 const std::string& class_name,
3661 std::ostringstream& buf,
int indent_level) {
3674 std::ostringstream typedefbuf;
3675 std::ostringstream callbuf;
3679 indent(callbuf, indent_level);
3680 const auto* CD = dyn_cast<CXXConstructorDecl>(FD);
3688 if (CD->isDefaultConstructor()) {
3689 callbuf <<
"if (nary > 1) {\n";
3690 indent(callbuf, indent_level);
3691 callbuf <<
"(*(" << class_name <<
"**)ret) = ";
3692 callbuf <<
"(is_arena) ? new (*(" << class_name <<
"**)ret) ";
3693 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
3696 callbuf <<
": new ";
3700 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
3706 indent(callbuf, indent_level);
3708 callbuf <<
"else {\n";
3714 indent(callbuf, indent_level);
3715 callbuf <<
"(*(" << class_name <<
"**)ret) = ";
3716 callbuf <<
"(is_arena) ? new (*(" << class_name <<
"**)ret) ";
3717 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
3719 callbuf <<
": new ";
3723 make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
3728 indent(callbuf, --indent_level);
3729 if (CD->isDefaultConstructor())
3731#if __has_feature(memory_sanitizer)
3734 indent(callbuf, indent_level);
3735 callbuf <<
"__msan_unpoison(*(void**)ret, sizeof(" << class_name
3736 <<
") * (nary > 1 ? nary : 1));\n";
3742 buf << typedefbuf.str() << callbuf.str();
3747 const unsigned N,
const std::string& class_name,
3748 std::ostringstream& buf,
int indent_level) {
3758 if (
const auto* CD = dyn_cast<CXXConstructorDecl>(FD)) {
3759 if (N <= 1 && llvm::isa<UsingShadowDecl>(FD)) {
3760 auto SpecMemKind = I.
getCI()->getSema().getSpecialMember(CD);
3761 if ((N == 0 && SpecMemKind == CXXSpecialMemberKind::DefaultConstructor) ||
3762 (N == 1 && (SpecMemKind == CXXSpecialMemberKind::CopyConstructor ||
3763 SpecMemKind == CXXSpecialMemberKind::MoveConstructor))) {
3771 make_narg_ctor_with_return(FD, N, class_name, buf, indent_level);
3774 QualType QT = FD->getReturnType();
3775 if (QT->isVoidType()) {
3776 std::ostringstream typedefbuf;
3777 std::ostringstream callbuf;
3778 indent(callbuf, indent_level);
3779 make_narg_call(FD,
"void", N, typedefbuf, callbuf, class_name,
3782 indent(callbuf, indent_level);
3783 callbuf <<
"return;\n";
3784 buf << typedefbuf.str() << callbuf.str();
3786 indent(buf, indent_level);
3788 std::string type_name;
3789 EReferenceType refType = kNotReference;
3790 bool isPointer =
false;
3792 std::ostringstream typedefbuf;
3793 std::ostringstream callbuf;
3795 collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
3796 isPointer, indent_level,
false);
3798 buf << typedefbuf.str();
3800 buf <<
"if (ret) {\n";
3806 indent(callbuf, indent_level);
3807 callbuf <<
"new (ret) ";
3811 callbuf <<
"(" << type_name.c_str();
3812 if (refType != kNotReference) {
3815 }
else if (isPointer) {
3824 make_narg_call(FD, type_name, N, typedefbuf, callbuf, class_name,
3830#if __has_feature(memory_sanitizer)
3831 indent(callbuf, indent_level);
3832 callbuf <<
"__msan_unpoison(ret, sizeof(" << type_name <<
"));\n";
3834 indent(callbuf, indent_level);
3835 callbuf <<
"return;\n";
3839 buf << typedefbuf.str() << callbuf.str();
3842 indent(buf, indent_level);
3844 indent(buf, indent_level);
3848 std::ostringstream typedefbuf;
3849 std::ostringstream callbuf;
3850 indent(callbuf, indent_level);
3851 callbuf <<
"(void)(";
3852 make_narg_call(FD, type_name, N, typedefbuf, callbuf, class_name,
3855 indent(callbuf, indent_level);
3856 callbuf <<
"return;\n";
3857 buf << typedefbuf.str() << callbuf.str();
3860 indent(buf, indent_level);
3866 std::string& wrapper_name, std::string& wrapper) {
3867 assert(FD &&
"generate_wrapper called without a function decl!");
3868 ASTContext& Context = FD->getASTContext();
3872 std::string class_name;
3873 const clang::DeclContext* DC = get_non_transparent_decl_context(FD);
3874 GetDeclName(cast<Decl>(DC), Context, class_name);
3879 bool needInstantiation =
false;
3880 const FunctionDecl* Definition = 0;
3882 if (!FD->isDefined(Definition)) {
3883 FunctionDecl::TemplatedKind TK = FD->getTemplatedKind();
3885 case FunctionDecl::TK_NonTemplate: {
3895 case FunctionDecl::TK_FunctionTemplate: {
3898 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3900 <<
"Cannot make wrapper for a function template!";
3903 case FunctionDecl::TK_MemberSpecialization: {
3910 if (!FD->isTemplateInstantiation()) {
3923 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3925 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3927 <<
"Cannot make wrapper for a member function "
3928 "instantiation with no pattern!";
3931 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3932 TemplateSpecializationKind PTSK =
3933 Pattern->getTemplateSpecializationKind();
3936 (PTK == FunctionDecl::TK_NonTemplate) ||
3939 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3940 ((PTSK == TSK_Undeclared) ||
3941 (PTSK == TSK_ExplicitSpecialization)))) {
3946 }
else if (!Pattern->hasBody()) {
3947 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3949 <<
"Cannot make wrapper for a member function "
3950 "instantiation with no body!";
3953 if (FD->isImplicitlyInstantiable()) {
3954 needInstantiation =
true;
3957 case FunctionDecl::TK_FunctionTemplateSpecialization: {
3962 if (!FD->isTemplateInstantiation()) {
3975 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
3977 llvm::errs() <<
"TClingCallFunc::make_wrapper"
3979 <<
"Cannot make wrapper for a function template"
3980 "instantiation with no pattern!";
3983 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
3984 TemplateSpecializationKind PTSK =
3985 Pattern->getTemplateSpecializationKind();
3988 (PTK == FunctionDecl::TK_NonTemplate) ||
3991 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
3992 ((PTSK == TSK_Undeclared) ||
3993 (PTSK == TSK_ExplicitSpecialization)))) {
4000 if (!Pattern->hasBody()) {
4001 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4003 <<
"Cannot make wrapper for a function template "
4004 <<
"instantiation with no body!";
4007 if (FD->isImplicitlyInstantiable()) {
4008 needInstantiation =
true;
4012 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
4020 if (!FD->isTemplateInstantiation()) {
4033 const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern();
4035 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4037 <<
"Cannot make wrapper for a dependent function template"
4038 "instantiation with no pattern!";
4041 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
4042 TemplateSpecializationKind PTSK =
4043 Pattern->getTemplateSpecializationKind();
4046 (PTK == FunctionDecl::TK_NonTemplate) ||
4049 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
4050 ((PTSK == TSK_Undeclared) ||
4051 (PTSK == TSK_ExplicitSpecialization)))) {
4057 if (!Pattern->hasBody()) {
4058 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4060 <<
"Cannot make wrapper for a dependent function template"
4061 "instantiation with no body!";
4064 if (FD->isImplicitlyInstantiable()) {
4065 needInstantiation =
true;
4071 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4073 <<
"Unhandled template kind!";
4095 if (needInstantiation) {
4096 clang::FunctionDecl* FDmod =
const_cast<clang::FunctionDecl*
>(FD);
4099 if (!FD->isDefined(Definition)) {
4100 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4102 <<
"Failed to force template instantiation!";
4107 FunctionDecl::TemplatedKind TK = Definition->getTemplatedKind();
4109 case FunctionDecl::TK_NonTemplate: {
4111 if (Definition->isDeleted()) {
4112 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4114 <<
"Cannot make wrapper for a deleted function!";
4116 }
else if (Definition->isLateTemplateParsed()) {
4117 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4119 <<
"Cannot make wrapper for a late template parsed "
4130 case FunctionDecl::TK_FunctionTemplate: {
4133 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4135 <<
"Cannot make wrapper for a function template!";
4138 case FunctionDecl::TK_MemberSpecialization: {
4142 if (Definition->isDeleted()) {
4143 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4145 <<
"Cannot make wrapper for a deleted member function "
4146 "of a specialization!";
4148 }
else if (Definition->isLateTemplateParsed()) {
4149 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4151 <<
"Cannot make wrapper for a late template parsed "
4152 "member function of a specialization!";
4162 case FunctionDecl::TK_FunctionTemplateSpecialization: {
4167 if (Definition->isDeleted()) {
4168 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4170 <<
"Cannot make wrapper for a deleted function "
4171 "template specialization!";
4173 }
else if (Definition->isLateTemplateParsed()) {
4174 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4176 <<
"Cannot make wrapper for a late template parsed "
4177 "function template specialization!";
4187 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
4195 if (Definition->isDeleted()) {
4196 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4198 <<
"Cannot make wrapper for a deleted dependent function "
4199 "template specialization!";
4201 }
else if (Definition->isLateTemplateParsed()) {
4202 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4204 <<
"Cannot make wrapper for a late template parsed "
4205 "dependent function template specialization!";
4218 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4220 <<
"Unhandled template kind!";
4228 unsigned min_args = FD->getMinRequiredExplicitArguments();
4229 unsigned num_params = FD->getNumNonObjectParams();
4234 std::ostringstream buf;
4240 buf <<
'_' << gWrapperSerial++;
4241 wrapper_name = buf.str();
4247 int indent_level = 0;
4248 std::ostringstream buf;
4249 buf <<
"#pragma clang diagnostic push\n"
4250 "#pragma clang diagnostic ignored \"-Wformat-security\"\n";
4251#if __has_feature(memory_sanitizer)
4254 buf <<
"extern \"C\" void __msan_unpoison(const volatile void*, "
4255 "unsigned long);\n";
4257 buf <<
"__attribute__((used)) "
4258 "__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
4259 "extern \"C\" void ";
4260 buf << wrapper_name;
4262 buf <<
"(void* ret, unsigned long nary, unsigned long nargs, void** args, "
4266 buf <<
"(void* obj, unsigned long nargs, void** args, void* ret)\n"
4270 if (min_args == num_params) {
4272 make_narg_call_with_return(I, FD, num_params, class_name, buf,
4277 for (
unsigned N = min_args; N <= num_params; ++N) {
4278 indent(buf, indent_level);
4279 buf <<
"if (nargs == " << N <<
") {\n";
4281 make_narg_call_with_return(I, FD, N, class_name, buf, indent_level);
4283 indent(buf, indent_level);
4289 "#pragma clang diagnostic pop";
4290 wrapper = buf.str();
4295 const FunctionDecl* FD) {
4298 auto R = WrapperStore.find(FD);
4299 if (R != WrapperStore.end())
4300 return (JitCall::GenericCall)R->second;
4302 std::string wrapper_name;
4303 std::string wrapper_code;
4305 if (get_wrapper_code(I, FD, wrapper_name, wrapper_code) == 0)
4310 std::string FuncName;
4311 llvm::raw_string_ostream FNS(FuncName);
4312 FD->getNameForDiagnostic(FNS, FD->getASTContext().getPrintingPolicy(),
4314 TI->appendToLog(
" // === Wrapper for " + FuncName +
" ===");
4316 llvm::StringRef WC(wrapper_code);
4317 while (!WC.empty()) {
4318 auto [Line, Rest] = WC.split(
'\n');
4320 TI->appendToLog((
" // " + Line).str());
4323 TI->appendToLog(
" // === End wrapper ===");
4329 bool withAccessControl =
true;
4331 if (
auto Ctor = dyn_cast<CXXConstructorDecl>(FD))
4332 withAccessControl = !Ctor->isDefaultConstructor();
4334 compile_wrapper(I, wrapper_name, wrapper_code, withAccessControl);
4336 WrapperStore.insert(std::make_pair(FD, wrapper));
4338 llvm::errs() <<
"TClingCallFunc::make_wrapper"
4340 <<
"Failed to compile\n"
4341 <<
"==== SOURCE BEGIN ====\n"
4342 << wrapper_code <<
"\n"
4343 <<
"==== SOURCE END ====\n";
4345 LLVM_DEBUG(dbgs() <<
"Compiled '" << (wrapper ?
"" :
"un")
4346 <<
"successfully:\n"
4347 << wrapper_code <<
"'\n");
4348 return (JitCall::GenericCall)wrapper;
4352static std::string PrepareStructorWrapper(
const Decl* D,
4353 const char* wrapper_prefix,
4354 std::string& class_name) {
4355 ASTContext& Context = D->getASTContext();
4356 GetDeclName(D, Context, class_name);
4361 std::string wrapper_name;
4363 std::ostringstream buf;
4364 buf << wrapper_prefix;
4369 buf <<
'_' << gWrapperSerial++;
4370 wrapper_name = buf.str();
4373 return wrapper_name;
4408 auto I = DtorWrapperStore.find(D);
4409 if (I != DtorWrapperStore.end())
4410 return (JitCall::DestructorCall)I->second;
4415 std::string class_name;
4416 std::string wrapper_name = PrepareStructorWrapper(D,
"__dtor", class_name);
4420 int indent_level = 0;
4421 std::ostringstream buf;
4422#if CPPINTEROP_ASAN_BUILD
4432 buf <<
"extern \"C\" void __lsan_ignore_object(const void*);\n";
4434 buf <<
"__attribute__((used)) ";
4435 buf <<
"extern \"C\" void ";
4436 buf << wrapper_name;
4437 buf <<
"(void* obj, unsigned long nary, int withFree)\n";
4449 indent(buf, indent_level);
4450 buf <<
"if (withFree) {\n";
4452#if CPPINTEROP_ASAN_BUILD
4453 indent(buf, indent_level);
4454 buf <<
"__lsan_ignore_object(obj);\n";
4456 indent(buf, indent_level);
4457 buf <<
"if (!nary) {\n";
4459 indent(buf, indent_level);
4460 buf <<
"delete (" << class_name <<
"*) obj;\n";
4462 indent(buf, indent_level);
4464 indent(buf, indent_level);
4467 indent(buf, indent_level);
4468 buf <<
"delete[] (" << class_name <<
"*) obj;\n";
4470 indent(buf, indent_level);
4473 indent(buf, indent_level);
4486 indent(buf, indent_level);
4489 indent(buf, indent_level);
4490 buf <<
"typedef " << class_name <<
" Nm;\n";
4491 buf <<
"if (!nary) {\n";
4493 indent(buf, indent_level);
4494 buf <<
"((Nm*)obj)->~Nm();\n";
4496 indent(buf, indent_level);
4498 indent(buf, indent_level);
4501 indent(buf, indent_level);
4504 indent(buf, indent_level);
4505 buf <<
"(((Nm*)obj)+(--nary))->~Nm();\n";
4507 indent(buf, indent_level);
4508 buf <<
"} while (nary);\n";
4510 indent(buf, indent_level);
4513 indent(buf, indent_level);
4519 std::string wrapper(buf.str());
4524 void* F = compile_wrapper(interp, wrapper_name, wrapper,
4527 DtorWrapperStore.insert(std::make_pair(D, F));
4529 llvm::errs() <<
"make_dtor_wrapper"
4530 <<
"Failed to compile\n"
4531 <<
"==== SOURCE BEGIN ====\n"
4532 << wrapper <<
"\n ==== SOURCE END ====";
4534 LLVM_DEBUG(dbgs() <<
"Compiled '" << (F ?
"" :
"un") <<
"successfully:\n"
4535 << wrapper <<
"'\n");
4536 return (JitCall::DestructorCall)F;
4544 const auto* D = unwrap<clang::Decl>(func);
4548 auto* interp = unwrap<compat::Interpreter>(I);
4551 if (
const auto* Dtor = dyn_cast<CXXDestructorDecl>(D)) {
4552 if (
auto Wrapper = make_dtor_wrapper(*interp, Dtor->getParent()))
4554 JitCall(JitCall::kDestructorCall,
Wrapper, wrap<ConstFuncRef>(Dtor)));
4559 if (
const auto* Ctor = dyn_cast<CXXConstructorDecl>(D)) {
4560 if (
auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D)))
4562 wrap<ConstFuncRef>(Ctor)));
4567 if (
auto Wrapper = make_wrapper(*interp, cast<FunctionDecl>(D))) {
4569 wrap<ConstFuncRef>(cast<FunctionDecl>(D))));
4581#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
4584 using namespace llvm;
4585 using namespace llvm::orc;
4588 JITDylib& DyLib = *Jit.getProcessSymbolsJITDylib().get();
4595 llvm::orc::SymbolMap InjectedSymbols{
4596 {Jit.mangleAndIntern(unmangled_name),
4597 ExecutorSymbolDef(ExecutorAddr(address), JITSymbolFlags::Exported)}};
4599 if (Error Err = DyLib.define(absoluteSymbols(InjectedSymbols))) {
4600 logAllUnhandledErrors(std::move(Err), errs(),
4601 "DefineAbsoluteSymbol error: ");
4608static std::string MakeResourcesPath() {
4610#ifdef LLVM_BINARY_DIR
4611 Dir = LLVM_BINARY_DIR;
4618 StringRef Dir = sys::path::parent_path(BinaryPath);
4620 Dir = sys::path::parent_path(Dir);
4621 Dir = sys::path::parent_path(Dir);
4622 Dir = sys::path::parent_path(Dir);
4623 Dir = sys::path::parent_path(Dir);
4626 llvm::SmallString<128> P(Dir);
4627 llvm::sys::path::append(P, CLANG_INSTALL_LIBDIR_BASENAME,
"clang",
4628 CLANG_VERSION_MAJOR_STRING);
4629 return std::string(P.str());
4632void AddLibrarySearchPaths(
const std::string& ResourceDir,
4641 std::string path1 = ResourceDir +
"/lib";
4643 size_t pos = ResourceDir.rfind(
"/llvm-");
4644 if (pos != std::string::npos) {
4648 pos = ResourceDir.rfind(
"/clang");
4649 if (pos != std::string::npos) {
4654std::string ExtractArgument(
const std::vector<const char*>& Args,
4655 const std::string& Arg) {
4657 for (
auto i = Args.begin(); i != Args.end(); i++)
4658 if ((++I < Args.size()) && (*i == Arg))
4665static bool exec(
const char* cmd, std::vector<std::string>& outputs) {
4666#define DEBUG_TYPE "exec"
4668 std::array<char, 256> buffer;
4669 struct file_deleter {
4670 void operator()(FILE* fp) { pclose(fp); }
4672 std::unique_ptr<FILE, file_deleter> pipe{popen(cmd,
"r")};
4673 LLVM_DEBUG(dbgs() <<
"Executing command '" << cmd <<
"'\n");
4676 LLVM_DEBUG(dbgs() <<
"Execute failed!\n");
4681 LLVM_DEBUG(dbgs() <<
"Execute returned:\n");
4682 while (fgets(buffer.data(),
static_cast<int>(buffer.size()), pipe.get())) {
4683 LLVM_DEBUG(dbgs() << buffer.data());
4684 llvm::StringRef trimmed = buffer.data();
4685 outputs.push_back(trimmed.trim().str());
4694 const std::vector<const char*>& GpuArgs ) {
4699 std::vector<std::string> ArgvStorage;
4700 ArgvStorage.push_back(sys::fs::getMainExecutable(
nullptr,
nullptr));
4707 std::string ResourceDir = ExtractArgument(Args,
"-resource-dir");
4708 if (ResourceDir.empty())
4709 ResourceDir = MakeResourcesPath();
4710 llvm::Triple T(llvm::sys::getProcessTriple());
4711 if ((!sys::fs::is_directory(ResourceDir)) &&
4712 (T.isOSDarwin() || T.isOSLinux()))
4715 if (!ResourceDir.empty()) {
4716 ArgvStorage.push_back(
"-resource-dir");
4717 ArgvStorage.push_back(ResourceDir);
4719 ArgvStorage.push_back(
"-std=c++14");
4722 ArgvStorage.push_back(
"-fno-delayed-template-parsing");
4724#if __has_feature(memory_sanitizer)
4729 ArgvStorage.push_back(
"-stdlib=libc++");
4737 if (!ResourceDir.empty()) {
4738 SmallString<256> P(ResourceDir);
4739 sys::path::remove_filename(P);
4740 sys::path::remove_filename(P);
4741 sys::path::remove_filename(P);
4742 sys::path::append(P,
"include",
"c++",
"v1");
4743 if (sys::fs::is_directory(P)) {
4744 ArgvStorage.push_back(
"-cxx-isystem");
4745 ArgvStorage.push_back(P.str().str());
4749 ArgvStorage.insert(ArgvStorage.end(), Args.begin(), Args.end());
4753 if (!GpuArgs.empty()) {
4754 llvm::StringRef Arg0 = GpuArgs[0];
4755 Arg0 = Arg0.trim().ltrim(
'-');
4756 if (Arg0 !=
"cuda") {
4757 llvm::errs() <<
"[CreateInterpreter]: Make sure --cuda is passed as the"
4758 <<
" first argument of the GpuArgs\n";
4762 ArgvStorage.insert(ArgvStorage.end(), GpuArgs.begin(), GpuArgs.end());
4765 auto EnvOpt = llvm::sys::Process::GetEnv(
"CPPINTEROP_EXTRA_INTERPRETER_ARGS");
4767 StringRef Env(*EnvOpt);
4768 while (!Env.empty()) {
4770 std::tie(Arg, Env) = Env.split(
' ');
4771 ArgvStorage.push_back(Arg.str());
4775 std::vector<const char*> ClingArgv;
4776 ClingArgv.reserve(ArgvStorage.size());
4777 for (
const std::string& Arg : ArgvStorage)
4778 ClingArgv.push_back(Arg.c_str());
4786 std::string MacOSSDK;
4787 if (T.isOSDarwin()) {
4788 const bool HasSysroot = llvm::any_of(ClingArgv, [](
const char* A) {
4789 return llvm::StringRef(A) ==
"-isysroot";
4791 auto SDKRootEnv = llvm::sys::Process::GetEnv(
"SDKROOT");
4792 const bool ValidSDKRoot = SDKRootEnv &&
4793 llvm::sys::path::is_absolute(*SDKRootEnv) &&
4794 llvm::sys::fs::exists(*SDKRootEnv) &&
4795 llvm::StringRef(*SDKRootEnv) !=
"/";
4796 if (!HasSysroot && !ValidSDKRoot) {
4797 std::vector<std::string> Out;
4798 if (
exec(
"xcrun --sdk macosx --show-sdk-path", Out) && !Out.empty())
4799 MacOSSDK = Out.back();
4800 if (!MacOSSDK.empty() && llvm::sys::fs::is_directory(MacOSSDK)) {
4801 ClingArgv.push_back(
"-isysroot");
4802 ClingArgv.push_back(MacOSSDK.c_str());
4810#ifdef CPPINTEROP_USE_CLING
4815 ClingArgv.data(),
nullptr, {},
nullptr,
true);
4818 auto* I = Interp.release();
4825 const CompilerInstance* Clang = I->getCI();
4826 if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
4827 unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
4828 auto Args = std::make_unique<const char*[]>(NumArgs + 2);
4829 Args[0] =
"clang (LLVM option parsing)";
4830 for (
unsigned i = 0; i != NumArgs; ++i)
4831 Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
4832 Args[NumArgs + 1] =
nullptr;
4833 llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
4837 AddLibrarySearchPaths(ResourceDir, I);
4841 namespace __internal_CppInterOp {
4842 template <typename Signature>
4844 template <typename Res, typename... ArgTypes>
4845 struct function<Res(ArgTypes...)> {
4846 typedef Res result_type;
4848 } // namespace __internal_CppInterOp
4855#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
4856 DefineAbsoluteSymbol(*I,
"__ci_newtag",
4859#if CLANG_VERSION_MAJOR >= 21
4860 DefineAbsoluteSymbol(
4861 *I,
"__clang_Interpreter_SetValueWithAlloc",
4866 unwrap<Decl>(
Cpp::GetNamed(
"__clang_Interpreter_SetValueWithAlloc"));
4867 if (
auto* FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
4868 auto GD = GlobalDecl(FD);
4869 std::string mangledName;
4871 DefineAbsoluteSymbol(
4872 *I, mangledName.c_str(),
4877 DefineAbsoluteSymbol(
4878 *I,
"__clang_Interpreter_SetValueNoAlloc",
4887 const auto& LO = interp->
getCI()->getLangOpts();
4895 auto standard = clang::LangStandard::getLangStandardForKind(LO.LangStd);
4896 auto lang =
static_cast<InterpreterLanguage
>(standard.getLanguage());
4897 assert(lang != InterpreterLanguage::Unknown &&
"Unknown language");
4898 assert(
static_cast<unsigned char>(lang) <=
4899 static_cast<unsigned char>(InterpreterLanguage::HLSL) &&
4900 "Unhandled Language");
4907 const auto& LO = interp->
getCI()->getLangOpts();
4908 auto langStandard =
static_cast<InterpreterLanguageStandard
>(LO.LangStd);
4909 assert(langStandard != InterpreterLanguageStandard::lang_unspecified &&
4910 "Unspecified language standard");
4911 assert(
static_cast<unsigned char>(langStandard) <=
4912 static_cast<unsigned char>(
4913 InterpreterLanguageStandard::lang_unspecified) &&
4914 "Unhandled language standard.");
4927 getInterp().getCI()->getHeaderSearchOpts().ResourceDir.c_str());
4932 std::string cmd = std::string(ClangBinaryName) +
" -print-resource-dir";
4933 std::vector<std::string> outs;
4934 exec(cmd.c_str(), outs);
4935 if (outs.empty() || outs.size() > 1)
4938 std::string detected_resource_dir = outs.back();
4940 std::string version = CLANG_VERSION_MAJOR_STRING;
4942 if (llvm::sys::path::filename(detected_resource_dir) != version)
4949 const char* CompilerName ) {
4951 std::string cmd =
"LC_ALL=C ";
4952 cmd += CompilerName;
4953 cmd +=
" -xc++ -E -v /dev/null 2>&1 | sed -n -e '/^.include/,${' -e '/^ "
4955 std::vector<std::string> outs;
4956 exec(cmd.c_str(), Paths);
4969 llvm::SmallVector<std::string> paths(1);
4971 for (
auto& i : paths)
4972 IncludePaths.push_back(i);
4979 clangSilent(clang::DiagnosticsEngine& diag) :
fDiagEngine(diag) {
4996 clang::DiagnosticsEngine& Diag = I.
getSema().getDiagnostics();
4997 clang::DiagnosticErrorTrap Trap(Diag);
4999 clangSilent diagSuppr(Diag);
5001 if (Trap.hasErrorOccurred())
5006 if (Trap.hasErrorOccurred())
5029 if (
const auto* BT = QT->getAs<clang::BuiltinType>()) {
5030 switch (BT->getKind()) {
5031 case clang::BuiltinType::Bool:
5033 case clang::BuiltinType::Char_S:
5035 case clang::BuiltinType::Char_U:
5039 case clang::BuiltinType::SChar:
5041 case clang::BuiltinType::UChar:
5043 case clang::BuiltinType::Short:
5045 case clang::BuiltinType::UShort:
5047 case clang::BuiltinType::Int:
5049 case clang::BuiltinType::UInt:
5051 case clang::BuiltinType::Long:
5053 case clang::BuiltinType::ULong:
5055 case clang::BuiltinType::LongLong:
5057 case clang::BuiltinType::ULongLong:
5059 case clang::BuiltinType::Float:
5061 case clang::BuiltinType::Double:
5063 case clang::BuiltinType::LongDouble:
5067 "clang::Value asserts on builtins outside the X-macro set");
5078 if (res != 0 || !V.hasValue())
5081 clang::QualType QT = V.getType();
5082 void* qt = QT.getAsOpaquePtr();
5084#define X(TyRef, name) \
5085 case Cpp::Box::K_##name: \
5086 return INTEROP_RETURN( \
5087 Cpp::Box::Create<TyRef>(compat::convertTo<TyRef>(V), qt));
5097 llvm_unreachable(
"Box::Kind not produced by classifyByQualType");
5099 llvm_unreachable(
"classifyByQualType returned an unhandled Kind");
5105 getInterp().getDynamicLibraryManager()->lookupLibrary(lib_name));
5123 bool search_system ) {
5127 DLM->searchLibrariesForSymbol(mangled_name, search_system));
5131 const char* linker_mangled_name,
5155 using namespace llvm;
5156 using namespace llvm::orc;
5160 llvm::orc::ExecutionSession& ES = Jit.getExecutionSession();
5161 JITDylib& DyLib = *Jit.getProcessSymbolsJITDylib().get();
5163 if (Error Err = Symbol.takeError()) {
5164 logAllUnhandledErrors(std::move(Err), errs(),
5165 "[InsertOrReplaceJitSymbol] error: ");
5166#define DEBUG_TYPE "orc"
5167 LLVM_DEBUG(ES.dump(dbgs()));
5173 if (*Symbol && *Symbol == address) {
5174 errs() <<
"[InsertOrReplaceJitSymbol] warning: redefining '"
5175 << linker_mangled_name <<
"' with the same address\n";
5180 llvm::orc::SymbolMap InjectedSymbols;
5182 char GlobalPrefix = DL.getGlobalPrefix();
5183 std::string tmp(linker_mangled_name);
5184 if (GlobalPrefix !=
'\0') {
5185 tmp = std::string(1, GlobalPrefix) + tmp;
5187 auto Name = ES.intern(tmp);
5188 InjectedSymbols[Name] =
5189 ExecutorSymbolDef(ExecutorAddr(address), JITSymbolFlags::Exported);
5192 if (Symbol && address)
5194 if (
auto Err = DyLib.remove({Name})) {
5195 logAllUnhandledErrors(std::move(Err), errs(),
5196 "[InsertOrReplaceJitSymbol] error: ");
5200 if (Error Err = DyLib.define(absoluteSymbols(InjectedSymbols))) {
5201 logAllUnhandledErrors(std::move(Err), errs(),
5202 "[InsertOrReplaceJitSymbol] error: ");
5222 TemplateArgumentListInfo& TLI, Sema& S,
5223 bool instantiate_body) {
5227 if (
auto* FunctionTemplate = dyn_cast<FunctionTemplateDecl>(TemplateD)) {
5228 FunctionDecl* Specialization =
nullptr;
5229 clang::sema::TemplateDeductionInfo Info(fakeLoc);
5230 TemplateDeductionResult Result =
5231 S.DeduceTemplateArguments(FunctionTemplate, &TLI, Specialization, Info,
5233 if (Result != TemplateDeductionResult::Success) {
5237 if (instantiate_body)
5239 return Specialization;
5242 if (
auto* VarTemplate = dyn_cast<VarTemplateDecl>(TemplateD)) {
5243#if CLANG_VERSION_MAJOR < 22
5244 DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI);
5246 DeclResult R = S.CheckVarTemplateId(VarTemplate, fakeLoc, fakeLoc, TLI,
5249 if (R.isInvalid()) {
5256 SourceLocation noLoc;
5257#if CLANG_VERSION_MAJOR < 22
5258 QualType TT = S.CheckTemplateIdType(TemplateName(TemplateD), noLoc, TLI);
5260 QualType TT = S.CheckTemplateIdType(
5261 ElaboratedTypeKeyword::None, TemplateName(TemplateD), noLoc, TLI,
5268 S.RequireCompleteType(fakeLoc, TT, diag::err_tentative_def_incomplete_type);
5283 ArrayRef<TemplateArgument> TemplateArgs, Sema& S,
5284 bool instantiate_body) {
5286 TemplateArgumentListInfo TLI{};
5287 for (
auto TA : TemplateArgs)
5289 S.getTrivialTemplateArgumentLoc(TA, QualType(), SourceLocation()));
5296 size_t template_args_size,
bool instantiate_body) {
5298 auto& C = S.getASTContext();
5300 llvm::SmallVector<TemplateArgument> TemplateArgs;
5301 TemplateArgs.reserve(template_args_size);
5302 for (
size_t i = 0; i < template_args_size; ++i) {
5303 QualType ArgTy = QualType::getFromOpaquePtr(template_args[i].m_Type);
5304 if (template_args[i].m_IntegralValue) {
5307 auto Res = llvm::APSInt(template_args[i].m_IntegralValue);
5308 Res = Res.extOrTrunc(C.getIntWidth(ArgTy));
5309 TemplateArgs.push_back(TemplateArgument(C, Res, ArgTy));
5311 TemplateArgs.push_back(ArgTy);
5315 auto* TmplD = unwrap<TemplateDecl>(tmpl);
5322 size_t template_args_size,
bool instantiate_body) {
5323 INTEROP_TRACE(tmpl, template_args, template_args_size, instantiate_body);
5325 getInterp(), tmpl, template_args, template_args_size, instantiate_body));
5329 const std::vector<TemplateArgInfo>& template_args,
5330 bool instantiate_body) {
5336 template_args.size(), instantiate_body));
5340 std::vector<TemplateArgInfo>& args) {
5342 const auto* CTSD = unwrap<ClassTemplateSpecializationDecl>(templ_instance);
5343 for (
const auto& TA : CTSD->getTemplateArgs().asArray()) {
5345 args.push_back({TA.getAsType().getAsOpaquePtr()});
5351 std::vector<TemplateArgInfo>& args) {
5353 const auto* CTSD = unwrap<ClassTemplateSpecializationDecl>(templ_instance);
5354 for (
const auto& TA : CTSD->getTemplateInstantiationArgs().asArray()) {
5355 switch (TA.getKind()) {
5357 assert(0 &&
"Not yet supported!");
5359 case TemplateArgument::Pack:
5360 for (
auto SubTA : TA.pack_elements())
5361 args.push_back({SubTA.getAsType().getAsOpaquePtr()});
5363 case TemplateArgument::Integral:
5369 case TemplateArgument::Type:
5370 args.push_back({TA.getAsType().getAsOpaquePtr()});
5382 static unsigned long long var_count = 0;
5383 std::string
id =
"__Cppyy_GetMethTmpl_" + std::to_string(var_count++);
5384 std::string instance =
"auto " +
id +
" = " + function_template +
";\n";
5388 DeclRefExpr* DRE = (DeclRefExpr*)VD->getInit()->IgnoreImpCasts();
5396 const auto* D = unwrap<clang::Decl>(DRef);
5397 clang::DeclContext* DC;
5398 clang::DeclContext::decl_iterator decl;
5402 if (
const auto* TD = dyn_cast_or_null<TagDecl>(D)) {
5403 DC = clang::TagDecl::castToDeclContext(TD);
5404 decl = DC->decls_begin();
5406 }
else if (
const auto* ND = dyn_cast_or_null<NamespaceDecl>(D)) {
5407 DC = clang::NamespaceDecl::castToDeclContext(ND);
5408 decl = DC->decls_begin();
5409 }
else if (
const auto* TUD = dyn_cast_or_null<TranslationUnitDecl>(D)) {
5410 DC = clang::TranslationUnitDecl::castToDeclContext(TUD);
5411 decl = DC->decls_begin();
5416 for (; decl != DC->decls_end(); decl++) {
5417 if (
const auto* ND = llvm::dyn_cast_or_null<NamedDecl>(*decl)) {
5418 names.insert(ND->getNameAsString());
5424void GetEnums(ConstDeclRef DRef, std::vector<std::string>& Result) {
5427 auto* D =
const_cast<clang::Decl*
>(unwrap<clang::Decl>(DRef));
5429 if (!llvm::isa_and_nonnull<clang::DeclContext>(D))
5432 auto* DC = llvm::dyn_cast<clang::DeclContext>(D);
5434 llvm::SmallVector<clang::DeclContext*, 4> DCs;
5435 DC->collectAllContexts(DCs);
5438 for (
auto* DC : DCs) {
5439 for (
auto decl = DC->decls_begin(); decl != DC->decls_end(); decl++) {
5440 if (
auto* ND = llvm::dyn_cast_or_null<EnumDecl>(*decl)) {
5441 Result.push_back(ND->getNameAsString());
5452 QualType Qual = QualType::getFromOpaquePtr(TyRef.data);
5455 Qual = Qual.getCanonicalType();
5456 std::vector<long int> dims;
5457 if (Qual->isArrayType()) {
5458 const auto* ArrayType = dyn_cast<clang::ArrayType>(Qual.getTypePtr());
5460 if (
const auto* CAT = dyn_cast_or_null<ConstantArrayType>(ArrayType)) {
5461 llvm::APSInt Size(CAT->getSize());
5462 long int ArraySize = Size.getLimitedValue();
5463 dims.push_back(ArraySize);
5467 dims.push_back(DimensionValue::UNKNOWN_SIZE);
5469 ArrayType = ArrayType->getElementType()->getAsArrayTypeUnsafe();
5480 auto derivedType = clang::QualType::getFromOpaquePtr(derived.data);
5481 auto baseType = clang::QualType::getFromOpaquePtr(base.data);
5484 return INTEROP_RETURN(S.IsDerivedFrom(fakeLoc, derivedType, baseType));
5489 const auto* D = unwrap<clang::Decl>(func);
5490 const clang::ParmVarDecl* PI =
nullptr;
5492 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
5493 PI = FD->getNonObjectParameter(param_index);
5495 else if (
const auto* FD =
5496 llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
5497 PI = (FD->getTemplatedDecl())->getNonObjectParameter(param_index);
5499 if (PI->hasDefaultArg()) {
5501 llvm::raw_string_ostream OS(Result);
5502 const Expr* DefaultArgExpr =
nullptr;
5504 if (PI->hasUninstantiatedDefaultArg())
5505 DefaultArgExpr = PI->getUninstantiatedDefaultArg();
5507 DefaultArgExpr = PI->getDefaultArg();
5508 DefaultArgExpr->printPretty(OS,
nullptr, PrintingPolicy(LangOptions()));
5514 if (PI->getType()->isFloatingType()) {
5515 if (!Result.empty() && Result.back() ==
'.')
5517 auto DefaultArgValue = std::stod(Result);
5518 std::ostringstream oss;
5519 oss << DefaultArgValue;
5532 const auto* D = unwrap<clang::Decl>(method);
5533 if (
const auto* func = dyn_cast<CXXMethodDecl>(D))
5541 const auto* D = unwrap<clang::Decl>(func);
5542 const clang::ParmVarDecl* PI =
nullptr;
5544 if (
const auto* FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(D))
5545 PI = FD->getNonObjectParameter(param_index);
5546 else if (
const auto* FD =
5547 llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(D))
5548 PI = (FD->getTemplatedDecl())->getNonObjectParameter(param_index);
5556 clang::getOperatorSpelling((clang::OverloadedOperatorKind)Operator));
5561#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5562 if ((Spelling) == op) { \
5563 return INTEROP_RETURN((Operator)OO_##Name); \
5565#include "clang/Basic/OperatorKinds.def"
5571 const auto* D = unwrap<Decl>(op);
5572 if (
const auto* FD = llvm::dyn_cast<FunctionDecl>(D)) {
5573 if (FD->isOverloadedOperator()) {
5574 switch (FD->getOverloadedOperator()) {
5575#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5577 if ((Unary) && (Binary)) \
5578 return INTEROP_RETURN(kBoth); \
5580 return INTEROP_RETURN(kUnary); \
5582 return INTEROP_RETURN(kBinary); \
5584#include "clang/Basic/OperatorKinds.def"
5594 std::vector<FuncRef>& operators, OperatorArity kind) {
5596 const auto* D = unwrap<Decl>(DRef);
5598 if (
const auto* CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
5599 auto fn = [&operators, kind, op](
const RecordDecl* RD) {
5600 ASTContext& C = RD->getASTContext();
5601 DeclContextLookupResult Result =
5602 RD->lookup(C.DeclarationNames.getCXXOperatorName(
5603 (clang::OverloadedOperatorKind)op));
5604 for (
auto* i : Result) {
5606 operators.push_back(i);
5611 CXXRD->forallBases(fn);
5612 }
else if (
const auto* DC = llvm::dyn_cast_or_null<DeclContext>(D)) {
5613 ASTContext& C =
getSema().getASTContext();
5614 DeclContextLookupResult Result =
5615 DC->lookup(C.DeclarationNames.getCXXOperatorName(
5616 (clang::OverloadedOperatorKind)op));
5618 for (
auto* i : Result) {
5620 operators.push_back(i);
5634 ::operator
delete(address.data, bytes);
5640 void* arena ,
size_t count ) {
5643 FuncRef ctorAsFunc = wrap<FuncRef>(DRef.data);
5649 FuncRef ctor =
nullptr;
5658 void* is_arena = arena ?
reinterpret_cast<void*
>(1) :
nullptr;
5660 JC.InvokeConstructor(&
result, count, {}, is_arena);
5673 bool withFree,
size_t nary) {
5674 if (
auto wrapper = make_dtor_wrapper(interp, Class)) {
5675 (*wrapper)(This.data, nary, withFree);
5682bool Destruct(ObjectRef This, DeclRef DRef,
bool withFree ,
5685 const auto* Class = unwrap<Decl>(DRef);
5690 FILE* m_TempFile =
nullptr;
5693 bool m_OwnsFile =
true;
5699 FILE* stream =
nullptr;
5701 err = tmpfile_s(&stream);
5703 printf(
"Cannot create temporary file!\n");
5709#if !defined(CPPINTEROP_USE_CLING) && !defined(_WIN32)
5711 if (I.isOutOfProcess()) {
5717 FILE* redirected = I.getRedirectionFileForOutOfProcess(FD);
5719 m_TempFile = redirected;
5721 if (ftruncate(fileno(m_TempFile), 0) != 0)
5722 perror(
"ftruncate");
5723 if (lseek(fileno(m_TempFile), 0, SEEK_SET) == -1)
5727 m_TempFile = tmpfile();
5730 m_TempFile = tmpfile();
5735 perror(
"StreamCaptureInfo: Unable to create temp file");
5744 ::fflush(FD == STDOUT_FILENO ? stdout : stderr);
5745 if (dup2(fileno(m_TempFile), FD) < 0)
5746 perror(
"StreamCaptureInfo:");
5754 assert(m_DupFD == -1 &&
"Captured output not used?");
5756 if (m_OwnsFile && m_TempFile)
5761 assert(m_DupFD != -1 &&
"Multiple calls to GetCapturedString");
5764 if (dup2(m_DupFD, m_FD) < 0)
5765 perror(
"StreamCaptureInfo:");
5767 if (fseek(m_TempFile, 0L, SEEK_END) != 0)
5768 perror(
"StreamCaptureInfo:");
5771 long bufsize = ftell(m_TempFile);
5772 if (bufsize == -1) {
5773 perror(
"StreamCaptureInfo:");
5780 std::unique_ptr<char[]> content(
new char[bufsize + 1]);
5783 if (fseek(m_TempFile, 0L, SEEK_SET) != 0)
5784 perror(
"StreamCaptureInfo:");
5787 size_t newLen = fread(content.get(),
sizeof(
char), bufsize, m_TempFile);
5788 if (ferror(m_TempFile) != 0)
5789 fputs(
"Error reading file", stderr);
5791 content[newLen++] =
'\0';
5793 std::string
result = content.get();
5796#if !defined(_WIN32) && !defined(CPPINTEROP_USE_CLING)
5798 if (I.isOutOfProcess()) {
5799 int fd = fileno(m_TempFile);
5800 if (ftruncate(fd, 0) != 0)
5801 perror(
"ftruncate");
5802 if (lseek(fd, 0, SEEK_SET) == -1)
5811 static std::stack<StreamCaptureInfo> sRedirectionStack;
5812 return sRedirectionStack;
5831 unsigned complete_line ,
5832 unsigned complete_column ) {
5842#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
std::unordered_map< const clang::FunctionDecl *, std::optional< AllocType > > & visitedFuncs
#define CPPINTEROP_MSAN_UNPOISON_VALUE(v)
clang::DiagnosticsEngine & fDiagEngine
void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,...)
std::optional< AllocType > result
std::unordered_map< const clang::VarDecl *, std::optional< AllocType > > varMap
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)
static std::optional< AllocType > AnalyzeAllocType(const clang::FunctionDecl *Fn, std::unordered_map< const clang::FunctionDecl *, std::optional< AllocType > > &visitedFuncs)
void DetectSystemCompilerIncludePaths(std::vector< std::string > &Paths, const char *CompilerName)
bool IsAllocator(ConstFuncRef Fn)
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()
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)
static VTableOverlayDtorSlotFn SlotToDtorFn(void *slot)
InterpreterLanguage GetLanguage(InterpRef I)
bool IsTemplatedFunction(ConstFuncRef func)
bool IsClassPolymorphic(ConstDeclRef DRef)
void GetClassTemplateInstantiationArgs(ConstDeclRef templ_instance, std::vector< TemplateArgInfo > &args)
bool IsDeallocator(ConstFuncRef Fn)
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(VTableOverlayDtorHost::*)() VTableOverlayDtorSlotFn
void CppInterOpTraceJitCallInvokeDestructorImpl(const JitCall *JC, void *object, unsigned long nary, int withFree)
void GetStaticDatamembers(ConstDeclRef DRef, std::vector< DeclRef > &datamembers)
AllocType GetAllocType(ConstFuncRef Fn)
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)
static void RegisterInterpreter(compat::Interpreter *I, bool Owned, std::vector< std::string > ArgvStorage={})
bool IsConstVariable(ConstDeclRef var)
void GetFunctionTemplatedDecls(ConstDeclRef DRef, std::vector< FuncRef > &methods)
bool IsFunctionProtoType(ConstTypeRef TyRef)
static void * DtorFnToSlot(VTableOverlayDtorSlotFn fn)
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)
VTableOverlayDtorSlotFn orig_dtor
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.