@@ -2040,6 +2040,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
20402040 output.clear ();
20412041}
20422042
2043+ TEST (FunctionReflectionTest, ConstructArray) {
2044+ #if defined(EMSCRIPTEN) && (CLANG_VERSION_MAJOR < 20)
2045+ GTEST_SKIP () << " Test fails for LLVM < 20 Emscripten builds" ;
2046+ #endif
2047+ if (llvm::sys::RunningOnValgrind ())
2048+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2049+ #ifdef _WIN32
2050+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2051+ #endif
2052+
2053+ Cpp::CreateInterpreter ();
2054+
2055+ Interp->declare (R"(
2056+ #include <new>
2057+ extern "C" int printf(const char*,...);
2058+ class C {
2059+ int x;
2060+ C() {
2061+ x = 42;
2062+ printf("\nConstructor Executed\n");
2063+ }
2064+ };
2065+ )" );
2066+
2067+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2068+ std::string output;
2069+
2070+ size_t a = 5 ; // Construct an array of 5 objects
2071+ void * where = Cpp::Allocate (scope, a); // operator new
2072+
2073+ testing::internal::CaptureStdout ();
2074+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2075+ // Check for the value of x which should be at the start of the object.
2076+ EXPECT_TRUE (*(int *)where == 42 );
2077+ // Check for the value of x in the second object
2078+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2079+ Cpp::SizeOf (scope));
2080+ EXPECT_TRUE (*obj == 42 );
2081+
2082+ // Check for the value of x in the last object
2083+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2084+ Cpp::SizeOf (scope) * 4 );
2085+ EXPECT_TRUE (*obj == 42 );
2086+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2087+ Cpp::Deallocate (scope, where, 5 );
2088+ output = testing::internal::GetCapturedStdout ();
2089+ EXPECT_EQ (output,
2090+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2091+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2092+ output.clear ();
2093+ }
2094+
20432095TEST (FunctionReflectionTest, Destruct) {
20442096#ifdef EMSCRIPTEN
20452097 GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2097,6 +2149,82 @@ TEST(FunctionReflectionTest, Destruct) {
20972149 clang_Interpreter_dispose (I);
20982150}
20992151
2152+ TEST (FunctionReflectionTest, DestructArray) {
2153+ #ifdef EMSCRIPTEN
2154+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2155+ #endif
2156+ if (llvm::sys::RunningOnValgrind ())
2157+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2158+
2159+ #ifdef _WIN32
2160+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2161+ #endif
2162+
2163+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2164+ Cpp::CreateInterpreter (interpreter_args);
2165+
2166+ Interp->declare (R"(
2167+ #include <new>
2168+ extern "C" int printf(const char*,...);
2169+ class C {
2170+ int x;
2171+ C() {
2172+ printf("\nCtor Executed\n");
2173+ x = 42;
2174+ }
2175+ ~C() {
2176+ printf("\nDestructor Executed\n");
2177+ }
2178+ };
2179+ )" );
2180+
2181+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2182+ std::string output;
2183+
2184+ size_t a = 5 ; // Construct an array of 5 objects
2185+ void * where = Cpp::Allocate (scope, a); // operator new
2186+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2187+
2188+ // verify the array of objects has been constructed
2189+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2190+ Cpp::SizeOf (scope) * 4 );
2191+ EXPECT_TRUE (*obj == 42 );
2192+
2193+ testing::internal::CaptureStdout ();
2194+ // destruct 3 out of 5 objects
2195+ Cpp::Destruct (where, scope, false , 3 );
2196+ output = testing::internal::GetCapturedStdout ();
2197+
2198+ EXPECT_EQ (
2199+ output,
2200+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2201+ output.clear ();
2202+ testing::internal::CaptureStdout ();
2203+
2204+ // destruct the rest
2205+ auto new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2206+ Cpp::SizeOf (scope) * 3 );
2207+ Cpp::Destruct (new_head, scope, false , 2 );
2208+
2209+ output = testing::internal::GetCapturedStdout ();
2210+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2211+ output.clear ();
2212+
2213+ // deallocate since we call the destructor withFree = false
2214+ Cpp::Deallocate (scope, where, 5 );
2215+
2216+ // perform the same withFree=true
2217+ where = Cpp::Allocate (scope, a);
2218+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2219+ testing::internal::CaptureStdout ();
2220+ // FIXME : This should work with the array of objects as well
2221+ // Cpp::Destruct(where, scope, true, 5);
2222+ Cpp::Destruct (where, scope, true );
2223+ output = testing::internal::GetCapturedStdout ();
2224+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2225+ output.clear ();
2226+ }
2227+
21002228TEST (FunctionReflectionTest, UndoTest) {
21012229#ifdef _WIN32
21022230 GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments