Skip to content

Commit

Permalink
Update GetBinaryOperator to GetOperator
Browse files Browse the repository at this point in the history
resolving unary operators and operators defined within namespaces
  • Loading branch information
Vipul-Cariappa committed Jan 4, 2025
1 parent 300aa0d commit b88a7d2
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 56 deletions.
93 changes: 56 additions & 37 deletions include/clang/Interpreter/CppInterOp.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,42 +37,57 @@ namespace Cpp {
using TInterp_t = void*;
using TCppObject_t = void*;

enum BinaryOperator {
PtrMemD = 0,
PtrMemI,
Mul,
Div,
Rem,
Add,
Sub,
Shl,
Shr,
Cmp,
LT,
GT,
LE,
GE,
EQ,
NE,
And,
Xor,
Or,
LAnd,
LOr,
Assign,
MulAssign,
DivAssign,
RemAssign,
AddAssign,
SubAssign,
ShlAssign,
ShrAssign,
AndAssign,
XorAssign,
OrAssign,
Comma,
enum Operator {
OP_None,
OP_New,
OP_Delete,
OP_Array_New,
OP_Array_Delete,
OP_Plus,
OP_Minus,
OP_Star,
OP_Slash,
OP_Percent,
OP_Caret,
OP_Amp,
OP_Pipe,
OP_Tilde,
OP_Exclaim,
OP_Equal,
OP_Less,
OP_Greater,
OP_PlusEqual,
OP_MinusEqual,
OP_StarEqual,
OP_SlashEqual,
OP_PercentEqual,
OP_CaretEqual,
OP_AmpEqual,
OP_PipeEqual,
OP_LessLess,
OP_GreaterGreater,
OP_LessLessEqual,
OP_GreaterGreaterEqual,
OP_EqualEqual,
OP_ExclaimEqual,
OP_LessEqual,
OP_GreaterEqual,
OP_Spaceship,
OP_AmpAmp,
OP_PipePipe,
OP_PlusPlus,
OP_MinusMinus,
OP_Comma,
OP_ArrowStar,
OP_Arrow,
OP_Call,
OP_Subscript,
OP_Conditional,
OP_Coawait,
};

enum OperatorArity { kUnary = 1, kBinary, kBoth };

/// 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.
Expand Down Expand Up @@ -513,9 +528,13 @@ namespace Cpp {
CPPINTEROP_API std::string GetFunctionArgName(TCppFunction_t func,
TCppIndex_t param_index);

///\returns function that performs operation op on lc and rc
void GetBinaryOperator(TCppScope_t scope, enum BinaryOperator op,
std::vector<TCppFunction_t>& operators);
///\returns arity of the operator or kNone
OperatorArity GetOperatorArity(TCppFunction_t op);

///\returns list of operator overloads
void GetOperator(TCppScope_t scope, Operator op,
std::vector<TCppFunction_t>& operators,
OperatorArity kind = kBoth);

/// Creates an instance of the interpreter we need for the various interop
/// services.
Expand Down
49 changes: 35 additions & 14 deletions lib/Interpreter/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3315,22 +3315,43 @@ namespace Cpp {
return PI->getNameAsString();
}

void GetBinaryOperator(TCppScope_t scope, enum BinaryOperator op,
std::vector<TCppFunction_t>& operators) {
Decl* D = static_cast<Decl*>(scope);
auto* DC = llvm::dyn_cast<DeclContext>(D);
Scope* S = getSema().getScopeForContext(DC);
if (!S)
return;

clang::UnresolvedSet<8> lookup;
OperatorArity GetOperatorArity(TCppFunction_t op) {
Decl* D = static_cast<Decl*>(op);
if (auto* FD = llvm::dyn_cast<FunctionDecl>(D)) {
if (FD->isOverloadedOperator()) {
switch (FD->getOverloadedOperator()) {
#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, \
MemberOnly) \
case OO_##Name: \
if ((Unary) && (Binary)) \
return kBoth; \
if (Unary) \
return kUnary; \
if (Binary) \
return kBinary; \
break;
#include "clang/Basic/OperatorKinds.def"
default:
break;
}
}
}
return (OperatorArity)~0U;
}

getSema().LookupBinOp(S, SourceLocation(), (clang::BinaryOperatorKind)op,
lookup);
void GetOperator(TCppScope_t scope, Operator op,
std::vector<TCppFunction_t>& operators, OperatorArity kind) {
Decl* D = static_cast<Decl*>(scope);
if (auto* DC = llvm::dyn_cast_or_null<DeclContext>(D)) {
ASTContext& C = getSema().getASTContext();
DeclContextLookupResult Result =
DC->lookup(C.DeclarationNames.getCXXOperatorName(
(clang::OverloadedOperatorKind)op));

for (NamedDecl* D : lookup) {
if (auto* FD = llvm::dyn_cast<Decl>(D))
operators.push_back(FD);
for (auto* i : Result) {
if (kind & GetOperatorArity(i))
operators.push_back(i);
}
}
}

Expand Down
38 changes: 33 additions & 5 deletions unittests/CppInterOp/ScopeReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@ TEST(ScopeReflectionTest, IncludeVector) {
Interp->process(code);
}

TEST(ScopeReflectionTest, GetBinaryOperator) {
TEST(ScopeReflectionTest, GetOperator) {
if (llvm::sys::RunningOnValgrind())
GTEST_SKIP() << "XFAIL due to Valgrind report";

Expand All @@ -988,27 +988,55 @@ TEST(ScopeReflectionTest, GetBinaryOperator) {
return MyClass(lhs.x + rhs.x);
}
namespace extra_ops {
MyClass operator+(MyClass lhs, int rhs) {
return MyClass(lhs.x + rhs);
}
MyClass operator+(int lhs, MyClass rhs) {
return MyClass(lhs + rhs.x);
}
MyClass operator~(MyClass self) {
return MyClass(-self.x);
}
}
)";

Cpp::Declare(code.c_str());

std::vector<Cpp::TCppFunction_t> ops;

Cpp::GetBinaryOperator(Cpp::GetGlobalScope(), Cpp::BinaryOperator::Add, ops);
EXPECT_EQ(ops.size(), 3);
Cpp::GetOperator(Cpp::GetGlobalScope(), Cpp::Operator::OP_Plus, ops);
EXPECT_EQ(ops.size(), 1);
ops.clear();

Cpp::GetOperator(Cpp::GetGlobalScope(), Cpp::Operator::OP_Minus, ops);
EXPECT_EQ(ops.size(), 1);
ops.clear();

Cpp::GetOperator(Cpp::GetGlobalScope(), Cpp::Operator::OP_Star, ops);
EXPECT_EQ(ops.size(), 0);
ops.clear();

// operators defined within a namespace
Cpp::GetOperator(Cpp::GetScope("extra_ops"), Cpp::Operator::OP_Plus, ops);
EXPECT_EQ(ops.size(), 2);
ops.clear();

// unary operator
Cpp::GetOperator(Cpp::GetScope("extra_ops"), Cpp::Operator::OP_Tilde, ops);
EXPECT_EQ(ops.size(), 1);
ops.clear();

Cpp::GetBinaryOperator(Cpp::GetGlobalScope(), Cpp::BinaryOperator::Sub, ops);
Cpp::GetOperator(Cpp::GetScope("extra_ops"), Cpp::Operator::OP_Tilde, ops,
Cpp::OperatorArity::kUnary);
EXPECT_EQ(ops.size(), 1);
ops.clear();

Cpp::GetBinaryOperator(Cpp::GetGlobalScope(), Cpp::BinaryOperator::Mul, ops);
Cpp::GetOperator(Cpp::GetScope("extra_ops"), Cpp::Operator::OP_Tilde, ops,
Cpp::OperatorArity::kBinary);
EXPECT_EQ(ops.size(), 0);
}

0 comments on commit b88a7d2

Please sign in to comment.