@@ -2040,6 +2040,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
2040
2040
output.clear ();
2041
2041
}
2042
2042
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
+
2043
2095
TEST (FunctionReflectionTest, Destruct) {
2044
2096
#ifdef EMSCRIPTEN
2045
2097
GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2097,6 +2149,82 @@ TEST(FunctionReflectionTest, Destruct) {
2097
2149
clang_Interpreter_dispose (I);
2098
2150
}
2099
2151
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
+
2100
2228
TEST (FunctionReflectionTest, UndoTest) {
2101
2229
#ifdef _WIN32
2102
2230
GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments