@@ -2050,6 +2050,61 @@ 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
+ #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
+
2053
2108
TEST (FunctionReflectionTest, Destruct) {
2054
2109
#ifdef EMSCRIPTEN
2055
2110
GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2107,6 +2162,85 @@ TEST(FunctionReflectionTest, Destruct) {
2107
2162
clang_Interpreter_dispose (I);
2108
2163
}
2109
2164
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
+
2110
2244
TEST (FunctionReflectionTest, UndoTest) {
2111
2245
#ifdef _WIN32
2112
2246
GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments