@@ -2050,6 +2050,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
2050
2050
output.clear ();
2051
2051
}
2052
2052
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
+
2053
2105
TEST (FunctionReflectionTest, Destruct) {
2054
2106
#ifdef EMSCRIPTEN
2055
2107
GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2107,6 +2159,82 @@ TEST(FunctionReflectionTest, Destruct) {
2107
2159
clang_Interpreter_dispose (I);
2108
2160
}
2109
2161
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
+
2110
2238
TEST (FunctionReflectionTest, UndoTest) {
2111
2239
#ifdef _WIN32
2112
2240
GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments