@@ -2050,6 +2050,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
20502050 output.clear ();
20512051}
20522052
2053+ TEST (FunctionReflectionTest, ConstructArray) {
2054+ #if defined(EMSCRIPTEN) && (CLANG_VERSION_MAJOR < 20)
2055+ GTEST_SKIP () << " Test fails for LLVM < 20 Emscripten builds" ;
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+
2063+ Cpp::CreateInterpreter ();
2064+
2065+ Interp->declare (R"(
2066+ #include <new>
2067+ extern "C" int printf(const char*,...);
2068+ class C {
2069+ int x;
2070+ C() {
2071+ x = 42;
2072+ printf("\nConstructor Executed\n");
2073+ }
2074+ };
2075+ )" );
2076+
2077+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2078+ std::string output;
2079+
2080+ size_t a = 5 ; // Construct an array of 5 objects
2081+ void * where = Cpp::Allocate (scope, a); // operator new
2082+
2083+ testing::internal::CaptureStdout ();
2084+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2085+ // Check for the value of x which should be at the start of the object.
2086+ EXPECT_TRUE (*(int *)where == 42 );
2087+ // Check for the value of x in the second object
2088+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2089+ Cpp::SizeOf (scope));
2090+ EXPECT_TRUE (*obj == 42 );
2091+
2092+ // Check for the value of x in the last object
2093+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2094+ (Cpp::SizeOf (scope) * 4 ));
2095+ EXPECT_TRUE (*obj == 42 );
2096+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2097+ Cpp::Deallocate (scope, where, 5 );
2098+ output = testing::internal::GetCapturedStdout ();
2099+ EXPECT_EQ (output,
2100+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2101+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2102+ output.clear ();
2103+ }
2104+
20532105TEST (FunctionReflectionTest, Destruct) {
20542106#ifdef EMSCRIPTEN
20552107 GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2107,6 +2159,82 @@ TEST(FunctionReflectionTest, Destruct) {
21072159 clang_Interpreter_dispose (I);
21082160}
21092161
2162+ TEST (FunctionReflectionTest, DestructArray) {
2163+ #ifdef EMSCRIPTEN
2164+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2165+ #endif
2166+ if (llvm::sys::RunningOnValgrind ())
2167+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2168+
2169+ #ifdef _WIN32
2170+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2171+ #endif
2172+
2173+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2174+ Cpp::CreateInterpreter (interpreter_args);
2175+
2176+ Interp->declare (R"(
2177+ #include <new>
2178+ extern "C" int printf(const char*,...);
2179+ class C {
2180+ int x;
2181+ C() {
2182+ printf("\nCtor Executed\n");
2183+ x = 42;
2184+ }
2185+ ~C() {
2186+ printf("\nDestructor Executed\n");
2187+ }
2188+ };
2189+ )" );
2190+
2191+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2192+ std::string output;
2193+
2194+ size_t a = 5 ; // Construct an array of 5 objects
2195+ void * where = Cpp::Allocate (scope, a); // operator new
2196+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2197+
2198+ // verify the array of objects has been constructed
2199+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2200+ Cpp::SizeOf (scope) * 4 );
2201+ EXPECT_TRUE (*obj == 42 );
2202+
2203+ testing::internal::CaptureStdout ();
2204+ // destruct 3 out of 5 objects
2205+ Cpp::Destruct (where, scope, false , 3 );
2206+ output = testing::internal::GetCapturedStdout ();
2207+
2208+ EXPECT_EQ (
2209+ output,
2210+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2211+ output.clear ();
2212+ testing::internal::CaptureStdout ();
2213+
2214+ // destruct the rest
2215+ auto *new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2216+ (Cpp::SizeOf (scope) * 3 ));
2217+ Cpp::Destruct (new_head, scope, false , 2 );
2218+
2219+ output = testing::internal::GetCapturedStdout ();
2220+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2221+ output.clear ();
2222+
2223+ // deallocate since we call the destructor withFree = false
2224+ Cpp::Deallocate (scope, where, 5 );
2225+
2226+ // perform the same withFree=true
2227+ where = Cpp::Allocate (scope, a);
2228+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2229+ testing::internal::CaptureStdout ();
2230+ // FIXME : This should work with the array of objects as well
2231+ // Cpp::Destruct(where, scope, true, 5);
2232+ Cpp::Destruct (where, scope, true );
2233+ output = testing::internal::GetCapturedStdout ();
2234+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2235+ output.clear ();
2236+ }
2237+
21102238TEST (FunctionReflectionTest, UndoTest) {
21112239#ifdef _WIN32
21122240 GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments