Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 54 additions & 22 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1689,7 +1689,7 @@ std::string Converter::GetEscapedUTF8CharLiteral(clang::Expr *expr) const {
}

std::string Converter::GetEscapedStringLiteral(clang::Expr *expr,
bool add_null_char) const {
uint64_t pad_nulls) const {
auto str_expr = clang::dyn_cast<clang::StringLiteral>(expr->IgnoreCasts());
assert(str_expr);
auto raw = str_expr->getString();
Expand All @@ -1698,15 +1698,31 @@ std::string Converter::GetEscapedStringLiteral(clang::Expr *expr,
for (unsigned char c : raw) {
out += GetEscapedCharLiteral(static_cast<char>(c));
}
if (add_null_char) {
for (uint64_t i = 0; i < pad_nulls; ++i) {
out += "\\0";
}
out.push_back('"');
return out;
}

bool Converter::VisitStringLiteral(clang::StringLiteral *expr) {
StrCat(std::format("b{}.as_ptr()", GetEscapedStringLiteral(expr, true)));
if (!curr_init_type_.empty() && curr_init_type_.top()->isArrayType()) {
if (auto *arr_ty = ctx_.getAsConstantArrayType(curr_init_type_.top())) {
uint64_t arr_size = arr_ty->getSize().getZExtValue();
if (expr->getString().empty()) {
StrCat(std::format("[0u8; {}]", arr_size));
return false;
}
uint64_t pad = arr_size > expr->getString().size()
? arr_size - expr->getString().size()
: 0;
StrCat(token::kStar,
std::format("b{}", GetEscapedStringLiteral(expr, pad)));
return false;
}
StrCat(token::kStar);
}
StrCat(std::format("b{}", GetEscapedStringLiteral(expr, 1)));
return false;
}

Expand All @@ -1726,23 +1742,26 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
SetValueFreshness(type);
break;
}
case clang::CastKind::CK_ArrayToPointerDecay:
if (clang::isa<clang::StringLiteral>(sub_expr) ||
clang::isa<clang::PredefinedExpr>(sub_expr)) {
return Convert(sub_expr);
}
case clang::CastKind::CK_ArrayToPointerDecay: {
// __va_list_tag [1] decays to __va_list_tag *. Just pass through by value
if (IsVaListType(sub_expr->getType())) {
Convert(sub_expr);
break;
}
Convert(sub_expr);
if (sub_expr->getType().isConstQualified()) {
StrCat(keyword_ptr_decay_const_);
bool dest_pointee_const =
expr->getType()->getPointeeType().isConstQualified();
if (clang::isa<clang::StringLiteral>(sub_expr) ||
clang::isa<clang::PredefinedExpr>(sub_expr)) {
StrCat(".as_ptr()");
if (!dest_pointee_const) {
StrCat(".cast_mut()");
}
} else {
StrCat(keyword_ptr_decay_);
StrCat(dest_pointee_const ? ".as_ptr()" : ".as_mut_ptr()");
}
break;
}
case clang::CastKind::CK_BitCast: {
PushParen paren(*this);
Convert(sub_expr);
Expand All @@ -1756,6 +1775,21 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
}
case clang::CastKind::CK_NoOp: {
Convert(sub_expr);
if (expr->getType()->isPointerType() &&
sub_expr->getType()->isPointerType() &&
!clang::isa<clang::CXXThisExpr>(expr->IgnoreImplicit())) {
switch (GetConstCastType(expr->getType()->getPointeeType(),
sub_expr->getType()->getPointeeType())) {
case ConstCastType::MutableToConst:
StrCat(".cast_const()");
break;
case ConstCastType::ConstToMutable:
StrCat(".cast_mut()");
break;
default:
break;
}
}
break;
}
case clang::CastKind::CK_FunctionToPointerDecay:
Expand Down Expand Up @@ -2949,9 +2983,8 @@ void Converter::ConvertVarInit(clang::QualType qual_type, clang::Expr *expr) {
if (auto *lambda = clang::dyn_cast<clang::LambdaExpr>(
expr->IgnoreUnlessSpelledInSource())) {
PushExprKind push(*this, ExprKind::AddrOf);
curr_init_type_.push(qual_type);
PushInitType init_type(*this, qual_type);
VisitLambdaExpr(lambda);
curr_init_type_.pop();
return;
}
}
Expand All @@ -2968,21 +3001,18 @@ void Converter::ConvertVarInit(clang::QualType qual_type, clang::Expr *expr) {
{
PushParen paren(*this);
StrCat(token::kStar);
curr_init_type_.push(qual_type);
PushInitType init_type(*this, qual_type);
Convert(expr);
curr_init_type_.pop();
}
StrCat(".clone()");
} else if (IsReferenceType(expr) || qual_type->isFunctionPointerType()) {
PushExprKind push(*this, ExprKind::AddrOf);
curr_init_type_.push(qual_type);
PushInitType init_type(*this, qual_type);
Convert(expr);
curr_init_type_.pop();
} else {
PushExprKind push(*this, ExprKind::RValue);
curr_init_type_.push(qual_type);
PushInitType init_type(*this, qual_type);
Convert(expr);
curr_init_type_.pop();
}
if (qual_type->isReferenceType() && !IsReferenceType(expr)) {
StrCat(keyword::kAs);
Expand Down Expand Up @@ -3056,9 +3086,11 @@ void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx,

void Converter::ConvertAssignment(clang::Expr *lhs, clang::Expr *rhs,
std::string_view assign_operator) {
curr_init_type_.push(lhs->getType());
auto lhs_as_string = ConvertLValue(lhs);
curr_init_type_.pop();
std::string lhs_as_string;
{
PushInitType init_type(*this, lhs->getType());
lhs_as_string = ConvertLValue(lhs);
}
auto rhs_as_string = ConvertFreshRValue(rhs);

PushBrace brace(*this, !isVoid());
Expand Down
15 changes: 14 additions & 1 deletion cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
std::string GetEscapedUTF8CharLiteral(clang::Expr *expr) const;

std::string GetEscapedStringLiteral(clang::Expr *expr,
bool add_null_char = false) const;
uint64_t pad_nulls = 0) const;
virtual bool VisitStringLiteral(clang::StringLiteral *expr);

virtual bool VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr *expr);
Expand Down Expand Up @@ -522,6 +522,19 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
std::stack<BreakTarget> &stack_;
};

class PushInitType {
public:
PushInitType(Converter &c, clang::QualType type) : c_(c) {
c_.curr_init_type_.push(type);
}
~PushInitType() { c_.curr_init_type_.pop(); }
PushInitType(const PushInitType &) = delete;
PushInitType &operator=(const PushInitType &) = delete;

private:
Converter &c_;
};

std::unordered_set<const clang::VarDecl *> map_iter_decls_;

struct ScopedMapIterDecl {
Expand Down
12 changes: 12 additions & 0 deletions cpp2rust/converter/converter_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -802,4 +802,16 @@ std::string ReplaceAll(std::string str, std::string_view from,
return str;
}

ConstCastType GetConstCastType(clang::QualType to, clang::QualType from) {
if (to.isConstQualified() && from.isConstQualified()) {
return ConstCastType::ConstToConst;
} else if (!to.isConstQualified() && from.isConstQualified()) {
return ConstCastType::ConstToMutable;
} else if (to.isConstQualified() && !from.isConstQualified()) {
return ConstCastType::MutableToConst;
} else {
return ConstCastType::MutableToMutable;
}
}

} // namespace cpp2rust
9 changes: 9 additions & 0 deletions cpp2rust/converter/converter_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,13 @@ void Unwrap(std::string &s, std::string_view prefix, std::string_view suffix);
std::string ReplaceAll(std::string str, std::string_view from,
std::string_view to);

enum class ConstCastType {
ConstToConst,
ConstToMutable,
MutableToConst,
MutableToMutable,
};

ConstCastType GetConstCastType(clang::QualType to, clang::QualType from);

} // namespace cpp2rust
22 changes: 22 additions & 0 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,22 @@ bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
}

