@@ -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+
25502589void 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