@@ -73,6 +73,23 @@ static bool IsValueField(clang::ASTContext &ctx,
7373 return type->isConstantArrayType () || IsBoxedType (ctx, type);
7474}
7575
76+ // Whether `expr` is an array field whose elements are accessed through
77+ // array_field_ptr!, such that they are found in the memory of the struct when
78+ // the struct is reinterpreted from other memory.
79+ static bool IsArrayFieldPtr (clang::ASTContext &ctx, const clang::Expr *expr) {
80+ auto *member =
81+ clang::dyn_cast<clang::MemberExpr>(expr->IgnoreParenImpCasts ());
82+ auto *field =
83+ member ? clang::dyn_cast<clang::FieldDecl>(member->getMemberDecl ())
84+ : nullptr ;
85+ if (!field || field->getParent ()->isUnion () ||
86+ Mapper::Contains (ctx, member)) {
87+ return false ;
88+ }
89+ auto *type = field->getType ()->getAsArrayTypeUnsafe ();
90+ return type && !type->getElementType ()->isArrayType ();
91+ }
92+
7693static bool IsPointerType (clang::ASTContext &ctx, clang::QualType type) {
7794 return type->isPointerType () || GetStrongestIteratorCategory (ctx, type) ==
7895 IteratorCategory::Contiguous;
@@ -421,7 +438,7 @@ bool ConverterRefCount::VisitArraySubscriptExpr(
421438 clang::ArraySubscriptExpr *expr) {
422439 auto *base = expr->getBase ();
423440 if (base->IgnoreCasts ()->getType ()->isPointerType () ||
424- IsUnionArrayMember (base) ||
441+ IsUnionArrayMember (base) || IsArrayFieldPtr (ctx_, base) ||
425442 (IsReferenceType (base) &&
426443 base->IgnoreCasts ()->getType ()->isArrayType ())) {
427444 ConvertPointerSubscript (expr);
@@ -1542,8 +1559,23 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
15421559 } else if (expr->getSubExpr ()->getType ()->isPointerType () &&
15431560 !expr->getSubExpr ()->isNullPointerConstant (
15441561 ctx_, clang::Expr::NPC_ValueDependentIsNull)) {
1545- StrCat (std::format (" {}.reinterpret_cast::<{}>()" ,
1546- ToString (expr->getSubExpr ()),
1562+ auto sub_expr = expr->getSubExpr ();
1563+ if (auto *array_type =
1564+ ctx_.getAsArrayType (sub_expr->getType ()->getPointeeType ())) {
1565+ // A pointer to an array is a pointer to its first element.
1566+ auto element_type = array_type->getElementType ();
1567+ PushConversionKind push (*this , ConversionKind::Unboxed);
1568+ StrCat (std::format (" ({} as Ptr<{}>)" , ToString (sub_expr),
1569+ ToString (element_type)));
1570+ if (!ctx_.hasSameUnqualifiedType (
1571+ element_type, expr->getType ()->getPointeeType ())) {
1572+ StrCat (std::format (" .reinterpret_cast::<{}>()" ,
1573+ ConvertPointeeType (expr->getType ())));
1574+ }
1575+ computed_expr_type_ = ComputedExprType::FreshPointer;
1576+ return false ;
1577+ }
1578+ StrCat (std::format (" {}.reinterpret_cast::<{}>()" , ToString (sub_expr),
15471579 ConvertPointeeType (expr->getType ())));
15481580 computed_expr_type_ = ComputedExprType::FreshPointer;
15491581 return false ;
@@ -1848,6 +1880,13 @@ bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) {
18481880 return false ;
18491881 }
18501882
1883+ if (isAddrOf () && IsArrayFieldPtr (ctx_, expr)) {
1884+ StrCat (std::format (" array_field_ptr!({}, {})" , ConvertRecordPtr (expr),
1885+ GetNamedDeclAsString (member)));
1886+ computed_expr_type_ = ComputedExprType::FreshPointer;
1887+ return false ;
1888+ }
1889+
18511890 std::string str;
18521891 if (known) {
18531892 str = GetMappedAsString (expr);
@@ -1893,18 +1932,7 @@ void ConverterRefCount::ConvertInlineField(clang::MemberExpr *expr) {
18931932 auto *base = expr->getBase ();
18941933 if (isAddrOf ()) {
18951934 // A pointer to the struct, offset to the field.
1896- std::string ptr;
1897- {
1898- Buffer buf (*this );
1899- PushExprKind push (*this , ExprKind::AddrOf);
1900- if (expr->isArrow ()) {
1901- ConvertArrow (base);
1902- } else {
1903- Convert (base);
1904- }
1905- ptr = std::move (buf).str ();
1906- }
1907- StrCat (std::format (" field_ptr!({}, {})" , ptr, name));
1935+ StrCat (std::format (" field_ptr!({}, {})" , ConvertRecordPtr (expr), name));
19081936 computed_expr_type_ = ComputedExprType::FreshPointer;
19091937 return ;
19101938 }
@@ -1939,6 +1967,17 @@ void ConverterRefCount::ConvertInlineField(clang::MemberExpr *expr) {
19391967 SetValueFreshness (type);
19401968}
19411969
1970+ std::string ConverterRefCount::ConvertRecordPtr (clang::MemberExpr *expr) {
1971+ Buffer buf (*this );
1972+ PushExprKind push (*this , ExprKind::AddrOf);
1973+ if (expr->isArrow ()) {
1974+ ConvertArrow (expr->getBase ());
1975+ } else {
1976+ Convert (expr->getBase ());
1977+ }
1978+ return std::move (buf).str ();
1979+ }
1980+
19421981std::string ConverterRefCount::ReadField (clang::MemberExpr *expr) {
19431982 // Unless the struct is reached through a pointer, in which case the field
19441983 // is read in a closure, the borrow of the struct ends at the end of the
0 commit comments