@@ -1987,6 +1987,49 @@ TEST(FunctionReflectionTest, Construct) {
19871987 clang_Interpreter_dispose (I);
19881988}
19891989
1990+ // Test zero initialization of PODs and default initialization cases
1991+ TEST (FunctionReflectionTest, ConstructPOD) {
1992+ #ifdef EMSCRIPTEN
1993+ #if CLANG_VERSION_MAJOR < 20
1994+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
1995+ #endif
1996+ #endif
1997+ if (llvm::sys::RunningOnValgrind ())
1998+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
1999+ #ifdef _WIN32
2000+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2001+ #endif
2002+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2003+ Cpp::CreateInterpreter (interpreter_args);
2004+
2005+ Interp->declare (R"(
2006+ namespace PODS {
2007+ struct SomePOD_B {
2008+ int fInt;
2009+ };
2010+ struct SomePOD_C {
2011+ int fInt;
2012+ double fDouble;
2013+ };
2014+ })" );
2015+
2016+ auto *ns = Cpp::GetNamed (" PODS" );
2017+ Cpp::TCppScope_t scope = Cpp::GetNamed (" SomePOD_B" , ns);
2018+ EXPECT_TRUE (scope);
2019+ Cpp::TCppObject_t object = Cpp::Construct (scope);
2020+ EXPECT_TRUE (object != nullptr );
2021+ int * fInt = reinterpret_cast <int *>(reinterpret_cast <char *>(object));
2022+ EXPECT_TRUE (*fInt == 0 );
2023+
2024+ scope = Cpp::GetNamed (" SomePOD_C" , ns);
2025+ EXPECT_TRUE (scope);
2026+ object = Cpp::Construct (scope);
2027+ EXPECT_TRUE (object);
2028+ auto * fDouble =
2029+ reinterpret_cast <double *>(reinterpret_cast <char *>(object) + sizeof (int ));
2030+ EXPECT_EQ (*fDouble , 0.0 );
2031+ }
2032+
19902033// Test nested constructor calls
19912034TEST (FunctionReflectionTest, ConstructNested) {
19922035#ifdef EMSCRIPTEN
@@ -2050,6 +2093,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
20502093 output.clear ();
20512094}
20522095
2096+ TEST (FunctionReflectionTest, ConstructArray) {
2097+ #if defined(EMSCRIPTEN)
2098+ GTEST_SKIP () << " Test fails for Emscripten builds" ;
2099+ #endif
2100+ if (llvm::sys::RunningOnValgrind ())
2101+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2102+ #ifdef _WIN32
2103+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2104+ #endif
2105+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2106+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2107+ #endif
2108+
2109+ Cpp::CreateInterpreter ();
2110+
2111+ Interp->declare (R"(
2112+ #include <new>
2113+ extern "C" int printf(const char*,...);
2114+ class C {
2115+ int x;
2116+ C() {
2117+ x = 42;
2118+ printf("\nConstructor Executed\n");
2119+ }
2120+ };
2121+ )" );
2122+
2123+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2124+ std::string output;
2125+
2126+ size_t a = 5 ; // Construct an array of 5 objects
2127+ void * where = Cpp::Allocate (scope, a); // operator new
2128+
2129+ testing::internal::CaptureStdout ();
2130+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2131+ // Check for the value of x which should be at the start of the object.
2132+ EXPECT_TRUE (*(int *)where == 42 );
2133+ // Check for the value of x in the second object
2134+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2135+ Cpp::SizeOf (scope));
2136+ EXPECT_TRUE (*obj == 42 );
2137+
2138+ // Check for the value of x in the last object
2139+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2140+ (Cpp::SizeOf (scope) * 4 ));
2141+ EXPECT_TRUE (*obj == 42 );
2142+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2143+ Cpp::Deallocate (scope, where, 5 );
2144+ output = testing::internal::GetCapturedStdout ();
2145+ EXPECT_EQ (output,
2146+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2147+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2148+ output.clear ();
2149+ }
2150+
20532151TEST (FunctionReflectionTest, Destruct) {
20542152#ifdef EMSCRIPTEN
20552153 GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2107,6 +2205,85 @@ TEST(FunctionReflectionTest, Destruct) {
21072205 clang_Interpreter_dispose (I);
21082206}
21092207
2208+ TEST (FunctionReflectionTest, DestructArray) {
2209+ #ifdef EMSCRIPTEN
2210+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2211+ #endif
2212+ if (llvm::sys::RunningOnValgrind ())
2213+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2214+
2215+ #ifdef _WIN32
2216+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2217+ #endif
2218+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2219+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2220+ #endif
2221+
2222+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2223+ Cpp::CreateInterpreter (interpreter_args);
2224+
2225+ Interp->declare (R"(
2226+ #include <new>
2227+ extern "C" int printf(const char*,...);
2228+ class C {
2229+ int x;
2230+ C() {
2231+ printf("\nCtor Executed\n");
2232+ x = 42;
2233+ }
2234+ ~C() {
2235+ printf("\nDestructor Executed\n");
2236+ }
2237+ };
2238+ )" );
2239+
2240+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2241+ std::string output;
2242+
2243+ size_t a = 5 ; // Construct an array of 5 objects
2244+ void * where = Cpp::Allocate (scope, a); // operator new
2245+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2246+
2247+ // verify the array of objects has been constructed
2248+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2249+ Cpp::SizeOf (scope) * 4 );
2250+ EXPECT_TRUE (*obj == 42 );
2251+
2252+ testing::internal::CaptureStdout ();
2253+ // destruct 3 out of 5 objects
2254+ Cpp::Destruct (where, scope, false , 3 );
2255+ output = testing::internal::GetCapturedStdout ();
2256+
2257+ EXPECT_EQ (
2258+ output,
2259+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2260+ output.clear ();
2261+ testing::internal::CaptureStdout ();
2262+
2263+ // destruct the rest
2264+ auto *new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2265+ (Cpp::SizeOf (scope) * 3 ));
2266+ Cpp::Destruct (new_head, scope, false , 2 );
2267+
2268+ output = testing::internal::GetCapturedStdout ();
2269+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2270+ output.clear ();
2271+
2272+ // deallocate since we call the destructor withFree = false
2273+ Cpp::Deallocate (scope, where, 5 );
2274+
2275+ // perform the same withFree=true
2276+ where = Cpp::Allocate (scope, a);
2277+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2278+ testing::internal::CaptureStdout ();
2279+ // FIXME : This should work with the array of objects as well
2280+ // Cpp::Destruct(where, scope, true, 5);
2281+ Cpp::Destruct (where, scope, true );
2282+ output = testing::internal::GetCapturedStdout ();
2283+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2284+ output.clear ();
2285+ }
2286+
21102287TEST (FunctionReflectionTest, UndoTest) {
21112288#ifdef _WIN32
21122289 GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments