Skip to content

Commit 74373aa

Browse files
committed
Handle non-uniform C++ st_mtim.tv_sec with Rust st_mtime
1 parent 943b97c commit 74373aa

1 file changed

Lines changed: 49 additions & 5 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,45 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
25472547
return false;
25482548
}
25492549

2550+
// Returns the inner member and the replacement string.
2551+
static std::pair<clang::MemberExpr *, std::string>
2552+
replaceNonUniformLibcField(clang::MemberExpr *expr) {
2553+
// Example: ::struct stat::st_mtim::tv_sec -> ::libc::stat::st_mtime
2554+
struct Mapping {
2555+
const char *record;
2556+
const char *inner_field;
2557+
const char *leaf_field;
2558+
const char *replacement;
2559+
};
2560+
static constexpr Mapping kFields[] = {
2561+
{"stat", "st_mtim", "tv_sec", "st_mtime"},
2562+
{"stat", "st_mtim", "tv_nsec", "st_mtime_nsec"},
2563+
};
2564+
2565+
auto getNamedIdentifierOrNull = [](auto *decl) {
2566+
return decl && decl->getDeclName().isIdentifier() ? decl : nullptr;
2567+
};
2568+
2569+
if (auto leaf = getNamedIdentifierOrNull(expr->getMemberDecl())) {
2570+
if (auto inner = clang::dyn_cast<clang::MemberExpr>(
2571+
expr->getBase()->IgnoreParenImpCasts())) {
2572+
if (auto field = getNamedIdentifierOrNull(
2573+
clang::dyn_cast<clang::FieldDecl>(inner->getMemberDecl()))) {
2574+
if (getNamedIdentifierOrNull(field->getParent())) {
2575+
for (const auto &m : kFields) {
2576+
if (field->getParent()->getName() == m.record &&
2577+
field->getName() == m.inner_field &&
2578+
leaf->getName() == m.leaf_field) {
2579+
return {inner, m.replacement};
2580+
}
2581+
}
2582+
}
2583+
}
2584+
}
2585+
}
2586+
return {nullptr, ""};
2587+
}
2588+
25502589
void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
25512590
if (auto mapped = GetMappedAsString(expr); !mapped.empty()) {
25522591
if (Mapper::ReturnsPointer(expr)) {
@@ -2558,6 +2597,11 @@ void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
25582597
}
25592598

25602599
auto *member = expr->getMemberDecl();
2600+
auto [inner, name_override] = replaceNonUniformLibcField(expr);
2601+
if (inner) {
2602+
expr = inner;
2603+
}
2604+
25612605
auto *base = expr->getBase();
25622606
bool base_is_this = clang::isa<clang::CXXThisExpr>(base->IgnoreCasts());
25632607
PushExprKind push(*this, isLValue() ? ExprKind::LValue : ExprKind::RValue);
@@ -2571,11 +2615,11 @@ void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
25712615
method && IsOverloadedMethod(method)) {
25722616
StrCat(token::kDot);
25732617
StrCat(GetOverloadedFunctionName(method));
2574-
} else {
2575-
if (member->getDeclName().isIdentifier()) {
2576-
StrCat(token::kDot);
2577-
StrCat(GetNamedDeclAsString(member));
2578-
}
2618+
} else if (!name_override.empty()) {
2619+
StrCat(token::kDot, name_override);
2620+
} else if (member->getDeclName().isIdentifier()) {
2621+
StrCat(token::kDot);
2622+
StrCat(GetNamedDeclAsString(member));
25792623
}
25802624
}
25812625

0 commit comments

Comments
 (0)