Skip to content

Commit 9c94230

Browse files
committed
Improve Cpp::Construct pointer logic for memory arena flags
Also handle both ctors and class scopes
1 parent 3474903 commit 9c94230

File tree

3 files changed

+41
-18
lines changed

3 files changed

+41
-18
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: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3784,22 +3784,25 @@ void Deallocate(TCppScope_t scope, TCppObject_t address, TCppIndex_t count) {
37843784
// FIXME: Add optional arguments to the operator new.
37853785
TCppObject_t Construct(compat::Interpreter& interp, TCppScope_t scope,
37863786
void* arena /*=nullptr*/, TCppIndex_t count /*=1UL*/) {
3787-
auto* Class = (Decl*)scope;
3788-
// FIXME: Diagnose.
3789-
if (!HasDefaultConstructor(Class))
3790-
return nullptr;
37913787

3792-
auto* const Ctor = GetDefaultConstructor(interp, Class);
3793-
if (JitCall JC = MakeFunctionCallable(&interp, Ctor)) {
3794-
if (arena) {
3795-
JC.InvokeConstructor(&arena, count, {},
3796-
(void*)~0); // Tell Invoke to use placement new.
3797-
return arena;
3798-
}
3788+
if (!Cpp::IsConstructor(scope) && !Cpp::IsClass(scope))
3789+
return nullptr;
3790+
if (Cpp::IsClass(scope) && !HasDefaultConstructor(scope))
3791+
return nullptr;
37993792

3800-
void* obj = nullptr;
3801-
JC.InvokeConstructor(&obj, count, {}, nullptr);
3802-
return obj;
3793+
TCppFunction_t ctor = nullptr;
3794+
if (Cpp::IsClass(scope))
3795+
ctor = Cpp::GetDefaultConstructor(scope);
3796+
else // a ctor
3797+
ctor = scope;
3798+
3799+
if (JitCall JC = MakeFunctionCallable(&interp, ctor)) {
3800+
// invoke the constructor (placement/heap) in one shot
3801+
// flag is non-null for placement new, null for normal new
3802+
void* is_arena = arena ? reinterpret_cast<void*>(1) : nullptr;
3803+
void* result = arena;
3804+
JC.InvokeConstructor(&result, count, /*args=*/{}, is_arena);
3805+
return result;
38033806
}
38043807
return nullptr;
38053808
}

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,20 +2122,24 @@ TEST(FunctionReflectionTest, Construct) {
21222122
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
21232123
#endif
21242124
std::vector<const char*> interpreter_args = {"-include", "new"};
2125-
Cpp::CreateInterpreter(interpreter_args);
2125+
std::vector<Decl*> Decls, SubDecls;
21262126

2127-
Interp->declare(R"(
2127+
std::string code = R"(
21282128
#include <new>
21292129
extern "C" int printf(const char*,...);
21302130
class C {
2131+
public:
21312132
int x;
21322133
C() {
21332134
x = 12345;
21342135
printf("Constructor Executed");
21352136
}
21362137
};
2137-
)");
2138+
void construct() { return; }
2139+
)";
21382140

2141+
GetAllTopLevelDecls(code, Decls, false, interpreter_args);
2142+
GetAllSubDecls(Decls[1], SubDecls);
21392143
testing::internal::CaptureStdout();
21402144
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
21412145
Cpp::TCppObject_t object = Cpp::Construct(scope);
@@ -2155,6 +2159,20 @@ TEST(FunctionReflectionTest, Construct) {
21552159
EXPECT_EQ(output, "Constructor Executed");
21562160
output.clear();
21572161

2162+
// Pass a constructor
2163+
testing::internal::CaptureStdout();
2164+
where = Cpp::Allocate(scope);
2165+
EXPECT_TRUE(where == Cpp::Construct(SubDecls[3], where));
2166+
EXPECT_TRUE(*(int*)where == 12345);
2167+
Cpp::Deallocate(scope, where);
2168+
output = testing::internal::GetCapturedStdout();
2169+
EXPECT_EQ(output, "Constructor Executed");
2170+
output.clear();
2171+
2172+
// Pass a non-class decl, this should fail
2173+
where = Cpp::Allocate(scope);
2174+
where = Cpp::Construct(Decls[2], where);
2175+
EXPECT_TRUE(where == nullptr);
21582176
// C API
21592177
testing::internal::CaptureStdout();
21602178
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());

0 commit comments

Comments
 (0)