Skip to content

Commit 6d22d46

Browse files
committed
Improve Cpp::Construct pointer logic for memory arena flags
Also handle both ctors and class scopes
1 parent 180869d commit 6d22d46

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

include/CppInterOp/CppInterOp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ class JitCall {
224224
///\param[in] nary - Use array new if we have to construct an array of
225225
/// objects (nary > 1).
226226
///\param[in] args - a pointer to a argument list and argument size.
227+
///\param[in] is_arena - a pointer that indicates if placement new is to be
228+
/// used
227229
// FIXME: Change the type of withFree from int to bool in the wrapper code.
228230
void InvokeConstructor(void* result, unsigned long nary = 1,
229231
ArgList args = {}, void* is_arena = nullptr) const {
@@ -849,7 +851,7 @@ CPPINTEROP_API void Deallocate(TCppScope_t scope, TCppObject_t address,
849851

850852
/// Creates one or more objects of class \c scope by calling its default
851853
/// constructor.
852-
/// \param[in] scope Class to construct
854+
/// \param[in] scope Class to construct, or handle to Constructor
853855
/// \param[in] arena If set, this API uses placement new to construct at this
854856
/// address.
855857
/// \param[in] is used to indicate the number of objects to construct.

lib/CppInterOp/CppInterOp.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3783,22 +3783,27 @@ void Deallocate(TCppScope_t scope, TCppObject_t address, TCppIndex_t count) {
37833783
// FIXME: Add optional arguments to the operator new.
37843784
TCppObject_t Construct(compat::Interpreter& interp, TCppScope_t scope,
37853785
void* arena /*=nullptr*/, TCppIndex_t count /*=1UL*/) {
3786-
auto* Class = (Decl*)scope;
3787-
// FIXME: Diagnose.
3788-
if (!HasDefaultConstructor(Class))
3786+
3787+
if (!Cpp::IsConstructor(scope) && !Cpp::IsClass(scope))
3788+
return nullptr;
3789+
if (Cpp::IsClass(scope) && !HasDefaultConstructor(scope))
37893790
return nullptr;
37903791

3791-
auto* const Ctor = GetDefaultConstructor(interp, Class);
3792-
if (JitCall JC = MakeFunctionCallable(&interp, Ctor)) {
3793-
if (arena) {
3794-
JC.InvokeConstructor(&arena, count, {},
3795-
(void*)~0); // Tell Invoke to use placement new.
3796-
return arena;
3797-
}
3792+
TCppFunction_t ctor = nullptr;
3793+
if (Cpp::IsClass(scope))
3794+
ctor = Cpp::GetDefaultConstructor(scope);
3795+
else // a ctor
3796+
ctor = scope;
37983797

3799-
void* obj = nullptr;
3800-
JC.InvokeConstructor(&obj, count, {}, nullptr);
3801-
return obj;
3798+
if (JitCall JC = MakeFunctionCallable(&interp, ctor)) {
3799+
if (JC.getKind() != Cpp::JitCall::kConstructorCall)
3800+
return nullptr;
3801+
// invoke the constructor (placement/heap) in one shot
3802+
// flag is non-null for placement new, null for normal new
3803+
void* flag = arena ? reinterpret_cast<void*>(1) : nullptr;
3804+
void* result = arena;
3805+
JC.InvokeConstructor(&result, count, {}, flag);
3806+
return result;
38023807
}
38033808
return nullptr;
38043809
}

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,9 +2107,9 @@ TEST(FunctionReflectionTest, Construct) {
21072107
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
21082108
#endif
21092109
std::vector<const char*> interpreter_args = {"-include", "new"};
2110-
Cpp::CreateInterpreter(interpreter_args);
2110+
std::vector<Decl*> Decls, SubDecls;
21112111

2112-
Interp->declare(R"(
2112+
std::string code =R"(
21132113
#include <new>
21142114
extern "C" int printf(const char*,...);
21152115
class C {
@@ -2119,8 +2119,10 @@ TEST(FunctionReflectionTest, Construct) {
21192119
printf("Constructor Executed");
21202120
}
21212121
};
2122-
)");
2122+
)";
21232123

2124+
GetAllTopLevelDecls(code, Decls, false, interpreter_args);
2125+
GetAllSubDecls(Decls[1], SubDecls);
21242126
testing::internal::CaptureStdout();
21252127
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
21262128
Cpp::TCppObject_t object = Cpp::Construct(scope);
@@ -2140,6 +2142,16 @@ TEST(FunctionReflectionTest, Construct) {
21402142
EXPECT_EQ(output, "Constructor Executed");
21412143
output.clear();
21422144

2145+
// Pass a constructor
2146+
testing::internal::CaptureStdout();
2147+
where = Cpp::Allocate(scope);
2148+
EXPECT_TRUE(where == Cpp::Construct(SubDecls[2], where));
2149+
EXPECT_TRUE(*(int *)where == 12345);
2150+
Cpp::Deallocate(scope, where);
2151+
output = testing::internal::GetCapturedStdout();
2152+
EXPECT_EQ(output, "Constructor Executed");
2153+
output.clear();
2154+
21432155
// C API
21442156
testing::internal::CaptureStdout();
21452157
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());

0 commit comments

Comments
 (0)