[clang] [clang-repl] Add a interpreter-specific overload of operator new for C++ (PR #76218)

via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 22 00:47:11 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Vassil Vassilev (vgvassilev)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/76218.diff


2 Files Affected:

- (modified) clang/lib/Interpreter/Interpreter.cpp (+16-2) 
- (modified) clang/test/Interpreter/incremental-mode.cpp (+2-1) 


``````````diff
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index c9fcef5b5b5af1..daceabafe4c938 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -248,7 +248,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*);
@@ -256,15 +256,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{};
+    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), __clang_Interpreter_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>>
@@ -814,3 +817,14 @@ __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{};
+void* operator new(__SIZE_TYPE__ __sz, void* __p, __clang_Interpreter_NewTag) noexcept {
+  // Just forward to the standard operator placement new.
+  return operator new(__sz, __p);
+}
diff --git a/clang/test/Interpreter/incremental-mode.cpp b/clang/test/Interpreter/incremental-mode.cpp
index e6350d237ef578..d63cee0dd6d15f 100644
--- a/clang/test/Interpreter/incremental-mode.cpp
+++ b/clang/test/Interpreter/incremental-mode.cpp
@@ -1,3 +1,4 @@
 // RUN: clang-repl -Xcc -E
-// RUN: clang-repl -Xcc -emit-llvm 
+// RUN: clang-repl -Xcc -emit-llvm
+// RUN: clang-repl -Xcc -xc
 // expected-no-diagnostics

``````````

</details>


https://github.com/llvm/llvm-project/pull/76218


More information about the cfe-commits mailing list