@@ -2027,6 +2027,49 @@ TEST(FunctionReflectionTest, Construct) {
20272027 clang_Interpreter_dispose (I);
20282028}
20292029
2030+ // Test zero initialization of PODs and default initialization cases
2031+ TEST (FunctionReflectionTest, ConstructPOD) {
2032+ #ifdef EMSCRIPTEN
2033+ #if CLANG_VERSION_MAJOR < 20
2034+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2035+ #endif
2036+ #endif
2037+ if (llvm::sys::RunningOnValgrind ())
2038+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2039+ #ifdef _WIN32
2040+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2041+ #endif
2042+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2043+ Cpp::CreateInterpreter (interpreter_args);
2044+
2045+ Interp->declare (R"(
2046+ namespace PODS {
2047+ struct SomePOD_B {
2048+ int fInt;
2049+ };
2050+ struct SomePOD_C {
2051+ int fInt;
2052+ double fDouble;
2053+ };
2054+ })" );
2055+
2056+ auto *ns = Cpp::GetNamed (" PODS" );
2057+ Cpp::TCppScope_t scope = Cpp::GetNamed (" SomePOD_B" , ns);
2058+ EXPECT_TRUE (scope);
2059+ Cpp::TCppObject_t object = Cpp::Construct (scope);
2060+ EXPECT_TRUE (object != nullptr );
2061+ int * fInt = reinterpret_cast <int *>(reinterpret_cast <char *>(object));
2062+ EXPECT_TRUE (*fInt == 0 );
2063+
2064+ scope = Cpp::GetNamed (" SomePOD_C" , ns);
2065+ EXPECT_TRUE (scope);
2066+ object = Cpp::Construct (scope);
2067+ EXPECT_TRUE (object);
2068+ auto * fDouble =
2069+ reinterpret_cast <double *>(reinterpret_cast <char *>(object) + sizeof (int ));
2070+ EXPECT_EQ (*fDouble , 0.0 );
2071+ }
2072+
20302073// Test nested constructor calls
20312074TEST (FunctionReflectionTest, ConstructNested) {
20322075#ifdef EMSCRIPTEN
@@ -2090,6 +2133,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
20902133 output.clear ();
20912134}
20922135
2136+ TEST (FunctionReflectionTest, ConstructArray) {
2137+ #if defined(EMSCRIPTEN)
2138+ GTEST_SKIP () << " Test fails for Emscripten builds" ;
2139+ #endif
2140+ if (llvm::sys::RunningOnValgrind ())
2141+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2142+ #ifdef _WIN32
2143+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2144+ #endif
2145+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2146+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2147+ #endif
2148+
2149+ Cpp::CreateInterpreter ();
2150+
2151+ Interp->declare (R"(
2152+ #include <new>
2153+ extern "C" int printf(const char*,...);
2154+ class C {
2155+ int x;
2156+ C() {
2157+ x = 42;
2158+ printf("\nConstructor Executed\n");
2159+ }
2160+ };
2161+ )" );
2162+
2163+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2164+ std::string output;
2165+
2166+ size_t a = 5 ; // Construct an array of 5 objects
2167+ void * where = Cpp::Allocate (scope, a); // operator new
2168+
2169+ testing::internal::CaptureStdout ();
2170+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2171+ // Check for the value of x which should be at the start of the object.
2172+ EXPECT_TRUE (*(int *)where == 42 );
2173+ // Check for the value of x in the second object
2174+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2175+ Cpp::SizeOf (scope));
2176+ EXPECT_TRUE (*obj == 42 );
2177+
2178+ // Check for the value of x in the last object
2179+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2180+ (Cpp::SizeOf (scope) * 4 ));
2181+ EXPECT_TRUE (*obj == 42 );
2182+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2183+ Cpp::Deallocate (scope, where, 5 );
2184+ output = testing::internal::GetCapturedStdout ();
2185+ EXPECT_EQ (output,
2186+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2187+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2188+ output.clear ();
2189+ }
2190+
20932191TEST (FunctionReflectionTest, Destruct) {
20942192#ifdef EMSCRIPTEN
20952193 GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2147,6 +2245,85 @@ TEST(FunctionReflectionTest, Destruct) {
21472245 clang_Interpreter_dispose (I);
21482246}
21492247
2248+ TEST (FunctionReflectionTest, DestructArray) {
2249+ #ifdef EMSCRIPTEN
2250+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2251+ #endif
2252+ if (llvm::sys::RunningOnValgrind ())
2253+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2254+
2255+ #ifdef _WIN32
2256+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2257+ #endif
2258+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2259+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2260+ #endif
2261+
2262+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2263+ Cpp::CreateInterpreter (interpreter_args);
2264+
2265+ Interp->declare (R"(
2266+ #include <new>
2267+ extern "C" int printf(const char*,...);
2268+ class C {
2269+ int x;
2270+ C() {
2271+ printf("\nCtor Executed\n");
2272+ x = 42;
2273+ }
2274+ ~C() {
2275+ printf("\nDestructor Executed\n");
2276+ }
2277+ };
2278+ )" );
2279+
2280+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2281+ std::string output;
2282+
2283+ size_t a = 5 ; // Construct an array of 5 objects
2284+ void * where = Cpp::Allocate (scope, a); // operator new
2285+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2286+
2287+ // verify the array of objects has been constructed
2288+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2289+ Cpp::SizeOf (scope) * 4 );
2290+ EXPECT_TRUE (*obj == 42 );
2291+
2292+ testing::internal::CaptureStdout ();
2293+ // destruct 3 out of 5 objects
2294+ Cpp::Destruct (where, scope, false , 3 );
2295+ output = testing::internal::GetCapturedStdout ();
2296+
2297+ EXPECT_EQ (
2298+ output,
2299+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2300+ output.clear ();
2301+ testing::internal::CaptureStdout ();
2302+
2303+ // destruct the rest
2304+ auto *new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2305+ (Cpp::SizeOf (scope) * 3 ));
2306+ Cpp::Destruct (new_head, scope, false , 2 );
2307+
2308+ output = testing::internal::GetCapturedStdout ();
2309+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2310+ output.clear ();
2311+
2312+ // deallocate since we call the destructor withFree = false
2313+ Cpp::Deallocate (scope, where, 5 );
2314+
2315+ // perform the same withFree=true
2316+ where = Cpp::Allocate (scope, a);
2317+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2318+ testing::internal::CaptureStdout ();
2319+ // FIXME : This should work with the array of objects as well
2320+ // Cpp::Destruct(where, scope, true, 5);
2321+ Cpp::Destruct (where, scope, true );
2322+ output = testing::internal::GetCapturedStdout ();
2323+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2324+ output.clear ();
2325+ }
2326+
21502327TEST (FunctionReflectionTest, UndoTest) {
21512328#ifdef _WIN32
21522329 GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments