Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions lib/CppInterOp/CppInterOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1484,9 +1484,28 @@ std::vector<TCppFunction_t> GetFunctionsUsingName(TCppScope_t scope,
D = GetUnderlyingScope(D);

std::vector<TCppFunction_t> funcs;
llvm::StringRef Name(name);
auto& S = getSema();
DeclarationName DName = &getASTContext().Idents.get(name);
auto& Ctx = getASTContext();
DeclarationName DName;

// Handle operator overloads (e.g. "operator==", "operator new"): these are
// stored under CXXOperatorName declaration names, not as identifiers.
static constexpr llvm::StringRef OperatorPrefix("operator");
llvm::StringRef NameRef(name);
if (NameRef.consume_front(OperatorPrefix) && !NameRef.empty() &&
!clang::isAsciiIdentifierContinue(
static_cast<unsigned char>(NameRef.front()))) {
llvm::StringRef Spelling = NameRef.trim();
#define OVERLOADED_OPERATOR(OpName, OpSpelling, Token, Unary, Binary, \
MemberOnly) \
if (Spelling == (OpSpelling)) \
DName = Ctx.DeclarationNames.getCXXOperatorName(clang::OO_##OpName);
#include "clang/Basic/OperatorKinds.def"
}

if (!DName)
DName = &Ctx.Idents.get(name);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use LookupOperatorName instead of the string comparisons?

Something similar to:

clang/lib/Sema/SemaCoroutine.cpp-829-ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) {
clang/lib/Sema/SemaCoroutine.cpp-830-  DeclarationName OpName =
clang/lib/Sema/SemaCoroutine.cpp-831-      Context.DeclarationNames.getCXXOperatorName(OO_Coawait);
clang/lib/Sema/SemaCoroutine.cpp-832-  LookupResult Operators(*this, OpName, SourceLocation(),
clang/lib/Sema/SemaCoroutine.cpp:833:                         Sema::LookupOperatorName);
clang/lib/Sema/SemaCoroutine.cpp-834-  LookupName(Operators, S);


clang::LookupResult R(S, DName, SourceLocation(), Sema::LookupOrdinaryName,
RedeclarationKind::ForVisibleRedeclaration);

Expand Down
51 changes: 51 additions & 0 deletions unittests/CppInterOp/FunctionReflectionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,57 @@ TYPED_TEST(CPPINTEROP_TEST_MODE, FunctionReflection_GetFunctionsUsingName) {
EXPECT_EQ(get_number_of_funcs_using_name(Decls[2], ""), 0);
}

TYPED_TEST(CPPINTEROP_TEST_MODE,
FunctionReflection_GetFunctionsUsingNameOperators) {
std::vector<Decl*> Decls;
std::string code = R"(
namespace ComparableSpace {
class NSComparable {};
bool operator==(const NSComparable&, const NSComparable&) { return true; }
bool operator==(const NSComparable&, int) { return false; }
bool operator!=(const NSComparable&, const NSComparable&) { return false; }
int operators_count() { return 1; }
}

struct WithOps {
bool operator==(const WithOps&) const { return true; }
WithOps& operator+=(int) { return *this; }
int operator[](int) const { return 0; }
int operator()(int, int) const { return 0; }
};
)";

GetAllTopLevelDecls(code, Decls);

auto count = [](Cpp::TCppScope_t scope, const std::string& name) {
return Cpp::GetFunctionsUsingName(scope, name).size();
};

// Namespace-scope operator overloads are now findable by name.
EXPECT_EQ(count(Decls[0], "operator=="), 2);
EXPECT_EQ(count(Decls[0], "operator!="), 1);

// Non-existent operator at this scope.
EXPECT_EQ(count(Decls[0], "operator+"), 0);

// Identifiers that merely start with "operator" must still resolve via the
// identifier lookup path, not be misread as an operator.
EXPECT_EQ(count(Decls[0], "operators_count"), 1);

// Class-scope operators, including multi-token "()" and "[]".
EXPECT_EQ(count(Decls[1], "operator=="), 1);
EXPECT_EQ(count(Decls[1], "operator+="), 1);
EXPECT_EQ(count(Decls[1], "operator[]"), 1);
EXPECT_EQ(count(Decls[1], "operator()"), 1);
EXPECT_EQ(count(Decls[1], "operator!="), 0);

// Sanity-check that the returned decls are the operator overloads.
auto eqs = Cpp::GetFunctionsUsingName(Decls[0], "operator==");
ASSERT_EQ(eqs.size(), 2u);
for (auto* f : eqs)
EXPECT_EQ(Cpp::GetName(f), "operator==");
}

TYPED_TEST(CPPINTEROP_TEST_MODE, FunctionReflection_GetClassDecls) {
std::vector<Decl*> Decls, SubDecls;
std::string code = R"(
Expand Down
Loading