diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 116d13b244..1d88629f39 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -133,6 +133,12 @@ Converter::GetTemplateArgumentAsString(const clang::TemplateArgument &arg) { case clang::TemplateArgument::Type: return GetUnboxedTypeAsString(arg.getAsType()); case clang::TemplateArgument::Integral: + if (!arg.getIntegralType()->isBooleanType()) { + llvm::SmallString<16> value; + arg.getAsIntegral().toString(value); + return std::string(value); + } + [[fallthrough]]; case clang::TemplateArgument::NullPtr: case clang::TemplateArgument::Declaration: case clang::TemplateArgument::StructuralValue: { @@ -5114,8 +5120,6 @@ std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args, if (!tgt_ir) return {}; - CheckRuleReturnType(expr); - auto saved_borrows = std::exchange(mut_borrows_, {}); auto *operand = tgt_ir->refExprOperand(); bool lvalue = operand && !isAddrOf(); diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 8e74dd489a..704fa21ad3 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -916,9 +916,6 @@ class Converter : public clang::RecursiveASTVisitor { return false; } - // Checks that the rule of expr returns the type that expr returns in C++. - virtual void CheckRuleReturnType(clang::Expr * /*expr*/) {} - bool RecordHasCopyableFields(const clang::RecordDecl *decl); bool ShouldReplaceWithMappedBody(const clang::ValueDecl *decl) const; diff --git a/cpp2rust/converter/mapper.cpp b/cpp2rust/converter/mapper.cpp index 0384f76170..432f7d1170 100644 --- a/cpp2rust/converter/mapper.cpp +++ b/cpp2rust/converter/mapper.cpp @@ -74,9 +74,4 @@ std::string GetParamType(Converter &converter, const clang::Expr *expr, return Matcher::InstantiateTgt(converter, subs, rule->params.at(index).type); } -std::string GetReturnType(Converter &converter, const clang::Expr *expr) { - auto [rule, subs] = RuleRegistry::Search(converter.GetASTContext(), expr); - return Matcher::InstantiateTgt(converter, subs, rule->return_type.type); -} - } // namespace cpp2rust::Mapper diff --git a/cpp2rust/converter/mapper.h b/cpp2rust/converter/mapper.h index ed0156b678..fff44f6336 100644 --- a/cpp2rust/converter/mapper.h +++ b/cpp2rust/converter/mapper.h @@ -27,5 +27,4 @@ std::string MapFunctionName(clang::ASTContext &ctx, const clang::FunctionDecl *decl); std::string GetParamType(Converter &converter, const clang::Expr *expr, unsigned index); -std::string GetReturnType(Converter &converter, const clang::Expr *expr); } // namespace cpp2rust::Mapper diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 5cee2b16af..1c7ce8a40b 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -438,29 +438,6 @@ std::string ConverterRefCount::ConvertElementPtr(clang::Expr *arg) { return ConvertObject(arg, ObjectShape::Element); } -void ConverterRefCount::CheckRuleReturnType(clang::Expr *expr) { - auto *call = clang::dyn_cast(expr); - if (!call || - !RuleRegistry::GetExprRule(ctx_, expr)->return_type.is_refcount_pointer) { - return; - } - auto type = RuleRegistry::GetDeclaredReturnType(expr); - if (auto ref = type->getAs()) { - auto pointee = ref->getPointeeType(); - type = pointee->isRecordType() && - RuleRegistry::MapsToRefcountPointer(ctx_, pointee) - ? pointee - : ctx_.getPointerType(pointee); - } - auto ret = NormalizeType(Mapper::GetReturnType(*this, expr)); - auto expected = NormalizeType(ToString(type)); - if (ret != expected) { - llvm::errs() << "rule return type " << ret << " is not " << expected - << '\n'; - llvm::report_fatal_error("rule return type does not match the C++ one"); - } -} - std::string ConverterRefCount::ConvertFreshObject(clang::Expr *expr) { return MakeFresh(ConvertObject(expr)); } diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index eef71cddf5..554d8e9eba 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -441,7 +441,6 @@ class ConverterRefCount final : public Converter { // The method that makes a pointer to an object of the given type, which is // one to its elements if they are what ConvertObject wants. std::string AsPointerMethod(clang::QualType type); - void CheckRuleReturnType(clang::Expr *expr) override; std::string ConvertTemporaryPointer( clang::Expr *expr, diff --git a/cpp2rust/converter/rules/expr_matcher.cpp b/cpp2rust/converter/rules/expr_matcher.cpp index 2d51f91b68..ef52420ad3 100644 --- a/cpp2rust/converter/rules/expr_matcher.cpp +++ b/cpp2rust/converter/rules/expr_matcher.cpp @@ -298,6 +298,32 @@ getExplicitTemplateArgs(const clang::Expr *expr) { return {}; } +void deduceNonTypeFromExplicitArg( + clang::ASTContext &ctx, const clang::TemplateArgument &rule_arg, + const clang::Expr *use, unsigned i, + std::vector &deduced) { + auto ref = llvm::dyn_cast( + rule_arg.getAsExpr()->IgnoreParenImpCasts()); + auto nttp = + ref ? llvm::dyn_cast(ref->getDecl()) + : nullptr; + if (!nttp) { + return; + } + auto call = llvm::cast(RuleDecls::SkipImplicit(use)); + auto callee = call->getDirectCallee(); + auto spec = callee ? callee->getTemplateSpecializationArgs() : nullptr; + assert(spec && i < spec->size() && + "explicit template argument of a non-specialized callee"); + const auto &value = spec->get(i); + assert(value.getKind() == clang::TemplateArgument::Integral && + "non-type template argument is not an integral"); + auto &slot = deduced[nttp->getIndex()]; + if (slot.isNull()) { + slot = clang::TemplateArgument(ctx, value.getAsIntegral(), nttp->getType()); + } +} + void deduceFromExplicitArgs(clang::Sema &sema, clang::FunctionTemplateDecl *rule, const clang::Expr *use, @@ -308,6 +334,10 @@ void deduceFromExplicitArgs(clang::Sema &sema, for (unsigned i = 0; i < rule_args.size() && i < use_args.size(); ++i) { const auto &rule_arg = rule_args[i].getArgument(); const auto &use_arg = use_args[i].getArgument(); + if (rule_arg.getKind() == clang::TemplateArgument::Expression) { + deduceNonTypeFromExplicitArg(sema.Context, rule_arg, use, i, deduced); + continue; + } if (rule_arg.getKind() != clang::TemplateArgument::Type || use_arg.getKind() != clang::TemplateArgument::Type) { continue; diff --git a/cpp2rust/converter/rules/registry.cpp b/cpp2rust/converter/rules/registry.cpp index f60397073b..ef867d4b97 100644 --- a/cpp2rust/converter/rules/registry.cpp +++ b/cpp2rust/converter/rules/registry.cpp @@ -496,23 +496,6 @@ std::string InitAliasName(Model model, const std::string &name) { model == Model::kRefCount ? "refcount" : "unsafe", name); } -clang::QualType GetDeclaredReturnType(const clang::Expr *expr) { - auto match = findExpr(expr); - assert(match.rule_decl && "expression must have a translation rule"); - auto function = match.rule_decl->decl->getAsFunction(); - assert(function && "rule is not a function"); - auto tmpl = function->getDescribedFunctionTemplate(); - if (!tmpl) { - return function->getReturnType(); - } - clang::MultiLevelTemplateArgumentList args(tmpl, match.args, - /*Final=*/false); - clang::Sema::InstantiatingTemplate inst( - *sema_, expr->getBeginLoc(), const_cast(function)); - return sema_->SubstType(function->getReturnType(), args, expr->getBeginLoc(), - clang::DeclarationName()); -} - bool HasExprRule(const clang::FunctionDecl *decl) { auto key = RuleKeys::GetDeclKey(decl); if (!key) { diff --git a/cpp2rust/converter/rules/registry.h b/cpp2rust/converter/rules/registry.h index 2c8a524be0..f25617ad4b 100644 --- a/cpp2rust/converter/rules/registry.h +++ b/cpp2rust/converter/rules/registry.h @@ -50,8 +50,6 @@ clang::QualType GetGenericType(clang::ASTContext &ctx, const clang::Expr *expr, clang::QualType GetConversionSourceType(clang::ASTContext &ctx, const clang::Expr *expr, unsigned to); -clang::QualType GetDeclaredReturnType(const clang::Expr *expr); - bool HasExprRule(const clang::FunctionDecl *decl); bool IsLibcPassthrough(clang::ASTContext &ctx, const clang::Expr *expr); bool ReturnsPointer(clang::ASTContext &ctx, const clang::Expr *expr); diff --git a/rule-preprocessor/src/syntactic.rs b/rule-preprocessor/src/syntactic.rs index f451e85dcf..08ff8fee76 100644 --- a/rule-preprocessor/src/syntactic.rs +++ b/rule-preprocessor/src/syntactic.rs @@ -481,9 +481,16 @@ impl<'a> FnIrBuilder<'a> { if let Some(gpl) = self.fn_item.generic_param_list() { for param in gpl.generic_params() { - if let ast::GenericParam::TypeParam(tp) = param { - let name = tp.name().map(|n| n.text().to_string()).unwrap_or_default(); - generics.insert(name, extract_bounds(tp.type_bound_list())); + match param { + ast::GenericParam::TypeParam(tp) => { + let name = tp.name().map(|n| n.text().to_string()).unwrap_or_default(); + generics.insert(name, extract_bounds(tp.type_bound_list())); + } + ast::GenericParam::ConstParam(cp) => { + let name = cp.name().map(|n| n.text().to_string()).unwrap_or_default(); + generics.insert(name, Vec::new()); + } + _ => {} } } } diff --git a/rules/array/src.cpp b/rules/array/src.cpp index c9669a1967..71c49b8d93 100644 --- a/rules/array/src.cpp +++ b/rules/array/src.cpp @@ -17,6 +17,9 @@ using t4 = typename std::array::pointer; template using t5 = typename std::array::const_pointer; +template +using t6 = typename std::tuple_element>::type; + template const T1 *f1(const std::array &o) { return o.data(); @@ -54,3 +57,23 @@ std::array &f7(std::array &dst, const std::array &src) { template std::array f8(T1 (&&a0)[T2]) { return std::array{a0}; } + +template +T2 &f9(std::array &a0) { + return std::get(a0); +} + +template +const T2 &f10(const std::array &a0) { + return std::get(a0); +} + +template +T2 &&f11(std::array &&a0) { + return std::get(std::move(a0)); +} + +template +const T2 &&f12(const std::array &&a0) { + return std::get(std::move(a0)); +} diff --git a/rules/array/tgt_refcount.rs b/rules/array/tgt_refcount.rs index d480649e65..ca9978f414 100644 --- a/rules/array/tgt_refcount.rs +++ b/rules/array/tgt_refcount.rs @@ -28,3 +28,19 @@ fn f5(a0: Ptr>, a1: &mut Vec) { fn f7(a0: Ptr>, a1: Vec) { a0.write(a1) } + +fn f9(a0: Ptr) -> Ptr { + a0.offset(T1 as isize) +} + +fn f10(a0: Ptr) -> Ptr { + a0.offset(T1 as isize) +} + +fn f11(a0: Ptr) -> Ptr { + a0.offset(T1 as isize) +} + +fn f12(a0: Ptr) -> Ptr { + a0.offset(T1 as isize) +} diff --git a/rules/array/tgt_unsafe.rs b/rules/array/tgt_unsafe.rs index 1e6ac5805c..6ab69c1e82 100644 --- a/rules/array/tgt_unsafe.rs +++ b/rules/array/tgt_unsafe.rs @@ -23,6 +23,10 @@ fn t5() -> *const T1 { ::std::ptr::null() } +fn t6() -> T2 { + unimplemented!() +} + unsafe fn f1(a0: Vec) -> *const T1 { a0.as_ptr() } @@ -54,3 +58,19 @@ unsafe fn f7(a0: &mut Vec, a1: Vec) { unsafe fn f8(a0: [T1; T2]) -> Vec { Vec::from(a0) } + +unsafe fn f9(a0: &mut Vec) -> *mut T2 { + a0.as_mut_ptr().offset(T1 as isize) +} + +unsafe fn f10(a0: &Vec) -> *const T2 { + a0.as_ptr().offset(T1 as isize) +} + +unsafe fn f11(a0: &mut Vec) -> *mut T2 { + a0.as_mut_ptr().offset(T1 as isize) +} + +unsafe fn f12(a0: &Vec) -> *const T2 { + a0.as_ptr().offset(T1 as isize) +} diff --git a/rules/pair/shim.rs b/rules/pair/shim.rs new file mode 100644 index 0000000000..c439c21214 --- /dev/null +++ b/rules/pair/shim.rs @@ -0,0 +1,78 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use crate::Value; + +pub trait TupleElement { + type Type; + + fn element(&self) -> &Self::Type; + + fn element_mut(&mut self) -> &mut Self::Type; +} + +pub trait TupleGet { + fn get(&self) -> &>::Type + where + Self: TupleElement, + { + TupleElement::::element(self) + } + + fn get_mut(&mut self) -> &mut >::Type + where + Self: TupleElement, + { + TupleElement::::element_mut(self) + } +} + +pub trait TupleElementValue: TupleElement { + type Values; + + fn value(values: &Self::Values) -> &Value; +} + +pub trait ValueTupleGet { + type Plain; + + fn get_value(&self) -> &Value<>::Type> + where + Self::Plain: TupleElementValue, + { + >::value(self) + } +} + +macro_rules! impl_tuple_get { + (@element ($($t:ident),+) $n:tt $element:ident) => { + impl<$($t),+> TupleElement<$n> for ($($t,)+) { + type Type = $element; + + fn element(&self) -> &$element { + &self.$n + } + + fn element_mut(&mut self) -> &mut $element { + &mut self.$n + } + } + + impl<$($t),+> TupleElementValue<$n> for ($($t,)+) { + type Values = ($(Value<$t>,)+); + + fn value(values: &Self::Values) -> &Value<$element> { + &values.$n + } + } + }; + ($tuple:tt; $($n:tt $element:ident),+) => { + impl<$($element),+> TupleGet for ($($element,)+) {} + impl<$($element),+> ValueTupleGet for ($(Value<$element>,)+) { + type Plain = ($($element,)+); + } + $(impl_tuple_get!(@element $tuple $n $element);)+ + }; +} + +impl_tuple_get!((T0, T1); 0 T0, 1 T1); diff --git a/rules/pair/src.cpp b/rules/pair/src.cpp index e6c24349c4..68bb027116 100644 --- a/rules/pair/src.cpp +++ b/rules/pair/src.cpp @@ -55,28 +55,22 @@ template const T1 &f16(const std::pair &a0) { return a0.first; } -template T1 &f17(std::pair &a0) { - return std::get<0>(a0); +template +typename std::tuple_element>::type & +f17(std::pair &a0) { + return std::get(a0); } -template T2 &f18(std::pair &a0) { - return std::get<1>(a0); +template +const typename std::tuple_element>::type & +f19(const std::pair &a0) { + return std::get(a0); } -template const T1 &f19(const std::pair &a0) { - return std::get<0>(a0); -} - -template const T2 &f20(const std::pair &a0) { - return std::get<1>(a0); -} - -template T1 &&f21(std::pair &&a0) { - return std::get<0>(std::move(a0)); -} - -template T2 &&f22(std::pair &&a0) { - return std::get<1>(std::move(a0)); +template +typename std::tuple_element>::type && +f21(std::pair &&a0) { + return std::get(std::move(a0)); } template < @@ -110,3 +104,9 @@ template < std::pair &f26(std::pair &a0, std::pair &&a1) { return a0.template operator= (std::move(a1)); } + +template +const typename std::tuple_element>::type && +f27(const std::pair &&a0) { + return std::get(std::move(a0)); +} diff --git a/rules/pair/tgt_refcount.rs b/rules/pair/tgt_refcount.rs index 5ca871e600..c1f93bf423 100644 --- a/rules/pair/tgt_refcount.rs +++ b/rules/pair/tgt_refcount.rs @@ -60,28 +60,25 @@ fn f16(a0: (Value, Value)) -> Value { a0.0 } -fn f17(a0: (Value, Value)) -> Ptr { - a0.0.as_pointer() +fn f17(a0: (Value, Value)) -> Ptr<<(T2, T3) as TupleElement>::Type> +where + (T2, T3): TupleElementValue, Value)>, +{ + a0.get_value::().as_pointer() } -fn f18(a0: (Value, Value)) -> Ptr { - a0.1.as_pointer() +fn f19(a0: (Value, Value)) -> Ptr<<(T2, T3) as TupleElement>::Type> +where + (T2, T3): TupleElementValue, Value)>, +{ + a0.get_value::().as_pointer() } -fn f19(a0: (Value, Value)) -> Ptr { - a0.0.as_pointer() -} - -fn f20(a0: (Value, Value)) -> Ptr { - a0.1.as_pointer() -} - -fn f21(a0: (Value, Value)) -> Ptr { - a0.0.as_pointer() -} - -fn f22(a0: (Value, Value)) -> Ptr { - a0.1.as_pointer() +fn f21(a0: (Value, Value)) -> Ptr<<(T2, T3) as TupleElement>::Type> +where + (T2, T3): TupleElementValue, Value)>, +{ + a0.get_value::().as_pointer() } fn f23, T2: CppFrom, T3, T4>( @@ -125,3 +122,10 @@ fn f26 + ByteRepr, T2: CppFrom + ByteRepr, T3, T4>( Rc::new(RefCell::new(T2::cpp_from_move(__a1.1.as_pointer()))), )) } + +fn f27(a0: (Value, Value)) -> Ptr<<(T2, T3) as TupleElement>::Type> +where + (T2, T3): TupleElementValue, Value)>, +{ + a0.get_value::().as_pointer() +} diff --git a/rules/pair/tgt_unsafe.rs b/rules/pair/tgt_unsafe.rs index b49796e166..9ed9227d3f 100644 --- a/rules/pair/tgt_unsafe.rs +++ b/rules/pair/tgt_unsafe.rs @@ -48,28 +48,25 @@ unsafe fn f16(a0: (T1, T2)) -> T1 { a0.0 } -unsafe fn f17(a0: &mut (T1, T2)) -> *mut T1 { - &mut a0.0 +unsafe fn f17(a0: &mut (T2, T3)) -> *mut <(T2, T3) as TupleElement>::Type +where + (T2, T3): TupleElement, +{ + &mut *a0.get_mut::() } -unsafe fn f18(a0: &mut (T1, T2)) -> *mut T2 { - &mut a0.1 +unsafe fn f19(a0: &(T2, T3)) -> *const <(T2, T3) as TupleElement>::Type +where + (T2, T3): TupleElement, +{ + &*a0.get::() } -unsafe fn f19(a0: &(T1, T2)) -> *const T1 { - &a0.0 -} - -unsafe fn f20(a0: &(T1, T2)) -> *const T2 { - &a0.1 -} - -unsafe fn f21(a0: &mut (T1, T2)) -> *mut T1 { - &mut a0.0 -} - -unsafe fn f22(a0: &mut (T1, T2)) -> *mut T2 { - &mut a0.1 +unsafe fn f21(a0: &mut (T2, T3)) -> *mut <(T2, T3) as TupleElement>::Type +where + (T2, T3): TupleElement, +{ + &mut *a0.get_mut::() } unsafe fn f23, T2: CppFromUnsafe, T3, T4>(a0: &mut (T3, T4)) -> (T1, T2) { @@ -91,3 +88,10 @@ unsafe fn f26, T2: CppFromUnsafe, T3, T4>(a0: &mut (T1 let mut __a1 = a1; *a0 = (T1::cpp_from_move(&mut __a1.0), T2::cpp_from_move(&mut __a1.1)) } + +unsafe fn f27(a0: &(T2, T3)) -> *const <(T2, T3) as TupleElement>::Type +where + (T2, T3): TupleElement, +{ + &*a0.get::() +} diff --git a/tests/unit/out/refcount/empty_array_init.rs b/tests/unit/out/refcount/empty_array_init.rs index 8481daae9c..d6a069ab30 100644 --- a/tests/unit/out/refcount/empty_array_init.rs +++ b/tests/unit/out/refcount/empty_array_init.rs @@ -12,7 +12,7 @@ pub fn main() { } fn main_0() -> i32 { let vec_: Value> = Rc::new(RefCell::new( - std::array::from_fn::<_, 3_usize, _>(|_| 0_i32).to_vec(), + std::array::from_fn::<_, 3, _>(|_| 0_i32).to_vec(), )); return 0; } diff --git a/tests/unit/out/refcount/inline_container_fields.rs b/tests/unit/out/refcount/inline_container_fields.rs index 7b0f76c350..0dd26e3dec 100644 --- a/tests/unit/out/refcount/inline_container_fields.rs +++ b/tests/unit/out/refcount/inline_container_fields.rs @@ -81,7 +81,7 @@ impl Default for State { grid: (0..2) .map(|_| (0..3).map(|_| 0_i32).collect::>()) .collect::]>>(), - arr: std::array::from_fn::<_, 3_usize, _>(|_| 0_i32).to_vec(), + arr: std::array::from_fn::<_, 3, _>(|_| 0_i32).to_vec(), elems: Default::default(), rows: Default::default(), } diff --git a/tests/unit/out/refcount/libc_struct_without_default.rs b/tests/unit/out/refcount/libc_struct_without_default.rs index a95057a7f5..37a3029e14 100644 --- a/tests/unit/out/refcount/libc_struct_without_default.rs +++ b/tests/unit/out/refcount/libc_struct_without_default.rs @@ -28,7 +28,7 @@ impl Default for UserDefined { fn default() -> Self { { UserDefined { - a: std::array::from_fn::<_, 1_usize, _>(|_| 0_i32).to_vec(), + a: std::array::from_fn::<_, 1, _>(|_| 0_i32).to_vec(), v: Default::default(), } } diff --git a/tests/unit/out/refcount/pair_get.rs b/tests/unit/out/refcount/pair_get.rs index 42bb3bac90..390d1aaf6a 100644 --- a/tests/unit/out/refcount/pair_get.rs +++ b/tests/unit/out/refcount/pair_get.rs @@ -7,10 +7,10 @@ use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn second_of_0(p: Ptr<(Value, Value)>) -> i32 { - return ((*p.upgrade().deref()).1.as_pointer().read()); + return ((*p.upgrade().deref()).get_value::<1>().as_pointer().read()); } pub fn first_of_1(p: Ptr<(Value, Value)>) -> f64 { - return ((*p.upgrade().deref()).0.as_pointer().read()); + return ((*p.upgrade().deref()).get_value::<0>().as_pointer().read()); } pub fn main() { __cpp2rust_init_globals(); @@ -21,8 +21,8 @@ fn main_0() -> i32 { Rc::new(RefCell::new(1.5_f64)), Rc::new(RefCell::new(2)), ))); - assert!((((*p.borrow()).0.as_pointer().read()) == 1.5_f64)); - assert!((((*p.borrow()).1.as_pointer().read()) == 2)); + assert!((((*p.borrow()).get_value::<0>().as_pointer().read()) == 1.5_f64)); + assert!((((*p.borrow()).get_value::<1>().as_pointer().read()) == 2)); assert!((({ first_of_1(p.as_pointer(),) }) == 1.5_f64)); assert!((({ second_of_0(p.as_pointer(),) }) == 2)); return 0; diff --git a/tests/unit/out/refcount/pair_tuple_element.rs b/tests/unit/out/refcount/pair_tuple_element.rs new file mode 100644 index 0000000000..991cbcfb34 --- /dev/null +++ b/tests/unit/out/refcount/pair_tuple_element.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 p: Value<(Value, Value)> = Rc::new(RefCell::new(( + Rc::new(RefCell::new(1.5_f64)), + Rc::new(RefCell::new(2)), + ))); + let mut first: f64 = ((*p.borrow()).get_value::<0>().as_pointer().read()); + let mut second: i32 = ((*p.borrow()).get_value::<1>().as_pointer().read()); + let ref_: Ptr = (*p.borrow()).get_value::<1>().as_pointer(); + ref_.write(7); + assert!((first == 1.5_f64)); + assert!((second == 2)); + assert!(((*(*p.borrow()).1.borrow()) == 7)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_array.rs b/tests/unit/out/refcount/structured_binding_array.rs index 1d8f51014e..c9f61e8657 100644 --- a/tests/unit/out/refcount/structured_binding_array.rs +++ b/tests/unit/out/refcount/structured_binding_array.rs @@ -29,6 +29,20 @@ fn main_0() -> i32 { }; assert!(((*arr.borrow())[(0) as usize] == 7)); assert!(((*arr.borrow())[(2) as usize] == 5)); + let std_arr: Value> = Rc::new(RefCell::new(Vec::from([4, 5, 6]))); + let mut last: i32 = (std_arr.decay().offset(2 as isize).read()); + std_arr.decay().offset(0 as isize).write(8); + let __decomp_2: Ptr> = std_arr.as_pointer(); + let p: Ptr = __decomp_2.decay().offset(0 as isize); + let q: Ptr = __decomp_2.decay().offset(1 as isize); + let r: Ptr = __decomp_2.decay().offset(2 as isize); + { + q.with_mut(|__v| *__v = *__v + 10) + }; + assert!((last == 6)); + assert!(({ (*std_arr.borrow())[0_usize] } == 8)); + assert!(({ (*std_arr.borrow())[1_usize] } == 15)); + assert!(((r.read()) == 6)); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_element_ctor.rs b/tests/unit/out/refcount/structured_binding_element_ctor.rs index 9dc730b538..082559913f 100644 --- a/tests/unit/out/refcount/structured_binding_element_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_element_ctor.rs @@ -110,8 +110,8 @@ fn main_0() -> i32 { Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - let x: Ptr = (*__decomp_7.borrow()).0.as_pointer(); - let y: Ptr = (*__decomp_7.borrow()).1.as_pointer(); + let x: Ptr = (*__decomp_7.borrow()).get_value::<0>().as_pointer(); + let y: Ptr = (*__decomp_7.borrow()).get_value::<1>().as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == (before_copies + 2))); assert!(({ (*x.upgrade().deref()).v } == ({ (*(*p.borrow()).0.borrow()).v } + 100))); assert!(({ (*y.upgrade().deref()).v } == ({ (*(*p.borrow()).1.borrow()).v } + 100))); diff --git a/tests/unit/out/refcount/structured_binding_pair.rs b/tests/unit/out/refcount/structured_binding_pair.rs index ceec5d1595..faaaa75cc7 100644 --- a/tests/unit/out/refcount/structured_binding_pair.rs +++ b/tests/unit/out/refcount/structured_binding_pair.rs @@ -16,8 +16,8 @@ pub fn main() { fn main_0() -> i32 { let __decomp_1: Value<(Value, Value)> = Rc::new(RefCell::new(({ make_std_pair_0(5) }))); - let value: Ptr = (*__decomp_1.borrow()).0.as_pointer(); - let positive: Ptr = (*__decomp_1.borrow()).1.as_pointer(); + let value: Ptr = (*__decomp_1.borrow()).get_value::<0>().as_pointer(); + let positive: Ptr = (*__decomp_1.borrow()).get_value::<1>().as_pointer(); assert!(((value.read()) == 5)); assert!(((positive.read()) as bool)); let p: Value<(Value, Value)> = Rc::new(RefCell::new(( @@ -28,15 +28,19 @@ fn main_0() -> i32 { Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - let a: Ptr = (*__decomp_2.borrow()).0.as_pointer(); - let b: Ptr = (*__decomp_2.borrow()).1.as_pointer(); + let a: Ptr = (*__decomp_2.borrow()).get_value::<0>().as_pointer(); + let b: Ptr = (*__decomp_2.borrow()).get_value::<1>().as_pointer(); a.write(10); assert!(((a.read()) == 10)); assert!(((b.read()) == 2)); assert!(((*(*p.borrow()).0.borrow()) == 1)); let __decomp_3: Ptr<(Value, Value)> = p.as_pointer(); - let x: Ptr = (*__decomp_3.upgrade().deref()).0.as_pointer(); - let y: Ptr = (*__decomp_3.upgrade().deref()).1.as_pointer(); + let x: Ptr = (*__decomp_3.upgrade().deref()) + .get_value::<0>() + .as_pointer(); + let y: Ptr = (*__decomp_3.upgrade().deref()) + .get_value::<1>() + .as_pointer(); x.write(3); { y.with_mut(|__v| *__v = *__v + 4) diff --git a/tests/unit/out/unsafe/empty_array_init.rs b/tests/unit/out/unsafe/empty_array_init.rs index f136eacfbb..77ba5f75c8 100644 --- a/tests/unit/out/unsafe/empty_array_init.rs +++ b/tests/unit/out/unsafe/empty_array_init.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut vec_: Vec = std::array::from_fn::<_, 3_usize, _>(|_| 0_i32).to_vec(); + let mut vec_: Vec = std::array::from_fn::<_, 3, _>(|_| 0_i32).to_vec(); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/inline_container_fields.rs b/tests/unit/out/unsafe/inline_container_fields.rs index afedecc9b6..495977e681 100644 --- a/tests/unit/out/unsafe/inline_container_fields.rs +++ b/tests/unit/out/unsafe/inline_container_fields.rs @@ -84,7 +84,7 @@ impl Default for State { State { count: 0_i32, grid: [[0_i32; 3]; 2], - arr: std::array::from_fn::<_, 3_usize, _>(|_| 0_i32).to_vec(), + arr: std::array::from_fn::<_, 3, _>(|_| 0_i32).to_vec(), elems: Default::default(), rows: Default::default(), } diff --git a/tests/unit/out/unsafe/libc_struct_without_default.rs b/tests/unit/out/unsafe/libc_struct_without_default.rs index 4ee4b2894a..11cc04c114 100644 --- a/tests/unit/out/unsafe/libc_struct_without_default.rs +++ b/tests/unit/out/unsafe/libc_struct_without_default.rs @@ -30,7 +30,7 @@ impl Default for UserDefined { fn default() -> Self { unsafe { UserDefined { - a: std::array::from_fn::<_, 1_usize, _>(|_| 0_i32).to_vec(), + a: std::array::from_fn::<_, 1, _>(|_| 0_i32).to_vec(), v: Default::default(), } } diff --git a/tests/unit/out/unsafe/pair_get.rs b/tests/unit/out/unsafe/pair_get.rs index a2c391af7a..64ca005027 100644 --- a/tests/unit/out/unsafe/pair_get.rs +++ b/tests/unit/out/unsafe/pair_get.rs @@ -7,10 +7,10 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn second_of_0(p: *const (f64, i32)) -> i32 { - return (*p).1; + return *(*p).get::<1>(); } pub unsafe fn first_of_1(p: *const (f64, i32)) -> f64 { - return (*p).0; + return *(*p).get::<0>(); } pub fn main() { unsafe { @@ -20,8 +20,8 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut p: (f64, i32) = (1.5_f64, 2); - assert!(((p.0) == (1.5_f64))); - assert!(((p.1) == (2))); + assert!(((*p.get_mut::<0>()) == (1.5_f64))); + assert!(((*p.get_mut::<1>()) == (2))); assert!(((unsafe { first_of_1(&p,) }) == (1.5_f64))); assert!(((unsafe { second_of_0(&p,) }) == (2))); return 0; diff --git a/tests/unit/out/unsafe/pair_tuple_element.rs b/tests/unit/out/unsafe/pair_tuple_element.rs new file mode 100644 index 0000000000..4741d77632 --- /dev/null +++ b/tests/unit/out/unsafe/pair_tuple_element.rs @@ -0,0 +1,26 @@ +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 p: (f64, i32) = (1.5_f64, 2); + let mut first: f64 = *p.get_mut::<0>(); + let mut second: i32 = *p.get_mut::<1>(); + let ref_: *mut i32 = &mut *p.get_mut::<1>(); + (*ref_) = 7; + assert!(((first) == (1.5_f64))); + assert!(((second) == (2))); + assert!(((p.1) == (7))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/structured_binding_array.rs b/tests/unit/out/unsafe/structured_binding_array.rs index 1bbfef98c9..19c0a3f333 100644 --- a/tests/unit/out/unsafe/structured_binding_array.rs +++ b/tests/unit/out/unsafe/structured_binding_array.rs @@ -25,6 +25,18 @@ unsafe fn main_0() -> i32 { (*__decomp_1)[(2) as usize] += (*__decomp_1)[(1) as usize]; assert!(((arr[(0) as usize]) == (7))); assert!(((arr[(2) as usize]) == (5))); + let mut std_arr: Vec = Vec::from([4, 5, 6]); + let mut last: i32 = (*std_arr.as_mut_ptr().offset(2 as isize)); + (*std_arr.as_mut_ptr().offset(0 as isize)) = 8; + let __decomp_2: *mut Vec = &mut std_arr; + let p: *mut i32 = (*__decomp_2).as_mut_ptr().offset(0 as isize); + let q: *mut i32 = (*__decomp_2).as_mut_ptr().offset(1 as isize); + let r: *mut i32 = (*__decomp_2).as_mut_ptr().offset(2 as isize); + (*q) += 10; + assert!(((last) == (6))); + assert!(((std_arr[(0_usize)]) == (8))); + assert!(((std_arr[(1_usize)]) == (15))); + assert!(((*r) == (6))); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/structured_binding_element_ctor.rs b/tests/unit/out/unsafe/structured_binding_element_ctor.rs index fa1aac1549..5db6196693 100644 --- a/tests/unit/out/unsafe/structured_binding_element_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_element_ctor.rs @@ -98,8 +98,8 @@ unsafe fn main_0() -> i32 { let mut p: (Elem, Elem) = (Elem::new({ 7 }), Elem::new({ 8 })); before_copies = (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)); let mut __decomp_7: (Elem, Elem) = p.clone(); - let x: *mut Elem = &mut __decomp_7.0; - let y: *mut Elem = &mut __decomp_7.1; + let x: *mut Elem = &mut *__decomp_7.get_mut::<0>(); + let y: *mut Elem = &mut *__decomp_7.get_mut::<1>(); assert!( ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == ((before_copies) + (2))) ); diff --git a/tests/unit/out/unsafe/structured_binding_pair.rs b/tests/unit/out/unsafe/structured_binding_pair.rs index 0d2f41474c..de1cf39b61 100644 --- a/tests/unit/out/unsafe/structured_binding_pair.rs +++ b/tests/unit/out/unsafe/structured_binding_pair.rs @@ -17,21 +17,21 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut __decomp_1: (i32, bool) = (unsafe { make_std_pair_0(5) }); - let value: *mut i32 = &mut __decomp_1.0; - let positive: *mut bool = &mut __decomp_1.1; + let value: *mut i32 = &mut *__decomp_1.get_mut::<0>(); + let positive: *mut bool = &mut *__decomp_1.get_mut::<1>(); assert!(((*value) == (5))); assert!(((*positive) as bool)); let mut p: (i32, i32) = (1, 2); let mut __decomp_2: (i32, i32) = p.clone(); - let a: *mut i32 = &mut __decomp_2.0; - let b: *mut i32 = &mut __decomp_2.1; + let a: *mut i32 = &mut *__decomp_2.get_mut::<0>(); + let b: *mut i32 = &mut *__decomp_2.get_mut::<1>(); (*a) = 10; assert!(((*a) == (10))); assert!(((*b) == (2))); assert!(((p.0) == (1))); let __decomp_3: *mut (i32, i32) = &mut p; - let x: *mut i32 = &mut (*__decomp_3).0; - let y: *mut i32 = &mut (*__decomp_3).1; + let x: *mut i32 = &mut *(*__decomp_3).get_mut::<0>(); + let y: *mut i32 = &mut *(*__decomp_3).get_mut::<1>(); (*x) = 3; (*y) += 4; assert!(((p.0) == (3))); diff --git a/tests/unit/pair_tuple_element.cpp b/tests/unit/pair_tuple_element.cpp new file mode 100644 index 0000000000..a95aa9effa --- /dev/null +++ b/tests/unit/pair_tuple_element.cpp @@ -0,0 +1,14 @@ +#include +#include + +int main() { + std::pair p(1.5, 2); + std::tuple_element<0, std::pair>::type first = std::get<0>(p); + std::tuple_element<1, std::pair>::type second = std::get<1>(p); + std::tuple_element<1, std::pair>::type &ref = std::get<1>(p); + ref = 7; + assert(first == 1.5); + assert(second == 2); + assert(p.second == 7); + return 0; +} diff --git a/tests/unit/structured_binding_array.cpp b/tests/unit/structured_binding_array.cpp index b7a6fc1b64..5ac65222e3 100644 --- a/tests/unit/structured_binding_array.cpp +++ b/tests/unit/structured_binding_array.cpp @@ -1,4 +1,5 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include #include int main() { @@ -16,5 +17,15 @@ int main() { z += y; assert(arr[0] == 7); assert(arr[2] == 5); + + std::array std_arr = {4, 5, 6}; + std::tuple_element<2, std::array>::type last = std::get<2>(std_arr); + std::get<0>(std_arr) = 8; + auto &[p, q, r] = std_arr; + q += 10; + assert(last == 6); + assert(std_arr[0] == 8); + assert(std_arr[1] == 15); + assert(r == 6); return 0; }