Skip to content
7 changes: 5 additions & 2 deletions include/CppInterOp/CppInterOp.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#endif
#endif

namespace Cpp {
namespace CppImpl {
using TCppIndex_t = size_t;
using TCppScope_t = void*;
using TCppConstScope_t = const void*;
Expand Down Expand Up @@ -945,6 +945,9 @@ CPPINTEROP_API int Undo(unsigned N = 1);
CPPINTEROP_API pid_t GetExecutorPID();
#endif

} // end namespace Cpp
} // namespace CppImpl

#ifndef CPPINTEROP_DISPATCH_H
namespace Cpp = CppImpl;
#endif
#endif // CPPINTEROP_CPPINTEROP_H
254 changes: 254 additions & 0 deletions include/CppInterOp/Dispatch.h

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions lib/CppInterOp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ endif(LLVM_LINK_LLVM_DYLIB)
add_llvm_library(clangCppInterOp
DISABLE_LLVM_LINK_LLVM_DYLIB
CppInterOp.cpp
Dispatch.cpp
CXCppInterOp.cpp
${DLM}
LINK_LIBS
Expand Down
20 changes: 10 additions & 10 deletions lib/CppInterOp/CXCppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,9 @@ void clang_Interpreter_addIncludePath(CXInterpreter I, const char* dir) {
getInterpreter(I)->AddIncludePath(dir);
}

namespace Cpp {
namespace CppImpl {
int Declare(compat::Interpreter& interp, const char* code, bool silent);
} // namespace Cpp
} // namespace CppImpl

enum CXErrorCode clang_Interpreter_declare(CXInterpreter I, const char* code,
bool silent) {
Expand Down Expand Up @@ -406,11 +406,11 @@ CXString clang_Interpreter_searchLibrariesForSymbol(CXInterpreter I,
mangled_name, search_system));
}

namespace Cpp {
namespace CppImpl {
bool InsertOrReplaceJitSymbol(compat::Interpreter& I,
const char* linker_mangled_name,
uint64_t address);
} // namespace Cpp
} // namespace CppImpl

