17
17
#include " clang-c/CXCppInterOp.h"
18
18
19
19
#include " llvm/ADT/SmallString.h"
20
+ #include " llvm/Support/FileSystem.h"
20
21
#include " llvm/Support/Path.h"
21
- #include < llvm/Support/FileSystem.h >
22
+ #include " llvm/Support/raw_ostream.h "
22
23
23
24
#include < gmock/gmock.h>
24
25
#include " gtest/gtest.h"
25
26
26
27
#include < algorithm>
28
+ #include < cstdint>
29
+ #include < thread>
27
30
#include < utility>
28
31
29
32
using ::testing::StartsWith;
@@ -247,7 +250,7 @@ TEST(InterpreterTest, DISABLED_DetectResourceDir) {
247
250
#ifdef _WIN32
248
251
GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
249
252
#endif
250
- Cpp::CreateInterpreter ();
253
+ auto * I = Cpp::CreateInterpreter ();
251
254
EXPECT_STRNE (Cpp::DetectResourceDir ().c_str (), Cpp::GetResourceDir ());
252
255
llvm::SmallString<256 > Clang (LLVM_BINARY_DIR);
253
256
llvm::sys::path::append (Clang, " bin" , " clang" );
@@ -256,7 +259,7 @@ TEST(InterpreterTest, DISABLED_DetectResourceDir) {
256
259
GTEST_SKIP () << " Test not run (Clang binary does not exist)" ;
257
260
258
261
std::string DetectedPath = Cpp::DetectResourceDir (Clang.str ().str ().c_str ());
259
- EXPECT_STREQ (DetectedPath.c_str (), Cpp::GetResourceDir ());
262
+ EXPECT_STREQ (DetectedPath.c_str (), Cpp::GetResourceDir (I ));
260
263
}
261
264
262
265
TEST (InterpreterTest, DetectSystemCompilerIncludePaths) {
@@ -364,26 +367,83 @@ if (llvm::sys::RunningOnValgrind())
364
367
#endif
365
368
}
366
369
370
+ static int printf_jit (const char * format, ...) {
371
+ llvm::errs () << " printf_jit called!\n " ;
372
+ return 0 ;
373
+ }
374
+
367
375
TEST (InterpreterTest, MultipleInterpreter) {
368
- #if CLANG_VERSION_MAJOR < 20 && defined( EMSCRIPTEN)
369
- GTEST_SKIP () << " Test fails for Emscipten LLVM 20 builds" ;
376
+ #ifdef EMSCRIPTEN
377
+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
370
378
#endif
371
- auto * I = Cpp::CreateInterpreter ();
372
- EXPECT_TRUE (I);
373
- Cpp::Declare (R"(
374
- void f() {}
375
- )" );
376
- Cpp::TCppScope_t f = Cpp::GetNamed (" f" );
379
+ #ifdef _WIN32
380
+ GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
381
+ #endif
382
+ // delete all old interpreters
383
+ while (Cpp::DeleteInterpreter ())
384
+ ;
385
+ std::vector<const char *> interpreter_args = {" -include" , " new" };
386
+ auto * I1 = Cpp::CreateInterpreter (interpreter_args);
387
+ EXPECT_TRUE (I1);
388
+
389
+ auto F = [](Cpp::TInterp_t I) {
390
+ bool hasError = true ;
391
+ EXPECT_TRUE (Cpp::Evaluate (" __cplusplus" , &hasError, I) == 201402 );
392
+ EXPECT_FALSE (hasError);
393
+
394
+ Cpp::Declare (R"(
395
+ #include <new>
396
+ extern "C" int printf(const char*,...);
397
+ class MyKlass {};
398
+ )" ,
399
+ false , I);
400
+ Cpp::TCppScope_t f = Cpp::GetNamed (" printf" , Cpp::GetGlobalScope (I));
401
+ EXPECT_TRUE (f);
402
+ EXPECT_TRUE (Cpp::GetComplexType (Cpp::GetType (" int" , I)));
403
+ Cpp::TCppType_t MyKlass = Cpp::GetType (" MyKlass" , I);
404
+ EXPECT_EQ (Cpp::GetTypeAsString (MyKlass), " MyKlass" );
405
+ EXPECT_EQ (Cpp::GetNumBases (MyKlass), 0 );
406
+ EXPECT_FALSE (Cpp::GetBaseClass (MyKlass, 3 ));
407
+ std::vector<Cpp::TCppScope_t> members;
408
+ Cpp::GetEnumConstantDatamembers (Cpp::GetScopeFromType (MyKlass), members);
409
+ EXPECT_EQ (members.size (), 0 );
410
+
411
+ EXPECT_FALSE (
412
+ Cpp::InsertOrReplaceJitSymbol (" printf" , (uint64_t )&printf_jit, I));
413
+
414
+ auto f_callable = Cpp::MakeFunctionCallable (f);
415
+ EXPECT_EQ (f_callable.getKind (), Cpp::JitCall::Kind::kGenericCall );
416
+
417
+ EXPECT_FALSE (
418
+ Cpp::TakeInterpreter ((TInterp_t)1 )); // try to take ownership of an
419
+ // interpreter that does not exist
420
+
421
+ std::vector<std::string> includes;
422
+ Cpp::AddIncludePath (" /non/existent/" , I);
423
+ Cpp::GetIncludePaths (includes, false , false , I);
424
+ EXPECT_NE (std::find (includes.begin (), includes.end (), " /non/existent/" ),
425
+ std::end (includes));
426
+
427
+ EXPECT_TRUE (Cpp::InsertOrReplaceJitSymbol (" non_existent" , (uint64_t )&f, I));
428
+ };
429
+ F (I1);
377
430
378
- auto * I2 = Cpp::CreateInterpreter ();
431
+ auto * I2 = Cpp::CreateInterpreter (interpreter_args);
432
+ auto * I3 = Cpp::CreateInterpreter (interpreter_args);
433
+ auto * I4 = Cpp::CreateInterpreter (interpreter_args);
379
434
EXPECT_TRUE (I2);
380
- Cpp::Declare (R"(
381
- void ff() {}
382
- )" );
383
- Cpp::TCppScope_t ff = Cpp::GetNamed (" ff" );
384
-
385
- auto f_callable = Cpp::MakeFunctionCallable (f);
386
- EXPECT_EQ (f_callable.getKind (), Cpp::JitCall::Kind::kGenericCall );
387
- auto ff_callable = Cpp::MakeFunctionCallable (ff);
388
- EXPECT_EQ (ff_callable.getKind (), Cpp::JitCall::Kind::kGenericCall );
435
+ EXPECT_TRUE (I3);
436
+ EXPECT_TRUE (I4);
437
+
438
+ std::thread t2 (F, I2);
439
+ std::thread t3 (F, I3);
440
+ std::thread t4 (F, I4);
441
+ t2.join ();
442
+ t3.join ();
443
+ t4.join ();
444
+
445
+ testing::internal::CaptureStderr ();
446
+ Cpp::Process (" printf(\" Blah\" );" , I2);
447
+ std::string cerrs = testing::internal::GetCapturedStderr ();
448
+ EXPECT_STREQ (cerrs.c_str (), " printf_jit called!\n " );
389
449
}
0 commit comments