@@ -2047,6 +2047,49 @@ TEST(FunctionReflectionTest, Construct) {
2047
2047
clang_Interpreter_dispose (I);
2048
2048
}
2049
2049
2050
+ // Test zero initialization of PODs and default initialization cases
2051
+ TEST (FunctionReflectionTest, ConstructPOD) {
2052
+ #ifdef EMSCRIPTEN
2053
+ #if CLANG_VERSION_MAJOR < 20
2054
+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2055
+ #endif
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
+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2063
+ Cpp::CreateInterpreter (interpreter_args);
2064
+
2065
+ Interp->declare (R"(
2066
+ namespace PODS {
2067
+ struct SomePOD_B {
2068
+ int fInt;
2069
+ };
2070
+ struct SomePOD_C {
2071
+ int fInt;
2072
+ double fDouble;
2073
+ };
2074
+ })" );
2075
+
2076
+ auto *ns = Cpp::GetNamed (" PODS" );
2077
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" SomePOD_B" , ns);
2078
+ EXPECT_TRUE (scope);
2079
+ Cpp::TCppObject_t object = Cpp::Construct (scope);
2080
+ EXPECT_TRUE (object != nullptr );
2081
+ int * fInt = reinterpret_cast <int *>(reinterpret_cast <char *>(object));
2082
+ EXPECT_TRUE (*fInt == 0 );
2083
+
2084
+ scope = Cpp::GetNamed (" SomePOD_C" , ns);
2085
+ EXPECT_TRUE (scope);
2086
+ object = Cpp::Construct (scope);
2087
+ EXPECT_TRUE (object);
2088
+ auto * fDouble =
2089
+ reinterpret_cast <double *>(reinterpret_cast <char *>(object) + sizeof (int ));
2090
+ EXPECT_EQ (*fDouble , 0.0 );
2091
+ }
2092
+
2050
2093
// Test nested constructor calls
2051
2094
TEST (FunctionReflectionTest, ConstructNested) {
2052
2095
#ifdef EMSCRIPTEN
@@ -2110,6 +2153,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
2110
2153
output.clear ();
2111
2154
}
2112
2155
2156
+ TEST (FunctionReflectionTest, ConstructArray) {
2157
+ #if defined(EMSCRIPTEN)
2158
+ GTEST_SKIP () << " Test fails for Emscripten builds" ;
2159
+ #endif
2160
+ if (llvm::sys::RunningOnValgrind ())
2161
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2162
+ #ifdef _WIN32
2163
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2164
+ #endif
2165
+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2166
+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2167
+ #endif
2168
+
2169
+ Cpp::CreateInterpreter ();
2170
+
2171
+ Interp->declare (R"(
2172
+ #include <new>
2173
+ extern "C" int printf(const char*,...);
2174
+ class C {
2175
+ int x;
2176
+ C() {
2177
+ x = 42;
2178
+ printf("\nConstructor Executed\n");
2179
+ }
2180
+ };
2181
+ )" );
2182
+
2183
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2184
+ std::string output;
2185
+
2186
+ size_t a = 5 ; // Construct an array of 5 objects
2187
+ void * where = Cpp::Allocate (scope, a); // operator new
2188
+
2189
+ testing::internal::CaptureStdout ();
2190
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2191
+ // Check for the value of x which should be at the start of the object.
2192
+ EXPECT_TRUE (*(int *)where == 42 );
2193
+ // Check for the value of x in the second object
2194
+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2195
+ Cpp::SizeOf (scope));
2196
+ EXPECT_TRUE (*obj == 42 );
2197
+
2198
+ // Check for the value of x in the last object
2199
+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2200
+ (Cpp::SizeOf (scope) * 4 ));
2201
+ EXPECT_TRUE (*obj == 42 );
2202
+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2203
+ Cpp::Deallocate (scope, where, 5 );
2204
+ output = testing::internal::GetCapturedStdout ();
2205
+ EXPECT_EQ (output,
2206
+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2207
+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2208
+ output.clear ();
2209
+ }
2210
+
2113
2211
TEST (FunctionReflectionTest, Destruct) {
2114
2212
#ifdef EMSCRIPTEN
2115
2213
GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2167,6 +2265,85 @@ TEST(FunctionReflectionTest, Destruct) {
2167
2265
clang_Interpreter_dispose (I);
2168
2266
}
2169
2267
2268
+ TEST (FunctionReflectionTest, DestructArray) {
2269
+ #ifdef EMSCRIPTEN
2270
+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2271
+ #endif
2272
+ if (llvm::sys::RunningOnValgrind ())
2273
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2274
+
2275
+ #ifdef _WIN32
2276
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2277
+ #endif
2278
+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2279
+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2280
+ #endif
2281
+
2282
+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2283
+ Cpp::CreateInterpreter (interpreter_args);
2284
+
2285
+ Interp->declare (R"(
2286
+ #include <new>
2287
+ extern "C" int printf(const char*,...);
2288
+ class C {
2289
+ int x;
2290
+ C() {
2291
+ printf("\nCtor Executed\n");
2292
+ x = 42;
2293
+ }
2294
+ ~C() {
2295
+ printf("\nDestructor Executed\n");
2296
+ }
2297
+ };
2298
+ )" );
2299
+
2300
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2301
+ std::string output;
2302
+
2303
+ size_t a = 5 ; // Construct an array of 5 objects
2304
+ void * where = Cpp::Allocate (scope, a); // operator new
2305
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2306
+
2307
+ // verify the array of objects has been constructed
2308
+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2309
+ Cpp::SizeOf (scope) * 4 );
2310
+ EXPECT_TRUE (*obj == 42 );
2311
+
2312
+ testing::internal::CaptureStdout ();
2313
+ // destruct 3 out of 5 objects
2314
+ Cpp::Destruct (where, scope, false , 3 );
2315
+ output = testing::internal::GetCapturedStdout ();
2316
+
2317
+ EXPECT_EQ (
2318
+ output,
2319
+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2320
+ output.clear ();
2321
+ testing::internal::CaptureStdout ();
2322
+
2323
+ // destruct the rest
2324
+ auto *new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2325
+ (Cpp::SizeOf (scope) * 3 ));
2326
+ Cpp::Destruct (new_head, scope, false , 2 );
2327
+
2328
+ output = testing::internal::GetCapturedStdout ();
2329
+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2330
+ output.clear ();
2331
+
2332
+ // deallocate since we call the destructor withFree = false
2333
+ Cpp::Deallocate (scope, where, 5 );
2334
+
2335
+ // perform the same withFree=true
2336
+ where = Cpp::Allocate (scope, a);
2337
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2338
+ testing::internal::CaptureStdout ();
2339
+ // FIXME : This should work with the array of objects as well
2340
+ // Cpp::Destruct(where, scope, true, 5);
2341
+ Cpp::Destruct (where, scope, true );
2342
+ output = testing::internal::GetCapturedStdout ();
2343
+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2344
+ output.clear ();
2345
+ }
2346
+
2170
2347
TEST (FunctionReflectionTest, UndoTest) {
2171
2348
#ifdef _WIN32
2172
2349
GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments