Skip to content

Commit 03135b6

Browse files
fix codegen for operator wrapper (#571)
* fix codegen for operator wrapper Generator operations instead of function calls similar to upstream * codegen: use qualified name in method calls similar to upstream * add tests
1 parent 28ba16e commit 03135b6

File tree

2 files changed

+62
-13
lines changed

2 files changed

+62
-13
lines changed

lib/Interpreter/CppInterOp.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,8 +1963,14 @@ namespace Cpp {
19631963
// Same applies with member methods which seem to cause parse failures
19641964
// even when we supply the object parameter. Therefore we only use it in
19651965
// cases where we know it works and set this variable to true when we do.
1966+
1967+
// true if not a overloaded operators or the overloaded operator is call
1968+
// operator
1969+
bool op_flag = !FD->isOverloadedOperator() ||
1970+
FD->getOverloadedOperator() == clang::OO_Call;
1971+
19661972
bool ShouldCastFunction =
1967-
!isa<CXXMethodDecl>(FD) && N == FD->getNumParams();
1973+
!isa<CXXMethodDecl>(FD) && N == FD->getNumParams() && op_flag;
19681974
if (ShouldCastFunction) {
19691975
callbuf << "(";
19701976
callbuf << "(";
@@ -2003,11 +2009,13 @@ namespace Cpp {
20032009
callbuf << "((const " << class_name << "*)obj)->";
20042010
else
20052011
callbuf << "((" << class_name << "*)obj)->";
2006-
} else if (const NamedDecl* ND =
2007-
dyn_cast<NamedDecl>(get_non_transparent_decl_context(FD))) {
2012+
2013+
if (op_flag)
2014+
callbuf << class_name << "::";
2015+
} else if (isa<NamedDecl>(get_non_transparent_decl_context(FD))) {
20082016
// This is a namespace member.
2009-
(void)ND;
2010-
callbuf << class_name << "::";
2017+
if (op_flag || N <= 1)
2018+
callbuf << class_name << "::";
20112019
}
20122020
// callbuf << fMethod->Name() << "(";
20132021
{
@@ -2030,7 +2038,8 @@ namespace Cpp {
20302038
name = name_without_template_args +
20312039
(template_args.empty() ? "" : " " + template_args);
20322040
}
2033-
callbuf << name;
2041+
if (op_flag || N <= 1)
2042+
callbuf << name;
20342043
}
20352044
if (ShouldCastFunction)
20362045
callbuf << ")";
@@ -2047,12 +2056,12 @@ namespace Cpp {
20472056
isPointer, indent_level, true);
20482057

20492058
if (i) {
2050-
callbuf << ',';
2051-
if (i % 2) {
2052-
callbuf << ' ';
2059+
if (op_flag) {
2060+
callbuf << ", ";
20532061
} else {
2054-
callbuf << "\n";
2055-
indent(callbuf, indent_level + 1);
2062+
callbuf << ' '
2063+
<< Cpp::getOperatorSpelling(FD->getOverloadedOperator())
2064+
<< ' ';
20562065
}
20572066
}
20582067

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,7 @@ TEST(FunctionReflectionTest, GetFunctionAddress) {
13811381
#ifdef EMSCRIPTEN
13821382
#if CLANG_VERSION_MAJOR < 20
13831383
GTEST_SKIP() << "Test fails for Emscipten builds";
1384-
#endif
1384+
#endif
13851385
#endif
13861386
if (llvm::sys::RunningOnValgrind())
13871387
GTEST_SKIP() << "XFAIL due to Valgrind report";
@@ -1684,6 +1684,46 @@ TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
16841684
bool boolean = false;
16851685
FCI_op.Invoke((void*)&boolean, {args, /*args_size=*/1}, toperator);
16861686
EXPECT_TRUE(boolean);
1687+
1688+
Interp->process(R"(
1689+
namespace N1 {
1690+
1691+
template <typename... _Tn> struct Klass3 {
1692+
using type = int;
1693+
};
1694+
1695+
namespace N2 {
1696+
template <typename T1, typename T2> class Klass1 {};
1697+
1698+
template <typename T1, typename T2> class Klass2 {};
1699+
1700+
template <typename T1, typename T2, typename T3, typename T4>
1701+
constexpr Klass2<
1702+
T1, typename Klass3<T2, Klass1<T3, T4>>::type>
1703+
operator+(const Klass2<T1, T2> &__lhs,
1704+
const Klass1<T3, T4> &__rhs) {
1705+
typedef Klass1<T3, T4> __T1;
1706+
typedef typename Klass3<T2, __T1>::type __ct;
1707+
typedef Klass2<T1, __ct> __T2;
1708+
return {};
1709+
}
1710+
} // namespace N2
1711+
} // namespace N1
1712+
1713+
N1::N2::Klass2<int, double> K1;
1714+
N1::N2::Klass1<char, float> K2;
1715+
)");
1716+
1717+
Cpp::TCppType_t K1 = Cpp::GetTypeFromScope(Cpp::GetNamed("K1"));
1718+
Cpp::TCppType_t K2 = Cpp::GetTypeFromScope(Cpp::GetNamed("K2"));
1719+
operators.clear();
1720+
Cpp::GetOperator(Cpp::GetScope("N2", Cpp::GetScope("N1")), Cpp::OP_Plus,
1721+
operators);
1722+
EXPECT_EQ(operators.size(), 1);
1723+
Cpp::TCppFunction_t kop =
1724+
Cpp::BestOverloadFunctionMatch(operators, {}, {K1, K2});
1725+
auto chrono_op_fn_callable = Cpp::MakeFunctionCallable(kop);
1726+
EXPECT_EQ(chrono_op_fn_callable.getKind(), Cpp::JitCall::kGenericCall);
16871727
}
16881728

16891729
TEST(FunctionReflectionTest, IsConstMethod) {
@@ -1992,4 +2032,4 @@ TEST(FunctionReflectionTest, UndoTest) {
19922032
EXPECT_EQ(ret, 1);
19932033
#endif
19942034
#endif
1995-
}
2035+
}

0 commit comments

Comments
 (0)