@@ -1987,6 +1987,49 @@ TEST(FunctionReflectionTest, Construct) {
1987
1987
clang_Interpreter_dispose (I);
1988
1988
}
1989
1989
1990
+ // Test zero initialization of PODs and default initialization cases
1991
+ TEST (FunctionReflectionTest, ConstructPOD) {
1992
+ #ifdef EMSCRIPTEN
1993
+ #if CLANG_VERSION_MAJOR < 20
1994
+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
1995
+ #endif
1996
+ #endif
1997
+ if (llvm::sys::RunningOnValgrind ())
1998
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
1999
+ #ifdef _WIN32
2000
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2001
+ #endif
2002
+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2003
+ Cpp::CreateInterpreter (interpreter_args);
2004
+
2005
+ Interp->declare (R"(
2006
+ namespace PODS {
2007
+ struct SomePOD_B {
2008
+ int fInt;
2009
+ };
2010
+ struct SomePOD_C {
2011
+ int fInt;
2012
+ double fDouble;
2013
+ };
2014
+ })" );
2015
+
2016
+ auto *ns = Cpp::GetNamed (" PODS" );
2017
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" SomePOD_B" , ns);
2018
+ EXPECT_TRUE (scope);
2019
+ Cpp::TCppObject_t object = Cpp::Construct (scope);
2020
+ EXPECT_TRUE (object != nullptr );
2021
+ int * fInt = reinterpret_cast <int *>(reinterpret_cast <char *>(object));
2022
+ EXPECT_TRUE (*fInt == 0 );
2023
+
2024
+ scope = Cpp::GetNamed (" SomePOD_C" , ns);
2025
+ EXPECT_TRUE (scope);
2026
+ object = Cpp::Construct (scope);
2027
+ EXPECT_TRUE (object);
2028
+ auto * fDouble =
2029
+ reinterpret_cast <double *>(reinterpret_cast <char *>(object) + sizeof (int ));
2030
+ EXPECT_EQ (*fDouble , 0.0 );
2031
+ }
2032
+
1990
2033
// Test nested constructor calls
1991
2034
TEST (FunctionReflectionTest, ConstructNested) {
1992
2035
#ifdef EMSCRIPTEN
@@ -2050,6 +2093,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
2050
2093
output.clear ();
2051
2094
}
2052
2095
2096
+ TEST (FunctionReflectionTest, ConstructArray) {
2097
+ #if defined(EMSCRIPTEN)
2098
+ GTEST_SKIP () << " Test fails for Emscripten builds" ;
2099
+ #endif
2100
+ if (llvm::sys::RunningOnValgrind ())
2101
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2102
+ #ifdef _WIN32
2103
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2104
+ #endif
2105
+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2106
+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2107
+ #endif
2108
+
2109
+ Cpp::CreateInterpreter ();
2110
+
2111
+ Interp->declare (R"(
2112
+ #include <new>
2113
+ extern "C" int printf(const char*,...);
2114
+ class C {
2115
+ int x;
2116
+ C() {
2117
+ x = 42;
2118
+ printf("\nConstructor Executed\n");
2119
+ }
2120
+ };
2121
+ )" );
2122
+
2123
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2124
+ std::string output;
2125
+
2126
+ size_t a = 5 ; // Construct an array of 5 objects
2127
+ void * where = Cpp::Allocate (scope, a); // operator new
2128
+
2129
+ testing::internal::CaptureStdout ();
2130
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2131
+ // Check for the value of x which should be at the start of the object.
2132
+ EXPECT_TRUE (*(int *)where == 42 );
2133
+ // Check for the value of x in the second object
2134
+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2135
+ Cpp::SizeOf (scope));
2136
+ EXPECT_TRUE (*obj == 42 );
2137
+
2138
+ // Check for the value of x in the last object
2139
+ obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2140
+ (Cpp::SizeOf (scope) * 4 ));
2141
+ EXPECT_TRUE (*obj == 42 );
2142
+ Cpp::Destruct (where, scope, /* withFree=*/ false , 5 );
2143
+ Cpp::Deallocate (scope, where, 5 );
2144
+ output = testing::internal::GetCapturedStdout ();
2145
+ EXPECT_EQ (output,
2146
+ " \n Constructor Executed\n\n Constructor Executed\n\n Constructor "
2147
+ " Executed\n\n Constructor Executed\n\n Constructor Executed\n " );
2148
+ output.clear ();
2149
+ }
2150
+
2053
2151
TEST (FunctionReflectionTest, Destruct) {
2054
2152
#ifdef EMSCRIPTEN
2055
2153
GTEST_SKIP () << " Test fails for Emscipten builds" ;
@@ -2107,6 +2205,85 @@ TEST(FunctionReflectionTest, Destruct) {
2107
2205
clang_Interpreter_dispose (I);
2108
2206
}
2109
2207
2208
+ TEST (FunctionReflectionTest, DestructArray) {
2209
+ #ifdef EMSCRIPTEN
2210
+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
2211
+ #endif
2212
+ if (llvm::sys::RunningOnValgrind ())
2213
+ GTEST_SKIP () << " XFAIL due to Valgrind report" ;
2214
+
2215
+ #ifdef _WIN32
2216
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
2217
+ #endif
2218
+ #if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2219
+ GTEST_SKIP () << " Test fails on Clang16 OS X" ;
2220
+ #endif
2221
+
2222
+ std::vector<const char *> interpreter_args = {" -include" , " new" };
2223
+ Cpp::CreateInterpreter (interpreter_args);
2224
+
2225
+ Interp->declare (R"(
2226
+ #include <new>
2227
+ extern "C" int printf(const char*,...);
2228
+ class C {
2229
+ int x;
2230
+ C() {
2231
+ printf("\nCtor Executed\n");
2232
+ x = 42;
2233
+ }
2234
+ ~C() {
2235
+ printf("\nDestructor Executed\n");
2236
+ }
2237
+ };
2238
+ )" );
2239
+
2240
+ Cpp::TCppScope_t scope = Cpp::GetNamed (" C" );
2241
+ std::string output;
2242
+
2243
+ size_t a = 5 ; // Construct an array of 5 objects
2244
+ void * where = Cpp::Allocate (scope, a); // operator new
2245
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a)); // placement new
2246
+
2247
+ // verify the array of objects has been constructed
2248
+ int * obj = reinterpret_cast <int *>(reinterpret_cast <char *>(where) +
2249
+ Cpp::SizeOf (scope) * 4 );
2250
+ EXPECT_TRUE (*obj == 42 );
2251
+
2252
+ testing::internal::CaptureStdout ();
2253
+ // destruct 3 out of 5 objects
2254
+ Cpp::Destruct (where, scope, false , 3 );
2255
+ output = testing::internal::GetCapturedStdout ();
2256
+
2257
+ EXPECT_EQ (
2258
+ output,
2259
+ " \n Destructor Executed\n\n Destructor Executed\n\n Destructor Executed\n " );
2260
+ output.clear ();
2261
+ testing::internal::CaptureStdout ();
2262
+
2263
+ // destruct the rest
2264
+ auto *new_head = reinterpret_cast <void *>(reinterpret_cast <char *>(where) +
2265
+ (Cpp::SizeOf (scope) * 3 ));
2266
+ Cpp::Destruct (new_head, scope, false , 2 );
2267
+
2268
+ output = testing::internal::GetCapturedStdout ();
2269
+ EXPECT_EQ (output, " \n Destructor Executed\n\n Destructor Executed\n " );
2270
+ output.clear ();
2271
+
2272
+ // deallocate since we call the destructor withFree = false
2273
+ Cpp::Deallocate (scope, where, 5 );
2274
+
2275
+ // perform the same withFree=true
2276
+ where = Cpp::Allocate (scope, a);
2277
+ EXPECT_TRUE (where == Cpp::Construct (scope, where, a));
2278
+ testing::internal::CaptureStdout ();
2279
+ // FIXME : This should work with the array of objects as well
2280
+ // Cpp::Destruct(where, scope, true, 5);
2281
+ Cpp::Destruct (where, scope, true );
2282
+ output = testing::internal::GetCapturedStdout ();
2283
+ EXPECT_EQ (output, " \n Destructor Executed\n " );
2284
+ output.clear ();
2285
+ }
2286
+
2110
2287
TEST (FunctionReflectionTest, UndoTest) {
2111
2288
#ifdef _WIN32
2112
2289
GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
0 commit comments