@@ -250,23 +250,26 @@ Interpreter::~Interpreter() {
250250// can't find the precise resource directory in unittests so we have to hard
251251// code them.
252252const char *const Runtimes = R"(
253- void* operator new(__SIZE_TYPE__, void* __p) noexcept;
253+ #ifdef __cplusplus
254254 void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*);
255255 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*);
256256 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*);
257257 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float);
258258 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double);
259259 void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double);
260260 void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long);
261+ struct __clang_Interpreter_NewTag{} __ci_newtag;
262+ void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept;
261263 template <class T, class = T (*)() /*disable for arrays*/>
262264 void __clang_Interpreter_SetValueCopyArr(T* Src, void* Placement, unsigned long Size) {
263265 for (auto Idx = 0; Idx < Size; ++Idx)
264- new ((void*)(((T*)Placement) + Idx)) T(Src[Idx]);
266+ new ((void*)(((T*)Placement) + Idx), __ci_newtag ) T(Src[Idx]);
265267 }
266268 template <class T, unsigned long N>
267269 void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) {
268270 __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size);
269271 }
272+ #endif // __cplusplus
270273)" ;
271274
272275llvm::Expected<std::unique_ptr<Interpreter>>
@@ -280,7 +283,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
280283 if (!PTU)
281284 return PTU.takeError ();
282285
283- Interp->ValuePrintingInfo .resize (3 );
286+ Interp->ValuePrintingInfo .resize (4 );
284287 // FIXME: This is a ugly hack. Undo command checks its availability by looking
285288 // at the size of the PTU list. However we have parsed something in the
286289 // beginning of the REPL so we have to mark them as 'Irrevocable'.
@@ -497,7 +500,7 @@ Interpreter::CompileDtorCall(CXXRecordDecl *CXXRD) {
497500static constexpr llvm::StringRef MagicRuntimeInterface[] = {
498501 " __clang_Interpreter_SetValueNoAlloc" ,
499502 " __clang_Interpreter_SetValueWithAlloc" ,
500- " __clang_Interpreter_SetValueCopyArr" };
503+ " __clang_Interpreter_SetValueCopyArr" , " __ci_newtag " };
501504
502505bool Interpreter::FindRuntimeInterface () {
503506 if (llvm::all_of (ValuePrintingInfo, [](Expr *E) { return E != nullptr ; }))
@@ -527,6 +530,9 @@ bool Interpreter::FindRuntimeInterface() {
527530 if (!LookupInterface (ValuePrintingInfo[CopyArray],
528531 MagicRuntimeInterface[CopyArray]))
529532 return false ;
533+ if (!LookupInterface (ValuePrintingInfo[NewTag],
534+ MagicRuntimeInterface[NewTag]))
535+ return false ;
530536 return true ;
531537}
532538
@@ -604,7 +610,9 @@ class RuntimeInterfaceBuilder
604610 .getValuePrintingInfo ()[Interpreter::InterfaceKind::CopyArray],
605611 SourceLocation (), Args, SourceLocation ());
606612 }
607- Expr *Args[] = {AllocCall.get ()};
613+ Expr *Args[] = {
614+ AllocCall.get (),
615+ Interp.getValuePrintingInfo ()[Interpreter::InterfaceKind::NewTag]};
608616 ExprResult CXXNewCall = S.BuildCXXNew (
609617 E->getSourceRange (),
610618 /* UseGlobal=*/ true , /* PlacementLParen=*/ SourceLocation (), Args,
@@ -625,8 +633,9 @@ class RuntimeInterfaceBuilder
625633 Interp.getValuePrintingInfo ()[Interpreter::InterfaceKind::NoAlloc],
626634 E->getBeginLoc (), Args, E->getEndLoc ());
627635 }
636+ default :
637+ llvm_unreachable (" Unhandled Interpreter::InterfaceKind" );
628638 }
629- llvm_unreachable (" Unhandled Interpreter::InterfaceKind" );
630639 }
631640
632641 Interpreter::InterfaceKind VisitRecordType (const RecordType *Ty) {
@@ -811,3 +820,15 @@ __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType,
811820 VRef = Value (static_cast <Interpreter *>(This), OpaqueType);
812821 VRef.setLongDouble (Val);
813822}
823+
824+ // A trampoline to work around the fact that operator placement new cannot
825+ // really be forward declared due to libc++ and libstdc++ declaration mismatch.
826+ // FIXME: __clang_Interpreter_NewTag is ODR violation because we get the same
827+ // definition in the interpreter runtime. We should move it in a runtime header
828+ // which gets included by the interpreter and here.
829+ struct __clang_Interpreter_NewTag {};
830+ REPL_EXTERNAL_VISIBILITY void *
831+ operator new (size_t __sz, void *__p, __clang_Interpreter_NewTag) noexcept {
832+ // Just forward to the standard operator placement new.
833+ return operator new (__sz, __p);
834+ }
0 commit comments