@@ -1959,6 +1959,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
19591959 output.clear ();
19601960}
19611961
1962+ TEST (FunctionReflectionTest, ConstructArray) {
1963+ #if defined(EMSCRIPTEN) && (CLANG_VERSION_MAJOR < 20)
1964+ GTEST_SKIP () << " Test fails for LLVM < 20 Emscripten builds" ;
1965+ #endif
1966+ if (llvm::sys::RunningOnValgrind ())
1967+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
1968+ #ifdef _WIN32
1969+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
1970+ #endif
1971+
1972+ Cpp::CreateInterpreter ();
1973+
1974+ Interp->declare (R"(
1975+ #include <new>
1976+ extern "C" int printf(const char*,...);
1977+ class C {
1978+ int x;
1979+ C() {
1980+ x = 42;
1981+ printf("\nConstructor Executed\n");
1982+ }
1983+ };
1984+ )" );
1985+
1986+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
1987+ std::string output;
1988+
1989+ size_t a = 5 ; // Construct an array of 5 objects
1990+ void * where = Cpp::Allocate (scope, a); // operator new
1991+
1992+ testing::internal::CaptureStdout ();
1993+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
1994+ // Check for the value of x which should be at the start of the object.
1995+ EXPECT_TRUE (*(int *)where == 42 );
1996+ // Check for the value of x in the second object
1997+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
1998+ Cpp::SizeOf (scope));
1999+ EXPECT_TRUE (*obj == 42 );
2000+
2001+ // Check for the value of x in the last object
2002+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2003+ Cpp::SizeOf (scope) * 4 );
2004+ EXPECT_TRUE (*obj == 42 );
2005+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2006+ Cpp::Deallocate (scope, where, 5 );
2007+ output = testing::internal::GetCapturedStdout ();
2008+ EXPECT_EQ (output,
2009+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2010+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2011+ output.clear ();
2012+ }
2013+
19622014TEST (FunctionReflectionTest, Destruct) {
19632015#ifdef EMSCRIPTEN
19642016 GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2016,6 +2068,82 @@ TEST(FunctionReflectionTest, Destruct) {
20162068 clang_Interpreter_dispose (I);
20172069}
20182070
2071+ TEST (FunctionReflectionTest, DestructArray) {
2072+ #ifdef EMSCRIPTEN
2073+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2074+ #endif
2075+ if (llvm::sys::RunningOnValgrind ())
2076+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2077+
2078+ #ifdef _WIN32
2079+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2080+ #endif
2081+
2082+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2083+ Cpp::CreateInterpreter (interpreter_args);
2084+
2085+ Interp->declare (R"(
2086+ #include <new>
2087+ extern "C" int printf(const char*,...);
2088+ class C {
2089+ int x;
2090+ C() {
2091+ printf("\nCtor Executed\n");
2092+ x = 42;
2093+ }
2094+ ~C() {
2095+ printf("\nDestructor Executed\n");
2096+ }
2097+ };
2098+ )" );
2099+
2100+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2101+ std::string output;
2102+
2103+ size_t a = 5 ; // Construct an array of 5 objects
2104+ void * where = Cpp::Allocate (scope, a); // operator new
2105+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2106+
2107+ // verify the array of objects has been constructed
2108+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2109+ Cpp::SizeOf (scope) * 4 );
2110+ EXPECT_TRUE (*obj == 42 );
2111+
2112+ testing::internal::CaptureStdout ();
2113+ // destruct 3 out of 5 objects
2114+ Cpp::Destruct (where, scope, false , 3 );
2115+ output = testing::internal::GetCapturedStdout ();
2116+
2117+ EXPECT_EQ (
2118+ output,
2119+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2120+ output.clear ();
2121+ testing::internal::CaptureStdout ();
2122+
2123+ // destruct the rest
2124+ auto new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2125+ Cpp::SizeOf (scope) * 3 );
2126+ Cpp::Destruct (new_head, scope, false , 2 );
2127+
2128+ output = testing::internal::GetCapturedStdout ();
2129+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2130+ output.clear ();
2131+
2132+ // deallocate since we call the destructor withFree = false
2133+ Cpp::Deallocate (scope, where, 5 );
2134+
2135+ // perform the same withFree=true
2136+ where = Cpp::Allocate (scope, a);
2137+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2138+ testing::internal::CaptureStdout ();
2139+ // FIXME : This should work with the array of objects as well
2140+ // Cpp::Destruct(where, scope, true, 5);
2141+ Cpp::Destruct (where, scope, true );
2142+ output = testing::internal::GetCapturedStdout ();
2143+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2144+ output.clear ();
2145+ }
2146+
20192147TEST (FunctionReflectionTest, UndoTest) {
20202148#ifdef _WIN32
20212149 GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments