Skip to content

Commit 1fce485

Browse files
committed
Fix array reference
1 parent f467a98 commit 1fce485

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,19 @@ ConverterRefCount::MaterializeTemp(const std::string &binding_name,
496496
clang::QualType param_type,
497497
clang::Expr *expr) {
498498
auto pointee = param_type.getNonReferenceType();
499-
auto value = ConvertFreshRValue(expr, pointee);
500-
auto type_str = ToStringBase(pointee);
501499
const auto *decl = in_const_initializer_ ? keyword::kStatic : keyword::kLet;
502-
503-
auto binding = std::format("{} {} : Value<{}> = Rc::new(RefCell::new({}));",
504-
decl, binding_name, type_str, value);
500+
std::string binding;
501+
if (pointee->isConstantArrayType()) {
502+
PushConversionKind push(*this, ConversionKind::FullRefCount);
503+
binding = std::format("{} {} : {} = {};", decl, binding_name,
504+
ToString(pointee),
505+
BoxValue(ConvertVarInitValue(pointee, expr)));
506+
} else {
507+
auto value = ConvertFreshRValue(expr, pointee);
508+
auto type_str = ToStringBase(pointee);
509+
binding = std::format("{} {} : Value<{}> = Rc::new(RefCell::new({}));",
510+
decl, binding_name, type_str, value);
511+
}
505512
auto ref =
506513
in_const_initializer_ ? ".with(Value::as_pointer)" : ".as_pointer()";
507514
return {binding, binding_name + ref};
@@ -1499,6 +1506,10 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
14991506
ToString(sub_expr->IgnoreParens())));
15001507
computed_expr_type_ = ComputedExprType::FreshPointer;
15011508
return false;
1509+
} else if (auto ptr = ConvertArrayPointerDeref(sub_expr); !ptr.empty()) {
1510+
StrCat(ptr);
1511+
computed_expr_type_ = ComputedExprType::FreshPointer;
1512+
return false;
15021513
} else {
15031514
// we need to write (var.as_pointer as Ptr<T>) because Rust isn't
15041515
// smart enough to pick the right specialization
@@ -2569,6 +2580,9 @@ std::string ConverterRefCount::ConvertVarInitValue(clang::QualType qual_type,
25692580
return std::format("Ptr::<{}>::from_string_literal({})", code_unit,
25702581
ToString(expr->IgnoreParens()->IgnoreImplicit()));
25712582
}
2583+
if (auto ptr = ConvertArrayPointerDeref(expr); !ptr.empty()) {
2584+
return ptr;
2585+
}
25722586
}
25732587
return ConvertFreshPointer(expr, qual_type);
25742588
}
@@ -3185,6 +3199,18 @@ bool ConverterRefCount::DerefReadsValue(clang::QualType pointee_type) {
31853199
return pointee_type.isPODType(ctx_) && !pointee_type->isRecordType();
31863200
}
31873201

3202+
std::string ConverterRefCount::ConvertArrayPointerDeref(clang::Expr *expr) {
3203+
auto *op =
3204+
clang::dyn_cast<clang::UnaryOperator>(expr->IgnoreParenNoopCasts(ctx_));
3205+
if (!op || op->getOpcode() != clang::UO_Deref ||
3206+
!op->getType()->isArrayType()) {
3207+
return {};
3208+
}
3209+
PushConversionKind push(*this, ConversionKind::Unboxed);
3210+
return std::format("({}{}.as_pointer())", ConvertRValue(op->getSubExpr()),
3211+
GetPointerDerefSuffix(op->getType()));
3212+
}
3213+
31883214
const char *
31893215
ConverterRefCount::GetPointerDerefSuffix(clang::QualType pointee_type) {
31903216
return DerefReadsValue(pointee_type) ? ".read()" : ".upgrade().deref()";

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ class ConverterRefCount final : public Converter {
348348
// returns a copy of the pointee, rather than a borrow of it.
349349
bool DerefReadsValue(clang::QualType pointee_type);
350350
const char *GetPointerDerefSuffix(clang::QualType pointee_type);
351+
352+
std::string ConvertArrayPointerDeref(clang::Expr *expr);
351353
// Sets the freshness of the dereference of a pointer to pointee_type: a
352354
// copy read with .read() is fresh.
353355
void SetDerefFreshness(clang::QualType pointee_type);

‎tests/unit/array_reference.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ int main() {
6565
assert(len(buf) == 4);
6666
int arr[3] = {1, 2, 3};
6767
assert(sum(arr) == 6);
68+
assert(sum({1, 2, 3}) == 6);
6869
fill(arr, 7);
6970
assert(sum(arr) == 21);
7071
assert(sum_twice(arr) == 42);
@@ -88,5 +89,14 @@ int main() {
8889

8990
const char *names[2] = {"ab", "cde"};
9091
assert(total_len(names) == 5);
92+
93+
int rows[2][3] = {{1, 2, 3}, {4, 5, 6}};
94+
int (*p)[3] = rows;
95+
++p;
96+
assert(*p == &rows[1][0]);
97+
int (&r)[3] = *p;
98+
assert(r[0] == 4);
99+
assert(sum(r) == 15);
100+
assert(sum(*p) == 15);
91101
return 0;
92102
}

0 commit comments

Comments
 (0)