Skip to content

Commit f4c269a

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

File tree

3 files changed

+42
-17
lines changed

3 files changed

+42
-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: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,20 +2107,24 @@ 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 {
2116+
public:
21162117
int x;
21172118
C() {
21182119
x = 12345;
21192120
printf("Constructor Executed");
21202121
}
21212122
};
2122-
)");
2123+
void construct() { return; }
2124+
)";
21232125

2126+
GetAllTopLevelDecls(code, Decls, false, interpreter_args);
2127+
GetAllSubDecls(Decls[1], SubDecls);
21242128
testing::internal::CaptureStdout();
21252129
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
21262130
Cpp::TCppObject_t object = Cpp::Construct(scope);
@@ -2140,6 +2144,20 @@ TEST(FunctionReflectionTest, Construct) {
21402144
EXPECT_EQ(output, "Constructor Executed");
21412145
output.clear();
21422146

2147+
// Pass a constructor
2148+
testing::internal::CaptureStdout();
2149+
where = Cpp::Allocate(scope);
2150+
EXPECT_TRUE(where == Cpp::Construct(SubDecls[3], where));
2151+
EXPECT_TRUE(*(int*)where == 12345);
2152+
Cpp::Deallocate(scope, where);
2153+
output = testing::internal::GetCapturedStdout();
2154+
EXPECT_EQ(output, "Constructor Executed");
2155+
output.clear();
2156+
2157+
// Pass a non-class decl, this should fail
2158+
where = Cpp::Allocate(scope);
2159+
where = Cpp::Construct(Decls[2], where);
2160+
EXPECT_TRUE(where == nullptr);
21432161
// C API
21442162
testing::internal::CaptureStdout();
21452163
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());

0 commit comments

Comments
 (0)