Skip to content

Commit 9bd4678

Browse files
Add GetBinaryOperator (#319)
1 parent 91e392d commit 9bd4678

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,43 @@ namespace Cpp {
3535
using TCppFuncAddr_t = void*;
3636
using TInterp_t = void*;
3737
using TCppObject_t = void*;
38+
39+
enum BinaryOperator {
40+
PtrMemD = 0,
41+
PtrMemI,
42+
Mul,
43+
Div,
44+
Rem,
45+
Add,
46+
Sub,
47+
Shl,
48+
Shr,
49+
Cmp,
50+
LT,
51+
GT,
52+
LE,
53+
GE,
54+
EQ,
55+
NE,
56+
And,
57+
Xor,
58+
Or,
59+
LAnd,
60+
LOr,
61+
Assign,
62+
MulAssign,
63+
DivAssign,
64+
RemAssign,
65+
AddAssign,
66+
SubAssign,
67+
ShlAssign,
68+
ShrAssign,
69+
AndAssign,
70+
XorAssign,
71+
OrAssign,
72+
Comma,
73+
};
74+
3875
/// A class modeling function calls for functions produced by the interpreter
3976
/// in compiled code. It provides an information if we are calling a standard
4077
/// function, constructor or destructor.
@@ -464,6 +501,11 @@ namespace Cpp {
464501
CPPINTEROP_API std::string GetFunctionArgName(TCppFunction_t func,
465502
TCppIndex_t param_index);
466503

504+
///\returns function that performs operation op on lc and rc
505+
TCppFunction_t GetBinaryOperator(TCppScope_t scope, enum BinaryOperator op,
506+
const std::string& lc,
507+
const std::string& rc);
508+
467509
/// Creates an instance of the interpreter we need for the various interop
468510
/// services.
469511
///\param[in] Args - the list of arguments for interpreter constructor.

lib/Interpreter/CppInterOp.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,6 +3161,49 @@ namespace Cpp {
31613161
return PI->getNameAsString();
31623162
}
31633163

3164+
TCppFunction_t GetBinaryOperator(TCppScope_t scope, enum BinaryOperator op,
3165+
const std::string& lc,
3166+
const std::string& rc) {
3167+
Decl* D = static_cast<Decl*>(scope);
3168+
if (!D)
3169+
return nullptr;
3170+
3171+
DeclContext* DC = nullptr;
3172+
if (llvm::isa_and_nonnull<TranslationUnitDecl>(D))
3173+
DC = llvm::dyn_cast<DeclContext>(D);
3174+
else
3175+
DC = D->getDeclContext();
3176+
3177+
if (!DC)
3178+
return nullptr;
3179+
3180+
Scope* S = getSema().getScopeForContext(DC);
3181+
if (!S)
3182+
return nullptr;
3183+
3184+
clang::UnresolvedSet<8> lookup;
3185+
3186+
getSema().LookupBinOp(S, SourceLocation(), (clang::BinaryOperatorKind)op,
3187+
lookup);
3188+
3189+
for (NamedDecl* D : lookup) {
3190+
if (auto* FD = llvm::dyn_cast<Decl>(D)) {
3191+
assert(GetFunctionNumArgs(FD) == 2 &&
3192+
"LookupBinOp returned function without 2 arguments");
3193+
3194+
std::string arg_type = GetTypeAsString(GetFunctionArgType(FD, 0));
3195+
if (arg_type != lc)
3196+
continue;
3197+
arg_type = GetTypeAsString(GetFunctionArgType(FD, 1));
3198+
if (arg_type != rc)
3199+
continue;
3200+
3201+
return FD;
3202+
}
3203+
}
3204+
return nullptr;
3205+
}
3206+
31643207
TCppObject_t Allocate(TCppScope_t scope) {
31653208
return (TCppObject_t)::operator new(Cpp::SizeOf(scope));
31663209
}

unittests/CppInterOp/ScopeReflectionTest.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,3 +952,50 @@ TEST(ScopeReflectionTest, IncludeVector) {
952952
)";
953953
Interp->process(code);
954954
}
955+
956+
TEST(ScopeReflectionTest, GetBinaryOperator) {
957+
if (llvm::sys::RunningOnValgrind())
958+
GTEST_SKIP() << "XFAIL due to Valgrind report";
959+
960+
Cpp::CreateInterpreter();
961+
962+
std::string code = R"(
963+
class MyClass {
964+
public:
965+
int x;
966+
MyClass(int x) : x(x) {}
967+
};
968+
969+
MyClass operator-(MyClass lhs, MyClass rhs) {
970+
return MyClass(lhs.x - rhs.x);
971+
}
972+
973+
MyClass operator+(MyClass lhs, MyClass rhs) {
974+
return MyClass(lhs.x + rhs.x);
975+
}
976+
977+
MyClass operator+(MyClass lhs, int rhs) {
978+
return MyClass(lhs.x + rhs);
979+
}
980+
981+
MyClass operator+(int lhs, MyClass rhs) {
982+
return MyClass(lhs + rhs.x);
983+
}
984+
)";
985+
986+
Cpp::Declare(code.c_str());
987+
988+
EXPECT_TRUE(Cpp::GetBinaryOperator(
989+
Cpp::GetGlobalScope(), Cpp::BinaryOperator::Add, "MyClass", "MyClass"));
990+
EXPECT_TRUE(Cpp::GetBinaryOperator(
991+
Cpp::GetGlobalScope(), Cpp::BinaryOperator::Sub, "MyClass", "MyClass"));
992+
EXPECT_TRUE(Cpp::GetBinaryOperator(
993+
Cpp::GetGlobalScope(), Cpp::BinaryOperator::Add, "MyClass", "int"));
994+
EXPECT_TRUE(Cpp::GetBinaryOperator(
995+
Cpp::GetGlobalScope(), Cpp::BinaryOperator::Add, "int", "MyClass"));
996+
997+
EXPECT_FALSE(Cpp::GetBinaryOperator(
998+
Cpp::GetGlobalScope(), Cpp::BinaryOperator::Add, "float", "MyClass"));
999+
EXPECT_FALSE(Cpp::GetBinaryOperator(
1000+
Cpp::GetGlobalScope(), Cpp::BinaryOperator::Add, "MyClass", "float"));
1001+
}

0 commit comments

Comments
 (0)