-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang-repl] Add a interpreter-specific overload of operator new for C++ #76218
Conversation
@llvm/pr-subscribers-clang Author: Vassil Vassilev (vgvassilev) ChangesThis 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:
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
|
114b93d
to
0578f4c
Compare
This PR should help compiler-research/CppInterOp#173 move forward. |
50a08a2
to
a3f213e
Compare
Ping. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good (sorry, this fell through)
…C++. 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#69072.
a3f213e
to
9d24f6d
Compare
Looks like after this patch https://lab.llvm.org/buildbot/#/builders/236/builds/8819 |
If the fix is not trivial please revert it since I am not on my laptop (very late on my end) |
`new` was introduced in this patch, but I don't see `delete` to release the memory.
@vgvassilev I end up with suppression, please check, when you have time, if this can be done better way, or just remove FIXME. |
@vitalybuka, thank you! I am trying to add a fix but I get diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index d6eb0684ba49..406a4871dff5 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -34,12 +34,6 @@ using namespace clang;
#define CLANG_INTERPRETER_NO_SUPPORT_EXEC
#endif
-#if LLVM_ADDRESS_SANITIZER_BUILD || LLVM_HWADDRESS_SANITIZER_BUILD
-#include <sanitizer/lsan_interface.h>
-#else
-extern "C" void __lsan_ignore_object(const void *p) {}
-#endif
-
int Global = 42;
// JIT reports symbol not found on Windows without the visibility attribute.
REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
@@ -317,8 +311,9 @@ TEST(IncrementalProcessing, InstantiateTemplate) {
auto fn =
cantFail(Interp->getSymbolAddress(MangledName)).toPtr<TemplateSpecFn>();
EXPECT_EQ(42, fn(NewA.getPtr()));
- // FIXME: release the memory.
- __lsan_ignore_object(NewA.getPtr());
+ // FIXME: Consider providing an option in clang::Value to take ownership of
+ // the memory created from the interpreter.
+ free(NewA.getPtr());
}
#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC I think that's going to work. |
I suspect asan may complain on new/free mismatch |
Yes, it fixes the leak but on asan bot it's mismatch https://lab.llvm.org/buildbot/#/builders/168/builds/18159/steps/10/logs/stdio |
Yes, you are right, I've put a fix here #78843. Can you take a look? |
…8843) This test demonstrates template instantiation via the interpreter code. In order to do that we can allocate the object on the stack and extend its lifetime by boxing it into a clang::Value. That avoids the subtle problem where we call the new operator on an object only known to the interpreter and we cannot destroy it from compiled code since there is not suitable facility in clang::Value yet. That should resolve the asan issues that was reported in #76218.
This test demonstrates template instantiation via the interpreter code. In order to do that we can allocate the object on the stack and extend its lifetime by boxing it into a clang::Value. That avoids the subtle problem where we call the new operator on an object only known to the interpreter and we cannot destroy it from compiled code since there is not suitable facility in clang::Value yet. That should resolve the asan issues that was reported in llvm/llvm-project#76218.
…C++ (llvm#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#69072. (cherry picked from commit 1566f1f)
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 #69072.