aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Interpreter/Interpreter.cpp
diff options
context:
space:
mode:
authorVassil Vassilev <v.g.vassilev@gmail.com>2024-01-18 16:06:04 +0200
committerGitHub <noreply@github.com>2024-01-18 16:06:04 +0200
commit1566f1ffc6b52bee659071d460123c1c4a358d01 (patch)
treeefc4ab60b9841879dde13bf9d0d52adf3b4fc8d8 /clang/lib/Interpreter/Interpreter.cpp
parente6a6a90fe739d5f792645bf237eb0e540fad8c69 (diff)
downloadllvm-1566f1ffc6b52bee659071d460123c1c4a358d01.zip
llvm-1566f1ffc6b52bee659071d460123c1c4a358d01.tar.gz
llvm-1566f1ffc6b52bee659071d460123c1c4a358d01.tar.bz2
[clang-repl] Add a interpreter-specific overload of operator new for C++ (#76218)
This patch brings back the basic support for C by inserting the required for value printing runtime only when we are in C++ mode. Additionally, it defines a new overload of operator placement new because we can't really forward declare it in a library-agnostic way. Fixes the issue described in llvm/llvm-project#69072.
Diffstat (limited to 'clang/lib/Interpreter/Interpreter.cpp')
-rw-r--r--clang/lib/Interpreter/Interpreter.cpp33
1 files changed, 27 insertions, 6 deletions
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 734fe90..d1764d0 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -249,7 +249,7 @@ Interpreter::~Interpreter() {
// can't find the precise resource directory in unittests so we have to hard
// code them.
const char *const Runtimes = R"(
- void* operator new(__SIZE_TYPE__, void* __p) noexcept;
+#ifdef __cplusplus
void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
@@ -257,15 +257,18 @@ const char *const Runtimes = R"(
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
+ struct __clang_Interpreter_NewTag{} __ci_newtag;
+ void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
template <class T, class = T (*)() /*disable for arrays*/>
void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
for (auto Idx = 0; Idx < Size; ++Idx)
- new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]);
+ new ((void*)(((T*)Placement) + Idx), __ci_newtag) T(Src[Idx]);
}
template <class T, unsigned long N>
void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
__clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
}
+#endif // __cplusplus
)";
llvm::Expected<std::unique_ptr<Interpreter>>
@@ -280,7 +283,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
if (!PTU)
return PTU.takeError();
- Interp->ValuePrintingInfo.resize(3);
+ Interp->ValuePrintingInfo.resize(4);
// FIXME: This is a ugly hack. Undo command checks its availability by looking
// at the size of the PTU list. However we have parsed something in the
// beginning of the REPL so we have to mark them as 'Irrevocable'.
@@ -501,7 +504,7 @@ Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) {
static constexpr llvm::StringRef MagicRuntimeInterface[] = {
"__clang_Interpreter_SetValueNoAlloc",
"__clang_Interpreter_SetValueWithAlloc",
- "__clang_Interpreter_SetValueCopyArr"};
+ "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
bool Interpreter::FindRuntimeInterface() {
if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
@@ -531,6 +534,9 @@ bool Interpreter::FindRuntimeInterface() {
if (!LookupInterface(ValuePrintingInfo[CopyArray],
MagicRuntimeInterface[CopyArray]))
return false;
+ if (!LookupInterface(ValuePrintingInfo[NewTag],
+ MagicRuntimeInterface[NewTag]))
+ return false;
return true;
}
@@ -608,7 +614,9 @@ public:
.getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
SourceLocation(), Args, SourceLocation());
}
- Expr *Args[] = {AllocCall.get()};
+ Expr *Args[] = {
+ AllocCall.get(),
+ Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
ExprResult CXXNewCall = S.BuildCXXNew(
E->getSourceRange(),
/*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
@@ -629,8 +637,9 @@ public:
Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
E->getBeginLoc(), Args, E->getEndLoc());
}
+ default:
+ llvm_unreachable("Unhandled Interpreter::InterfaceKind");
}
- llvm_unreachable("Unhandled Interpreter::InterfaceKind");
}
Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
@@ -815,3 +824,15 @@ __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
VRef = Value(static_cast<Interpreter *>(This), OpaqueType);
VRef.setLongDouble(Val);
}
+
+// A trampoline to work around the fact that operator placement new cannot
+// really be forward declared due to libc++ and libstdc++ declaration mismatch.
+// FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
+// definition in the interpreter runtime. We should move it in a runtime header
+// which gets included by the interpreter and here.
+struct __clang_Interpreter_NewTag {};
+REPL_EXTERNAL_VISIBILITY void *
+operator new(size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
+ // Just forward to the standard operator placement new.
+ return operator new(__sz, __p);
+}