diff --git a/include/clang/Interpreter/CppInterOp.h b/include/clang/Interpreter/CppInterOp.h index 12e16eecb..cc5f87ab6 100644 --- a/include/clang/Interpreter/CppInterOp.h +++ b/include/clang/Interpreter/CppInterOp.h @@ -35,6 +35,14 @@ namespace Cpp { using TCppFuncAddr_t = void*; using TInterp_t = void*; using TCppObject_t = void*; + + struct TemplateArgInfo { + TCppType_t m_Type; + const char* m_IntegralValue; + TemplateArgInfo(TCppScope_t type, const char* integral_value = nullptr) + : m_Type(type), m_IntegralValue(integral_value) {} + }; + /// A class modeling function calls for functions produced by the interpreter /// in compiled code. It provides an information if we are calling a standard /// function, constructor or destructor. @@ -318,6 +326,13 @@ namespace Cpp { CPPINTEROP_API std::vector GetFunctionsUsingName(TCppScope_t scope, const std::string& name); + TCppFunction_t GetFunctionUsingArgs(TCppScope_t scope, + const std::string& name, + TCppType_t* arg_types, + size_t arg_types_size, + TemplateArgInfo* template_args, + size_t template_args_size); + /// Gets the return type of the provided function. CPPINTEROP_API TCppType_t GetFunctionReturnType(TCppFunction_t func); diff --git a/unittests/CppInterOp/FunctionReflectionTest.cpp b/unittests/CppInterOp/FunctionReflectionTest.cpp index 5b76e1001..e81113f61 100644 --- a/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -277,6 +277,83 @@ TEST(FunctionReflectionTest, GetClassDecls) { EXPECT_EQ(Cpp::GetName(methods[3]) , Cpp::GetName(SubDecls[8])); } +TEST(FunctionReflectionTest, GetFunctionUsingArgs) { + std::vector Decls; + std::string code = R"( + // Overloaded functions + void f1(int a) {} + void f1() {} + + // Templated functions + template + void f2() { T t; } + + // Templated functions deducible from args + template + void f3(const T& t1, T* t2) {} + + // Overloaded templated functions + template + void f4() { T t; } + template + void f4() { T1 t1; T2 t2; } + )"; + + auto get_function_name_using_args = + [&](Cpp::TCppScope_t scope, const std::string& name, + std::vector arg_types, + std::vector template_args = {}) { + Cpp::TCppFunction_t function = Cpp::GetFunctionUsingArgs( + scope, name, arg_types.data(), arg_types.size(), + template_args.data(), template_args.size()); + + if (function == (void*)-1 || function == 0) + return std::string(""); + + return Cpp::GetFunctionSignature(function); + }; + + std::vector arg_types; + std::vector template_args; + + arg_types = {}; + EXPECT_EQ(get_function_name_using_args(nullptr, "f1", arg_types), + "void f1()"); + arg_types = {Cpp::GetType("int")}; + EXPECT_EQ(get_function_name_using_args(nullptr, "f1", arg_types), + "void f1(int a)"); + + arg_types = {}; + template_args = {{Cpp::GetType("int")}}; + EXPECT_EQ( + get_function_name_using_args(nullptr, "f2", arg_types, template_args), + "void f2()"); + arg_types = {}; + template_args = {{Cpp::GetType("double")}}; + EXPECT_EQ( + get_function_name_using_args(nullptr, "f2", arg_types, template_args), + "void f2()"); + + arg_types = {Cpp::GetType("const std::string &"), + Cpp::GetType("std::string *")}; + EXPECT_EQ(get_function_name_using_args(nullptr, "f3", arg_types), + "void f3(const std::string &t1, std::string *t2)"); + arg_types = {Cpp::GetType("const int &"), Cpp::GetType("int *")}; + EXPECT_EQ(get_function_name_using_args(nullptr, "f3", arg_types), + "void f3(const int &t1, int *t2)"); + + arg_types = {}; + template_args = {{Cpp::GetType("double")}}; + EXPECT_EQ( + get_function_name_using_args(nullptr, "f4", arg_types, template_args), + "void f4()"); + arg_types = {}; + template_args = {{Cpp::GetType("double")}, {Cpp::GetType("int")}}; + EXPECT_EQ( + get_function_name_using_args(nullptr, "f4", arg_types, template_args), + "void f4()"); +} + TEST(FunctionReflectionTest, GetFunctionReturnType) { std::vector Decls, SubDecls, TemplateSubDecls; std::string code = R"(