diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 1b9fa943e..87eb63bff 100755 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -1963,8 +1963,14 @@ namespace Cpp { // Same applies with member methods which seem to cause parse failures // even when we supply the object parameter. Therefore we only use it in // cases where we know it works and set this variable to true when we do. + + // true if not a overloaded operators or the overloaded operator is call + // operator + bool op_flag = !FD->isOverloadedOperator() || + FD->getOverloadedOperator() == clang::OO_Call; + bool ShouldCastFunction = - !isa(FD) && N == FD->getNumParams(); + !isa(FD) && N == FD->getNumParams() && op_flag; if (ShouldCastFunction) { callbuf << "("; callbuf << "("; @@ -2003,11 +2009,13 @@ namespace Cpp { callbuf << "((const " << class_name << "*)obj)->"; else callbuf << "((" << class_name << "*)obj)->"; - } else if (const NamedDecl* ND = - dyn_cast(get_non_transparent_decl_context(FD))) { + + if (op_flag) + callbuf << class_name << "::"; + } else if (isa(get_non_transparent_decl_context(FD))) { // This is a namespace member. - (void)ND; - callbuf << class_name << "::"; + if (op_flag || N <= 1) + callbuf << class_name << "::"; } // callbuf << fMethod->Name() << "("; { @@ -2030,7 +2038,8 @@ namespace Cpp { name = name_without_template_args + (template_args.empty() ? "" : " " + template_args); } - callbuf << name; + if (op_flag || N <= 1) + callbuf << name; } if (ShouldCastFunction) callbuf << ")"; @@ -2047,12 +2056,12 @@ namespace Cpp { isPointer, indent_level, true); if (i) { - callbuf << ','; - if (i % 2) { - callbuf << ' '; + if (op_flag) { + callbuf << ", "; } else { - callbuf << "\n"; - indent(callbuf, indent_level + 1); + callbuf << ' ' + << Cpp::getOperatorSpelling(FD->getOverloadedOperator()) + << ' '; } } diff --git a/unittests/CppInterOp/FunctionReflectionTest.cpp b/unittests/CppInterOp/FunctionReflectionTest.cpp index 3b1e47e15..7448cbe30 100644 --- a/unittests/CppInterOp/FunctionReflectionTest.cpp +++ b/unittests/CppInterOp/FunctionReflectionTest.cpp @@ -1381,7 +1381,7 @@ TEST(FunctionReflectionTest, GetFunctionAddress) { #ifdef EMSCRIPTEN #if CLANG_VERSION_MAJOR < 20 GTEST_SKIP() << "Test fails for Emscipten builds"; -#endif +#endif #endif if (llvm::sys::RunningOnValgrind()) GTEST_SKIP() << "XFAIL due to Valgrind report"; @@ -1684,6 +1684,46 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) { bool boolean = false; FCI_op.Invoke((void*)&boolean, {args, /*args_size=*/1}, toperator); EXPECT_TRUE(boolean); + + Interp->process(R"( + namespace N1 { + + template struct Klass3 { + using type = int; + }; + + namespace N2 { + template class Klass1 {}; + + template class Klass2 {}; + + template + constexpr Klass2< + T1, typename Klass3>::type> + operator+(const Klass2 &__lhs, + const Klass1 &__rhs) { + typedef Klass1 __T1; + typedef typename Klass3::type __ct; + typedef Klass2 __T2; + return {}; + } + } // namespace N2 + } // namespace N1 + + N1::N2::Klass2 K1; + N1::N2::Klass1 K2; + )"); + + Cpp::TCppType_t K1 = Cpp::GetTypeFromScope(Cpp::GetNamed("K1")); + Cpp::TCppType_t K2 = Cpp::GetTypeFromScope(Cpp::GetNamed("K2")); + operators.clear(); + Cpp::GetOperator(Cpp::GetScope("N2", Cpp::GetScope("N1")), Cpp::OP_Plus, + operators); + EXPECT_EQ(operators.size(), 1); + Cpp::TCppFunction_t kop = + Cpp::BestOverloadFunctionMatch(operators, {}, {K1, K2}); + auto chrono_op_fn_callable = Cpp::MakeFunctionCallable(kop); + EXPECT_EQ(chrono_op_fn_callable.getKind(), Cpp::JitCall::kGenericCall); } TEST(FunctionReflectionTest, IsConstMethod) { @@ -1992,4 +2032,4 @@ TEST(FunctionReflectionTest, UndoTest) { EXPECT_EQ(ret, 1); #endif #endif - } +}