1717#include " clang-c/CXCppInterOp.h"
1818
1919#include " llvm/ADT/SmallString.h"
20+ #include " llvm/Support/FileSystem.h"
2021#include " llvm/Support/Path.h"
21- #include < llvm/Support/FileSystem.h >
22+ #include " llvm/Support/raw_ostream.h "
2223
2324#include < gmock/gmock.h>
2425#include " gtest/gtest.h"
2526
2627#include < algorithm>
28+ #include < cstdint>
29+ #include < thread>
2730#include < utility>
2831
2932using ::testing::StartsWith;
@@ -247,7 +250,7 @@ TEST(InterpreterTest, DISABLED_DetectResourceDir) {
247250#ifdef _WIN32
248251 GTEST_SKIP () << " Disabled on Windows. Needs fixing." ;
249252#endif
250- Cpp::CreateInterpreter ();
253+ auto * I = Cpp::CreateInterpreter ();
251254 EXPECT_STRNE (Cpp::DetectResourceDir ().c_str (), Cpp::GetResourceDir ());
252255 llvm::SmallString<256 > Clang (LLVM_BINARY_DIR);
253256 llvm::sys::path::append (Clang, " bin" , " clang" );
@@ -256,7 +259,7 @@ TEST(InterpreterTest, DISABLED_DetectResourceDir) {
256259 GTEST_SKIP () << " Test not run (Clang binary does not exist)" ;
257260
258261 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 ));
260263}
261264
262265TEST (InterpreterTest, DetectSystemCompilerIncludePaths) {
@@ -364,26 +367,83 @@ if (llvm::sys::RunningOnValgrind())
364367#endif
365368}
366369
370+ static int printf_jit (const char * format, ...) {
371+ llvm::errs () << " printf_jit called!\n " ;
372+ return 0 ;
373+ }
374+
367375TEST (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" ;
370378#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);
377430
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);
379434 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 " );
389449}
0 commit comments