Skip to content

Conversation

kr-2003
Copy link
Contributor

@kr-2003 kr-2003 commented Sep 20, 2025

No description provided.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

There were too many comments to post at once. Showing the first 10 out of 16. Check the log or trigger a new build to see more.


inline std::unique_ptr<clang::Interpreter>
createClangInterpreter(std::vector<const char*>& args) {
createClangInterpreter(std::vector<const char*>& args, int stdin_fd = 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::vector" is directly included [misc-include-cleaner]

lib/CppInterOp/Compatibility.h:14:

+ #include <vector>

m_FD = fileno(m_TempFile);
m_OwnsFile = false;
} else {
m_TempFile = tmpfile();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: assigning newly created 'gsl::owner<>' to non-owner 'FILE *' (aka '_IO_FILE *') [cppcoreguidelines-owning-memory]

      m_TempFile = tmpfile();
      ^

~StreamCaptureInfo() {
assert(m_DupFD == -1 && "Captured output not used?");
if (m_TempFile && m_OwnsFile) {
fclose(m_TempFile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: calling legacy resource function without passing a 'gsl::owner<>' [cppcoreguidelines-owning-memory]

      fclose(m_TempFile);
      ^

size_t newLen =
fread(content.get(), sizeof(char), bufsize, m_TempFile.get());
if (ferror(m_TempFile.get()) != 0)
size_t newLen = fread(content.get(), sizeof(char), bufsize, m_TempFile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: The 1st argument to 'fread' is a buffer with size 0 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 1) times the 3rd argument (which is 18446744073709551615) [clang-analyzer-unix.StdCLibraryFunctions]

    size_t newLen = fread(content.get(), sizeof(char), bufsize, m_TempFile);
                    ^
Additional context

lib/CppInterOp/CppInterOp.cpp:4409: Calling 'StreamCaptureInfo::GetCapturedString'

  std::string result = SCI.GetCapturedString();
                       ^

lib/CppInterOp/CppInterOp.cpp:4356: Taking false branch

    if (dup2(m_DupFD, m_FD) < 0)
    ^

lib/CppInterOp/CppInterOp.cpp:4359: Taking false branch

    if (fseek(m_TempFile, 0L, SEEK_END) != 0)
    ^

lib/CppInterOp/CppInterOp.cpp:4363: Assuming that 'ftell' fails

    long bufsize = ftell(m_TempFile);
                   ^

lib/CppInterOp/CppInterOp.cpp:4363: 'bufsize' initialized here

    long bufsize = ftell(m_TempFile);
    ^

lib/CppInterOp/CppInterOp.cpp:4364: Taking true branch

    if (bufsize == -1)
    ^

lib/CppInterOp/CppInterOp.cpp:4368: Storing uninitialized value

    std::unique_ptr<char[]> content(new char[bufsize + 1]);
                                    ^

lib/CppInterOp/CppInterOp.cpp:4368: Passing value via 1st parameter '__p'

    std::unique_ptr<char[]> content(new char[bufsize + 1]);
                                    ^

lib/CppInterOp/CppInterOp.cpp:4368: Calling constructor for 'unique_ptr<char[], std::default_delete<char[]>>'

    std::unique_ptr<char[]> content(new char[bufsize + 1]);
                            ^

/usr/include/c++/13/bits/unique_ptr.h:603: Calling constructor for '__uniq_ptr_data<char, std::default_delete<char[]>, true, true>'

	: _M_t(__p)
   ^

/usr/include/c++/13/bits/unique_ptr.h:603: Passing '' via 1st parameter '__p'

	: _M_t(__p)
        ^

/usr/include/c++/13/bits/unique_ptr.h:603: Calling constructor for '__uniq_ptr_impl<char, std::default_delete<char[]>>'

	: _M_t(__p)
   ^

/usr/include/c++/13/bits/unique_ptr.h:175: Calling '__uniq_ptr_impl::_M_ptr'

      __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
                                              ^

/usr/include/c++/13/bits/unique_ptr.h:196: Calling 'get<0UL, char *, std::default_delete<char[]>>'

      pointer&   _M_ptr() noexcept { return std::get<0>(_M_t); }
                                            ^

/usr/include/c++/13/tuple:1803: Calling '__get_helper<0UL, char *, std::default_delete<char[]>>'

    { return std::__get_helper<__i>(__t); }
             ^

/usr/include/c++/13/tuple:1787: Calling '_Tuple_impl::_M_head'

    { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
             ^

/usr/include/c++/13/tuple:268: Calling '_Head_base::_M_head'

      _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
                                                  ^

/usr/include/c++/13/tuple:268: Returning from '_Head_base::_M_head'

      _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
                                                  ^

/usr/include/c++/13/tuple:1787: Returning from '_Tuple_impl::_M_head'

    { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
             ^

/usr/include/c++/13/tuple:1803: Returning from '__get_helper<0UL, char *, std::default_delete<char[]>>'

    { return std::__get_helper<__i>(__t); }
             ^

/usr/include/c++/13/bits/unique_ptr.h:196: Returning from 'get<0UL, char *, std::default_delete<char[]>>'

      pointer&   _M_ptr() noexcept { return std::get<0>(_M_t); }
                                            ^

/usr/include/c++/13/bits/unique_ptr.h:175: Returning from '__uniq_ptr_impl::_M_ptr'

      __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
                                              ^

/usr/include/c++/13/bits/unique_ptr.h:175: The value of '__p' is assigned to 'content._M_t._M_t._M_head_impl'

      __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
                                              ^

/usr/include/c++/13/bits/unique_ptr.h:603: Returning from constructor for '__uniq_ptr_impl<char, std::default_delete<char[]>>'

	: _M_t(__p)
   ^

/usr/include/c++/13/bits/unique_ptr.h:603: Returning from constructor for '__uniq_ptr_data<char, std::default_delete<char[]>, true, true>'

	: _M_t(__p)
   ^

lib/CppInterOp/CppInterOp.cpp:4368: Returning from constructor for 'unique_ptr<char[], std::default_delete<char[]>>'

    std::unique_ptr<char[]> content(new char[bufsize + 1]);
                            ^

lib/CppInterOp/CppInterOp.cpp:4371: Taking false branch

    if (fseek(m_TempFile, 0L, SEEK_SET) != 0)
    ^

lib/CppInterOp/CppInterOp.cpp:4375: The 1st argument to 'fread' is a buffer with size 0 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 1) times the 3rd argument (which is 18446744073709551615)

    size_t newLen = fread(content.get(), sizeof(char), bufsize, m_TempFile);
                    ^

struct FileDeleter {
void operator()(FILE* f /* owns */) {
if (f)
fclose(f);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: calling legacy resource function without passing a 'gsl::owner<>' [cppcoreguidelines-owning-memory]

        fclose(f);
        ^

"with in-process JIT execution.\n";
io_ctx->outOfProcess = false;
} else {
stdin_fd = fileno(io_ctx->stdin_file.get());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "fileno" is directly included [misc-include-cleaner]

lib/CppInterOp/CppInterOpInterpreter.h:25:

- #if CLANG_VERSION_MAJOR >= 19
+ #include <stdio.h>
+ #if CLANG_VERSION_MAJOR >= 19


return std::unique_ptr<Interpreter>(new Interpreter(std::move(CI)));
return std::unique_ptr<Interpreter>(
new Interpreter(std::move(CI), std::move(io_ctx)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: use std::make_unique instead [modernize-make-unique]

Suggested change
new Interpreter(std::move(CI), std::move(io_ctx)));
return std::make_unique<Interpreter>(
std::move(CI), std::move(io_ctx));

operator const clang::Interpreter&() const { return *inner; }
operator clang::Interpreter&() { return *inner; }

bool isOutOfProcess() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'isOutOfProcess' should be marked [[nodiscard]] [modernize-use-nodiscard]

Suggested change
bool isOutOfProcess() const {
[[nodiscard]] bool isOutOfProcess() const {

return llvm::orc::ExecutorAddr(*AddrOrErr);
}

pid_t getOutOfProcessExecutorPID() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'getOutOfProcessExecutorPID' should be marked [[nodiscard]] [modernize-use-nodiscard]

Suggested change
pid_t getOutOfProcessExecutorPID() const {
[[nodiscard]] pid_t getOutOfProcessExecutorPID() const {

return llvm::orc::ExecutorAddr(*AddrOrErr);
}

pid_t getOutOfProcessExecutorPID() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: method 'getOutOfProcessExecutorPID' can be made static [readability-convert-member-functions-to-static]

Suggested change
pid_t getOutOfProcessExecutorPID() const {
static pid_t getOutOfProcessExecutorPID() {

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

return llvm::orc::ExecutorAddr(*AddrOrErr);
}

pid_t getOutOfProcessExecutorPID() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "pid_t" is directly included [misc-include-cleaner]

lib/CppInterOp/CppInterOpInterpreter.h:25:

- #if CLANG_VERSION_MAJOR >= 19
+ #include <sched.h>
+ #if CLANG_VERSION_MAJOR >= 19

if (llvm::sys::RunningOnValgrind())
GTEST_SKIP() << "XFAIL due to Valgrind report";
TestUtils::CreateInterpreter();
pid_t pid = Cpp::GetExecutorPID();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "pid_t" is directly included [misc-include-cleaner]

unittests/CppInterOp/FunctionReflectionTest.cpp:15:

- #include <string>
+ #include <sched.h>
+ #include <string>

testing::internal::CaptureStderr();
Cpp::Process("int c = 12;");
cerrs = testing::internal::GetCapturedStderr();
std::cout << cerrs << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]

Suggested change
std::cout << cerrs << std::endl;
std::cout << cerrs << '\n';

testing::internal::CaptureStderr();
Cpp::Process("int c = 12;");
cerrs = testing::internal::GetCapturedStderr();
std::cout << cerrs << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::cout" is directly included [misc-include-cleaner]

unittests/CppInterOp/InterpreterTest.cpp:2:

+ #include <iostream>

testing::internal::CaptureStderr();
Cpp::Process("int c = 12;");
cerrs = testing::internal::GetCapturedStderr();
std::cout << cerrs << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::endl" is directly included [misc-include-cleaner]

unittests/CppInterOp/InterpreterTest.cpp:2:

+ #include <ostream>

}
}

TInterp_t
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "TInterp_t" is directly included [misc-include-cleaner]

unittests/CppInterOp/Utils.cpp:13:

- #include <string>
+ #include <clang-c/CXCppInterOp.h>
+ #include <string>

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

GTEST_SKIP() << "XFAIL due to Valgrind report";
std::vector<const char*> interpreter_args = { "-include", "new" };
auto* I = Cpp::CreateInterpreter(interpreter_args);
std::vector<const char*> interpreter_args = {"-include", "new"};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::vector" is directly included [misc-include-cleaner]

unittests/CppInterOp/InterpreterTest.cpp:2:

+ #include <vector>

TEST(InterpreterTest, CreateInterpreterCAPI) {
const char* argv[] = {"-std=c++17"};
auto *CXI = clang_createInterpreter(argv, 1);
auto* CXI = clang_createInterpreter(argv, 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay]

  auto* CXI = clang_createInterpreter(argv, 1);
                                      ^

#endif
const char* argv[] = {"-fsyntax-only", "-Xclang", "-invalid-plugin"};
auto *CXI = clang_createInterpreter(argv, 3);
auto* CXI = clang_createInterpreter(argv, 3);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead [cppcoreguidelines-pro-bounds-array-to-pointer-decay]

  auto* CXI = clang_createInterpreter(argv, 3);
                                      ^

Cpp::GetIncludePaths(includes);
EXPECT_NE(std::find(includes.begin(), includes.end(), "/non/existent/"),
std::end(includes));
std::end(includes));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "std::end" is directly included [misc-include-cleaner]

unittests/CppInterOp/InterpreterTest.cpp:2:

+ #include <iterator>

@mcbarton
Copy link
Collaborator

Before pushing commits to this PR please either ping me, or delete caches as they are made. This PR has caused a large number of llvm cached builds to be deleted on main, which in turn has required multiple PRs workflow runs to be stopped while the cache is rebuilt.

valgrind --show-error-list=yes --track-origins=yes --error-exitcode=1 unittests/CppInterOp/CppInterOpTests/unittests/bin/${{ env.BUILD_TYPE }}/CppInterOpTests
fi
if [[ "${{ matrix.oop-jit }}" == "On" ]]; then
./unittests/CppInterOp/CppInterOpTests/unittests/bin/${{ env.BUILD_TYPE }}/CppInterOpTests --use-oop-jit
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This --use-oop-jit option should be taken care of in the cmakelists.txt

add_test(NAME cppinterop-${name} COMMAND ${name})
by changing the executed command based on whether LLVM_BUILT_WITH_OOP_JIT is on or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when LLVM_BUILT_WITH_OOP_JIT is on, the tests need to be run two times. First in-process and second time out-of-process. It does make easy for the users to run tests explicitly by just passing a flag.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no reason for the user to need to run the tests manually with this flag. You can make the cmake execute two commands (once with the flag and once without), when LLVM_BUILT_WITH_OOP_JIT is on. @vgvassilev What is your opinion on this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we resolved the static compilation flag already. It should be a runtime flag that we pass to the interpreter and in this way we can make this a test thing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add a new test as following:

if (LLVM_BUILT_WITH_OOP_JIT)
  add_test(NAME cppinterop-oop-${name} COMMAND ${name} --use-oop-jit)
endif()

Then in the CI yaml, it becomes

if [[ "${{ matrix.oop-jit }}" == "On" ]]; then
  cmake --build . --target check-cppinterop-oop --parallel ${{ env.ncpus }}
fi

I thought we resolved the static compilation flag already. It should be a runtime flag that we pass to the interpreter

Because we have a patch on top of LLVM, we do it conditionally based on whether the patch is applied (LLVM_BUILT_WITH_OOP_JIT is defined or not). We will not require this flag/macro when LLVM starts supporting this natively.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you add the

if (LLVM_BUILT_WITH_OOP_JIT)
  add_test(NAME cppinterop-oop-${name} COMMAND ${name} --use-oop-jit)
endif()

here as suggested

add_test(NAME cppinterop-${name} COMMAND ${name})
, then you don't need to run a check-cppinterop-oop command. It should pick up these tests as part of check-cppinterop already (see
add_custom_target(check-cppinterop COMMAND ${CMAKE_CTEST_COMMAND} -V --build-config $<CONFIG>
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we can make this a pure runtime thing by calling clang-repl --host-supports-out-of-process-jit or even better, construct an interpreter with out-of-process flags and run some code. If successful we have oop support: https://github.com/llvm/llvm-project/blob/2cb530868ca1d6e66e950f4b247b0905ee95d7eb/clang/test/lit.cfg.py#L120

This must not leak outside of a simple test fixture..

CMakeLists.txt Outdated
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})

string(REGEX REPLACE "/build/lib/cmake/llvm$" "" LLVM_SOURCE_DIR "${LLVM_DIR}")
Copy link
Collaborator

@mcbarton mcbarton Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it is convention to name the build folder build, it doesn't necessarily have to be.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I believe you can just strip till /lib, and that would be fine. I sometimes build stuff in bin/.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

}

#ifndef _WIN32
pid_t getOutOfProcessExecutorPID() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: function 'getOutOfProcessExecutorPID' should be marked [[nodiscard]] [modernize-use-nodiscard]

Suggested change
pid_t getOutOfProcessExecutorPID() const {
[[nodiscard]] pid_t getOutOfProcessExecutorPID() const {

}

#ifndef _WIN32
pid_t getOutOfProcessExecutorPID() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: method 'getOutOfProcessExecutorPID' can be made static [readability-convert-member-functions-to-static]

Suggested change
pid_t getOutOfProcessExecutorPID() const {
static pid_t getOutOfProcessExecutorPID() {

}

#ifndef _WIN32
pid_t getOutOfProcessExecutorPID() const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "pid_t" is directly included [misc-include-cleaner]

lib/CppInterOp/CppInterOpInterpreter.h:25:

- #if CLANG_VERSION_MAJOR >= 19
+ #include <sched.h>
+ #if CLANG_VERSION_MAJOR >= 19

Copy link

codecov bot commented Oct 2, 2025

Codecov Report

❌ Patch coverage is 74.33628% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.45%. Comparing base (fe3de3c) to head (cfbb303).

Files with missing lines Patch % Lines
lib/CppInterOp/CppInterOpInterpreter.h 67.39% 15 Missing ⚠️
lib/CppInterOp/Compatibility.h 58.62% 12 Missing ⚠️
lib/CppInterOp/CppInterOp.cpp 94.73% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #717      +/-   ##
==========================================
- Coverage   81.03%   80.45%   -0.59%     
==========================================
  Files           9        9              
  Lines        4214     4307      +93     
==========================================
+ Hits         3415     3465      +50     
- Misses        799      842      +43     
Files with missing lines Coverage Δ
include/CppInterOp/CppInterOp.h 95.55% <ø> (ø)
lib/CppInterOp/CppInterOp.cpp 88.67% <94.73%> (-0.13%) ⬇️
lib/CppInterOp/Compatibility.h 77.53% <58.62%> (-14.50%) ⬇️
lib/CppInterOp/CppInterOpInterpreter.h 83.89% <67.39%> (-4.19%) ⬇️
Files with missing lines Coverage Δ
include/CppInterOp/CppInterOp.h 95.55% <ø> (ø)
lib/CppInterOp/CppInterOp.cpp 88.67% <94.73%> (-0.13%) ⬇️
lib/CppInterOp/Compatibility.h 77.53% <58.62%> (-14.50%) ⬇️
lib/CppInterOp/CppInterOpInterpreter.h 83.89% <67.39%> (-4.19%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.


#include "llvm/Support/Error.h"

#ifdef LLVM_BUILT_WITH_OOP_JIT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this to be a separate build flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The oop changes only work with clang20+my_patch. For clang19, clang20(normal), clang18, it won't work. That's why I had this flag enabled.

Do you want me to have conditional check based on LLVM_VERSION?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that’s probably a good idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same for the tests. We run in both modes all tests if we are in the right llvm version.

Copy link
Collaborator

@Vipul-Cariappa Vipul-Cariappa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please look at the comments.

valgrind --show-error-list=yes --track-origins=yes --error-exitcode=1 unittests/CppInterOp/CppInterOpTests/unittests/bin/${{ env.BUILD_TYPE }}/CppInterOpTests
fi
if [[ "${{ matrix.oop-jit }}" == "On" ]]; then
./unittests/CppInterOp/CppInterOpTests/unittests/bin/${{ env.BUILD_TYPE }}/CppInterOpTests --use-oop-jit
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add a new test as following:

if (LLVM_BUILT_WITH_OOP_JIT)
  add_test(NAME cppinterop-oop-${name} COMMAND ${name} --use-oop-jit)
endif()

Then in the CI yaml, it becomes

if [[ "${{ matrix.oop-jit }}" == "On" ]]; then
  cmake --build . --target check-cppinterop-oop --parallel ${{ env.ncpus }}
fi

I thought we resolved the static compilation flag already. It should be a runtime flag that we pass to the interpreter

Because we have a patch on top of LLVM, we do it conditionally based on whether the patch is applied (LLVM_BUILT_WITH_OOP_JIT is defined or not). We will not require this flag/macro when LLVM starts supporting this natively.

CMakeLists.txt Outdated
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})

string(REGEX REPLACE "/build/lib/cmake/llvm$" "" LLVM_SOURCE_DIR "${LLVM_DIR}")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I believe you can just strip till /lib, and that would be fine. I sometimes build stuff in bin/.

Interp->process(R"(
#include <stdio.h>
printf("%s\n", "Hello World");
fflush(stdout);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check if it works without fflush?
You have the setvbuf right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it does not work without fflush.

Comment on lines +4298 to +4316
StreamCaptureInfo(int FD) : mode(FD) {
#endif
#if !defined(CPPINTEROP_USE_CLING) && !defined(_WIN32)
auto& I = getInterp(NULLPTR);
if (I.isOutOfProcess() && FD == STDOUT_FILENO) {
m_TempFile = I.getTempFileForOOP(FD);
::fflush(m_TempFile);
m_FD = fileno(m_TempFile);
m_OwnsFile = false;
} else {
m_TempFile = tmpfile();
m_FD = FD;
m_OwnsFile = true;
}
#else
m_TempFile = tmpfile();
m_FD = FD;
m_OwnsFile = true;
(void)mode;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to change anything for the current implementation of redirection.
You are currently redirecting stdout and stderr to the parent process's stdout and stderr. So, the current implementation of StreamCaptureInfo should, "in theory", just work out of the box. You will also be able to remove the Interpreter::FileDeleter and Interpreter::IOContext in that case.
stdin is a different matter, and I am not sure how that works. But this class (StreamCaptureInfo) does not deal with stdin anyway.

Let me know if I am wrong about not needing any changes here. Or you think this changes are required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I revert the changes that I did in StreamCaptureInfo, then the redirection will not work.

  1. Streams.StreamsRedirectJIT fails.
  2. xeus-cpp does not print output.
TEST(Streams, StreamRedirectJIT) {
#ifdef EMSCRIPTEN
  GTEST_SKIP() << "Test fails for Emscipten builds";
#endif
  if (llvm::sys::RunningOnValgrind())
    GTEST_SKIP() << "XFAIL due to Valgrind report";
#ifdef _WIN32
  GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
#endif
#ifdef CPPINTEROP_USE_CLING
  GTEST_SKIP() << "Test fails for cling builds";
#endif
  TestUtils::CreateInterpreter();

  Cpp::BeginStdStreamCapture(Cpp::kStdOut);
  Cpp::BeginStdStreamCapture(Cpp::kStdErr);
  Interp->process(R"(
    #include <stdio.h>
    printf("%s\n", "Hello World");
    fflush(stdout);
    )");
  std::string CapturedStringErr = Cpp::EndStdStreamCapture();
  std::string CapturedStringOut = Cpp::EndStdStreamCapture();

  EXPECT_STREQ(CapturedStringOut.c_str(), "Hello World\n");
  EXPECT_STREQ(CapturedStringErr.c_str(), "");
}

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

}
}

TInterp_t
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "TInterp_t" is directly included [misc-include-cleaner]

unittests/CppInterOp/Utils.cpp:15:

- #include <string>
+ #include <clang-c/CXCppInterOp.h>
+ #include <string>

@mcbarton
Copy link
Collaborator

mcbarton commented Oct 5, 2025

Codecov Report

❌ Patch coverage is 74.33628% with 29 lines in your changes missing coverage. Please review. ✅ Project coverage is 80.45%. Comparing base (fe3de3c) to head (cfbb303).
Files with missing lines Patch % Lines
lib/CppInterOp/CppInterOpInterpreter.h 67.39% 15 Missing ⚠️
lib/CppInterOp/Compatibility.h 58.62% 12 Missing ⚠️
lib/CppInterOp/CppInterOp.cpp 94.73% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #717      +/-   ##
==========================================
- Coverage   81.03%   80.45%   -0.59%     
==========================================
  Files           9        9              
  Lines        4214     4307      +93     
==========================================
+ Hits         3415     3465      +50     
- Misses        799      842      +43     

Files with missing lines Coverage Δ
include/CppInterOp/CppInterOp.h 95.55% <ø> (ø)
lib/CppInterOp/CppInterOp.cpp 88.67% <94.73%> (-0.13%) ⬇️
lib/CppInterOp/Compatibility.h 77.53% <58.62%> (-14.50%) ⬇️
lib/CppInterOp/CppInterOpInterpreter.h 83.89% <67.39%> (-4.19%) ⬇️
Files with missing lines Coverage Δ
include/CppInterOp/CppInterOp.h 95.55% <ø> (ø)
lib/CppInterOp/CppInterOp.cpp 88.67% <94.73%> (-0.13%) ⬇️
lib/CppInterOp/Compatibility.h 77.53% <58.62%> (-14.50%) ⬇️
lib/CppInterOp/CppInterOpInterpreter.h 83.89% <67.39%> (-4.19%) ⬇️
🚀 New features to boost your workflow:

The tests are not covering over 1/4 of this patch. @kr-2003 can you improve the coverage?

Comment on lines +319 to +335
```

On Windows execute

```powershell
mkdir CppInterOp\build\
cd CppInterOp\build\
```

```powershell
cmake -DLLVM_DIR=$env:LLVM_DIR\build\lib\cmake\llvm -DClang_DIR=$env:LLVM_DIR\build\lib\cmake\clang -DCMAKE_INSTALL_PREFIX=$env:CPPINTEROP_DIR ..
cmake --build . --target install --parallel $env:ncpus
```

on Windows. If alternatively you would like to install CppInterOp with Cling then execute the following commands on Linux and MacOS.

```bash
Copy link
Collaborator

@mcbarton mcbarton Oct 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this added Windows related text. It makes 0 sense. This is not in the Windows section, and is text that is already contained in the readme in the Windows section

<summary><strong>Windows</strong></summary>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants