@@ -2047,6 +2047,49 @@ TEST(FunctionReflectionTest, Construct) {
20472047 clang_Interpreter_dispose (I);
20482048}
20492049
2050+ // Test zero initialization of PODs and default initialization cases
2051+ TEST (FunctionReflectionTest, ConstructPOD) {
2052+ #ifdef EMSCRIPTEN
2053+ #if CLANG_VERSION_MAJOR < 20
2054+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2055+ #endif
2056+ #endif
2057+ if (llvm::sys::RunningOnValgrind ())
2058+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2059+ #ifdef _WIN32
2060+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2061+ #endif
2062+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2063+ Cpp::CreateInterpreter (interpreter_args);
2064+
2065+ Interp->declare (R"(
2066+ namespace PODS {
2067+ struct SomePOD_B {
2068+ int fInt;
2069+ };
2070+ struct SomePOD_C {
2071+ int fInt;
2072+ double fDouble;
2073+ };
2074+ })" );
2075+
2076+ auto *ns = Cpp::GetNamed (" PODS" );
2077+ Cpp::TCppScope_t scope = Cpp::GetNamed (" SomePOD_B" , ns);
2078+ EXPECT_TRUE (scope);
2079+ Cpp::TCppObject_t object = Cpp::Construct (scope);
2080+ EXPECT_TRUE (object != nullptr );
2081+ int * fInt = reinterpret_cast <int *>(reinterpret_cast <char *>(object));
2082+ EXPECT_TRUE (*fInt == 0 );
2083+
2084+ scope = Cpp::GetNamed (" SomePOD_C" , ns);
2085+ EXPECT_TRUE (scope);
2086+ object = Cpp::Construct (scope);
2087+ EXPECT_TRUE (object);
2088+ auto * fDouble =
2089+ reinterpret_cast <double *>(reinterpret_cast <char *>(object) + sizeof (int ));
2090+ EXPECT_EQ (*fDouble , 0.0 );
2091+ }
2092+
20502093// Test nested constructor calls
20512094TEST (FunctionReflectionTest, ConstructNested) {
20522095#ifdef EMSCRIPTEN
@@ -2110,6 +2153,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
21102153 output.clear ();
21112154}
21122155
2156+ TEST (FunctionReflectionTest, ConstructArray) {
2157+ #if defined(EMSCRIPTEN)
2158+ GTEST_SKIP () << " Test fails for Emscripten builds" ;
2159+ #endif
2160+ if (llvm::sys::RunningOnValgrind ())
2161+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2162+ #ifdef _WIN32
2163+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2164+ #endif
2165+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2166+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2167+ #endif
2168+
2169+ Cpp::CreateInterpreter ();
2170+
2171+ Interp->declare (R"(
2172+ #include <new>
2173+ extern "C" int printf(const char*,...);
2174+ class C {
2175+ int x;
2176+ C() {
2177+ x = 42;
2178+ printf("\nConstructor Executed\n");
2179+ }
2180+ };
2181+ )" );
2182+
2183+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2184+ std::string output;
2185+
2186+ size_t a = 5 ; // Construct an array of 5 objects
2187+ void * where = Cpp::Allocate (scope, a); // operator new
2188+
2189+ testing::internal::CaptureStdout ();
2190+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2191+ // Check for the value of x which should be at the start of the object.
2192+ EXPECT_TRUE (*(int *)where == 42 );
2193+ // Check for the value of x in the second object
2194+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2195+ Cpp::SizeOf (scope));
2196+ EXPECT_TRUE (*obj == 42 );
2197+
2198+ // Check for the value of x in the last object
2199+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2200+ (Cpp::SizeOf (scope) * 4 ));
2201+ EXPECT_TRUE (*obj == 42 );
2202+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2203+ Cpp::Deallocate (scope, where, 5 );
2204+ output = testing::internal::GetCapturedStdout ();
2205+ EXPECT_EQ (output,
2206+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2207+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2208+ output.clear ();
2209+ }
2210+
21132211TEST (FunctionReflectionTest, Destruct) {
21142212#ifdef EMSCRIPTEN
21152213 GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2167,6 +2265,85 @@ TEST(FunctionReflectionTest, Destruct) {
21672265 clang_Interpreter_dispose (I);
21682266}
21692267
2268+ TEST (FunctionReflectionTest, DestructArray) {
2269+ #ifdef EMSCRIPTEN
2270+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2271+ #endif
2272+ if (llvm::sys::RunningOnValgrind ())
2273+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2274+
2275+ #ifdef _WIN32
2276+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2277+ #endif
2278+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2279+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2280+ #endif
2281+
2282+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2283+ Cpp::CreateInterpreter (interpreter_args);
2284+
2285+ Interp->declare (R"(
2286+ #include <new>
2287+ extern "C" int printf(const char*,...);
2288+ class C {
2289+ int x;
2290+ C() {
2291+ printf("\nCtor Executed\n");
2292+ x = 42;
2293+ }
2294+ ~C() {
2295+ printf("\nDestructor Executed\n");
2296+ }
2297+ };
2298+ )" );
2299+
2300+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2301+ std::string output;
2302+
2303+ size_t a = 5 ; // Construct an array of 5 objects
2304+ void * where = Cpp::Allocate (scope, a); // operator new
2305+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2306+
2307+ // verify the array of objects has been constructed
2308+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2309+ Cpp::SizeOf (scope) * 4 );
2310+ EXPECT_TRUE (*obj == 42 );
2311+
2312+ testing::internal::CaptureStdout ();
2313+ // destruct 3 out of 5 objects
2314+ Cpp::Destruct (where, scope, false , 3 );
2315+ output = testing::internal::GetCapturedStdout ();
2316+
2317+ EXPECT_EQ (
2318+ output,
2319+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2320+ output.clear ();
2321+ testing::internal::CaptureStdout ();
2322+
2323+ // destruct the rest
2324+ auto *new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2325+ (Cpp::SizeOf (scope) * 3 ));
2326+ Cpp::Destruct (new_head, scope, false , 2 );
2327+
2328+ output = testing::internal::GetCapturedStdout ();
2329+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2330+ output.clear ();
2331+
2332+ // deallocate since we call the destructor withFree = false
2333+ Cpp::Deallocate (scope, where, 5 );
2334+
2335+ // perform the same withFree=true
2336+ where = Cpp::Allocate (scope, a);
2337+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2338+ testing::internal::CaptureStdout ();
2339+ // FIXME : This should work with the array of objects as well
2340+ // Cpp::Destruct(where, scope, true, 5);
2341+ Cpp::Destruct (where, scope, true );
2342+ output = testing::internal::GetCapturedStdout ();
2343+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2344+ output.clear ();
2345+ }
2346+
21702347TEST (FunctionReflectionTest, UndoTest) {
21712348#ifdef _WIN32
21722349 GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments