diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 9f9d10247..c11ea4977 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -214,6 +214,14 @@ bool IsUnionArrayMember(const clang::Expr *base) { return false; } +clang::Expr *SubscriptedArray(clang::Expr *base) { + while (auto *sub = clang::dyn_cast( + base->IgnoreImplicit())) { + base = sub->getBase(); + } + return base; +} + // TODO: this will be gone when the AST matcher lands std::tuple ReplaceNonUniformLibcField(clang::MemberExpr *expr) { diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index 5843ed862..384455d50 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -57,6 +57,8 @@ bool IsInMainFile(const clang::Decl *decl); bool IsUnionArrayMember(const clang::Expr *base); +clang::Expr *SubscriptedArray(clang::Expr *base); + std::tuple ReplaceNonUniformLibcField(clang::MemberExpr *expr); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 11d44dc09..5edffdeb3 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -101,36 +101,14 @@ static bool IsPointerType(clang::ASTContext &ctx, clang::QualType type) { IteratorCategory::Contiguous; } -bool ConverterRefCount::PendingDeref::compute_inner_boxed( - clang::Expr *expr) const { - if (!expr) { - return false; - } - if (!IsBoxedType(ctx, expr->getType().getNonReferenceType())) { - return false; - } - if (auto *ase = clang::dyn_cast(expr)) { - auto base_type = ase->getBase()->IgnoreCasts()->getType(); - if (base_type->isPointerType()) - return IsBoxedType(ctx, base_type->getPointeeType()); - return IsBoxedType(ctx, base_type.getNonReferenceType()); - } - if (auto *oce = clang::dyn_cast(expr)) { - return IsBoxedType(ctx, oce->getArg(0)->getType().getNonReferenceType()); - } - return false; -} - -void ConverterRefCount::PendingDeref::set(std::string str, bool fresh, - clang::Expr *expr) { +void ConverterRefCount::PendingDeref::set(std::string str, bool fresh) { assert_consumed(); - set_unchecked(std::move(str), fresh, expr); + set_unchecked(std::move(str), fresh); } -void ConverterRefCount::PendingDeref::set_unchecked(std::string str, bool fresh, - clang::Expr *expr) { +void ConverterRefCount::PendingDeref::set_unchecked(std::string str, + bool fresh) { value = std::move(str); - pointee_is_boxed = compute_inner_boxed(expr); ptr_is_fresh = fresh; type = ComputedExprType::Pending; } @@ -148,22 +126,6 @@ std::string ConverterRefCount::GetInnerType(clang::QualType type) { return std::move(str).substr(pos + 1, end - pos - 1); } -ConverterRefCount::PushUnboxedIfSimple::PushUnboxedIfSimple( - ConverterRefCount &c, std::string_view outer, clang::QualType inner_type) - : c(c) { - bool unboxed = outer == "Ptr<%>" || outer == "%"; - - // Vectors are boxed until the last element - if (!unboxed && (outer == "Vec<%>" || outer == "Box<%>")) { - if (!IsBoxedType(c.ctx_, inner_type)) { - unboxed = true; - } - } - - c.conversion_kind_.push_back(unboxed ? ConversionKind::Unboxed - : ConversionKind::FullRefCount); -} - std::string ConverterRefCount::GetSafeTypeAsString(clang::QualType qual_type) const { std::string type_as_string; @@ -278,7 +240,9 @@ bool ConverterRefCount::VisitIncompleteArrayType( clang::IncompleteArrayType *type) { std::string str; { - PushUnboxedIfSimple push(*this, "Box<%>", type->getElementType()); + PushConversionKind push(*this, type->getElementType()->isArrayType() + ? ConversionKind::Pointee + : ConversionKind::Unboxed); str = std::format("Box<[{}]>", ToString(type->getElementType())); } StrCat(BoxType(std::move(str))); @@ -298,7 +262,7 @@ bool ConverterRefCount::VisitReferenceType(clang::ReferenceType *type) { auto element_type = pointee_type->getAsArrayTypeUnsafe()->getElementType(); PushConversionKind push1(*this, ConversionKind::Ptr, !element_type->isArrayType()); - PushConversionKind push2(*this, ConversionKind::FullRefCount, + PushConversionKind push2(*this, ConversionKind::Pointee, element_type->isArrayType()); StrCat("Ptr<"); Convert(element_type); @@ -338,8 +302,7 @@ bool ConverterRefCount::VisitPointerType(clang::PointerType *type) { bool pointee_is_array = pointee_type->isArrayType() && !IsVaListType(pointee_type); PushConversionKind push1(*this, ConversionKind::Ptr, !pointee_is_array); - PushConversionKind push2(*this, ConversionKind::FullRefCount, - pointee_is_array); + PushConversionKind push2(*this, ConversionKind::Pointee, pointee_is_array); if (pointee_type->isRecordType() && IsAbstractUserClass(pointee_type->getAsRecordDecl())) { StrCat("PtrDyngetSize()).c_str())); break; case ConversionKind::Ptr: { - PushConversionKind elem(*this, ConversionKind::FullRefCount, + PushConversionKind elem(*this, ConversionKind::Pointee, type->getElementType()->isArrayType()); Convert(type->getElementType()); break; } case ConversionKind::Pointee: case ConversionKind::FullRefCount: { - PushConversionKind elem(*this, ConversionKind::FullRefCount, + PushConversionKind elem(*this, ConversionKind::Pointee, type->getElementType()->isArrayType()); StrCat("Box<["); Convert(type->getElementType()); @@ -403,6 +366,7 @@ std::string ConverterRefCount::ConvertObject(clang::Expr *expr, if (shape == ObjectShape::Element && expr->getType()->isPointerType()) { auto pointee = expr->getType()->getPointeeType(); if (IsBoxedType(ctx_, pointee) || pointee->isArrayType()) { + PushConversionKind push(*this, ConversionKind::Pointee); computed_expr_type_ = ComputedExprType::FreshPointer; return std::format("Ptr::<{}>::decay(&({}))", ToString(pointee), std::move(str)); @@ -532,13 +496,23 @@ std::string ConverterRefCount::ConvertPtrType(clang::QualType type) { return std::format("Ptr<{}>", std::move(str)); } -bool ConverterRefCount::VisitArraySubscriptExpr( - clang::ArraySubscriptExpr *expr) { +bool ConverterRefCount::IsPointerSubscript( + const clang::ArraySubscriptExpr *expr) const { auto *base = expr->getBase(); if (base->IgnoreCasts()->getType()->isPointerType() || IsUnionArrayMember(base) || IsArrayFieldPtr(ctx_, base) || (IsReferenceType(base) && base->IgnoreCasts()->getType()->isArrayType())) { + return true; + } + auto *row = clang::dyn_cast(base->IgnoreCasts()); + return row && IsPointerSubscript(row); +} + +bool ConverterRefCount::VisitArraySubscriptExpr( + clang::ArraySubscriptExpr *expr) { + auto *base = expr->getBase(); + if (IsPointerSubscript(expr)) { ConvertPointerSubscript(expr); } else { if (!base->IgnoreCasts()->getType()->isArrayType()) { @@ -546,7 +520,7 @@ bool ConverterRefCount::VisitArraySubscriptExpr( pending_deref_.assert_consumed(); Buffer buf(*this); ConvertArraySubscript(base, expr->getIdx(), expr->getType()); - pending_deref_.set_unchecked(std::move(buf).str(), isFresh(), expr); + pending_deref_.set_unchecked(std::move(buf).str(), isFresh()); return false; } PushParen paren(*this); @@ -1945,10 +1919,13 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { } auto conv = getConversionKind(); - // 2D arrays are FullRefCount'ed on the second level as well. - PushConversionKind push( - *this, ConversionKind::Unboxed, - !(expr->getNumInits() > 0 && expr->getInit(0)->getType()->isArrayType())); + bool rows = + expr->getNumInits() > 0 && expr->getInit(0)->getType()->isArrayType(); + PushConversionKind push(*this, + rows && conv == ConversionKind::FullRefCount + ? ConversionKind::Pointee + : ConversionKind::Unboxed, + !rows || conv == ConversionKind::FullRefCount); switch (conv) { case ConversionKind::Unboxed: @@ -2210,7 +2187,9 @@ bool ConverterRefCount::VisitCXXNewExpr(clang::CXXNewExpr *expr) { } else { auto array_size_as_string = ToString(*expr->getArraySize()); auto alloc_type = expr->getAllocatedType(); - PushConversionKind push(*this, ConversionKind::Unboxed); + PushConversionKind push(*this, alloc_type->isArrayType() + ? ConversionKind::Pointee + : ConversionKind::Unboxed); auto alloc_type_as_string = ToString(alloc_type); auto default_alloc_type_as_string = GetDefaultAsString(alloc_type); @@ -2301,28 +2280,10 @@ bool ConverterRefCount::VisitCXXForRangeStmtVector( PushBrace brace(*this); - // handle multi-level types such as Vec>> - if (IsBoxedType(ctx_, stmt->getRangeInit()->getType()) && - GetInnerType(stmt->getRangeInit()->getType()).starts_with("Value<")) { - StrCat(keyword::kLet, loop_var_name, token::kColon); - - if (loop_var->getType()->isReferenceType()) { - StrCat(ToString(loop_var->getType()), token::kAssign, loop_var_name, - GetPointerDerefSuffix(loop_var->getType().getNonReferenceType()), - ".as_pointer()"); - } else { - PushConversionKind push(*this, ConversionKind::FullRefCount); - StrCat(ToString(loop_var->getType()), token::kAssign, - "Rc::new(RefCell::new(", loop_var_name, - GetPointerDerefSuffix(loop_var->getType()), ".borrow().clone()))"); - } - StrCat(token::kSemiColon); - } else { - auto type = loop_var->getType(); - bool copy = type.isPODType(ctx_) && !type->isRecordType(); - EmitByValueShadow(loop_var, loop_var_name + GetPointerDerefSuffix(type) + - (copy ? "" : ".clone()")); - } + auto type = loop_var->getType(); + bool copy = type.isPODType(ctx_) && !type->isRecordType(); + EmitByValueShadow(loop_var, loop_var_name + GetPointerDerefSuffix(type) + + (copy ? "" : ".clone()")); ConvertForRangeBody(stmt); @@ -2529,7 +2490,7 @@ ConverterRefCount::GetArrayDefaultAsString(clang::QualType qual_type) { size_as_string.c_str(), default_as_string); } PushConversionKind push(*this, element_type->isArrayType() - ? ConversionKind::FullRefCount + ? ConversionKind::Pointee : ConversionKind::Unboxed); auto element_type_as_string = ToString(element_type); auto default_as_string = GetDefaultAsString(element_type); @@ -2947,7 +2908,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr( ConvertObject(expr->getArg(0), ObjectShape::Element), ConvertPtrType(expr->getArg(0)->getType()), ConvertSubscriptIndex(expr->getArg(1))), - /*fresh=*/true, expr); + /*fresh=*/true); break; } @@ -2971,7 +2932,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr( : std::format("{}.offset({})", ptr, idx)); if (is_inner_boxed) { - StrCat(GetPointerDerefSuffix(expr->getType()), ".as_pointer()"); + StrCat(".as_pointer()"); if (!isObject()) { StrCat(std::format("as Ptr<{}>)", ToString(expr->getType()))); } @@ -3024,9 +2985,8 @@ clang::DeclRefExpr *ConverterRefCount::GetGlobalArrayRValue(clang::Expr *base) { return nullptr; } // Records are accessed in place, as their fields may be written to. - auto elem_ty = arr_ty->getElementType(); - if (!TypeIsCopyable(elem_ty) && !elem_ty->isPointerType() && - !elem_ty->isArrayType()) { + auto elem_ty = ctx_.getBaseElementType(arr_ty->getElementType()); + if (!TypeIsCopyable(elem_ty) && !elem_ty->isPointerType()) { return nullptr; } return ref; @@ -3062,34 +3022,32 @@ void ConverterRefCount::ConvertArraySubscript(clang::Expr *base, } if (is_inner_boxed) { - StrCat(GetPointerDerefSuffix(type), ".as_pointer()"); + StrCat(".as_pointer()"); } } computed_expr_type_ = ComputedExprType::FreshPointer; - } else if (auto *global = GetGlobalArrayRValue(base)) { - // Read just the element instead of cloning the whole global array. - // The index is evaluated first, as it may itself access the global. - StrCat(std::format( - "({{ let __idx = ({}) as usize; {}.with(|rc| rc.borrow()[__idx]{}) }})", - ConvertRValue(idx), ConvertDeclRef(global, global->getDecl()), - TypeIsCopyable(type) ? "" : ".clone()")); + } else if (auto *global = GetGlobalArrayRValue(SubscriptedArray(base))) { + std::vector idxs = {idx}; + for (auto *row = base->IgnoreImplicit(); + auto *sub = clang::dyn_cast(row); + row = sub->getBase()->IgnoreImplicit()) { + idxs.push_back(sub->getIdx()); + } + std::string lets; + std::string path; + for (unsigned i = idxs.size(); i-- > 0;) { + auto n = idxs.size() - 1 - i; + lets += std::format("let __idx{} = ({}) as usize; ", n, + ConvertRValue(idxs[i])); + path += std::format("[__idx{}]", n); + } + StrCat(std::format("({{ {}{}.with(|rc| rc.borrow(){}{}) }})", lets, + ConvertDeclRef(global, global->getDecl()), path, + TypeIsCopyable(type) ? "" : ".clone()")); SetFreshType(type); } else { - if (isLValue() && - clang::isa(base->IgnoreImplicit())) { - PushExprKind push(*this, ExprKind::RValue); - Convert(base->IgnoreImplicit()); - } else { - Convert(base->IgnoreImplicit()); - } - if (clang::isa(base->IgnoreImplicit())) { - if (isRValue()) { - StrCat(".borrow()"); - } else { - StrCat(".borrow_mut()"); - } - } + Convert(base->IgnoreImplicit()); StrCat(std::format("[({}) as usize]", ConvertRValue(idx))); SetValueFreshness(type); } @@ -3110,7 +3068,7 @@ void ConverterRefCount::ConvertPointerSubscript( pending_deref_.assert_consumed(); Buffer buf(*this); ConvertPointerElem(base, idx); - pending_deref_.set_unchecked(std::move(buf).str(), isFresh(), expr); + pending_deref_.set_unchecked(std::move(buf).str(), isFresh()); return; } @@ -3122,7 +3080,7 @@ void ConverterRefCount::ConvertPointerSubscript( } else { ConvertPointerOffset(base, idx); if (expr->getType()->isArrayType()) { - StrCat(GetPointerDerefSuffix(expr->getType()), ".as_pointer()"); + StrCat(".as_pointer()"); } } if (deref) { @@ -3165,8 +3123,10 @@ void ConverterRefCount::ConvertAddrOf(clang::Expr *expr, auto pointee_type = pointer_type->getPointeeType(); if (isObject() && WantsElementPtr() && (IsBoxedType(ctx_, pointee_type) || pointee_type->isArrayType())) { + auto ptr = ConvertPointer(expr); + PushConversionKind push(*this, ConversionKind::Pointee); StrCat(std::format("Ptr::<{}>::decay(&({}))", ToString(pointee_type), - ConvertPointer(expr))); + std::move(ptr))); computed_expr_type_ = ComputedExprType::FreshPointer; return; } @@ -3206,12 +3166,12 @@ void ConverterRefCount::ConvertDeref(clang::Expr *expr) { } if (isAddrOf() && pointee_type->isArrayType()) { - str = std::format("({}){}.as_pointer()", std::move(str), - GetPointerDerefSuffix(pointee_type)); + str = std::format("({}).as_pointer()", std::move(str)); } if (isObject() && WantsElementPtr() && (IsBoxedType(ctx_, pointee_type) || pointee_type->isArrayType())) { + PushConversionKind push(*this, ConversionKind::Pointee); StrCat(std::format("Ptr::<{}>::decay(&({}))", ToString(pointee_type), std::move(str))); computed_expr_type_ = ComputedExprType::FreshPointer; @@ -3354,17 +3314,10 @@ std::string ConverterRefCount::ConvertMappedMethodCall( return receiver + ConvertIRFragment(mc.body, expr, args, num_args, ctx); } - bool is_boxed = pending_deref_.is_boxed(); auto ptr = pending_deref_.take(); auto body = ConvertIRFragment(mc.body, expr, args, num_args, ctx); SetFreshType(expr->getType()); - if (is_boxed) { - return std::format( - "{}.with_mut(|__v: &mut Value<{}>| (*__v.borrow_mut()){})", ptr, - ToString(arg->getType()), body); - } - return std::format("{}.with_mut(|__v: {}| __v{})", ptr, param_type, body); } @@ -3373,7 +3326,7 @@ std::string ConverterRefCount::ConvertPointeeType(clang::QualType ptr_type) { PushConversionKind push(*this, ConversionKind::Unboxed); auto pointee = ptr_type->getPointeeType(); if (pointee->isArrayType()) { - PushConversionKind array(*this, ConversionKind::FullRefCount); + PushConversionKind array(*this, ConversionKind::Pointee); return std::string(Trim(ToString(pointee))); } if (!pointee->isRecordType()) { diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index e76995a74..b2e54bd63 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -294,6 +294,8 @@ class ConverterRefCount final : public Converter { clang::DeclRefExpr *GetGlobalArrayRValue(clang::Expr *base); void ConvertPointerSubscript(clang::ArraySubscriptExpr *expr) override; + bool IsPointerSubscript(const clang::ArraySubscriptExpr *expr) const; + void ConvertFunctionMain(const clang::FunctionDecl *decl, const std::string_view main_function_name) override; @@ -494,14 +496,6 @@ class ConverterRefCount final : public Converter { } }; - struct PushUnboxedIfSimple { - ConverterRefCount &c; - PushUnboxedIfSimple(ConverterRefCount &c, std::string_view outer_type, - clang::QualType inner_type); - - ~PushUnboxedIfSimple() { c.conversion_kind_.pop_back(); } - }; - std::string BoxType(std::string &&str) const; std::string BoxValue(std::string &&str) const; @@ -514,32 +508,25 @@ class ConverterRefCount final : public Converter { // emit ptr.write(rhs), or by ConvertMappedMethodCall to emit // ptr.with_mut(...). struct PendingDeref { - PendingDeref(ComputedExprType &type, clang::ASTContext &ctx) - : type(type), ctx(ctx) {} - void set(std::string str, bool fresh, clang::Expr *expr = nullptr); - void set_unchecked(std::string str, bool fresh, - clang::Expr *expr = nullptr); + PendingDeref(ComputedExprType &type) : type(type) {} + void set(std::string str, bool fresh); + void set_unchecked(std::string str, bool fresh); std::string take() { auto result = std::move(value); value.clear(); - pointee_is_boxed = false; ptr_is_fresh = false; return result; } bool empty() const { return value.empty(); } - bool is_boxed() const { return pointee_is_boxed; } bool is_fresh() const { return ptr_is_fresh; } void assert_consumed() const { assert(value.empty() && "pending_deref_ not consumed"); } private: - bool compute_inner_boxed(clang::Expr *expr) const; ComputedExprType &type; - clang::ASTContext &ctx; std::string value; - bool pointee_is_boxed = false; bool ptr_is_fresh = false; - } pending_deref_{computed_expr_type_, ctx_}; + } pending_deref_{computed_expr_type_}; }; } // namespace cpp2rust diff --git a/docs/src/codegen/types/boxing.md b/docs/src/codegen/types/boxing.md index 9f055eaef..f0cc94fa2 100644 --- a/docs/src/codegen/types/boxing.md +++ b/docs/src/codegen/types/boxing.md @@ -48,12 +48,13 @@ the copy on entry then lets the body treat parameters exactly like local variables. The preamble skips reference parameters, which are a `Ptr` and never boxed. -Nested containers, library ones and arrays alike, box each level except the -innermost, so that every inner container can be borrowed and mutated on its own, -and a pointer can be taken to it. The boxing is written into the type rules -themselves: `std::vector>` maps to `Vec>>`, and -the `carray` rules map `int a[2][2]` to `Box<[Value>]>`, both before -the outer `Value<...>` of the declaration is added. +Nested containers, library ones and arrays alike, store their inner levels +inline: `std::vector>` maps to `Vec>`, and +`int a[2][2]` to `Box<[Box<[i32]>]>`, both inside the outer `Value<...>` of the +declaration. Copying a nested container with `clone` hence copies every level, +as C++ does. A pointer into an inner container is a `Nested` pointer (see +[Pointer kinds](../../runtime/rc.md#pointer-kinds)), which reaches the inner +container through the outer one. Struct fields are stored inline, so that a whole struct is a single allocation, and a pointer to a field records the struct's allocation and the field's byte diff --git a/docs/src/codegen/types/mappings.md b/docs/src/codegen/types/mappings.md index 02bd111b5..6030d9a33 100644 --- a/docs/src/codegen/types/mappings.md +++ b/docs/src/codegen/types/mappings.md @@ -3,24 +3,24 @@ The table gives the spelling of each C++ type in both models, before any refcount boxing. `T` stands for the translated inner type. -| C++ | Unsafe model | Refcount model | -| ------------------------------ | ----------------------------------------------- | --------------------------------------------------------- | -| `bool` | `bool` | `bool` | -| `int`, `unsigned long`, ... | `i32`, `u64`, ... (host width) | same | -| `float`, `double` | `f32`, `f64` | same | -| `char` | `libc::c_char` | `u8` | -| `size_t` and other typedefs | by type rule (`usize`), else desugared | same | -| `T[N]` | `[T; N]` | `Box<[T]>` | -| `T[]` | `[T]` | `Box<[T]>` | -| `struct S`, `enum E` | `S`, `E` | same | -| `T *`, `T &` | `*mut T`, `*const T` | [`Ptr`](../../runtime/rc.md#values-and-pointers) | -| `Abstract *` | `*mut dyn Abstract` | [`PtrDyn`](../../runtime/ptr-dyn.md) | -| `void *` | `*mut ::libc::c_void` | [`AnyPtr`](../../runtime/void.md) | -| `R (*)(A)` | `Option R>` | [`FnPtr R>`](../../runtime/fn-ptr.md) | -| `va_list` | [`VaList`](../../runtime/va-args.md) | [`VaList`](../../runtime/va-args.md) | -| lambda closure | `impl Fn(A) -> R` as a parameter, `_` elsewhere | same | -| `std::unique_ptr` | by type rule (`Option>`) | by type rule (`Option>`) | -| `std::vector` and other STL | by type rule (`Vec`) | by type rule (`Vec`, `Vec>>` when nested) | +| C++ | Unsafe model | Refcount model | +| ------------------------------ | ----------------------------------------------- | --------------------------------------------------- | +| `bool` | `bool` | `bool` | +| `int`, `unsigned long`, ... | `i32`, `u64`, ... (host width) | same | +| `float`, `double` | `f32`, `f64` | same | +| `char` | `libc::c_char` | `u8` | +| `size_t` and other typedefs | by type rule (`usize`), else desugared | same | +| `T[N]` | `[T; N]` | `Box<[T]>` | +| `T[]` | `[T]` | `Box<[T]>` | +| `struct S`, `enum E` | `S`, `E` | same | +| `T *`, `T &` | `*mut T`, `*const T` | [`Ptr`](../../runtime/rc.md#values-and-pointers) | +| `Abstract *` | `*mut dyn Abstract` | [`PtrDyn`](../../runtime/ptr-dyn.md) | +| `void *` | `*mut ::libc::c_void` | [`AnyPtr`](../../runtime/void.md) | +| `R (*)(A)` | `Option R>` | [`FnPtr R>`](../../runtime/fn-ptr.md) | +| `va_list` | [`VaList`](../../runtime/va-args.md) | [`VaList`](../../runtime/va-args.md) | +| lambda closure | `impl Fn(A) -> R` as a parameter, `_` elsewhere | same | +| `std::unique_ptr` | by type rule (`Option>`) | by type rule (`Option>`) | +| `std::vector` and other STL | by type rule (`Vec`) | by type rule (`Vec`) | Other built-ins (`wchar_t`, `long double`, `char16_t`) are omitted. Rvalue references (`T &&`) have no mapping of their own; they reach the converter only diff --git a/docs/src/codegen/types/traits.md b/docs/src/codegen/types/traits.md index 734cf67d7..d76157c46 100644 --- a/docs/src/codegen/types/traits.md +++ b/docs/src/codegen/types/traits.md @@ -25,11 +25,10 @@ The refcount model skips `Clone` altogether when the copy constructor is deleted, and never derives `Copy`. It derives `Clone` for C structs and for classes with an implicit or defaulted copy constructor, which copy each field with its own `clone`, i.e., its C++ copy constructor. The exceptions are fields -that are or nest a `Value`, such as `std::vector` (`Value>`, see -[Boxing](boxing.md)) or `std::vector>` -(`Value>>>`), whose derived `clone` would share the `Value`s -instead of copying them; the generated `Clone` then translates the implicit copy -constructor, which copies them deeply. +that are a `Value`, such as `std::vector` (`Value>`, see +[Boxing](boxing.md)), whose derived `clone` would share the `Value` instead of +copying it; the generated `Clone` then translates the implicit copy constructor, +which copies them deeply. A user-defined copy constructor takes a `Ptr` to the source, while `clone` only has `&self`. `clone` passes it a pointer to a shallow copy of `self`, built diff --git a/docs/src/rules/rewriting.md b/docs/src/rules/rewriting.md index 7ce8efda4..0d3588001 100644 --- a/docs/src/rules/rewriting.md +++ b/docs/src/rules/rewriting.md @@ -61,20 +61,6 @@ reference usages (`r.push_back(20)` with `std::vector &r = *p`); both are [translated as a `Ptr`](../codegen/pointers.md), and that `Ptr` is what `with_mut` is called on. -When the pointee is itself a boxed value (`Value`, i.e. `Rc>`), -the closure takes `&mut Value` and an extra borrow is inserted. This is the -case for nested containers: the refcount model translates -`std::vector>` as `Vec>>` so that each element -has interior mutability of its own, and a `Ptr` to an inner vector therefore -points at a `Value>`, not a `Vec`: - -```rust -ptr.with_mut(|__v: &mut Value>| (*__v.borrow_mut()).push(20)) -``` - -The closure type is built from the C++ argument's type, not the rule's declared -parameter type. - ## The read-access counterpart For read access the converter does not emit a closure. A pointer receiver whose diff --git a/docs/src/runtime/rc.md b/docs/src/runtime/rc.md index aedb8d9e3..1ea11b348 100644 --- a/docs/src/runtime/rc.md +++ b/docs/src/runtime/rc.md @@ -60,6 +60,11 @@ A `Ptr` knows what it points into: - `StackArray` and `HeapArray`: a fixed-size array. - `StackVec` and `HeapVec`: a growable buffer; `std::vector` contents and string literals live in one. +- `Nested`: an inner vector or array of a nested container, such as a row of + `std::vector>` or of `int[2][3]`. The inner container is + stored inline in the outer one, so the pointer holds the pointer to it, as an + `Rc>`, and reaches it through the outer container on every + access. - `Field`: a field of a struct (see [Pointers to fields](#pointers-to-fields)). - `Reinterpreted`: a byte-level view produced by a cast (see [Type Reinterpretation](./reinterpret.md)). @@ -300,9 +305,11 @@ through every other pointer at once. Where the code generator needs a different view of the same allocation, it does not upgrade at all. `decay` turns a pointer to a whole `Vec` or `Box<[T]>` -into a pointer to its first element by re-tagging the existing weak reference, -and `Ptr::to_dyn` (see [Virtual Classes](./ptr-dyn.md)) does the same for the -upcast to a trait object. +into a pointer to its first element by re-tagging the existing weak reference; +when the `Vec` or `Box<[T]>` is itself an element of another container, it +instead allocates a `Nested` pointer that holds the pointer to it. `Ptr::to_dyn` +(see [Virtual Classes](./ptr-dyn.md)) re-tags the weak reference in the same way +for the upcast to a trait object. ## Arithmetic diff --git a/libcc2rs/src/cstr.rs b/libcc2rs/src/cstr.rs index 500ec7279..62e7086c5 100644 --- a/libcc2rs/src/cstr.rs +++ b/libcc2rs/src/cstr.rs @@ -261,6 +261,10 @@ impl Ptr { let b = rc.borrow(); f(until_nul(&b[self.offset..])) } + PtrKind::Nested(parent) => { + let root = parent.root(); + f(until_nul(&parent.borrow_slice(&*root)[self.offset..])) + } PtrKind::Field(root) => { let root = crate::field::upgrade(root); let b = Ptr::::borrow_field(&*root, self.offset); diff --git a/libcc2rs/src/field.rs b/libcc2rs/src/field.rs index 6fb1ece05..cc76e129e 100644 --- a/libcc2rs/src/field.rs +++ b/libcc2rs/src/field.rs @@ -152,6 +152,9 @@ impl FieldPtr for Ptr { PtrKind::StackArray(w) | PtrKind::HeapArray(w) => (w.clone(), start()), PtrKind::StackVec(w) | PtrKind::HeapVec(w) => (w.clone(), start()), PtrKind::Field(root) => (root.clone(), self.offset), + PtrKind::Nested(_) => { + panic!("pointers to fields of elements of nested containers are not supported") + } PtrKind::Reinterpreted(_) => { let (alloc, byte_offset) = self.original_alloc().unwrap(); return Ptr::from_original_alloc(alloc, byte_offset.wrapping_add(offset)); diff --git a/libcc2rs/src/rc.rs b/libcc2rs/src/rc.rs index 0a0e37252..a9a3345c8 100644 --- a/libcc2rs/src/rc.rs +++ b/libcc2rs/src/rc.rs @@ -5,7 +5,7 @@ use crate::{CChar, PostfixDec, PostfixInc, PrefixDec, PrefixInc}; use std::any::{Any, TypeId}; use std::{ - cell::{Ref, RefCell}, + cell::{Ref, RefCell, RefMut}, fmt, ops::Sub, rc::{Rc, Weak}, @@ -29,6 +29,71 @@ impl DeepClone for Value { } } +pub trait SliceParent { + fn root(&self) -> Rc; + fn borrow_slice<'a>(&self, root: &'a dyn Any) -> Ref<'a, [T]>; + fn borrow_slice_mut<'a>(&self, root: &'a dyn Any) -> RefMut<'a, [T]>; + fn address(&self) -> usize; +} + +impl SliceParent for Ptr +where + C: AsRef<[T]> + AsMut<[T]> + 'static, +{ + fn root(&self) -> Rc { + match &self.kind { + PtrKind::StackVec(weak) | PtrKind::HeapVec(weak) => { + weak.upgrade().unwrap_or_else(|| dangling()) + } + PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => { + weak.upgrade().unwrap_or_else(|| dangling()) + } + PtrKind::Nested(parent) => parent.root(), + _ => unreachable!(), + } + } + + fn borrow_slice<'a>(&self, root: &'a dyn Any) -> Ref<'a, [T]> { + let offset = self.offset; + match &self.kind { + PtrKind::StackVec(_) | PtrKind::HeapVec(_) => Ref::map( + root.downcast_ref::>>().unwrap().borrow(), + |v| v[offset].as_ref(), + ), + PtrKind::StackArray(_) | PtrKind::HeapArray(_) => Ref::map( + root.downcast_ref::>>().unwrap().borrow(), + |a| a[offset].as_ref(), + ), + PtrKind::Nested(parent) => Ref::map(parent.borrow_slice(root), |s| s[offset].as_ref()), + _ => unreachable!(), + } + } + + fn borrow_slice_mut<'a>(&self, root: &'a dyn Any) -> RefMut<'a, [T]> { + let offset = self.offset; + match &self.kind { + PtrKind::StackVec(_) | PtrKind::HeapVec(_) => RefMut::map( + root.downcast_ref::>>().unwrap().borrow_mut(), + |v| v[offset].as_mut(), + ), + PtrKind::StackArray(_) | PtrKind::HeapArray(_) => RefMut::map( + root.downcast_ref::>>() + .unwrap() + .borrow_mut(), + |a| a[offset].as_mut(), + ), + PtrKind::Nested(parent) => { + RefMut::map(parent.borrow_slice_mut(root), |s| s[offset].as_mut()) + } + _ => unreachable!(), + } + } + + fn address(&self) -> usize { + self.kind.address().wrapping_add(self.byte_offset()) + } +} + pub(crate) struct ReinterpretedView { // Pointer to the source of reinterpret pub(crate) alloc: OriginalAlloc, @@ -48,6 +113,7 @@ pub(crate) enum PtrKind { HeapArray(Weak>>), StackVec(Weak>>), HeapVec(Weak>>), + Nested(Rc>), Field(Weak), Reinterpreted(Rc), } @@ -62,6 +128,11 @@ pub enum StrongPtr { rc: Rc>>, offset: usize, }, + Nested { + root: Rc, + parent: Rc>, + offset: usize, + }, Field { root: Rc, offset: usize, @@ -84,6 +155,11 @@ impl StrongPtr { StrongPtr::StackSingle(rc) => rc.borrow(), StrongPtr::Vec { rc, offset } => Ref::map(rc.borrow(), |v| &v[*offset]), StrongPtr::StackArray { rc, offset } => Ref::map(rc.borrow(), |a| &a[*offset]), + StrongPtr::Nested { + root, + parent, + offset, + } => Ref::map(parent.borrow_slice(&**root), |v| &v[*offset]), StrongPtr::Field { root, offset } => Ptr::borrow_field(&**root, *offset), StrongPtr::Reinterpreted { alloc, @@ -114,6 +190,7 @@ impl fmt::Debug for PtrKind { PtrKind::Null => write!(f, "Null"), PtrKind::StackVec(w) => write!(f, "StackVec({:?})", w.as_ptr()), PtrKind::HeapVec(w) => write!(f, "HeapVec({:?})", w.as_ptr()), + PtrKind::Nested(parent) => write!(f, "Nested(0x{:x})", parent.address()), PtrKind::StackSingle(w) => write!(f, "StackSingle({:?})", w.as_ptr()), PtrKind::HeapSingle(w) => write!(f, "HeapSingle({:?})", w.as_ptr()), PtrKind::StackArray(w) => write!(f, "StackArray({:?})", w.as_ptr()), @@ -133,6 +210,7 @@ impl Clone for PtrKind { PtrKind::Null => PtrKind::Null, PtrKind::StackVec(weak) => PtrKind::StackVec(weak.clone()), PtrKind::HeapVec(weak) => PtrKind::HeapVec(weak.clone()), + PtrKind::Nested(parent) => PtrKind::Nested(Rc::clone(parent)), PtrKind::StackSingle(weak) => PtrKind::StackSingle(weak.clone()), PtrKind::HeapSingle(weak) => PtrKind::HeapSingle(weak.clone()), PtrKind::StackArray(weak) => PtrKind::StackArray(weak.clone()), @@ -149,6 +227,7 @@ impl PtrKind { PtrKind::Null => 0, PtrKind::StackSingle(w) | PtrKind::HeapSingle(w) => w.as_ptr() as usize, PtrKind::StackVec(w) | PtrKind::HeapVec(w) => w.as_ptr() as usize, + PtrKind::Nested(parent) => parent.address(), PtrKind::StackArray(w) | PtrKind::HeapArray(w) => w.as_ptr() as usize, PtrKind::Field(root) => root.as_ptr() as *const () as usize, PtrKind::Reinterpreted(data) => data.alloc.address(), @@ -321,6 +400,7 @@ impl Ptr { PtrKind::StackVec(weak) | PtrKind::HeapVec(weak) => { weak.upgrade().expect("ub: dangling pointer").borrow().len() } + PtrKind::Nested(parent) => parent.borrow_slice(&*parent.root()).len(), PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => { weak.upgrade().expect("ub: dangling pointer").borrow().len() } @@ -338,6 +418,7 @@ impl Ptr { .expect("ub: dangling pointer") .borrow() .is_empty(), + PtrKind::Nested(parent) => parent.borrow_slice(&*parent.root()).is_empty(), PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => weak .upgrade() .expect("ub: dangling pointer") @@ -394,6 +475,11 @@ impl Ptr { rc: weak.upgrade().unwrap_or_else(|| dangling()), offset: self.offset, }, + PtrKind::Nested(parent) => StrongPtr::Nested { + root: parent.root(), + parent: Rc::clone(parent), + offset: self.offset, + }, PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => StrongPtr::StackArray { rc: weak.upgrade().unwrap_or_else(|| dangling()), offset: self.offset, @@ -449,6 +535,10 @@ impl Ptr { OriginalAlloc::slice(weak), self.offset.wrapping_mul(T::byte_size()), ), + PtrKind::Nested(parent) => ( + OriginalAlloc::nested(parent), + self.offset.wrapping_mul(T::byte_size()), + ), PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => ( OriginalAlloc::slice(weak), self.offset.wrapping_mul(T::byte_size()), @@ -532,6 +622,10 @@ impl Ptr { let mut borrow = rc.borrow_mut(); f(&mut borrow[offset]) } + PtrKind::Nested(parent) => { + let root = parent.root(); + f(&mut parent.borrow_slice_mut(&*root)[offset]) + } PtrKind::Field(root) => { let root = upgrade_root(root); f(&mut Self::borrow_field_mut(&*root, offset)) @@ -598,6 +692,10 @@ impl Ptr { let borrow = rc.borrow(); f(&borrow[offset]) } + PtrKind::Nested(parent) => { + let root = parent.root(); + f(&parent.borrow_slice(&*root)[offset]) + } PtrKind::Field(root) => { let root = upgrade_root(root); f(&Self::borrow_field(&*root, offset)) @@ -654,6 +752,10 @@ impl Ptr { let mut b = rc.borrow_mut(); f(&mut b[off..off + len]) } + PtrKind::Nested(parent) => { + let root = parent.root(); + f(&mut parent.borrow_slice_mut(&*root)[off..off + len]) + } PtrKind::Field(root) => { assert!(len <= 1, "ub: with_slice_mut out of bounds"); let root = upgrade_root(root); @@ -689,6 +791,10 @@ impl Ptr { let b = rc.borrow(); f(&b[off..off + len]) } + PtrKind::Nested(parent) => { + let root = parent.root(); + f(&parent.borrow_slice(&*root)[off..off + len]) + } PtrKind::Field(root) => { assert!(len <= 1, "ub: with_slice out of bounds"); let root = upgrade_root(root); @@ -744,6 +850,10 @@ impl Ptr { let strong = weak.upgrade().expect("ub: dangling pointer"); (*strong.borrow_mut())[self.get_offset()..last].sort(); } + PtrKind::Nested(ref parent) => { + let root = parent.root(); + parent.borrow_slice_mut(&*root)[self.get_offset()..last].sort(); + } PtrKind::StackArray(ref weak) | PtrKind::HeapArray(ref weak) => { let strong = weak.upgrade().expect("ub: dangling pointer"); (*strong.borrow_mut())[self.get_offset()..last].sort(); @@ -788,6 +898,11 @@ impl Ptr { let mut borrow = strong.borrow_mut(); sort(&mut borrow, self.get_offset(), last, &mut cmp); } + PtrKind::Nested(ref parent) => { + let root = parent.root(); + let mut borrow = parent.borrow_slice_mut(&*root); + sort(&mut borrow, self.get_offset(), last, &mut cmp); + } PtrKind::StackArray(ref weak) | PtrKind::HeapArray(ref weak) => { let strong = weak.upgrade().expect("ub: dangling pointer"); let mut borrow = strong.borrow_mut(); @@ -1052,7 +1167,21 @@ impl AsPointer for Rc>> { } } -impl Ptr> { +impl AsPointer> for Ptr> { + #[inline] + fn as_pointer(&self) -> Ptr> { + self.clone() + } +} + +impl AsPointer for Ptr> { + #[inline] + fn as_pointer(&self) -> Ptr { + self.decay() + } +} + +impl Ptr> { #[inline] pub fn decay(&self) -> Ptr { match &self.kind { @@ -1065,12 +1194,34 @@ impl Ptr> { offset: self.offset, kind: PtrKind::HeapVec(weak.clone()), }, + PtrKind::StackVec(_) + | PtrKind::HeapVec(_) + | PtrKind::StackArray(_) + | PtrKind::HeapArray(_) + | PtrKind::Nested(_) => Ptr { + offset: 0, + kind: PtrKind::Nested(Rc::new(self.clone())), + }, _ => panic!("ub: invalid decay"), } } } -impl Ptr> { +impl AsPointer> for Ptr> { + #[inline] + fn as_pointer(&self) -> Ptr> { + self.clone() + } +} + +impl AsPointer for Ptr> { + #[inline] + fn as_pointer(&self) -> Ptr { + self.decay() + } +} + +impl Ptr> { #[inline] pub fn decay(&self) -> Ptr { match &self.kind { @@ -1083,6 +1234,14 @@ impl Ptr> { offset: self.offset, kind: PtrKind::HeapArray(weak.clone()), }, + PtrKind::StackVec(_) + | PtrKind::HeapVec(_) + | PtrKind::StackArray(_) + | PtrKind::HeapArray(_) + | PtrKind::Nested(_) => Ptr { + offset: 0, + kind: PtrKind::Nested(Rc::new(self.clone())), + }, _ => panic!("ub: invalid decay"), } } @@ -1111,7 +1270,9 @@ impl ToOwnedOption for Ptr { PtrKind::StackSingle(_) | PtrKind::StackArray(_) => { panic!("Can't own a stack variable") } - PtrKind::StackVec(_) | PtrKind::HeapVec(_) => panic!("Can't own a vector"), + PtrKind::StackVec(_) | PtrKind::HeapVec(_) | PtrKind::Nested(_) => { + panic!("Can't own a vector") + } PtrKind::Field(..) => panic!("Can't own a field"), PtrKind::HeapArray(_) => panic!("Can't own an array variable as single"), PtrKind::Reinterpreted(_) => panic!("Can't own a reinterpreted pointer"), @@ -1138,7 +1299,9 @@ impl ToOwnedOption> for Ptr { PtrKind::StackSingle(_) | PtrKind::StackArray(_) => { panic!("Can't own a stack variable") } - PtrKind::StackVec(_) | PtrKind::HeapVec(_) => panic!("Can't own a vector"), + PtrKind::StackVec(_) | PtrKind::HeapVec(_) | PtrKind::Nested(_) => { + panic!("Can't own a vector") + } PtrKind::Field(..) => panic!("Can't own a field"), PtrKind::HeapSingle(_) => panic!("Can't own a single variable as an array"), PtrKind::Reinterpreted(_) => panic!("Can't own a reinterpreted pointer"), @@ -1159,7 +1322,9 @@ impl fmt::Debug for Ptr { PtrKind::StackVec(w) | PtrKind::HeapVec(w) => { (Weak::as_ptr(w) as usize).wrapping_add(self.byte_offset()) } - PtrKind::Field(..) => self.kind.address().wrapping_add(self.byte_offset()), + PtrKind::Nested(..) | PtrKind::Field(..) => { + self.kind.address().wrapping_add(self.byte_offset()) + } PtrKind::Reinterpreted(data) => data.alloc.address().wrapping_add(self.byte_offset()), }; write!(f, "0x{:x}", addr) diff --git a/libcc2rs/src/reinterpret.rs b/libcc2rs/src/reinterpret.rs index d103561f0..6c7f7e3bb 100644 --- a/libcc2rs/src/reinterpret.rs +++ b/libcc2rs/src/reinterpret.rs @@ -9,7 +9,7 @@ use std::{ }; use crate::field::{Root, upgrade as upgrade_root}; -use crate::rc::Ptr; +use crate::rc::{Ptr, SliceParent}; pub trait ByteRepr: 'static { fn byte_size() -> usize @@ -182,6 +182,7 @@ pub struct OriginalAlloc { enum Storage { Alloc(Weak), Field(Weak, usize), + Nested(Rc, usize), } // The storage passed to the AllocOps of a field. @@ -213,6 +214,13 @@ impl OriginalAlloc { } } + pub(crate) fn nested(parent: &Rc>) -> Self { + Self { + storage: Storage::Nested(Rc::new(Rc::clone(parent)), parent.address()), + ops: &NestedOps::(PhantomData), + } + } + #[inline] fn with_storage(&self, f: impl FnOnce(&dyn Any) -> R) -> R { match &self.storage { @@ -221,6 +229,7 @@ impl OriginalAlloc { root: upgrade_root(root), field: *field, }), + Storage::Nested(parent, _) => f(&**parent), } } @@ -245,6 +254,7 @@ impl OriginalAlloc { Storage::Field(root, field) => { (root.as_ptr() as *const () as usize).wrapping_add(*field) } + Storage::Nested(_, address) => *address, } } @@ -460,3 +470,25 @@ impl AllocOps for FieldOps { T::byte_size() } } + +struct NestedOps(PhantomData T>); + +impl AllocOps for NestedOps { + fn read_bytes(&self, parent: &dyn Any, byte_offset: usize, buf: &mut [u8]) { + let parent = parent.downcast_ref::>>().unwrap(); + let root = parent.root(); + slice_read_bytes(&parent.borrow_slice(&*root), byte_offset, buf); + } + + fn write_bytes(&self, parent: &dyn Any, byte_offset: usize, data: &[u8]) { + let parent = parent.downcast_ref::>>().unwrap(); + let root = parent.root(); + slice_write_bytes(&mut parent.borrow_slice_mut(&*root), byte_offset, data); + } + + fn total_byte_len(&self, parent: &dyn Any) -> usize { + let parent = parent.downcast_ref::>>().unwrap(); + let root = parent.root(); + parent.borrow_slice(&*root).len() * T::byte_size() + } +} diff --git a/rules/deque/src.cpp b/rules/deque/src.cpp index 4850169ff..bbabcdf39 100644 --- a/rules/deque/src.cpp +++ b/rules/deque/src.cpp @@ -22,8 +22,7 @@ template void f4(std::deque &o, T1 &&value) { template void f5(std::deque &o) { return o.pop_front(); } -template -void f7(std::deque> &o, const std::vector &value) { +template void f7(std::deque &o, const T1 &value) { return o.push_back(value); } @@ -50,10 +49,4 @@ T1 &f12(std::deque &o, Init &&...args) { return o.emplace_back(std::forward(args)...); } -template -std::vector &f13(std::deque> &o, - Init, Args> &&...args) { - return o.emplace_back(std::forward(args)...); -} - template std::deque f14() { return std::deque(); } diff --git a/rules/deque/tgt_refcount.rs b/rules/deque/tgt_refcount.rs index b70e9d05d..107fa289c 100644 --- a/rules/deque/tgt_refcount.rs +++ b/rules/deque/tgt_refcount.rs @@ -2,8 +2,6 @@ // Distributed under the MIT license that can be found in the LICENSE file. use libcc2rs::*; -use std::cell::RefCell; -use std::rc::Rc; fn f1(a0: Ptr) -> Ptr { a0.to_last() @@ -13,10 +11,6 @@ fn f2(a0: Ptr) -> Ptr { a0 } -fn f7(a0: Ptr>>>, a1: Value>) { - a0.with_mut(|__v: &mut Vec>>| __v.push(a1)) -} - fn f10(a0: Ptr>, a1: Vec) { a0.write(a1) } @@ -24,8 +18,3 @@ fn f10(a0: Ptr>, a1: Vec) { fn f11(a0: Ptr>, a1: &mut Vec) { a0.write(std::mem::take(&mut *a1)) } - -fn f13(a0: Ptr>>>, init: Vec) { - let __init = init; - a0.with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new(__init)))) -} diff --git a/rules/deque/tgt_unsafe.rs b/rules/deque/tgt_unsafe.rs index bcd63fda9..85a1eafc4 100644 --- a/rules/deque/tgt_unsafe.rs +++ b/rules/deque/tgt_unsafe.rs @@ -33,7 +33,7 @@ unsafe fn f5(a0: &mut Vec) -> T1 { a0.remove(0) } -unsafe fn f7(a0: &mut Vec>, a1: Vec) { +unsafe fn f7(a0: &mut Vec, a1: T1) { a0.push(a1) } @@ -58,11 +58,6 @@ unsafe fn f12(a0: &mut Vec, init: T1) { a0.push(__init) } -unsafe fn f13(a0: &mut Vec>, init: Vec) { - let __init = init; - a0.push(__init) -} - unsafe fn f14() -> Vec { Vec::new() } diff --git a/rules/deque_cxx11/src.cpp b/rules/deque_cxx11/src.cpp index 5df869405..a61657225 100644 --- a/rules/deque_cxx11/src.cpp +++ b/rules/deque_cxx11/src.cpp @@ -10,8 +10,3 @@ template void f1(std::deque &o, Init &&...args) { return o.emplace_back(std::forward(args)...); } - -template -void f2(std::deque> &o, Init, Args> &&...args) { - return o.emplace_back(std::forward(args)...); -} diff --git a/rules/deque_cxx11/tgt_refcount.rs b/rules/deque_cxx11/tgt_refcount.rs deleted file mode 100644 index f7ac46cf4..000000000 --- a/rules/deque_cxx11/tgt_refcount.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2022-present INESC-ID. -// Distributed under the MIT license that can be found in the LICENSE file. - -use libcc2rs::*; -use std::cell::RefCell; -use std::rc::Rc; - -fn f2(a0: Ptr>>>, init: Vec) { - let __init = init; - a0.with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new(__init)))) -} diff --git a/rules/deque_cxx11/tgt_unsafe.rs b/rules/deque_cxx11/tgt_unsafe.rs index b5d238af7..c41e321a0 100644 --- a/rules/deque_cxx11/tgt_unsafe.rs +++ b/rules/deque_cxx11/tgt_unsafe.rs @@ -5,8 +5,3 @@ unsafe fn f1(a0: &mut Vec, init: T1) { let __init = init; a0.push(__init) } - -unsafe fn f2(a0: &mut Vec>, init: Vec) { - let __init = init; - a0.push(__init) -} diff --git a/rules/vector/src.cpp b/rules/vector/src.cpp index 56917b184..d3f7918ed 100644 --- a/rules/vector/src.cpp +++ b/rules/vector/src.cpp @@ -9,7 +9,6 @@ template using t1 = std::vector; template using t2 = typename std::vector::iterator; -template using t3 = std::vector>; template using t4 = typename std::vector::const_iterator; template > @@ -147,25 +146,6 @@ typename std::vector::iterator f28(typename std::vector::iterator a0, return a0.operator++(a1); } -template -std::vector> f29(const std::vector> &&o) { - return std::vector>(std::move(o)); -} - -template std::vector> f30(std::size_t n) { - return std::vector>(n); -} - -template -void f31(std::vector> &o, std::vector &&value) { - return o.push_back(std::move(value)); -} - -template -void f32(std::vector> &o, std::size_t n) { - return o.resize(n); -} - template typename std::vector::iterator::difference_type f33(const typename std::vector::iterator &it1, @@ -236,11 +216,6 @@ template const T1 &f51(const std::vector &o) { return o.back(); } -template -void f52(std::vector> &o, const std::vector &value) { - return o.push_back(value); -} - template typename std::vector::iterator f53(std::vector &o, typename std::vector::const_iterator pos, @@ -259,10 +234,6 @@ std::vector &f55(std::vector &dst, std::vector &&src) { return dst.operator=(std::move(src)); } -template std::vector &f56(std::vector> &o) { - return o.back(); -} - template typename std::vector::const_iterator f57(const std::vector &o) { return o.cend(); @@ -494,12 +465,6 @@ const T1 &f99(const std::vector &o) { return o.back(); } -template > -void f100(std::vector> &o, - const std::vector &value) { - return o.push_back(value); -} - template > typename std::vector::iterator f101(std::vector &o, typename std::vector::const_iterator pos, @@ -553,23 +518,11 @@ std::vector f110(const std::vector &o) { return std::vector(o); } -template -std::vector> &f111(std::vector> &dst, - std::vector> &&src) { - return dst.operator=(std::move(src)); -} - template T1 &f112(std::vector &o, Init &&...args) { return o.emplace_back(std::forward(args)...); } -template -std::vector &f113(std::vector> &o, - Init, Args> &&...args) { - return o.emplace_back(std::forward(args)...); -} - template , typename... Args> T1 &f114(std::vector &o, Init &&...args) { return o.emplace_back(std::forward(args)...); diff --git a/rules/vector/tgt_refcount.rs b/rules/vector/tgt_refcount.rs index d380838ed..30fccec46 100644 --- a/rules/vector/tgt_refcount.rs +++ b/rules/vector/tgt_refcount.rs @@ -2,17 +2,11 @@ // Distributed under the MIT license that can be found in the LICENSE file. use libcc2rs::*; -use std::cell::RefCell; -use std::rc::Rc; fn t2() -> Ptr { Ptr::null() } -fn t3() -> Vec>> { - Vec::new() -} - fn t4() -> Ptr { Ptr::null() } @@ -97,29 +91,6 @@ fn f28(a0: &mut Ptr) -> Ptr { a0.postfix_inc() } -fn f29(a0: Vec>>) -> Vec>> { - a0.iter() - .map(|inner_vec| Rc::new(RefCell::new(inner_vec.borrow().clone()))) - .collect() -} - -fn f30(a0: usize) -> Vec>> { - (0..(a0) as usize) - .map(|_| >>::default()) - .collect::>() -} - -fn f31(a0: Ptr>>>, a1: &mut Vec) { - a0.with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new(std::mem::take(&mut *a1)))) - }) -} - -fn f32(a0: Ptr>>>, a1: usize) { - let _a0 = a1 as usize; - a0.with_mut(|__v: &mut Vec>>| __v.resize_with(_a0, >>::default)) -} - fn f33(a0: Ptr, a1: Ptr) -> isize { ((a0.get_offset() as isize) - (a1.get_offset() as isize)) } @@ -181,10 +152,6 @@ fn f51(a0: Ptr) -> Ptr { a0.to_last() } -fn f52(a0: Ptr>>>, a1: Vec) { - a0.with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new(a1)))) -} - fn f53( a0: Ptr>, a1: Ptr, @@ -200,10 +167,6 @@ fn f53( a0 + start_idx } -fn f56(a0: &Vec>>) -> Ptr> { - a0[a0.len() - 1].as_pointer() -} - fn f55(a0: Ptr>, a1: &mut Vec) { a0.write(std::mem::take(&mut *a1)) } @@ -365,12 +328,3 @@ fn f104(a0: Ptr) -> Ptr { fn f105(a0: Ptr>, a1: Vec) { a0.write(a1) } - -fn f111(a0: Ptr>>>, a1: &mut Vec>>) { - a0.write(std::mem::take(&mut *a1)) -} - -fn f113(a0: Ptr>>>, init: Vec) { - let __init = init; - a0.with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new(__init)))) -} diff --git a/rules/vector/tgt_unsafe.rs b/rules/vector/tgt_unsafe.rs index 64809e678..ad8092f99 100644 --- a/rules/vector/tgt_unsafe.rs +++ b/rules/vector/tgt_unsafe.rs @@ -11,10 +11,6 @@ fn t2() -> *mut T1 { Default::default() } -fn t3() -> Vec> { - Vec::new() -} - fn t4() -> *const T1 { Default::default() } @@ -138,21 +134,6 @@ unsafe fn f27(a0: *const T1, a1: *const T1) -> bool { unsafe fn f28(a0: &mut *mut T1) -> *mut T1 { a0.postfix_inc() } -unsafe fn f29(a0: Vec>) -> Vec> { - a0.clone() -} - -unsafe fn f30(a0: usize) -> Vec> { - (0..(a0) as usize) - .map(|_| >::default()) - .collect::>() -} -unsafe fn f31(a0: &mut Vec>, a1: &mut Vec) { - a0.push(std::mem::take(&mut *a1)) -} -unsafe fn f32(a0: &mut Vec>, a1: usize) { - a0.resize_with(a1 as usize, || >::default()) -} unsafe fn f33(a0: *const T1, a1: *const T1) -> isize { a0.offset_from(a1) @@ -226,10 +207,6 @@ unsafe fn f51(a0: &Vec) -> &T1 { ((a0).last().unwrap()) } -unsafe fn f52(a0: &mut Vec>, a1: Vec) { - a0.push(a1.clone()) -} - unsafe fn f53(a0: &mut Vec, a1: *const T1, a2: *const T1, a3: *const T1) -> *mut T1 { let __off = a1.offset_from(a0.as_ptr()) as usize; let count = a3.offset_from(a2) as usize; @@ -249,10 +226,6 @@ unsafe fn f55(a0: &mut Vec, a1: &mut Vec) { *a0 = std::mem::take(&mut *a1) } -unsafe fn f56(a0: &mut Vec>) -> *mut Vec { - ((a0).last_mut().unwrap()) -} - unsafe fn f57(a0: Vec) -> *const T1 { a0.as_ptr().add(a0.len()) } @@ -447,10 +420,6 @@ unsafe fn f99(a0: &Vec) -> &T1 { ((a0).last().unwrap()) } -unsafe fn f100(a0: &mut Vec>, a1: Vec) { - a0.push(a1.clone()) -} - unsafe fn f101( a0: &mut Vec, a1: *const T1, @@ -503,20 +472,11 @@ unsafe fn f110(a0: Vec) -> Vec { a0.clone() } -unsafe fn f111(a0: &mut Vec>, a1: &mut Vec>) { - *a0 = std::mem::take(&mut *a1) -} - unsafe fn f112(a0: &mut Vec, init: T1) { let __init = init; a0.push(__init) } -unsafe fn f113(a0: &mut Vec>, init: Vec) { - let __init = init; - a0.push(__init) -} - unsafe fn f114(a0: &mut Vec, init: T1) { let __init = init; a0.push(__init) diff --git a/rules/vector_cxx11/src.cpp b/rules/vector_cxx11/src.cpp index 8cf783dce..9262acfba 100644 --- a/rules/vector_cxx11/src.cpp +++ b/rules/vector_cxx11/src.cpp @@ -10,12 +10,6 @@ void f1(std::vector &o, Init &&...args) { return o.emplace_back(std::forward(args)...); } -template -void f2(std::vector> &o, - Init, Args> &&...args) { - return o.emplace_back(std::forward(args)...); -} - template , typename... Args> void f3(std::vector &o, Init &&...args) { return o.emplace_back(std::forward(args)...); diff --git a/rules/vector_cxx11/tgt_refcount.rs b/rules/vector_cxx11/tgt_refcount.rs deleted file mode 100644 index 061e768fb..000000000 --- a/rules/vector_cxx11/tgt_refcount.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2022-present INESC-ID. -// Distributed under the MIT license that can be found in the LICENSE file. - -use libcc2rs::*; -use std::cell::RefCell; -use std::rc::Rc; - -fn f2(a0: Ptr>>>, init: Vec) { - let __init = init; - a0.with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new(__init)))) -} diff --git a/rules/vector_cxx11/tgt_unsafe.rs b/rules/vector_cxx11/tgt_unsafe.rs index 34c9cf8b4..57802c699 100644 --- a/rules/vector_cxx11/tgt_unsafe.rs +++ b/rules/vector_cxx11/tgt_unsafe.rs @@ -6,11 +6,6 @@ unsafe fn f1(a0: &mut Vec, init: T1) { a0.push(__init) } -unsafe fn f2(a0: &mut Vec>, init: Vec) { - let __init = init; - a0.push(__init) -} - unsafe fn f3(a0: &mut Vec, init: T1) { let __init = init; a0.push(__init) diff --git a/tests/ub/out/refcount/row_ptr_outlives_array.rs b/tests/ub/out/refcount/row_ptr_outlives_array.rs new file mode 100644 index 000000000..b98f54202 --- /dev/null +++ b/tests/ub/out/refcount/row_ptr_outlives_array.rs @@ -0,0 +1,26 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn second_row_0() -> Ptr { + let rows: Value]>> = Rc::new(RefCell::new(Box::new([ + Box::new([1, 2, 3]), + Box::new([4, 5, 6]), + ]))); + return (((rows.as_pointer() as Ptr>) + .offset(1) + .as_pointer()) as Ptr); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let mut p: Ptr = ({ second_row_0() }); + return (elem!(p, 0).read()); +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/refcount/row_ptr_outlives_vector.rs b/tests/ub/out/refcount/row_ptr_outlives_vector.rs new file mode 100644 index 000000000..f3f7de668 --- /dev/null +++ b/tests/ub/out/refcount/row_ptr_outlives_vector.rs @@ -0,0 +1,23 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn second_row_0() -> Ptr { + let rows: Value>> = Rc::new(RefCell::new(vec![vec![1, 2, 3], vec![4, 5, 6]])); + return ((rows.as_pointer() as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let mut p: Ptr = ({ second_row_0() }); + return (elem!(p, 0).read()); +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/refcount/row_ptr_past_row_end.rs b/tests/ub/out/refcount/row_ptr_past_row_end.rs new file mode 100644 index 000000000..9114480d6 --- /dev/null +++ b/tests/ub/out/refcount/row_ptr_past_row_end.rs @@ -0,0 +1,23 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let rows: Value]>> = Rc::new(RefCell::new(Box::new([ + Box::new([1, 2, 3]), + Box::new([4, 5, 6]), + ]))); + let mut p: Ptr = (((rows.as_pointer() as Ptr>) + .offset(0) + .as_pointer()) as Ptr); + return (elem!(p, 3).read()); +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/refcount/row_ptr_sub_across_rows.rs b/tests/ub/out/refcount/row_ptr_sub_across_rows.rs new file mode 100644 index 000000000..5bbe0d2e2 --- /dev/null +++ b/tests/ub/out/refcount/row_ptr_sub_across_rows.rs @@ -0,0 +1,27 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let rows: Value]>> = Rc::new(RefCell::new(Box::new([ + Box::new([1, 2, 3]), + Box::new([4, 5, 6]), + ]))); + return ((((((rows.as_pointer() as Ptr>) + .offset(1) + .as_pointer()) as Ptr) + - (((((rows.as_pointer() as Ptr>) + .offset(0) + .as_pointer()) as Ptr) + .offset(0)) + .offset((2) as isize))) as i64) as i32); +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/unsafe/row_ptr_outlives_array.rs b/tests/ub/out/unsafe/row_ptr_outlives_array.rs new file mode 100644 index 000000000..624517491 --- /dev/null +++ b/tests/ub/out/unsafe/row_ptr_outlives_array.rs @@ -0,0 +1,23 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn second_row_0() -> *mut i32 { + let mut rows: [[i32; 3]; 2] = [[1, 2, 3], [4, 5, 6]]; + return rows[(1) as usize].as_mut_ptr(); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut p: *mut i32 = (unsafe { second_row_0() }); + return (*p.offset((0) as isize)); +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/unsafe/row_ptr_outlives_vector.rs b/tests/ub/out/unsafe/row_ptr_outlives_vector.rs new file mode 100644 index 000000000..51b8fbe4d --- /dev/null +++ b/tests/ub/out/unsafe/row_ptr_outlives_vector.rs @@ -0,0 +1,23 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn second_row_0() -> *mut i32 { + let mut rows: Vec> = vec![vec![1, 2, 3], vec![4, 5, 6]]; + return rows[(1_usize)].as_mut_ptr(); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut p: *mut i32 = (unsafe { second_row_0() }); + return (*p.offset((0) as isize)); +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/unsafe/row_ptr_past_row_end.rs b/tests/ub/out/unsafe/row_ptr_past_row_end.rs new file mode 100644 index 000000000..63002e23b --- /dev/null +++ b/tests/ub/out/unsafe/row_ptr_past_row_end.rs @@ -0,0 +1,20 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut rows: [[i32; 3]; 2] = [[1, 2, 3], [4, 5, 6]]; + let mut p: *mut i32 = rows[(0) as usize].as_mut_ptr(); + return (*p.offset((3) as isize)); +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/ub/out/unsafe/row_ptr_sub_across_rows.rs b/tests/ub/out/unsafe/row_ptr_sub_across_rows.rs new file mode 100644 index 000000000..b027bd5d4 --- /dev/null +++ b/tests/ub/out/unsafe/row_ptr_sub_across_rows.rs @@ -0,0 +1,21 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut rows: [[i32; 3]; 2] = [[1, 2, 3], [4, 5, 6]]; + return ((((rows[(1) as usize].as_mut_ptr() as usize + - ((&mut rows[(0) as usize][(0) as usize] as *mut i32).offset((2) as isize)) as usize) + / ::std::mem::size_of::()) as i64) as i32); +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/ub/row_ptr_outlives_array.cpp b/tests/ub/row_ptr_outlives_array.cpp new file mode 100644 index 000000000..1b552f4a6 --- /dev/null +++ b/tests/ub/row_ptr_outlives_array.cpp @@ -0,0 +1,10 @@ +// panic-ub: refcount +// nondet-result: unsafe +int *second_row() { + int rows[2][3] = {{1, 2, 3}, {4, 5, 6}}; + return rows[1]; +} +int main() { + int *p = second_row(); + return p[0]; +} diff --git a/tests/ub/row_ptr_outlives_vector.cpp b/tests/ub/row_ptr_outlives_vector.cpp new file mode 100644 index 000000000..786ba9076 --- /dev/null +++ b/tests/ub/row_ptr_outlives_vector.cpp @@ -0,0 +1,12 @@ +// panic-ub: refcount +// nondet-result: unsafe +#include + +int *second_row() { + std::vector> rows = {{1, 2, 3}, {4, 5, 6}}; + return rows[1].data(); +} +int main() { + int *p = second_row(); + return p[0]; +} diff --git a/tests/ub/row_ptr_past_row_end.cpp b/tests/ub/row_ptr_past_row_end.cpp new file mode 100644 index 000000000..4cb3f2d1d --- /dev/null +++ b/tests/ub/row_ptr_past_row_end.cpp @@ -0,0 +1,7 @@ +// panic-ub: refcount +// nondet-result: unsafe +int main() { + int rows[2][3] = {{1, 2, 3}, {4, 5, 6}}; + int *p = rows[0]; + return p[3]; +} diff --git a/tests/ub/row_ptr_sub_across_rows.cpp b/tests/ub/row_ptr_sub_across_rows.cpp new file mode 100644 index 000000000..07abfa859 --- /dev/null +++ b/tests/ub/row_ptr_sub_across_rows.cpp @@ -0,0 +1,6 @@ +// panic-ub: refcount +// nondet-result: unsafe +int main() { + int rows[2][3] = {{1, 2, 3}, {4, 5, 6}}; + return rows[1] - (&rows[0][0] + 2); +} diff --git a/tests/unit/array_reference.cpp b/tests/unit/array_reference.cpp index b86f967fa..35037357a 100644 --- a/tests/unit/array_reference.cpp +++ b/tests/unit/array_reference.cpp @@ -1,4 +1,5 @@ #include +#include int len(const char (&s)[5]) { int n = 0; @@ -59,6 +60,8 @@ int total_len(const char *(&names)[2]) { return len5(names[0]) + len5(names[1]); } +const int kTable[2][3] = {{1, 2, 3}, {4, 5, 6}}; + int main() { assert(len("beta") == 4); char buf[5] = "abcd"; @@ -101,5 +104,17 @@ int main() { int (*q)[3] = rows; assert(sum(q[1]) == 15); assert(q[1] == &rows[1][0]); + q[1][2] = 8; + assert(rows[1][2] == 8 && rows[0][2] == 3); + rows[0][1] = rows[0][2]; + q[1][0] = q[0][1]; + q[1][1] += q[0][2]; + assert(rows[0][1] == 3 && rows[1][0] == 3 && rows[1][1] == 8); + assert(&rows[1][2] - &rows[1][0] == 2); + + int key[4] = {0, 4, 5, 6}; + assert(memcmp(&key[1], kTable[1], sizeof(kTable[1])) == 0); + assert(memcmp(&key[1], kTable[0], sizeof(kTable[0])) != 0); + assert(kTable[1][2] == 6 && kTable[0][1] == 2); return 0; } diff --git a/tests/unit/out/refcount/12_test.rs b/tests/unit/out/refcount/12_test.rs index a756517e3..492fe1f82 100644 --- a/tests/unit/out/refcount/12_test.rs +++ b/tests/unit/out/refcount/12_test.rs @@ -11,14 +11,13 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value>>> = Rc::new(RefCell::new(Vec::new())); - (v.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new( - (0..(10_usize) as usize) - .map(|_| ::default()) - .collect::>(), - ))) - }); + let v: Value>> = Rc::new(RefCell::new(Vec::new())); + { + let __a1 = (0..(10_usize) as usize) + .map(|_| ::default()) + .collect::>(); + (*v.borrow_mut()).push(__a1) + }; return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/addr_of_global.rs b/tests/unit/out/refcount/addr_of_global.rs index 854475880..55b55ef76 100644 --- a/tests/unit/out/refcount/addr_of_global.rs +++ b/tests/unit/out/refcount/addr_of_global.rs @@ -46,16 +46,16 @@ pub fn main() { fn main_0() -> i32 { assert!( (({ - let __idx = (0) as usize; - items_3.with(|rc| rc.borrow()[__idx].clone()) + let __idx0 = (0) as usize; + items_3.with(|rc| rc.borrow()[__idx0].clone()) }) .with(|__s| __s.value) == 1) ); assert!( (({ - let __idx = (1) as usize; - items_3.with(|rc| rc.borrow()[__idx].clone()) + let __idx0 = (1) as usize; + items_3.with(|rc| rc.borrow()[__idx0].clone()) }) .with(|__s| __s.value) == 2) @@ -63,16 +63,16 @@ fn main_0() -> i32 { assert!(({ (*obj_4.with(Value::clone).borrow()).p.clone() }.with(|__s| __s.value) == 42)); assert!( (({ - let __idx = (0) as usize; - cache_5.with(|rc| rc.borrow()[__idx].clone()) + let __idx0 = (0) as usize; + cache_5.with(|rc| rc.borrow()[__idx0].clone()) }) .with(|__s| __s.value) == 1) ); assert!( (({ - let __idx = (1) as usize; - cache_5.with(|rc| rc.borrow()[__idx].clone()) + let __idx0 = (1) as usize; + cache_5.with(|rc| rc.borrow()[__idx0].clone()) }) .with(|__s| __s.value) == 2) diff --git a/tests/unit/out/refcount/array_2d_default.rs b/tests/unit/out/refcount/array_2d_default.rs index 84f0af9dc..44e29720d 100644 --- a/tests/unit/out/refcount/array_2d_default.rs +++ b/tests/unit/out/refcount/array_2d_default.rs @@ -15,44 +15,36 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let grid: Value>]>> = Rc::new(RefCell::new( + let grid: Value]>> = Rc::new(RefCell::new( (0..3) - .map(|_| Rc::new(RefCell::new((0..6).map(|_| 0_i8).collect::>()))) - .collect::>]>>(), + .map(|_| (0..6).map(|_| 0_i8).collect::>()) + .collect::]>>(), )); let mut i: i32 = 0; 'loop_: while (((i < 3) as i32) != 0) { ({ - let _row: Ptr = (((grid.as_pointer() as Ptr>>) - .offset(i) - .read() - .as_pointer()) as Ptr); + let _row: Ptr = + (((grid.as_pointer() as Ptr>).offset(i).as_pointer()) as Ptr); let _c: i8 = ((('a' as i32) + i) as i8); fill_row_0(_row, _c) }); i.postfix_inc(); } assert!( - (((((*grid.borrow())[(0) as usize].borrow()[(0) as usize] as i32) == ('a' as i32)) as i32) - != 0) + (((((*grid.borrow())[(0) as usize][(0) as usize] as i32) == ('a' as i32)) as i32) != 0) ); assert!( - (((((*grid.borrow())[(1) as usize].borrow()[(0) as usize] as i32) == ('b' as i32)) as i32) - != 0) + (((((*grid.borrow())[(1) as usize][(0) as usize] as i32) == ('b' as i32)) as i32) != 0) ); assert!( - (((((*grid.borrow())[(2) as usize].borrow()[(0) as usize] as i32) == ('c' as i32)) as i32) - != 0) + (((((*grid.borrow())[(2) as usize][(0) as usize] as i32) == ('c' as i32)) as i32) != 0) ); assert!( - (((((*grid.borrow())[(1) as usize].borrow()[(1) as usize] as i32) == ('\0' as i32)) - as i32) - != 0) + (((((*grid.borrow())[(1) as usize][(1) as usize] as i32) == ('\0' as i32)) as i32) != 0) ); - (*grid.borrow())[(2) as usize].borrow_mut()[(5) as usize] = (('z' as i32) as i8); + (*grid.borrow_mut())[(2) as usize][(5) as usize] = (('z' as i32) as i8); assert!( - (((((*grid.borrow())[(2) as usize].borrow()[(5) as usize] as i32) == ('z' as i32)) as i32) - != 0) + (((((*grid.borrow())[(2) as usize][(5) as usize] as i32) == ('z' as i32)) as i32) != 0) ); return 0; } diff --git a/tests/unit/out/refcount/array_reference.rs b/tests/unit/out/refcount/array_reference.rs index a7ca6c1f7..ed34c37e0 100644 --- a/tests/unit/out/refcount/array_reference.rs +++ b/tests/unit/out/refcount/array_reference.rs @@ -89,6 +89,12 @@ pub fn shift_points_12(p: Ptr, mut d: i32) { pub fn total_len_13(names: Ptr>) -> i32 { return (({ len5_1((elem!((names), 0).read())) }) + ({ len5_1((elem!((names), 1).read())) })); } +thread_local!( + pub static kTable_14: Value]>> = Rc::new(RefCell::new(Box::new([ + Box::new([1, 2, 3]), + Box::new([4, 5, 6]), + ]))); +); pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -136,36 +142,103 @@ fn main_0() -> i32 { Ptr::::from_string_literal(b"cde"), ]))); assert!((({ total_len_13(names.as_pointer(),) }) == 5)); - let rows: Value>]>> = Rc::new(RefCell::new(Box::new([ - Rc::new(RefCell::new(Box::new([1, 2, 3]))), - Rc::new(RefCell::new(Box::new([4, 5, 6]))), + let rows: Value]>> = Rc::new(RefCell::new(Box::new([ + Box::new([1, 2, 3]), + Box::new([4, 5, 6]), ]))); - let mut p: Ptr>> = (rows.as_pointer() as Ptr>>); + let mut p: Ptr> = (rows.as_pointer() as Ptr>); p.prefix_inc(); assert!( - ({ ((p).read().as_pointer() as Ptr::).clone() } == { - ((((rows.as_pointer() as Ptr>>) + ({ ((p).as_pointer() as Ptr::).clone() } == { + ((((rows.as_pointer() as Ptr>) .offset(1) - .read() .as_pointer()) as Ptr) .offset(0)) }) ); - let r: Ptr = ((p).read().as_pointer()).clone(); + let r: Ptr = ((p).as_pointer()).clone(); assert!(((elem!((r), 0).read()) == 4)); assert!((({ sum_2((r).clone(),) }) == 15)); - assert!((({ sum_2(((p).read().as_pointer()).clone(),) }) == 15)); - let mut q: Ptr>> = (rows.as_pointer() as Ptr>>); - assert!((({ sum_2(q.offset((1) as isize).read().as_pointer(),) }) == 15)); + assert!((({ sum_2(((p).as_pointer()).clone(),) }) == 15)); + let mut q: Ptr> = (rows.as_pointer() as Ptr>); + assert!((({ sum_2(q.offset((1) as isize).as_pointer(),) }) == 15)); assert!( - ({ (q.offset((1) as isize).read().as_pointer() as Ptr::) } == { - ((((rows.as_pointer() as Ptr>>) + ({ (q.offset((1) as isize).as_pointer() as Ptr::) } == { + ((((rows.as_pointer() as Ptr>) .offset(1) - .read() .as_pointer()) as Ptr) .offset(0)) }) ); + elem!((q.offset((1) as isize).as_pointer() as Ptr::), 2).write(8); + assert!( + ((*rows.borrow())[(1) as usize][(2) as usize] == 8) + && ((*rows.borrow())[(0) as usize][(2) as usize] == 3) + ); + (*rows.borrow_mut())[(0) as usize][(1) as usize] = + { (*rows.borrow())[(0) as usize][(2) as usize] }; + elem!((q.offset((1) as isize).as_pointer() as Ptr::), 0) + .write({ (elem!((q.offset((0) as isize).as_pointer() as Ptr::), 1).read()) }); + { + let __rhs = { (elem!((q.offset((0) as isize).as_pointer() as Ptr::), 2).read()) }; + elem!((q.offset((1) as isize).as_pointer() as Ptr::), 1) + .with_mut(|__v| *__v = *__v + __rhs) + }; + assert!( + (((*rows.borrow())[(0) as usize][(1) as usize] == 3) + && ((*rows.borrow())[(1) as usize][(0) as usize] == 3)) + && ((*rows.borrow())[(1) as usize][(1) as usize] == 8) + ); + assert!( + ((((((rows.as_pointer() as Ptr>) + .offset(1) + .as_pointer()) as Ptr) + .offset(2)) + - ((((rows.as_pointer() as Ptr>) + .offset(1) + .as_pointer()) as Ptr) + .offset(0))) as i64 + == 2_i64) + ); + let key: Value> = Rc::new(RefCell::new(Box::new([0, 4, 5, 6]))); + assert!( + ((((key.as_pointer() as Ptr).offset(1)) as Ptr::) + .to_any() + .memcmp( + &((((kTable_14.with(|v| v.as_pointer()) as Ptr>) + .offset(1) + .as_pointer()) as Ptr::) as Ptr::) + .to_any(), + ::std::mem::size_of::<[i32; 3]>() + ) + == 0) + ); + assert!( + ((((key.as_pointer() as Ptr).offset(1)) as Ptr::) + .to_any() + .memcmp( + &((((kTable_14.with(|v| v.as_pointer()) as Ptr>) + .offset(0) + .as_pointer()) as Ptr::) as Ptr::) + .to_any(), + ::std::mem::size_of::<[i32; 3]>() + ) + != 0) + ); + assert!( + (({ + let __idx0 = (1) as usize; + let __idx1 = (2) as usize; + kTable_14.with(|rc| rc.borrow()[__idx0][__idx1]) + }) == 6) + && (({ + let __idx0 = (0) as usize; + let __idx1 = (1) as usize; + kTable_14.with(|rc| rc.borrow()[__idx0][__idx1]) + }) == 2) + ); return 0; } -pub fn __cpp2rust_init_globals() {} +pub fn __cpp2rust_init_globals() { + let _ = kTable_14.with(|_| ()); +} diff --git a/tests/unit/out/refcount/clone_vs_move.rs b/tests/unit/out/refcount/clone_vs_move.rs index 4909dfc3e..e542b1edf 100644 --- a/tests/unit/out/refcount/clone_vs_move.rs +++ b/tests/unit/out/refcount/clone_vs_move.rs @@ -146,33 +146,23 @@ fn main_0() -> i32 { assert!((v1[(i as usize)] == i)); i.prefix_inc(); } - let m1: Value>>> = Rc::new(RefCell::new(Vec::new())); + let m1: Value>> = Rc::new(RefCell::new(Vec::new())); let mut i: i32 = 0; 'loop_: while (i < N) { - (m1.as_pointer() as Ptr>>>).with_mut( - |__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new( - (0..(10_usize) as usize) - .map(|_| ::default()) - .collect::>(), - ))) - }, - ); + { + let __a1 = (0..(10_usize) as usize) + .map(|_| ::default()) + .collect::>(); + (*m1.borrow_mut()).push(__a1) + }; i.prefix_inc(); } - let m2: Value>>> = Rc::new(RefCell::new( - (*m1.borrow()) - .iter() - .map(|inner_vec| Rc::new(RefCell::new(inner_vec.borrow().clone()))) - .collect(), - )); + let m2: Value>> = Rc::new(RefCell::new((*m1.borrow()).clone())); let mut i: i32 = 0; 'loop_: while (i < N) { assert!( - ((*((m1.as_pointer() as Ptr>>) + ((*((m1.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -180,10 +170,8 @@ fn main_0() -> i32 { == 10_usize) ); assert!( - ((*((m2.as_pointer() as Ptr>>) + ((*((m2.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -194,10 +182,8 @@ fn main_0() -> i32 { 'loop_: while (j < 10) { assert!( ((elem!( - ((m1.as_pointer() as Ptr>>) + ((m1.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr), (j as usize) ) @@ -206,10 +192,8 @@ fn main_0() -> i32 { ); assert!( ((elem!( - ((m2.as_pointer() as Ptr>>) + ((m2.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr), (j as usize) ) @@ -225,10 +209,8 @@ fn main_0() -> i32 { let mut j: i32 = 0; 'loop_: while (j < 10) { elem!( - ((m2.as_pointer() as Ptr>>) + ((m2.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr), (j as usize) ) @@ -240,10 +222,8 @@ fn main_0() -> i32 { let mut i: i32 = 0; 'loop_: while (i < N) { assert!( - ((*((m1.as_pointer() as Ptr>>) + ((*((m1.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -251,10 +231,8 @@ fn main_0() -> i32 { == 10_usize) ); assert!( - ((*((m2.as_pointer() as Ptr>>) + ((*((m2.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -265,10 +243,8 @@ fn main_0() -> i32 { 'loop_: while (j < 10) { assert!( ((elem!( - ((m1.as_pointer() as Ptr>>) + ((m1.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr), (j as usize) ) @@ -277,10 +253,8 @@ fn main_0() -> i32 { ); assert!( ((elem!( - ((m2.as_pointer() as Ptr>>) + ((m2.as_pointer() as Ptr>) .offset((i as usize)) - .upgrade() - .deref() .as_pointer() as Ptr), (j as usize) ) diff --git a/tests/unit/out/refcount/copy_move_defaulted.rs b/tests/unit/out/refcount/copy_move_defaulted.rs index 6841629f9..2bf9f951f 100644 --- a/tests/unit/out/refcount/copy_move_defaulted.rs +++ b/tests/unit/out/refcount/copy_move_defaulted.rs @@ -121,7 +121,7 @@ pub struct Buffer { pub data: Value>, #[offset(24)] #[byte_size(24)] - pub rows: Value>>>, + pub rows: Value>>, #[offset(48)] pub n: i32, #[offset(52)] @@ -137,13 +137,10 @@ impl Buffer { arr: Rc::new(RefCell::new(Box::new([n, (n + 1)]))), })); let this: Ptr = __this.as_pointer(); - (this.with(|__s| __s.rows.as_pointer()) as Ptr>>>).with_mut( - |__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new( - (*this.with(|__s| __s.data.clone()).borrow()).clone(), - ))) - }, - ); + { + let a0_clone = (*this.with(|__s| __s.data.clone()).borrow()).clone(); + (*this.with(|__s| __s.rows.clone()).borrow_mut()).push(a0_clone) + }; Rc::try_unwrap(__this).ok().unwrap().into_inner() } pub fn move_from(_a0: Ptr) -> Self { @@ -166,7 +163,7 @@ impl Default for Buffer { { Buffer { data: Rc::new(RefCell::new(Default::default())), - rows: Rc::new(RefCell::new(Vec::new())), + rows: Rc::new(RefCell::new(Default::default())), n: 0_i32, arr: Rc::new(RefCell::new((0..2).map(|_| 0_i32).collect::>())), } @@ -361,10 +358,8 @@ fn main_0() -> i32 { ); assert!( (((*{ (*r.borrow()).rows.clone() }.borrow()).len() == 1_usize) - && ((*(({ (*r.borrow()).rows.as_pointer() } as Ptr>>) + && ((*(({ (*r.borrow()).rows.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -458,9 +453,9 @@ impl BufferImpl for Ptr { ((*self).with(|__s| __s.data.as_pointer()) as Ptr>).write(std::mem::take( &mut (*{ (*_a0.upgrade().deref()).data.clone() }.borrow_mut()), )); - ((*self).with(|__s| __s.rows.as_pointer()) as Ptr>>>).write( - std::mem::take(&mut (*{ (*_a0.upgrade().deref()).rows.clone() }.borrow_mut())), - ); + ((*self).with(|__s| __s.rows.as_pointer()) as Ptr>>).write(std::mem::take( + &mut (*{ (*_a0.upgrade().deref()).rows.clone() }.borrow_mut()), + )); field!((*self), n).write({ { (*_a0.upgrade().deref()).n } }); { ((array_field_ptr!((*self), arr)) as Ptr) diff --git a/tests/unit/out/refcount/destructor.rs b/tests/unit/out/refcount/destructor.rs index 80d970846..62a6b62c7 100644 --- a/tests/unit/out/refcount/destructor.rs +++ b/tests/unit/out/refcount/destructor.rs @@ -169,20 +169,20 @@ fn main_0() -> i32 { assert!((order_count_2.with(|rc| *rc.borrow()) == 3)); assert!( (({ - let __idx = (0) as usize; - order_1.with(|rc| rc.borrow()[__idx]) + let __idx0 = (0) as usize; + order_1.with(|rc| rc.borrow()[__idx0]) }) == 3) ); assert!( (({ - let __idx = (1) as usize; - order_1.with(|rc| rc.borrow()[__idx]) + let __idx0 = (1) as usize; + order_1.with(|rc| rc.borrow()[__idx0]) }) == 2) ); assert!( (({ - let __idx = (2) as usize; - order_1.with(|rc| rc.borrow()[__idx]) + let __idx0 = (2) as usize; + order_1.with(|rc| rc.borrow()[__idx0]) }) == 1) ); let mut before: i32 = global_0.with(|rc| *rc.borrow()); diff --git a/tests/unit/out/refcount/foreach_double.rs b/tests/unit/out/refcount/foreach_double.rs index f1ea9f2cf..293f327e3 100644 --- a/tests/unit/out/refcount/foreach_double.rs +++ b/tests/unit/out/refcount/foreach_double.rs @@ -47,27 +47,23 @@ fn main_0() -> i32 { square += { ({ (e1.read()) } * { (e2.read()) }) }; } } - let m: Value>>> = Rc::new(RefCell::new(Vec::new())); + let m: Value>> = Rc::new(RefCell::new(Vec::new())); let v1: Value> = Rc::new(RefCell::new(Vec::new())); - (m.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new(std::mem::take( - &mut (*v1.borrow_mut()), - )))) - }); + { + let __a1 = std::mem::take(&mut (*v1.borrow_mut())); + (*m.borrow_mut()).push(__a1) + }; let v2: Value> = Rc::new(RefCell::new(Vec::new())); - (m.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new(std::mem::take( - &mut (*v2.borrow_mut()), - )))) - }); + { + let __a1 = std::mem::take(&mut (*v2.borrow_mut())); + (*m.borrow_mut()).push(__a1) + }; let v3: Value> = Rc::new(RefCell::new(Vec::new())); - (m.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new(std::mem::take( - &mut (*v3.borrow_mut()), - )))) - }); - 'loop_: for mut row in m.as_pointer() as Ptr>> { - let row: Ptr> = row.upgrade().deref().as_pointer(); + { + let __a1 = std::mem::take(&mut (*v3.borrow_mut())); + (*m.borrow_mut()).push(__a1) + }; + 'loop_: for mut row in m.as_pointer() as Ptr> { 'loop_: for mut col in Ptr::>::decay(&(row)) as Ptr { square += { (col.read()) }; } diff --git a/tests/unit/out/refcount/global_non_const_init.rs b/tests/unit/out/refcount/global_non_const_init.rs index 5bb1678fc..08c6f2dda 100644 --- a/tests/unit/out/refcount/global_non_const_init.rs +++ b/tests/unit/out/refcount/global_non_const_init.rs @@ -111,15 +111,15 @@ pub fn main() { fn main_0() -> i32 { assert!( ((({ - let __idx = (0) as usize; - signature_3.with(|rc| rc.borrow()[__idx]) + let __idx0 = (0) as usize; + signature_3.with(|rc| rc.borrow()[__idx0]) }) as i32) == 10) ); assert!( ((({ - let __idx = (1) as usize; - signature_3.with(|rc| rc.borrow()[__idx]) + let __idx0 = (1) as usize; + signature_3.with(|rc| rc.borrow()[__idx0]) }) as i32) == 4) ); diff --git a/tests/unit/out/refcount/global_pointers.rs b/tests/unit/out/refcount/global_pointers.rs index b6c502cb5..1cd06ac95 100644 --- a/tests/unit/out/refcount/global_pointers.rs +++ b/tests/unit/out/refcount/global_pointers.rs @@ -59,8 +59,8 @@ fn main_0() -> i32 { ); assert!( ({ - let __idx = (i) as usize; - arr_of_pointers_2.with(|rc| rc.borrow()[__idx].clone()) + let __idx0 = (i) as usize; + arr_of_pointers_2.with(|rc| rc.borrow()[__idx0].clone()) }) .is_null() ); diff --git a/tests/unit/out/refcount/ignored_rule.rs b/tests/unit/out/refcount/ignored_rule.rs index b5e5a9f0d..ab24a0d6a 100644 --- a/tests/unit/out/refcount/ignored_rule.rs +++ b/tests/unit/out/refcount/ignored_rule.rs @@ -11,10 +11,8 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let a: Value>]>> = Rc::new(RefCell::new(Box::new([ - Rc::new(RefCell::new(Box::new([1, 2]))), - Rc::new(RefCell::new(Box::new([3, 4]))), - ]))); + let a: Value]>> = + Rc::new(RefCell::new(Box::new([Box::new([1, 2]), Box::new([3, 4])]))); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/nested_vector.rs b/tests/unit/out/refcount/nested_vector.rs index 649d7eb24..2558959f8 100644 --- a/tests/unit/out/refcount/nested_vector.rs +++ b/tests/unit/out/refcount/nested_vector.rs @@ -11,13 +11,14 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v1: Value>>> = Rc::new(RefCell::new(Vec::new())); + let v1: Value>> = Rc::new(RefCell::new(Vec::new())); let mut v2: Vec = vec![1]; - (v1.as_pointer() as Ptr>>>) - .with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new((v2).clone())))); + { + let a0_clone = v2.clone(); + (*v1.borrow_mut()).push(a0_clone) + }; assert!( - (((Ptr::>::decay(&((*v1.borrow())[(*v1.borrow()).len() - 1].as_pointer())) - as Ptr) + (((Ptr::>::decay(&((v1.as_pointer() as Ptr>).to_last())) as Ptr) .offset(0_usize as isize) .read()) == 1) diff --git a/tests/unit/out/refcount/null_in_statics.rs b/tests/unit/out/refcount/null_in_statics.rs index 44412bcb6..1b524fdcf 100644 --- a/tests/unit/out/refcount/null_in_statics.rs +++ b/tests/unit/out/refcount/null_in_statics.rs @@ -50,8 +50,8 @@ fn main_0() -> i32 { 'loop_: while (i < 4) { assert!( ({ - let __idx = (i) as usize; - arr_of_ptr_3.with(|rc| rc.borrow()[__idx].clone()) + let __idx0 = (i) as usize; + arr_of_ptr_3.with(|rc| rc.borrow()[__idx0].clone()) }) .is_null() ); @@ -62,8 +62,8 @@ fn main_0() -> i32 { 'loop_: while (i < 3) { assert!( ({ - let __idx = (i) as usize; - const_arr_of_ptr_5.with(|rc| rc.borrow()[__idx].clone()) + let __idx0 = (i) as usize; + const_arr_of_ptr_5.with(|rc| rc.borrow()[__idx0].clone()) }) .is_null() ); diff --git a/tests/unit/out/refcount/operator_member_pointer_member.rs b/tests/unit/out/refcount/operator_member_pointer_member.rs index 2cd8e505a..4ad2e26fa 100644 --- a/tests/unit/out/refcount/operator_member_pointer_member.rs +++ b/tests/unit/out/refcount/operator_member_pointer_member.rs @@ -71,8 +71,8 @@ fn main_0() -> i32 { ({ Table::operator_index(1) }).write(80); assert!( (({ - let __idx = (1) as usize; - table_0.with(|rc| rc.borrow()[__idx]) + let __idx0 = (1) as usize; + table_0.with(|rc| rc.borrow()[__idx0]) }) == 80) ); return 0; diff --git a/tests/unit/out/refcount/pointer_usize_arith.rs b/tests/unit/out/refcount/pointer_usize_arith.rs index e9bc6a51f..968ed1f3a 100644 --- a/tests/unit/out/refcount/pointer_usize_arith.rs +++ b/tests/unit/out/refcount/pointer_usize_arith.rs @@ -74,14 +74,13 @@ fn main_0() -> i32 { assert!(((q5.read()) == 13)); let mut q6: Ptr = ((arr.as_pointer() as Ptr).offset(n)); assert!(({ (q6).clone() } == { (q5).clone() })); - let matrix: Value>]>> = Rc::new(RefCell::new(Box::new([ - Rc::new(RefCell::new(Box::new([0, 1, 2, 3]))), - Rc::new(RefCell::new(Box::new([4, 5, 6, 7]))), - Rc::new(RefCell::new(Box::new([8, 9, 10, 11]))), + let matrix: Value]>> = Rc::new(RefCell::new(Box::new([ + Box::new([0, 1, 2, 3]), + Box::new([4, 5, 6, 7]), + Box::new([8, 9, 10, 11]), ]))); - let mut row1: Ptr = ((((matrix.as_pointer() as Ptr>>) + let mut row1: Ptr = ((((matrix.as_pointer() as Ptr>) .offset(1) - .read() .as_pointer()) as Ptr) .offset(0)); assert!(((elem!(row1, 2).read()) == 6)); diff --git a/tests/unit/out/refcount/push_emplace_back.rs b/tests/unit/out/refcount/push_emplace_back.rs index 4b7b125af..6e956759f 100644 --- a/tests/unit/out/refcount/push_emplace_back.rs +++ b/tests/unit/out/refcount/push_emplace_back.rs @@ -27,25 +27,27 @@ pub struct Writer { pub struct JPEGData { #[offset(0)] #[byte_size(24)] - pub com_data: Value>>>, + pub com_data: Value>>, #[offset(24)] #[byte_size(24)] - pub app_data: Value>>>, + pub app_data: Value>>, } -pub fn push_param_0(mut dest: Ptr>>>) { - ((dest).clone() as Ptr>>>) - .with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new(Vec::new())))); +pub fn push_param_0(mut dest: Ptr>>) { + { + let __a1 = Vec::new(); + dest.with_mut(|__v: &mut Vec>| __v.push(__a1)) + }; } pub fn push_local_from_field_1(mut jpg: Ptr, mut cond: bool) { let head: Value> = Rc::new(RefCell::new(Box::new([1_u8, 2_u8, 3_u8]))); - let mut dest: Ptr>>> = Ptr::>>>::null(); + let mut dest: Ptr>> = Ptr::>>::null(); if cond { dest = (jpg.with(|__s| __s.com_data.as_pointer())); } else { dest = (jpg.with(|__s| __s.app_data.as_pointer())); } - ((dest).clone() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new({ + { + let __a1 = { let __count = (head.as_pointer() as Ptr) .offset((3) as isize) .get_offset() @@ -53,8 +55,9 @@ pub fn push_local_from_field_1(mut jpg: Ptr, mut cond: bool) { PtrValueIter::new(&(head.as_pointer() as Ptr), __count) .map(|item| u8::try_from(item).ok().unwrap()) .collect::>() - }))) - }); + }; + dest.with_mut(|__v: &mut Vec>| __v.push(__a1)) + }; } pub fn shrink_through_ptr_2(mut comps: Ptr>) { comps.with_mut(|__v: &mut Vec| __v.shrink_to_fit()); @@ -68,7 +71,7 @@ pub fn nested_push_move_3(mut bw: Ptr) { } pub fn emplace_local_from_field_4(mut jpg: Ptr, mut cond: bool) { let head: Value> = Rc::new(RefCell::new(Box::new([1_u8, 2_u8, 3_u8]))); - let mut dest: Ptr>>> = Ptr::>>>::null(); + let mut dest: Ptr>> = Ptr::>>::null(); if cond { dest = (jpg.with(|__s| __s.com_data.as_pointer())); } else { @@ -84,8 +87,7 @@ pub fn emplace_local_from_field_4(mut jpg: Ptr, mut cond: bool) { .map(|item| u8::try_from(item).ok().unwrap()) .collect::>() }; - ((dest).clone() as Ptr>>>) - .with_mut(|__v: &mut Vec>>| __v.push(Rc::new(RefCell::new(__init)))) + dest.with_mut(|__v: &mut Vec>| __v.push(__init)) }; } pub fn nested_emplace_move_5(mut bw: Ptr) { @@ -177,14 +179,12 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let vecs: Value>>> = Rc::new(RefCell::new(Vec::new())); + let vecs: Value>> = Rc::new(RefCell::new(Vec::new())); ({ push_param_0((vecs.as_pointer())) }); assert!(((*vecs.borrow()).len() == 1_usize)); assert!( - (*((vecs.as_pointer() as Ptr>>) + (*((vecs.as_pointer() as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -194,10 +194,8 @@ fn main_0() -> i32 { ({ push_local_from_field_1((jpg.as_pointer()), true) }); assert!(((*{ (*jpg.borrow()).com_data.clone() }.borrow()).len() == 1_usize)); assert!( - ((*(({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>>) + ((*(({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -206,10 +204,8 @@ fn main_0() -> i32 { ); assert!( (((elem!( - (({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>>) + (({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 0_usize ) @@ -218,10 +214,8 @@ fn main_0() -> i32 { ); assert!( (((elem!( - (({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>>) + (({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 1_usize ) @@ -230,10 +224,8 @@ fn main_0() -> i32 { ); assert!( (((elem!( - (({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>>) + (({ (*jpg.borrow()).com_data.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 2_usize ) @@ -253,10 +245,8 @@ fn main_0() -> i32 { ({ emplace_local_from_field_4((jpg.as_pointer()), false) }); assert!(((*{ (*jpg.borrow()).app_data.clone() }.borrow()).len() == 1_usize)); assert!( - ((*(({ (*jpg.borrow()).app_data.as_pointer() } as Ptr>>) + ((*(({ (*jpg.borrow()).app_data.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr>) .upgrade() .deref()) @@ -265,10 +255,8 @@ fn main_0() -> i32 { ); assert!( (((elem!( - (({ (*jpg.borrow()).app_data.as_pointer() } as Ptr>>) + (({ (*jpg.borrow()).app_data.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 0_usize ) @@ -277,10 +265,8 @@ fn main_0() -> i32 { ); assert!( (((elem!( - (({ (*jpg.borrow()).app_data.as_pointer() } as Ptr>>) + (({ (*jpg.borrow()).app_data.as_pointer() } as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 2_usize ) diff --git a/tests/unit/out/refcount/string_escape.rs b/tests/unit/out/refcount/string_escape.rs index 9a00b7d5c..bc76ecd2c 100644 --- a/tests/unit/out/refcount/string_escape.rs +++ b/tests/unit/out/refcount/string_escape.rs @@ -22,8 +22,8 @@ fn main_0() -> i32 { assert!( ({ ((elem!(special, i).read()) as i32) } == { (({ - let __idx = (i) as usize; - expected_0.with(|rc| rc.borrow()[__idx]) + let __idx0 = (i) as usize; + expected_0.with(|rc| rc.borrow()[__idx0]) }) as i32) }) ); diff --git a/tests/unit/out/refcount/struct_2d_array_field.rs b/tests/unit/out/refcount/struct_2d_array_field.rs index 52f5b18e2..d6de67636 100644 --- a/tests/unit/out/refcount/struct_2d_array_field.rs +++ b/tests/unit/out/refcount/struct_2d_array_field.rs @@ -11,7 +11,7 @@ use std::rc::{Rc, Weak}; pub struct table { #[offset(0)] #[byte_size(30)] - pub rows: Value>]>>, + pub rows: Value]>>, #[offset(32)] pub count: usize, } @@ -21,10 +21,8 @@ impl Default for table { table { rows: Rc::new(RefCell::new( (0..3) - .map(|_| { - Rc::new(RefCell::new((0..10).map(|_| 0_i8).collect::>())) - }) - .collect::>]>>(), + .map(|_| (0..10).map(|_| 0_i8).collect::>()) + .collect::]>>(), )), count: 0_usize, } @@ -34,9 +32,9 @@ impl Default for table { thread_local!( pub static T1_0: Value = Rc::new(RefCell::new(table { rows: Rc::new(RefCell::new(Box::new([ - Rc::new(RefCell::new(i8::array_from_literal(b"alpha\0\0\0\0\0"))), - Rc::new(RefCell::new(Box::new([0; 10]))), - Rc::new(RefCell::new(Box::new([0; 10]))), + i8::array_from_literal(b"alpha\0\0\0\0\0"), + Box::new([0; 10]), + Box::new([0; 10]), ]))), count: 1_usize, })); @@ -44,9 +42,9 @@ thread_local!( thread_local!( pub static T2_1: Value
= Rc::new(RefCell::new(table { rows: Rc::new(RefCell::new(Box::new([ - Rc::new(RefCell::new(i8::array_from_literal(b"alpha\0\0\0\0\0"))), - Rc::new(RefCell::new(i8::array_from_literal(b"beta\0\0\0\0\0\0"))), - Rc::new(RefCell::new(Box::new([0; 10]))), + i8::array_from_literal(b"alpha\0\0\0\0\0"), + i8::array_from_literal(b"beta\0\0\0\0\0\0"), + Box::new([0; 10]), ]))), count: 2_usize, })); @@ -60,9 +58,8 @@ fn main_0() -> i32 { assert!( ((({ let mut __it1 = ((({ (*T1_0.with(Value::clone).borrow()).rows.as_pointer() } - as Ptr>>) + as Ptr>) .offset(0) - .read() .as_pointer()) as Ptr) .to_c_string_iterator(); let mut __it2 = Ptr::::from_string_literal(b"alpha").to_c_string_iterator(); @@ -80,7 +77,7 @@ fn main_0() -> i32 { != 0) ); assert!( - (((((*{ (*T1_0.with(Value::clone).borrow()).rows.clone() }.borrow())[(1) as usize].borrow() + (((((*{ (*T1_0.with(Value::clone).borrow()).rows.clone() }.borrow())[(1) as usize] [(0) as usize] as i32) == ('\0' as i32)) as i32) != 0) @@ -89,9 +86,8 @@ fn main_0() -> i32 { assert!( ((({ let mut __it1 = ((({ (*T2_1.with(Value::clone).borrow()).rows.as_pointer() } - as Ptr>>) + as Ptr>) .offset(0) - .read() .as_pointer()) as Ptr) .to_c_string_iterator(); let mut __it2 = Ptr::::from_string_literal(b"alpha").to_c_string_iterator(); @@ -111,9 +107,8 @@ fn main_0() -> i32 { assert!( ((({ let mut __it1 = ((({ (*T2_1.with(Value::clone).borrow()).rows.as_pointer() } - as Ptr>>) + as Ptr>) .offset(1) - .read() .as_pointer()) as Ptr) .to_c_string_iterator(); let mut __it2 = Ptr::::from_string_literal(b"beta").to_c_string_iterator(); @@ -131,24 +126,23 @@ fn main_0() -> i32 { != 0) ); assert!( - (((((*{ (*T2_1.with(Value::clone).borrow()).rows.clone() }.borrow())[(2) as usize].borrow() + (((((*{ (*T2_1.with(Value::clone).borrow()).rows.clone() }.borrow())[(2) as usize] [(0) as usize] as i32) == ('\0' as i32)) as i32) != 0) ); let local: Value
= Rc::new(RefCell::new(table { rows: Rc::new(RefCell::new(Box::new([ - Rc::new(RefCell::new(i8::array_from_literal(b"one\0\0\0\0\0\0\0"))), - Rc::new(RefCell::new(i8::array_from_literal(b"two\0\0\0\0\0\0\0"))), - Rc::new(RefCell::new(i8::array_from_literal(b"three\0\0\0\0\0"))), + i8::array_from_literal(b"one\0\0\0\0\0\0\0"), + i8::array_from_literal(b"two\0\0\0\0\0\0\0"), + i8::array_from_literal(b"three\0\0\0\0\0"), ]))), count: 3_usize, })); assert!( ((({ - let mut __it1 = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>>) + let mut __it1 = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>) .offset(2) - .read() .as_pointer()) as Ptr) .to_c_string_iterator(); let mut __it2 = Ptr::::from_string_literal(b"three").to_c_string_iterator(); @@ -165,13 +159,12 @@ fn main_0() -> i32 { } == 0) as i32) != 0) ); - (*{ (*local.borrow()).rows.clone() }.borrow())[(1) as usize].borrow_mut()[(0) as usize] = + (*{ (*local.borrow()).rows.clone() }.borrow_mut())[(1) as usize][(0) as usize] = (('T' as i32) as i8); assert!( ((({ - let mut __it1 = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>>) + let mut __it1 = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>) .offset(1) - .read() .as_pointer()) as Ptr) .to_c_string_iterator(); let mut __it2 = Ptr::::from_string_literal(b"Two").to_c_string_iterator(); @@ -190,9 +183,8 @@ fn main_0() -> i32 { ); assert!( ((({ - let mut __it1 = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>>) + let mut __it1 = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>) .offset(0) - .read() .as_pointer()) as Ptr) .to_c_string_iterator(); let mut __it2 = Ptr::::from_string_literal(b"one").to_c_string_iterator(); @@ -209,9 +201,8 @@ fn main_0() -> i32 { } == 0) as i32) != 0) ); - let mut p: Ptr = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>>) + let mut p: Ptr = ((({ (*local.borrow()).rows.as_pointer() } as Ptr>) .offset(2) - .read() .as_pointer()) as Ptr); assert!((((((elem!(p, 0).read()) as i32) == ('t' as i32)) as i32) != 0)); assert!(((({ (*local.borrow()).count } == 3_usize) as i32) != 0)); diff --git a/tests/unit/out/refcount/vector3.rs b/tests/unit/out/refcount/vector3.rs index 0f6c15101..34d9098d1 100644 --- a/tests/unit/out/refcount/vector3.rs +++ b/tests/unit/out/refcount/vector3.rs @@ -11,67 +11,55 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value>>> = Rc::new(RefCell::new(Vec::new())); + let v: Value>> = Rc::new(RefCell::new(Vec::new())); { - let _a0 = 2_usize as usize; - (v.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.resize_with(_a0, >>::default) - }) + let __a0 = 2_usize as usize; + (*v.borrow_mut()).resize_with(__a0, || >::default()) }; { let __a0 = 2_usize as usize; - elem!((v.as_pointer() as Ptr>>), 0_usize).with_mut( - |__v: &mut Value>| (*__v.borrow_mut()).resize_with(__a0, || ::default()), - ) + elem!((v.as_pointer() as Ptr>), 0_usize) + .with_mut(|__v: &mut Vec| __v.resize_with(__a0, || ::default())) }; { let __a0 = 1_usize as usize; - elem!((v.as_pointer() as Ptr>>), 1_usize).with_mut( - |__v: &mut Value>| (*__v.borrow_mut()).resize_with(__a0, || ::default()), - ) + elem!((v.as_pointer() as Ptr>), 1_usize) + .with_mut(|__v: &mut Vec| __v.resize_with(__a0, || ::default())) }; elem!( - ((v.as_pointer() as Ptr>>) + ((v.as_pointer() as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 0_usize ) .write(1); elem!( - ((v.as_pointer() as Ptr>>) + ((v.as_pointer() as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 1_usize ) .write(5); elem!( - ((v.as_pointer() as Ptr>>) + ((v.as_pointer() as Ptr>) .offset(1_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 0_usize ) .write(6); - 'loop_: for mut v2 in v.as_pointer() as Ptr>> { - let v2: Ptr> = v2.upgrade().deref().as_pointer(); + 'loop_: for mut v2 in v.as_pointer() as Ptr> { 'loop_: for mut i in Ptr::>::decay(&(v2)) as Ptr { i.with_mut(|__v| __v.prefix_inc()); } } - 'loop_: for mut v2 in v.as_pointer() as Ptr>> { - let v2: Ptr> = v2.upgrade().deref().as_pointer(); + 'loop_: for mut v2 in v.as_pointer() as Ptr> { 'loop_: for mut i in Ptr::>::decay(&(v2)) as Ptr { let mut i: i32 = i.read(); println!("{}", (i + 3)); } } - 'loop_: for mut v2 in v.as_pointer() as Ptr>> { - let v2: Value> = Rc::new(RefCell::new(v2.upgrade().deref().borrow().clone())); + 'loop_: for mut v2 in v.as_pointer() as Ptr> { + let v2: Value> = Rc::new(RefCell::new(v2.upgrade().deref().clone())); 'loop_: for mut i in v2.as_pointer() as Ptr { let mut i: i32 = i.read(); println!("{}", i); diff --git a/tests/unit/out/refcount/vector_addr_of_back.rs b/tests/unit/out/refcount/vector_addr_of_back.rs index 8911a04c6..3a8c6b25a 100644 --- a/tests/unit/out/refcount/vector_addr_of_back.rs +++ b/tests/unit/out/refcount/vector_addr_of_back.rs @@ -11,15 +11,16 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let outer: Value>>> = Rc::new(RefCell::new(Vec::new())); + let outer: Value>> = Rc::new(RefCell::new(Vec::new())); let mut inner: Vec = Vec::new(); - (outer.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new((inner).clone()))) - }); - let mut sink: Ptr> = ((*outer.borrow())[(*outer.borrow()).len() - 1].as_pointer()); + { + let a0_clone = inner.clone(); + (*outer.borrow_mut()).push(a0_clone) + }; + let mut sink: Ptr> = ((outer.as_pointer() as Ptr>).to_last()); assert!(((*sink.upgrade().deref()).len() == 0_usize)); - let mut p: Ptr>>> = (outer.as_pointer()); - sink = ((*p.upgrade().deref())[(*p.upgrade().deref()).len() - 1].as_pointer()); + let mut p: Ptr>> = (outer.as_pointer()); + sink = ((Ptr::>>::decay(&(p)) as Ptr>).to_last()); assert!(((*sink.upgrade().deref()).len() == 0_usize)); return 0; } diff --git a/tests/unit/out/refcount/vector_deque_vector_string.rs b/tests/unit/out/refcount/vector_deque_vector_string.rs new file mode 100644 index 000000000..ee5cda203 --- /dev/null +++ b/tests/unit/out/refcount/vector_deque_vector_string.rs @@ -0,0 +1,309 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let v: Value>>>> = Rc::new(RefCell::new(Vec::new())); + { + let __init = Vec::new(); + (*v.borrow_mut()).push(__init) + }; + { + let __init = Vec::new(); + (*v.borrow_mut()).push(__init) + }; + let row: Value>> = Rc::new(RefCell::new(Vec::new())); + { + let __a1 = { + let mut __bytes = Ptr::::from_string_literal(b"a").to_c_bytes(); + __bytes.push(0); + __bytes + }; + (*row.borrow_mut()).push(__a1) + }; + { + let __a1 = { + let mut __bytes = Ptr::::from_string_literal(b"bc").to_c_bytes(); + __bytes.push(0); + __bytes + }; + (*row.borrow_mut()).push(__a1) + }; + elem!((v.as_pointer() as Ptr>>>), 0_usize) + .with_mut(|__v: &mut Vec>>| __v.push((*row.borrow()).clone())); + { + let __a1 = { + let mut __bytes = Ptr::::from_string_literal(b"def").to_c_bytes(); + __bytes.push(0); + __bytes + }; + (*row.borrow_mut()).push(__a1) + }; + elem!((v.as_pointer() as Ptr>>>), 1_usize) + .with_mut(|__v: &mut Vec>>| __v.push((*row.borrow()).clone())); + { + let __init = Vec::new(); + elem!((v.as_pointer() as Ptr>>>), 1_usize) + .with_mut(|__v: &mut Vec>>| __v.push(__init)) + }; + { + let __a1 = { + let mut r = (*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .clone(); + r.pop(); + Ptr::::from_string_literal(b"x").with_c_str(|__s| r.extend_from_slice(__s)); + r.push(0); + r + }; + ((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>) + .to_last() + .with_mut(|__v: &mut Vec>| __v.push(__a1)) + }; + assert!( + ((*((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>) + .upgrade() + .deref()) + .len() + == 2_usize) + ); + assert!( + ((*((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>) + .upgrade() + .deref()) + .len() + == 3_usize) + && (Ptr::::from_string_literal(b"def").with_c_str(|__s| { + (*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(2_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref())[..(*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(2_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1)] + == *__s + })) + ); + assert!(Ptr::::from_string_literal(b"bcx").with_c_str(|__s| { + (*((Ptr::>>::decay( + &(((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>) + .to_last()), + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref())[..(*((Ptr::>>::decay( + &(((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>) + .to_last()), + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1)] + == *__s + })); + let copy: Value>>>> = Rc::new(RefCell::new((*v.borrow()).clone())); + ((Ptr::>>::decay( + &((copy.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .write({ + let mut __bytes = Ptr::::from_string_literal(b"z").to_c_bytes(); + __bytes.push(0); + __bytes + }); + if 0_usize as usize + >= (*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1) + { + panic!("out of bounds access") + } else { + ((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr>) + .decay() + .offset(0_usize as isize) + } + .write(('B' as i8)); + assert!( + (Ptr::::from_string_literal(b"a").with_c_str(|__s| (*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>) + ) as Ptr>) + .offset(0_usize) + .as_pointer() + as Ptr>) + .upgrade() + .deref())[..(*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>) + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1)] + == *__s)) + && (Ptr::::from_string_literal(b"z").with_c_str(|__s| { + (*((Ptr::>>::decay( + &((copy.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref())[..(*((Ptr::>>::decay( + &((copy.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1)] + == *__s + })) + ); + assert!( + (Ptr::::from_string_literal(b"Bc").with_c_str(|__s| (*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>) + ) as Ptr>) + .offset(1_usize) + .as_pointer() + as Ptr>) + .upgrade() + .deref())[..(*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>) + ) as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1)] + == *__s)) + && (Ptr::::from_string_literal(b"bc").with_c_str(|__s| { + (*((Ptr::>>::decay( + &((copy.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref())[..(*((Ptr::>>::decay( + &((copy.as_pointer() as Ptr>>>) + .offset(0_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1)] + == *__s + })) + ); + elem!((v.as_pointer() as Ptr>>>), 1_usize) + .with_mut(|__v: &mut Vec>>| __v.remove(0)); + assert!(Ptr::::from_string_literal(b"bcx").with_c_str(|__s| { + (*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref())[..(*((Ptr::>>::decay( + &((v.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>), + ) as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr>) + .upgrade() + .deref()) + .len() + .saturating_sub(1)] + == *__s + })); + assert!( + ((*((copy.as_pointer() as Ptr>>>) + .offset(1_usize) + .as_pointer() as Ptr>>) + .upgrade() + .deref()) + .len() + == 3_usize) + ); + assert!(((*row.borrow()).len() == 3_usize)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/vector_subscript_direct.rs b/tests/unit/out/refcount/vector_subscript_direct.rs index b87d91254..1522be315 100644 --- a/tests/unit/out/refcount/vector_subscript_direct.rs +++ b/tests/unit/out/refcount/vector_subscript_direct.rs @@ -164,44 +164,88 @@ fn main_0() -> i32 { .x } == 7) ); - let grid: Value>>> = Rc::new(RefCell::new(Vec::new())); - (grid.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new(vec![0; 3_usize as usize]))) - }); - (grid.as_pointer() as Ptr>>>).with_mut(|__v: &mut Vec>>| { - __v.push(Rc::new(RefCell::new(vec![0; 3_usize as usize]))) - }); + let grid: Value>> = Rc::new(RefCell::new(Vec::new())); + { + let __a1 = vec![0; 3_usize as usize]; + (*grid.borrow_mut()).push(__a1) + }; + { + let __a1 = vec![0; 3_usize as usize]; + (*grid.borrow_mut()).push(__a1) + }; elem!( - ((grid.as_pointer() as Ptr>>) + ((grid.as_pointer() as Ptr>) .offset(1_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 2_usize ) .write(8); assert!( ((elem!( - ((grid.as_pointer() as Ptr>>) + ((grid.as_pointer() as Ptr>) .offset(1_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 2_usize ) .read()) == 8) && ((elem!( - ((grid.as_pointer() as Ptr>>) + ((grid.as_pointer() as Ptr>) .offset(0_usize) - .upgrade() - .deref() .as_pointer() as Ptr), 2_usize ) .read()) == 0) ); + let __rhs = (elem!( + ((grid.as_pointer() as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr), + 2_usize + ) + .read()); + elem!( + ((grid.as_pointer() as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr), + 1_usize + ) + .write(__rhs); + let __rhs = (elem!( + ((grid.as_pointer() as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr), + 1_usize + ) + .read()); + { + elem!( + ((grid.as_pointer() as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr), + 0_usize + ) + .with_mut(|__v| *__v = *__v + __rhs) + }; + assert!( + ((elem!( + ((grid.as_pointer() as Ptr>) + .offset(0_usize) + .as_pointer() as Ptr), + 1_usize + ) + .read()) + == 8) + && ((elem!( + ((grid.as_pointer() as Ptr>) + .offset(1_usize) + .as_pointer() as Ptr), + 0_usize + ) + .read()) + == 8) + ); let a: Value> = Rc::new(RefCell::new(vec![4, 5, 6])); let __rhs = ({ (*a.borrow())[0_usize] } + { (*a.borrow())[2_usize] }); (*a.borrow_mut())[1_usize] = __rhs; diff --git a/tests/unit/out/unsafe/12_test.rs b/tests/unit/out/unsafe/12_test.rs index 4980993e8..9b3a0bebf 100644 --- a/tests/unit/out/unsafe/12_test.rs +++ b/tests/unit/out/unsafe/12_test.rs @@ -14,11 +14,12 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut v: Vec> = Vec::new(); - v.push( - (0..(10_usize) as usize) + { + let __a1 = (0..(10_usize) as usize) .map(|_| ::default()) - .collect::>(), - ); + .collect::>(); + v.push(__a1) + }; return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/array_reference.rs b/tests/unit/out/unsafe/array_reference.rs index 56eccd5bb..f1edac698 100644 --- a/tests/unit/out/unsafe/array_reference.rs +++ b/tests/unit/out/unsafe/array_reference.rs @@ -74,6 +74,8 @@ pub unsafe fn total_len_13(names: *mut [*const libc::c_char; 2]) -> i32 { return ((unsafe { len5_1((*names)[(0) as usize]) }) + (unsafe { len5_1((*names)[(1) as usize]) })); } +pub static mut kTable_14: std::cell::LazyCell<[[i32; 3]; 2]> = + std::cell::LazyCell::new(|| unsafe { [[1, 2, 3], [4, 5, 6]] }); pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -131,6 +133,76 @@ unsafe fn main_0() -> i32 { (((*q.offset((1) as isize)).as_mut_ptr()) == (&mut rows[(1) as usize][(0) as usize] as *mut i32)) ); + (*q.offset((1) as isize))[(2) as usize] = 8; + assert!( + ((rows[(1) as usize][(2) as usize]) == (8)) && ((rows[(0) as usize][(2) as usize]) == (3)) + ); + rows[(0) as usize][(1) as usize] = rows[(0) as usize][(2) as usize]; + (*q.offset((1) as isize))[(0) as usize] = (*q.offset((0) as isize))[(1) as usize]; + (*q.offset((1) as isize))[(1) as usize] += (*q.offset((0) as isize))[(2) as usize]; + assert!( + (((rows[(0) as usize][(1) as usize]) == (3)) + && ((rows[(1) as usize][(0) as usize]) == (3))) + && ((rows[(1) as usize][(1) as usize]) == (8)) + ); + assert!( + (((((&mut rows[(1) as usize][(2) as usize] as *mut i32) as usize + - (&mut rows[(1) as usize][(0) as usize] as *mut i32) as usize) + / ::std::mem::size_of::()) as i64) + == (2_i64)) + ); + let mut key: [i32; 4] = [0, 4, 5, 6]; + assert!( + (({ + let sa = core::slice::from_raw_parts( + ((&mut key[(1) as usize] as *mut i32) as *const ::libc::c_void) as *const u8, + ::std::mem::size_of::<[i32; 3]>() as usize, + ); + let sb = core::slice::from_raw_parts( + ((*std::cell::LazyCell::force_mut(&mut *&raw mut kTable_14))[(1) as usize].as_ptr() + as *const ::libc::c_void) as *const u8, + ::std::mem::size_of::<[i32; 3]>() as usize, + ); + let mut diff = 0_i32; + for (x, y) in sa.iter().zip(sb.iter()) { + if x != y { + diff = (*x as i32) - (*y as i32); + break; + } + } + diff + }) == (0)) + ); + assert!( + (({ + let sa = core::slice::from_raw_parts( + ((&mut key[(1) as usize] as *mut i32) as *const ::libc::c_void) as *const u8, + ::std::mem::size_of::<[i32; 3]>() as usize, + ); + let sb = core::slice::from_raw_parts( + ((*std::cell::LazyCell::force_mut(&mut *&raw mut kTable_14))[(0) as usize].as_ptr() + as *const ::libc::c_void) as *const u8, + ::std::mem::size_of::<[i32; 3]>() as usize, + ); + let mut diff = 0_i32; + for (x, y) in sa.iter().zip(sb.iter()) { + if x != y { + diff = (*x as i32) - (*y as i32); + break; + } + } + diff + }) != (0)) + ); + assert!( + (((*std::cell::LazyCell::force_mut(&mut *&raw mut kTable_14))[(1) as usize][(2) as usize]) + == (6)) + && (((*std::cell::LazyCell::force_mut(&mut *&raw mut kTable_14))[(0) as usize] + [(1) as usize]) + == (2)) + ); return 0; } -pub unsafe fn __cpp2rust_init_globals() {} +pub unsafe fn __cpp2rust_init_globals() { + std::cell::LazyCell::force(&*&raw const kTable_14); +} diff --git a/tests/unit/out/unsafe/clone_vs_move.rs b/tests/unit/out/unsafe/clone_vs_move.rs index 7398992ff..a744210f7 100644 --- a/tests/unit/out/unsafe/clone_vs_move.rs +++ b/tests/unit/out/unsafe/clone_vs_move.rs @@ -124,11 +124,12 @@ unsafe fn main_0() -> i32 { let mut m1: Vec> = Vec::new(); let mut i: i32 = 0; 'loop_: while ((i) < (N)) { - m1.push( - (0..(10_usize) as usize) + { + let __a1 = (0..(10_usize) as usize) .map(|_| ::default()) - .collect::>(), - ); + .collect::>(); + m1.push(__a1) + }; i.prefix_inc(); } let mut m2: Vec> = m1.clone(); diff --git a/tests/unit/out/unsafe/copy_move_defaulted.rs b/tests/unit/out/unsafe/copy_move_defaulted.rs index 4f9f5272b..b64ddf832 100644 --- a/tests/unit/out/unsafe/copy_move_defaulted.rs +++ b/tests/unit/out/unsafe/copy_move_defaulted.rs @@ -113,7 +113,10 @@ impl Buffer { n: n, arr: [n, ((n) + (1))], }; - this.rows.push(this.data.clone()); + { + let a0_clone = this.data.clone(); + this.rows.push(a0_clone) + }; this } pub unsafe fn move_from(_a0: *mut Buffer) -> Self { diff --git a/tests/unit/out/unsafe/foreach_double.rs b/tests/unit/out/unsafe/foreach_double.rs index 8035a31b5..7c6e3f33a 100644 --- a/tests/unit/out/unsafe/foreach_double.rs +++ b/tests/unit/out/unsafe/foreach_double.rs @@ -57,11 +57,20 @@ unsafe fn main_0() -> i32 { } let mut m: Vec> = Vec::new(); let mut v1: Vec = Vec::new(); - m.push(std::mem::take(&mut v1)); + { + let __a1 = std::mem::take(&mut v1); + m.push(__a1) + }; let mut v2: Vec = Vec::new(); - m.push(std::mem::take(&mut v2)); + { + let __a1 = std::mem::take(&mut v2); + m.push(__a1) + }; let mut v3: Vec = Vec::new(); - m.push(std::mem::take(&mut v3)); + { + let __a1 = std::mem::take(&mut v3); + m.push(__a1) + }; 'loop_: for row in 0..(m.len()) { let mut row = m.as_mut_ptr().add(row); 'loop_: for col in 0..((*row).len()) { diff --git a/tests/unit/out/unsafe/nested_vector.rs b/tests/unit/out/unsafe/nested_vector.rs index 7468956df..eb1173d97 100644 --- a/tests/unit/out/unsafe/nested_vector.rs +++ b/tests/unit/out/unsafe/nested_vector.rs @@ -15,7 +15,10 @@ pub fn main() { unsafe fn main_0() -> i32 { let mut v1: Vec> = Vec::new(); let mut v2: Vec = vec![1]; - v1.push(v2.clone()); + { + let a0_clone = v2.clone(); + v1.push(a0_clone) + }; assert!(((*(&mut (*((v1).last_mut().unwrap()))[0_usize as usize] as *mut i32)) == (1))); return 0; } diff --git a/tests/unit/out/unsafe/push_emplace_back.rs b/tests/unit/out/unsafe/push_emplace_back.rs index 07cc382fb..22ed160a4 100644 --- a/tests/unit/out/unsafe/push_emplace_back.rs +++ b/tests/unit/out/unsafe/push_emplace_back.rs @@ -24,7 +24,10 @@ pub struct JPEGData { pub app_data: Vec>, } pub unsafe fn push_param_0(mut dest: *mut Vec>) { - (*dest).push(Vec::new()); + { + let __a1 = Vec::new(); + (*dest).push(__a1) + }; } pub unsafe fn push_local_from_field_1(mut jpg: *mut JPEGData, mut cond: bool) { let mut head: [u8; 3] = [1_u8, 2_u8, 3_u8]; @@ -34,15 +37,16 @@ pub unsafe fn push_local_from_field_1(mut jpg: *mut JPEGData, mut cond: bool) { } else { dest = (&mut (*jpg).app_data as *mut Vec>); } - (*dest).push( - core::slice::from_raw_parts( + { + let __a1 = core::slice::from_raw_parts( head.as_mut_ptr(), (head.as_mut_ptr().offset((3) as isize)).offset_from(head.as_mut_ptr()) as usize, ) .iter() .map(|x| u8::try_from(x.clone()).ok().unwrap()) - .collect(), - ); + .collect(); + (*dest).push(__a1) + }; } pub unsafe fn shrink_through_ptr_2(mut comps: *mut Vec) { (*comps).shrink_to_fit(); diff --git a/tests/unit/out/unsafe/vector3.rs b/tests/unit/out/unsafe/vector3.rs index 116740ed0..7bb74550e 100644 --- a/tests/unit/out/unsafe/vector3.rs +++ b/tests/unit/out/unsafe/vector3.rs @@ -14,7 +14,10 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut v: Vec> = Vec::new(); - v.resize_with(2_usize as usize, || >::default()); + { + let __a0 = 2_usize as usize; + v.resize_with(__a0, || >::default()) + }; { let __a0 = 2_usize as usize; v[(0_usize)].resize_with(__a0, || ::default()) diff --git a/tests/unit/out/unsafe/vector_addr_of_back.rs b/tests/unit/out/unsafe/vector_addr_of_back.rs index b07ee1ae0..0f8f2bab4 100644 --- a/tests/unit/out/unsafe/vector_addr_of_back.rs +++ b/tests/unit/out/unsafe/vector_addr_of_back.rs @@ -15,7 +15,10 @@ pub fn main() { unsafe fn main_0() -> i32 { let mut outer: Vec> = Vec::new(); let mut inner: Vec = Vec::new(); - outer.push(inner.clone()); + { + let a0_clone = inner.clone(); + outer.push(a0_clone) + }; let mut sink: *mut Vec = ((outer).last_mut().unwrap()); assert!((((*(sink).cast_const()).len()) == (0_usize))); let mut p: *mut Vec> = (&mut outer as *mut Vec>); diff --git a/tests/unit/out/unsafe/vector_deque_vector_string.rs b/tests/unit/out/unsafe/vector_deque_vector_string.rs new file mode 100644 index 000000000..50428bec7 --- /dev/null +++ b/tests/unit/out/unsafe/vector_deque_vector_string.rs @@ -0,0 +1,131 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut v: Vec>>> = Vec::new(); + { + let __init = Vec::new(); + v.push(__init) + }; + { + let __init = Vec::new(); + v.push(__init) + }; + let mut row: Vec> = Vec::new(); + { + let __a1 = { + let s = c"a".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }; + row.push(__a1) + }; + { + let __a1 = { + let s = c"bc".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }; + row.push(__a1) + }; + v[(0_usize)].push((row).clone()); + { + let __a1 = { + let s = c"def".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }; + row.push(__a1) + }; + v[(1_usize)].push((row).clone()); + { + let __init = Vec::new(); + v[(1_usize)].push(__init) + }; + { + let __a1 = { + let mut __tmp2 = (*((v[(0_usize)]).first_mut().unwrap()))[(1_usize)].clone(); + __tmp2.pop(); + let __from = c"x".as_ptr(); + __tmp2.extend_from_slice(::std::slice::from_raw_parts( + __from, + (0..).position(|i| *__from.add(i) == 0).unwrap(), + )); + __tmp2.push(0); + __tmp2 + }; + (*(v[(1_usize)].last_mut().unwrap())).push(__a1) + }; + assert!((((*((v[(0_usize)]).first_mut().unwrap())).len()) == (2_usize))); + assert!( + (((*((v[(1_usize)]).first_mut().unwrap())).len()) == (3_usize)) + && ((*((v[(1_usize)]).first_mut().unwrap()))[(2_usize)] == { + let s = c"def".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }) + ); + assert!( + (*(v[(1_usize)].last_mut().unwrap()))[(0_usize)] == { + let s = c"bcx".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + } + ); + let mut copy: Vec>>> = v.clone(); + (*((copy[(0_usize)]).first_mut().unwrap()))[(0_usize)] = { + let s = c"z".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1).to_vec() + }; + (*if 0_usize as usize >= (*((v[(0_usize)]).first_mut().unwrap()))[(1_usize)].len() - 1 { + panic!("out of bounds access") + } else { + (&mut (*((v[(0_usize)]).first_mut().unwrap()))[(1_usize)][0_usize as usize] + as *mut libc::c_char) + }) = ('B' as libc::c_char); + assert!( + ((*((v[(0_usize)]).first_mut().unwrap()))[(0_usize)] == { + let s = c"a".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }) && ((*((copy[(0_usize)]).first_mut().unwrap()))[(0_usize)] == { + let s = c"z".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }) + ); + assert!( + ((*((v[(0_usize)]).first_mut().unwrap()))[(1_usize)] == { + let s = c"Bc".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }) && ((*((copy[(0_usize)]).first_mut().unwrap()))[(1_usize)] == { + let s = c"bc".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + }) + ); + v[(1_usize)].remove(0); + assert!( + (*((v[(1_usize)]).first_mut().unwrap()))[(0_usize)] == { + let s = c"bcx".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + } + ); + assert!((((*((copy[(1_usize)]).first_mut().unwrap())).len()) == (3_usize))); + assert!(((row.len()) == (3_usize))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/vector_deque_vector_string.cpp b/tests/unit/vector_deque_vector_string.cpp new file mode 100644 index 000000000..3dca5dd8a --- /dev/null +++ b/tests/unit/vector_deque_vector_string.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +int main() { + std::vector>> v; + v.emplace_back(); + v.emplace_back(); + + std::vector row; + row.push_back("a"); + row.push_back("bc"); + v[0].push_back(row); + row.push_back("def"); + v[1].push_back(row); + v[1].emplace_back(); + v[1].back().push_back(v[0].front()[1] + "x"); + + assert(v[0].front().size() == 2); + assert(v[1].front().size() == 3 && v[1].front()[2] == "def"); + assert(v[1].back()[0] == "bcx"); + + auto copy = v; + copy[0].front()[0] = std::string("z"); + v[0].front()[1].at(0) = 'B'; + assert(v[0].front()[0] == "a" && copy[0].front()[0] == "z"); + assert(v[0].front()[1] == "Bc" && copy[0].front()[1] == "bc"); + + v[1].pop_front(); + assert(v[1].front()[0] == "bcx"); + assert(copy[1].front().size() == 3); + assert(row.size() == 3); + return 0; +} diff --git a/tests/unit/vector_subscript_direct.cpp b/tests/unit/vector_subscript_direct.cpp index 20601121a..1858dbf24 100644 --- a/tests/unit/vector_subscript_direct.cpp +++ b/tests/unit/vector_subscript_direct.cpp @@ -76,6 +76,9 @@ int main() { grid.push_back(std::vector(3, 0)); grid[1][2] = 8; assert(grid[1][2] == 8 && grid[0][2] == 0); + grid[0][1] = grid[1][2]; + grid[1][0] += grid[0][1]; + assert(grid[0][1] == 8 && grid[1][0] == 8); std::array a = {4, 5, 6}; a[1] = a[0] + a[2];