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