bool ConverterRefCount::VisitStringLiteral(clang::StringLiteral *expr) {
if (!curr_init_type_.empty() && curr_init_type_.top()->isArrayType()) {
uint64_t pad = 1;
if (auto *arr_ty = ctx_.getAsConstantArrayType(curr_init_type_.top())) {
uint64_t arr_size = arr_ty->getSize().getZExtValue();
if (expr->getString().empty()) {
StrCat(std::format("vec![0u8; {}].into_boxed_slice()", arr_size));
return false;
}
pad = arr_size > expr->getString().size()
? arr_size - expr->getString().size()
: 0;
}
StrCat(std::format("Box::<[u8]>::from(b{}.as_slice())",
GetEscapedStringLiteral(expr, pad)));
return false;
}
StrCat(GetEscapedStringLiteral(expr));
return false;
}
Expand Down Expand Up @@ -1035,6 +1051,11 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
return false;
}

if (expr->getCastKind() == clang::CastKind::CK_NoOp) {
Convert(sub_expr);
return false;
}

return Converter::VisitImplicitCastExpr(expr);
}

Expand Down Expand Up @@ -1656,6 +1677,7 @@ void ConverterRefCount::ConvertVarInit(clang::QualType qual_type,
bool is_ref = qual_type->isReferenceType();
in_function_formals_ = true;
PushConversionKind push(*this, ConversionKind::Unboxed, is_ref);
PushInitType init_type(*this, qual_type);
StrCat(BoxValue((is_ref || qual_type->isFunctionPointerType())
? ConvertFreshPointer(expr)
: ConvertFreshRValue(expr)));
Expand Down
6 changes: 3 additions & 3 deletions rules/string/ir_unsafe.json
Original file line number Diff line number Diff line change
Expand Up @@ -1548,21 +1548,21 @@
{
"placeholder": {
"arg": "a0",
"access": "read"
"access": "write"
}
}
],
"body": [
{
"text": ".as_ptr()"
"text": ".as_mut_ptr()"
}
]
}
}
],
"params": {
"a0": {
"type": "Vec<u8>"
"type": "&mut Vec<u8>"
}
},
"return_type": {
Expand Down
4 changes: 2 additions & 2 deletions rules/string/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ unsafe fn f4(a0: &mut Vec<u8>, a1: *mut u8, a2: usize) {
unsafe fn f5(a0: Vec<u8>) -> *const u8 {
a0.as_ptr()
}
unsafe fn f6(a0: Vec<u8>) -> *const u8 {
a0.as_ptr()
unsafe fn f6(a0: &mut Vec<u8>) -> *const u8 {
a0.as_mut_ptr()
}
unsafe fn f7(a0: *const u8, a1: usize) -> Vec<u8> {
std::slice::from_raw_parts(a0, a1 as usize)
Expand Down
63 changes: 63 additions & 0 deletions tests/unit/out/refcount/string_literals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
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 foo_mut_0(str: Ptr<u8>) {
let str: Value<Ptr<u8>> = Rc::new(RefCell::new(str));
}
pub fn foo_const_1(str: Ptr<u8>) {
let str: Value<Ptr<u8>> = Rc::new(RefCell::new(str));
}
pub fn main() {
std::process::exit(main_0());
}
fn main_0() -> i32 {
let immutable_strings: Value<Box<[Ptr<u8>]>> = Rc::new(RefCell::new(Box::new([
Ptr::from_string_literal("a"),
Ptr::from_string_literal("b"),
Ptr::from_string_literal("c"),
])));
let immutable_string: Value<Ptr<u8>> = Rc::new(RefCell::new(Ptr::from_string_literal("hello")));
let mutable_string_arr: Value<Box<[u8]>> =
Rc::new(RefCell::new(Box::<[u8]>::from(b"papanasi\0".as_slice())));
let immutable_string_arr: Value<Box<[u8]>> =
Rc::new(RefCell::new(Box::<[u8]>::from(b"papanasi\0".as_slice())));
let immutable_empty: Value<Ptr<u8>> = Rc::new(RefCell::new(Ptr::from_string_literal("")));
let mutable_empty_arr: Value<Box<[u8]>> =
Rc::new(RefCell::new(vec![0u8; 1].into_boxed_slice()));
let immutable_empty_arr: Value<Box<[u8]>> =
Rc::new(RefCell::new(vec![0u8; 1].into_boxed_slice()));
({
let _str: Ptr<u8> = (mutable_string_arr.as_pointer() as Ptr<u8>);
foo_mut_0(_str)
});
({
let _str: Ptr<u8> = Ptr::from_string_literal("world");
foo_const_1(_str)
});
({
let _str: Ptr<u8> = (*immutable_string.borrow()).clone();
foo_const_1(_str)
});
({
let _str: Ptr<u8> = (immutable_string_arr.as_pointer() as Ptr<u8>);
foo_const_1(_str)
});
({
let _str: Ptr<u8> = Ptr::from_string_literal("");
foo_const_1(_str)
});
({
let _str: Ptr<u8> = (*immutable_empty.borrow()).clone();
foo_const_1(_str)
});
({
let _str: Ptr<u8> = (immutable_empty_arr.as_pointer() as Ptr<u8>);
foo_const_1(_str)
});
return 0;
}
Loading
Loading