bool clang_Interpreter_insertOrReplaceJitSymbol(CXInterpreter I,
const char* linker_mangled_name,
Expand Down Expand Up @@ -556,12 +556,12 @@ bool clang_existsFunctionTemplate(const char* name, CXScope parent) {
return true;
}

namespace Cpp {
namespace CppImpl {
TCppScope_t InstantiateTemplate(compat::Interpreter& I, TCppScope_t tmpl,
const TemplateArgInfo* template_args,
size_t template_args_size,
bool instantiate_body = false);
} // namespace Cpp
} // namespace CppImpl

CXScope clang_instantiateTemplate(CXScope tmpl,
CXTemplateArgInfo* template_args,
Expand All @@ -584,10 +584,10 @@ CXObject clang_allocate(unsigned int n) { return ::operator new(n); }

void clang_deallocate(CXObject address) { ::operator delete(address); }

namespace Cpp {
namespace CppImpl {
void* Construct(compat::Interpreter& interp, TCppScope_t scope,
void* arena /*=nullptr*/, TCppIndex_t count);
} // namespace Cpp
} // namespace CppImpl

CXObject clang_construct(CXScope scope, void* arena, size_t count) {
return Cpp::Construct(*getInterpreter(scope),
Expand All @@ -600,10 +600,10 @@ void clang_invoke(CXScope func, void* result, void** args, size_t n,
.Invoke(result, {args, n}, self);
}

namespace Cpp {
namespace CppImpl {
bool Destruct(compat::Interpreter& interp, TCppObject_t This,
const clang::Decl* Class, bool withFree, size_t nary);
} // namespace Cpp
} // namespace CppImpl

bool clang_destruct(CXObject This, CXScope S, bool withFree, size_t nary) {
return Cpp::Destruct(*getInterpreter(S), This, getDecl(S), withFree, nary);
Expand Down
10 changes: 5 additions & 5 deletions lib/CppInterOp/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
#include <unistd.h>
#endif // WIN32

// Runtime symbols required if the library using JIT (Cpp::Evaluate) does not
// link to llvm
// Runtime symbols required if the library using JIT (Cpp::Evaluate) does
// not link to llvm
#if !defined(CPPINTEROP_USE_CLING) && !defined(EMSCRIPTEN)
struct __clang_Interpreter_NewTag {
} __ci_newtag;
Expand All @@ -125,7 +125,7 @@ void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*,
#endif
#endif // CPPINTEROP_USE_CLING

namespace Cpp {
namespace CppImpl {

using namespace clang;
using namespace llvm;
Expand Down Expand Up @@ -3175,7 +3175,7 @@ static JitCall::DestructorCall make_dtor_wrapper(compat::Interpreter& interp,
return (JitCall::DestructorCall)F;
}
#undef DEBUG_TYPE
} // namespace
} // namespace CppImpl
// End of JitCall Helper Functions

CPPINTEROP_API JitCall MakeFunctionCallable(TInterp_t I,
Expand Down Expand Up @@ -4290,4 +4290,4 @@ pid_t GetExecutorPID() {

#endif

} // end namespace Cpp
} // namespace CppImpl
20 changes: 20 additions & 0 deletions lib/CppInterOp/Dispatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <CppInterOp/Dispatch.h>

#include <string>
#include <unordered_map>
Copy link
Contributor

Choose a reason for hiding this comment

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

warning: included header string is not used directly [misc-include-cleaner]

Suggested change
#include <unordered_map>
#include <unordered_map>


static const std::unordered_map<std::string_view, CppFnPtrTy>
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::string_view" is directly included [misc-include-cleaner]

lib/CppInterOp/Dispatch.cpp:3:

- #include <unordered_map>
+ #include <string_view>
+ #include <unordered_map>

DispatchMap = {
#define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)},
CPPINTEROP_API_TABLE
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 C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]

        CPPINTEROP_API_TABLE
        ^
Additional context

include/CppInterOp/Dispatch.h:44: expanded from macro 'CPPINTEROP_API_TABLE'

  DISPATCH_API(CreateInterpreter, decltype(&CppImpl::CreateInterpreter))                  \
  ^

lib/CppInterOp/Dispatch.cpp:7: expanded from macro 'DISPATCH_API'

#define DISPATCH_API(name, type) {#name, (CppFnPtrTy) static_cast<type>(&CppImpl::name)},
                                         ^

#undef DISPATCH_API
};

static inline CppFnPtrTy _cppinterop_get_proc_address(const char* funcName) {
Copy link
Contributor

Choose a reason for hiding this comment

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

warning: declaration uses identifier '_cppinterop_get_proc_address', which is reserved in the global namespace [bugprone-reserved-identifier]

static inline CppFnPtrTy _cppinterop_get_proc_address(const char* funcName) {
                         ^

this fix will not be applied because it overlaps with another fix

Copy link
Contributor

Choose a reason for hiding this comment

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

warning: invalid case style for function '_cppinterop_get_proc_address' [readability-identifier-naming]

static inline CppFnPtrTy _cppinterop_get_proc_address(const char* funcName) {
                         ^

this fix will not be applied because it overlaps with another fix

auto it = DispatchMap.find(funcName);
return (it != DispatchMap.end()) ? it->second : nullptr;
}

void (*CppGetProcAddress(const unsigned char* procName))(void) {
return _cppinterop_get_proc_address(reinterpret_cast<const char*>(procName));
}
12 changes: 11 additions & 1 deletion unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,20 @@ add_dependencies(CppInterOpUnitTests clangCppInterOp)

set (TIMEOUT_VALUE 2400)
function(add_cppinterop_unittest name)
add_executable(${name} EXCLUDE_FROM_ALL ${ARGN})
list(REMOVE_ITEM ARGN "TEST_DISPATCH")
set(SOURCE_FILES ${ARGN})
add_executable(${name} EXCLUDE_FROM_ALL ${SOURCE_FILES})
add_dependencies(CppInterOpUnitTests ${name})
target_include_directories(${name} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${GTEST_INCLUDE_DIR})
set_property(TARGET ${name} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

# Check if the test executable should run in the API dispatch mode.
if("TEST_DISPATCH" IN_LIST ARGV)
target_compile_definitions(${name} PRIVATE
ENABLE_DISPATCH_TESTS
CPPINTEROP_LIB_DIR="${CMAKE_BINARY_DIR}/lib/libclangCppInterOp${CMAKE_SHARED_LIBRARY_SUFFIX}"
)
endif()
if(WIN32)
target_link_libraries(${name} PUBLIC ${ARG_LIBRARIES} ${gtest_libs})
set_property(TARGET ${name} APPEND_STRING PROPERTY LINK_FLAGS "${MSVC_EXPORTS}")
Expand Down
30 changes: 30 additions & 0 deletions unittests/CppInterOp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ add_cppinterop_unittest(CppInterOpTests
${EXTRA_TEST_SOURCE_FILES}
)

# Run tests with API Dispatch mode. Requires shared library build.
if(BUILD_SHARED_LIBS)
add_cppinterop_unittest(CppInterOpDispatchTests
EnumReflectionTest.cpp
FunctionReflectionTest.cpp
InterpreterTest.cpp
JitTest.cpp
ScopeReflectionTest.cpp
TypeReflectionTest.cpp
Utils.cpp
VariableReflectionTest.cpp
${EXTRA_TEST_SOURCE_FILES}
TEST_DISPATCH
)
endif()

if(EMSCRIPTEN)
string(REPLACE "@" "@@" ESCAPED_SYSROOT_PATH "${SYSROOT_PATH}")
# Explanation of Emscripten-specific link flags for CppInterOpTests:
Expand Down Expand Up @@ -65,12 +81,23 @@ target_link_libraries(CppInterOpTests
PRIVATE
clangCppInterOp
)
# We only link the Dispatch tests for the necessary LLVM and Clang symbols
# referenced by CppInterOpInterpreter.h
target_link_libraries(CppInterOpDispatchTests
PRIVATE
clangCppInterOp
)

set_output_directory(CppInterOpTests
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES}
LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES}
)

set_output_directory(CppInterOpDispatchTests
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES}
LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${EXTRA_PATH_TEST_BINARIES}
)

if(NOT WIN32)
set_source_files_properties(VariableReflectionTest.cpp PROPERTIES COMPILE_FLAGS
"-Wno-pedantic"
Expand All @@ -81,6 +108,7 @@ set_source_files_properties(InterpreterTest.cpp PROPERTIES COMPILE_DEFINITIONS
"LLVM_BINARY_DIR=\"${LLVM_BINARY_DIR}\""
)
export_executable_symbols(CppInterOpTests)
export_executable_symbols(CppInterOpDispatchTests)

unset(LLVM_LINK_COMPONENTS)

Expand Down Expand Up @@ -119,9 +147,11 @@ endif()
if (EMSCRIPTEN)
if (BUILD_SHARED_LIBS)
target_compile_definitions(CppInterOpTests PRIVATE "EMSCRIPTEN_SHARED_LIBRARY")
target_compile_definitions(CppInterOpDispatchTests PRIVATE "EMSCRIPTEN_SHARED_LIBRARY")
target_compile_definitions(DynamicLibraryManagerTests PRIVATE "EMSCRIPTEN_SHARED_LIBRARY")
else()
target_compile_definitions(CppInterOpTests PRIVATE "EMSCRIPTEN_STATIC_LIBRARY")
target_compile_definitions(CppInterOpDispatchTests PRIVATE "EMSCRIPTEN_STATIC_LIBRARY")
target_compile_definitions(DynamicLibraryManagerTests PRIVATE "EMSCRIPTEN_STATIC_LIBRARY")
endif()
endif()
Expand Down
8 changes: 4 additions & 4 deletions unittests/CppInterOp/CUDATest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static bool HasCudaSDK() {
if (!Cpp::CreateInterpreter({}, {"--cuda"}))
return false;
return Cpp::Declare("__global__ void test_func() {}"
"test_func<<<1,1>>>();") == 0;
"test_func<<<1,1>>>();", false) == 0;
};
static bool hasCuda = supportsCudaSDK();
return hasCuda;
Expand All @@ -35,9 +35,9 @@ static bool HasCudaRuntime() {
if (!Cpp::CreateInterpreter({}, {"--cuda"}))
return false;
if (Cpp::Declare("__global__ void test_func() {}"
"test_func<<<1,1>>>();"))
"test_func<<<1,1>>>();", false))
return false;
intptr_t result = Cpp::Evaluate("(bool)cudaGetLastError()");
intptr_t result = Cpp::Evaluate("(bool)cudaGetLastError()", nullptr);
return !(bool)result;
};
static bool hasCuda = supportsCuda();
Expand Down Expand Up @@ -65,7 +65,7 @@ TEST(CUDATest, CUDAH) {
GTEST_SKIP() << "Skipping CUDA tests as CUDA SDK not found";

Cpp::CreateInterpreter({}, {"--cuda"});
bool success = !Cpp::Declare("#include <cuda.h>");
bool success = !Cpp::Declare("#include <cuda.h>", false);
EXPECT_TRUE(success);
}

Expand Down
4 changes: 2 additions & 2 deletions unittests/CppInterOp/DynamicLibraryManagerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ std::string GetExecutablePath(const char* Argv0) {
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}

TYPED_TEST(CppInterOpTest, DynamicLibraryManagerTestSanity) {
TYPED_TEST(CPPINTEROP_TEST_MODE, DynamicLibraryManager_Sanity) {
#ifdef EMSCRIPTEN
GTEST_SKIP() << "Test fails for Emscipten builds";
#endif
Expand Down Expand Up @@ -69,7 +69,7 @@ TYPED_TEST(CppInterOpTest, DynamicLibraryManagerTestSanity) {
// EXPECT_FALSE(Cpp::GetFunctionAddress("ret_zero"));
}

TYPED_TEST(CppInterOpTest, DynamicLibraryManagerTestBasicSymbolLookup) {
TYPED_TEST(CPPINTEROP_TEST_MODE, DynamicLibraryManager_BasicSymbolLookup) {
#ifndef EMSCRIPTEN
GTEST_SKIP() << "This test is only intended for Emscripten builds.";
#else
Expand Down
18 changes: 9 additions & 9 deletions unittests/CppInterOp/EnumReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ using namespace TestUtils;
using namespace llvm;
using namespace clang;

TYPED_TEST(CppInterOpTest, EnumReflectionTestIsEnumType) {
TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_IsEnumType) {
std::vector<Decl *> Decls;
std::string code = R"(
enum class E {
Expand Down Expand Up @@ -40,7 +40,7 @@ TYPED_TEST(CppInterOpTest, EnumReflectionTestIsEnumType) {
EXPECT_TRUE(Cpp::IsEnumType(Cpp::GetVariableType(Decls[5])));
}

TYPED_TEST(CppInterOpTest, EnumReflectionTestGetIntegerTypeFromEnumScope) {
TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetIntegerTypeFromEnumScope) {
std::vector<Decl *> Decls;
std::string code = R"(
enum Switch : bool {
Expand Down Expand Up @@ -90,7 +90,7 @@ TYPED_TEST(CppInterOpTest, EnumReflectionTestGetIntegerTypeFromEnumScope) {
EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetIntegerTypeFromEnumScope(Decls[5])),"NULL TYPE");
}

TYPED_TEST(CppInterOpTest, EnumReflectionTestGetIntegerTypeFromEnumType) {
TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetIntegerTypeFromEnumType) {
std::vector<Decl *> Decls;
std::string code = R"(
enum Switch : bool {
Expand Down Expand Up @@ -150,7 +150,7 @@ TYPED_TEST(CppInterOpTest, EnumReflectionTestGetIntegerTypeFromEnumType) {
EXPECT_EQ(get_int_type_from_enum_var(Decls[11]), "NULL TYPE"); // When a non Enum Type variable is used
}

TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnumConstants) {
TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetEnumConstants) {
std::vector<Decl *> Decls;
std::string code = R"(
enum ZeroEnum {
Expand Down Expand Up @@ -194,7 +194,7 @@ TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnumConstants) {
EXPECT_EQ(Cpp::GetEnumConstants(Decls[5]).size(), 0);
}

TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnumConstantType) {
TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetEnumConstantType) {
std::vector<Decl *> Decls;
std::string code = R"(
enum Enum0 {
Expand Down Expand Up @@ -225,7 +225,7 @@ TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnumConstantType) {
EXPECT_EQ(get_enum_constant_type_as_str(nullptr), "NULL TYPE");
}

TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnumConstantValue) {
TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetEnumConstantValue) {
std::vector<Decl *> Decls;
std::string code = R"(
enum Counter {
Expand Down Expand Up @@ -253,7 +253,7 @@ TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnumConstantValue) {
EXPECT_EQ(Cpp::GetEnumConstantValue(Decls[1]), 0); // Checking value of non enum constant
}

TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnums) {
TYPED_TEST(CPPINTEROP_TEST_MODE, EnumReflection_GetEnums) {
std::string code = R"(
enum Color {
Red,
Expand Down Expand Up @@ -302,8 +302,8 @@ TYPED_TEST(CppInterOpTest, EnumReflectionTestGetEnums) {
Cpp::TCppScope_t myClass_scope = Cpp::GetScope("myClass", 0);
Cpp::TCppScope_t unsupported_scope = Cpp::GetScope("myVariable", 0);

Cpp::GetEnums(globalscope,enumNames1);
Cpp::GetEnums(Animals_scope,enumNames2);
Cpp::GetEnums(globalscope, enumNames1);
Cpp::GetEnums(Animals_scope, enumNames2);
Cpp::GetEnums(myClass_scope, enumNames3);
Cpp::GetEnums(unsupported_scope, enumNames4);

Expand Down
Loading
Loading