diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 6b01f51c97..da59176e05 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2741,7 +2741,8 @@ bool Converter::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { case clang::Stmt::CXXReinterpretCastExprClass: case clang::Stmt::CXXStaticCastExprClass: case clang::Stmt::CStyleCastExprClass: - if (expr->getType() == sub_expr->getType()) { + if (expr->getType() == sub_expr->getType() || + (expr->getCastKind() == clang::CK_NoOp && type->isRecordType())) { return Convert(sub_expr); } if (type->isFunctionPointerType() || diff --git a/cpp2rust/converter/models/boxed_vars.cpp b/cpp2rust/converter/models/boxed_vars.cpp index d0ef168c25..e38209cfa4 100644 --- a/cpp2rust/converter/models/boxed_vars.cpp +++ b/cpp2rust/converter/models/boxed_vars.cpp @@ -4,6 +4,7 @@ #include "converter/models/boxed_vars.h" #include +#include #include #include @@ -110,6 +111,14 @@ class AddressTakenVisitor bool shouldVisitTemplateInstantiations() const { return true; } + bool TraverseDecl(clang::Decl *decl) { + if (decl && !llvm::isa(decl) && + ctx_.getSourceManager().isInSystemHeader(decl->getLocation())) { + return true; + } + return RecursiveASTVisitor::TraverseDecl(decl); + } + // Only the semantic form of an initializer list is converted, in which the // values of variables are read through lvalue-to-rvalue conversions. bool TraverseInitListExpr(clang::InitListExpr *expr, diff --git a/cpp2rust/converter/rules/rules_loader.cpp b/cpp2rust/converter/rules/rules_loader.cpp index 03592bf950..a7dcd559ee 100644 --- a/cpp2rust/converter/rules/rules_loader.cpp +++ b/cpp2rust/converter/rules/rules_loader.cpp @@ -473,6 +473,10 @@ std::string DeclKey(const clang::NamedDecl *decl) { } std::string ExprKey(clang::ASTContext &ctx, const clang::Expr *expr) { + expr = RuleDecls::SkipImplicit(expr); + if (auto cast = llvm::dyn_cast(expr)) { + return ExprKey(ctx, cast->getSubExpr()); + } expr = expr->IgnoreParenImpCasts(); if (llvm::isa(expr) && expr->getBeginLoc().isMacroID()) { diff --git a/rules/chrono/src_cxx20.cpp b/rules/chrono/src_cxx20.cpp new file mode 100644 index 0000000000..8a2cc49822 --- /dev/null +++ b/rules/chrono/src_cxx20.cpp @@ -0,0 +1,10 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +#include + +using t1 = std::chrono::day; + +std::chrono::day f1(unsigned a0) { return std::chrono::day(a0); } + +unsigned f2(const std::chrono::day &a0) { return static_cast(a0); } diff --git a/rules/chrono/tgt_unsafe.rs b/rules/chrono/tgt_unsafe.rs new file mode 100644 index 0000000000..e8d446da18 --- /dev/null +++ b/rules/chrono/tgt_unsafe.rs @@ -0,0 +1,14 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +fn t1() -> u32 { + 0_u32 +} + +unsafe fn f1(a0: u32) -> u32 { + a0 +} + +unsafe fn f2(a0: u32) -> u32 { + a0 +} diff --git a/rules/fs_path/src_cxx17.cpp b/rules/fs_path/src_cxx17.cpp new file mode 100644 index 0000000000..8d8e5b1927 --- /dev/null +++ b/rules/fs_path/src_cxx17.cpp @@ -0,0 +1,13 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +#include +#include + +using t1 = std::filesystem::path; + +std::filesystem::path f1(const char *a0) { return std::filesystem::path(a0); } + +std::string f2(const std::filesystem::path &a0) { + return static_cast(a0); +} diff --git a/rules/fs_path/tgt_refcount.rs b/rules/fs_path/tgt_refcount.rs new file mode 100644 index 0000000000..0c0aa15ac7 --- /dev/null +++ b/rules/fs_path/tgt_refcount.rs @@ -0,0 +1,19 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use libcc2rs::*; + +fn t1() -> Vec { + vec![0] +} + +fn f1(a0: Ptr) -> Vec { + let mut __v = Vec::new(); + a0.with_c_str(|__s| __v.extend_from_slice(__s)); + __v.push(0); + __v +} + +fn f2(a0: Vec) -> Vec { + a0 +} diff --git a/rules/fs_path/tgt_unsafe.rs b/rules/fs_path/tgt_unsafe.rs new file mode 100644 index 0000000000..a76d55f60b --- /dev/null +++ b/rules/fs_path/tgt_unsafe.rs @@ -0,0 +1,20 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +fn t1() -> Vec { + vec![0] +} + +unsafe fn f1(a0: *const libc::c_char) -> Vec { + let mut __v = ::std::ffi::CStr::from_ptr(a0) + .to_bytes() + .iter() + .map(|&__b| __b as libc::c_char) + .collect::>(); + __v.push(0); + __v +} + +unsafe fn f2(a0: Vec) -> Vec { + a0 +} diff --git a/tests/unit/out/refcount/stl_conversion_operators.rs b/tests/unit/out/refcount/stl_conversion_operators.rs new file mode 100644 index 0000000000..2e2399a8ec --- /dev/null +++ b/tests/unit/out/refcount/stl_conversion_operators.rs @@ -0,0 +1,32 @@ +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 mut n: u32 = 17_u32; + let d: Value = Rc::new(RefCell::new(n)); + assert!(((*d.borrow()) == 17_u32)); + let mut name: Ptr = Ptr::::from_string_literal(b"dir/file.txt"); + let p: Value> = Rc::new(RefCell::new({ + let mut __v = Vec::new(); + name.with_c_str(|__s| __v.extend_from_slice(__s)); + __v.push(0); + __v + })); + let mut s: Vec = (*p.borrow()).clone(); + assert!(((s.len() - 1) == 12_usize)); + assert!( + Ptr::::from_string_literal(b"dir/file.txt") + .with_c_str(|__s| s[..s.len().saturating_sub(1)] == *__s) + ); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/stl_conversion_operators.rs b/tests/unit/out/unsafe/stl_conversion_operators.rs new file mode 100644 index 0000000000..6ed9e4c5d8 --- /dev/null +++ b/tests/unit/out/unsafe/stl_conversion_operators.rs @@ -0,0 +1,40 @@ +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 n: u32 = 17_u32; + let mut d: u32 = n; + assert!(((d) == (17_u32))); + let mut name: *const libc::c_char = c"dir/file.txt".as_ptr(); + let mut p: Vec = { + let mut __v = ::std::ffi::CStr::from_ptr(name) + .to_bytes() + .iter() + .map(|&__b| __b as libc::c_char) + .collect::>(); + __v.push(0); + __v + }; + let mut s: Vec = p; + assert!(((s.len() - 1) == (12_usize))); + assert!( + s == { + let s = c"dir/file.txt".as_ptr(); + std::slice::from_raw_parts(s, (0..).take_while(|&i| *s.add(i) != 0).count() + 1) + .to_vec() + } + ); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/stl_conversion_operators.cpp b/tests/unit/stl_conversion_operators.cpp new file mode 100644 index 0000000000..7bb5c0a523 --- /dev/null +++ b/tests/unit/stl_conversion_operators.cpp @@ -0,0 +1,18 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++20 +#include +#include +#include +#include + +int main() { + unsigned n = 17; + std::chrono::day d(n); + assert(static_cast(d) == 17); + + const char *name = "dir/file.txt"; + std::filesystem::path p(name); + std::string s = static_cast(p); + assert(s.size() == 12); + assert(s == "dir/file.txt"); + return 0; +}