@@ -2027,6 +2027,49 @@ TEST(FunctionReflectionTest, Construct) {
2027
2027
clang_Interpreter_dispose (I);
2028
2028
}
2029
2029
2030
+ // Test zero initialization of PODs and default initialization cases
2031
+ TEST (FunctionReflectionTest, ConstructPOD) {
2032
+ #ifdef EMSCRIPTEN
2033
+ #if CLANG_VERSION_MAJOR < 20
2034
+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2035
+ #endif
2036
+ #endif
2037
+ if (llvm::sys::RunningOnValgrind ())
2038
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2039
+ #ifdef _WIN32
2040
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2041
+ #endif
2042
+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2043
+ Cpp::CreateInterpreter (interpreter_args);
2044
+
2045
+ Interp->declare (R"(
2046
+ namespace PODS {
2047
+ struct SomePOD_B {
2048
+ int fInt;
2049
+ };
2050
+ struct SomePOD_C {
2051
+ int fInt;
2052
+ double fDouble;
2053
+ };
2054
+ })" );
2055
+
2056
+ auto *ns = Cpp::GetNamed (" PODS" );
2057
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" SomePOD_B" , ns);
2058
+ EXPECT_TRUE (scope);
2059
+ Cpp::TCppObject_t object = Cpp::Construct (scope);
2060
+ EXPECT_TRUE (object != nullptr );
2061
+ int * fInt = reinterpret_cast <int *>(reinterpret_cast <char *>(object));
2062
+ EXPECT_TRUE (*fInt == 0 );
2063
+
2064
+ scope = Cpp::GetNamed (" SomePOD_C" , ns);
2065
+ EXPECT_TRUE (scope);
2066
+ object = Cpp::Construct (scope);
2067
+ EXPECT_TRUE (object);
2068
+ auto * fDouble =
2069
+ reinterpret_cast <double *>(reinterpret_cast <char *>(object) + sizeof (int ));
2070
+ EXPECT_EQ (*fDouble , 0.0 );
2071
+ }
2072
+
2030
2073
// Test nested constructor calls
2031
2074
TEST (FunctionReflectionTest, ConstructNested) {
2032
2075
#ifdef EMSCRIPTEN
@@ -2090,6 +2133,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
2090
2133
output.clear ();
2091
2134
}
2092
2135
2136
+ TEST (FunctionReflectionTest, ConstructArray) {
2137
+ #if defined(EMSCRIPTEN)
2138
+ GTEST_SKIP () << " Test fails for Emscripten builds" ;
2139
+ #endif
2140
+ if (llvm::sys::RunningOnValgrind ())
2141
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2142
+ #ifdef _WIN32
2143
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2144
+ #endif
2145
+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2146
+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2147
+ #endif
2148
+
2149
+ Cpp::CreateInterpreter ();
2150
+
2151
+ Interp->declare (R"(
2152
+ #include <new>
2153
+ extern "C" int printf(const char*,...);
2154
+ class C {
2155
+ int x;
2156
+ C() {
2157
+ x = 42;
2158
+ printf("\nConstructor Executed\n");
2159
+ }
2160
+ };
2161
+ )" );
2162
+
2163
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2164
+ std::string output;
2165
+
2166
+ size_t a = 5 ; // Construct an array of 5 objects
2167
+ void * where = Cpp::Allocate (scope, a); // operator new
2168
+
2169
+ testing::internal::CaptureStdout ();
2170
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2171
+ // Check for the value of x which should be at the start of the object.
2172
+ EXPECT_TRUE (*(int *)where == 42 );
2173
+ // Check for the value of x in the second object
2174
+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2175
+ Cpp::SizeOf (scope));
2176
+ EXPECT_TRUE (*obj == 42 );
2177
+
2178
+ // Check for the value of x in the last object
2179
+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2180
+ (Cpp::SizeOf (scope) * 4 ));
2181
+ EXPECT_TRUE (*obj == 42 );
2182
+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2183
+ Cpp::Deallocate (scope, where, 5 );
2184
+ output = testing::internal::GetCapturedStdout ();
2185
+ EXPECT_EQ (output,
2186
+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2187
+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2188
+ output.clear ();
2189
+ }
2190
+
2093
2191
TEST (FunctionReflectionTest, Destruct) {
2094
2192
#ifdef EMSCRIPTEN
2095
2193
GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2147,6 +2245,85 @@ TEST(FunctionReflectionTest, Destruct) {
2147
2245
clang_Interpreter_dispose (I);
2148
2246
}
2149
2247
2248
+ TEST (FunctionReflectionTest, DestructArray) {
2249
+ #ifdef EMSCRIPTEN
2250
+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2251
+ #endif
2252
+ if (llvm::sys::RunningOnValgrind ())
2253
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2254
+
2255
+ #ifdef _WIN32
2256
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2257
+ #endif
2258
+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2259
+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2260
+ #endif
2261
+
2262
+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2263
+ Cpp::CreateInterpreter (interpreter_args);
2264
+
2265
+ Interp->declare (R"(
2266
+ #include <new>
2267
+ extern "C" int printf(const char*,...);
2268
+ class C {
2269
+ int x;
2270
+ C() {
2271
+ printf("\nCtor Executed\n");
2272
+ x = 42;
2273
+ }
2274
+ ~C() {
2275
+ printf("\nDestructor Executed\n");
2276
+ }
2277
+ };
2278
+ )" );
2279
+
2280
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2281
+ std::string output;
2282
+
2283
+ size_t a = 5 ; // Construct an array of 5 objects
2284
+ void * where = Cpp::Allocate (scope, a); // operator new
2285
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2286
+
2287
+ // verify the array of objects has been constructed
2288
+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2289
+ Cpp::SizeOf (scope) * 4 );
2290
+ EXPECT_TRUE (*obj == 42 );
2291
+
2292
+ testing::internal::CaptureStdout ();
2293
+ // destruct 3 out of 5 objects
2294
+ Cpp::Destruct (where, scope, false , 3 );
2295
+ output = testing::internal::GetCapturedStdout ();
2296
+
2297
+ EXPECT_EQ (
2298
+ output,
2299
+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2300
+ output.clear ();
2301
+ testing::internal::CaptureStdout ();
2302
+
2303
+ // destruct the rest
2304
+ auto *new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2305
+ (Cpp::SizeOf (scope) * 3 ));
2306
+ Cpp::Destruct (new_head, scope, false , 2 );
2307
+
2308
+ output = testing::internal::GetCapturedStdout ();
2309
+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2310
+ output.clear ();
2311
+
2312
+ // deallocate since we call the destructor withFree = false
2313
+ Cpp::Deallocate (scope, where, 5 );
2314
+
2315
+ // perform the same withFree=true
2316
+ where = Cpp::Allocate (scope, a);
2317
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2318
+ testing::internal::CaptureStdout ();
2319
+ // FIXME : This should work with the array of objects as well
2320
+ // Cpp::Destruct(where, scope, true, 5);
2321
+ Cpp::Destruct (where, scope, true );
2322
+ output = testing::internal::GetCapturedStdout ();
2323
+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2324
+ output.clear ();
2325
+ }
2326
+
2150
2327
TEST (FunctionReflectionTest, UndoTest) {
2151
2328
#ifdef _WIN32
2152
2329
GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments