Skip to content

Commit b6f88a3

Browse files
lucic71nunoplopes
authored andcommitted
Translate wide strings (#381)
1 parent 2012814 commit b6f88a3

76 files changed

Lines changed: 1011 additions & 395 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎cpp2rust/converter/converter.cpp‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,6 +2226,13 @@ bool Converter::VisitFloatingLiteral(clang::FloatingLiteral *expr) {
22262226
}
22272227

22282228
bool Converter::VisitCharacterLiteral(clang::CharacterLiteral *expr) {
2229+
if (expr->getKind() != clang::CharacterLiteralKind::Ascii) {
2230+
PushParen paren(*this);
2231+
StrCat(std::to_string(expr->getValue()), keyword::kAs,
2232+
ToStringBase(expr->getType()));
2233+
computed_expr_type_ = ComputedExprType::FreshValue;
2234+
return false;
2235+
}
22292236
auto uc = static_cast<unsigned char>(expr->getValue());
22302237
std::string ch = GetEscapedCharLiteral(expr->getValue());
22312238
ch = (uc > 0x7F ? "b'" : "'") + std::move(ch) + '\'';
@@ -2290,7 +2297,37 @@ std::string Converter::GetEscapedStringLiteral(clang::Expr *expr,
22902297
return out;
22912298
}
22922299

2300+
bool Converter::IsArrayInitContext() const {
2301+
return !curr_init_type_.empty() && curr_init_type_.back()->isArrayType();
2302+
}
2303+
2304+
std::string
2305+
Converter::GetCodeUnitArrayLiteral(const clang::StringLiteral *expr) {
2306+
auto elem_type =
2307+
ToStringBase(ctx_.getAsArrayType(expr->getType())->getElementType());
2308+
uint64_t len = expr->getLength();
2309+
uint64_t total = len + 1;
2310+
if (IsArrayInitContext()) {
2311+
if (auto *arr_ty = ctx_.getAsConstantArrayType(curr_init_type_.back())) {
2312+
total = std::max(arr_ty->getSize().getZExtValue(), len);
2313+
}
2314+
}
2315+
std::string out = "[";
2316+
for (uint64_t i = 0; i < total; ++i) {
2317+
out += std::format("{} as {}, ", i < len ? expr->getCodeUnit(i) : 0,
2318+
elem_type);
2319+
}
2320+
out += ']';
2321+
return out;
2322+
}
2323+
22932324
bool Converter::VisitStringLiteral(clang::StringLiteral *expr) {
2325+
if (IsCodeUnitStringLiteral(expr)) {
2326+
StrCat(GetCodeUnitArrayLiteral(expr));
2327+
computed_expr_type_ = ComputedExprType::FreshValue;
2328+
return false;
2329+
}
2330+
22942331
auto init_type = curr_init_type_.empty()
22952332
? clang::QualType()
22962333
: curr_init_type_.back().getNonReferenceType();

‎cpp2rust/converter/converter.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
350350
virtual bool VisitCharacterLiteral(clang::CharacterLiteral *expr);
351351

352352
std::string GetEscapedCharLiteral(char character) const;
353+
std::string GetCodeUnitArrayLiteral(const clang::StringLiteral *expr);
354+
bool IsArrayInitContext() const;
353355

354356
std::string GetEscapedUTF8CharLiteral(clang::Expr *expr) const;
355357

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ bool IsStringLiteralExpr(const clang::Expr *expr) {
149149
clang::isa<clang::PredefinedExpr>(stripped);
150150
}
151151

152+
bool IsCodeUnitStringLiteral(const clang::StringLiteral *expr) {
153+
return expr->getCharByteWidth() != 1 ||
154+
expr->getKind() == clang::StringLiteralKind::UTF8;
155+
}
156+
152157
bool IsUserDefinedDecl(const clang::Decl *decl) {
153158
const auto &ctx = decl->getASTContext();
154159
const auto &src_mgr = ctx.getSourceManager();

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ bool IsUnionArrayMember(const clang::Expr *base);
4646

4747
bool IsStringLiteralExpr(const clang::Expr *expr);
4848

49+
bool IsCodeUnitStringLiteral(const clang::StringLiteral *expr);
50+
4951
bool IsUserDefinedDecl(const clang::Decl *decl);
5052

5153
bool RefersToUserDefinedDecl(const clang::Expr *expr);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,15 @@ bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
11901190
}
11911191

11921192
bool ConverterRefCount::VisitStringLiteral(clang::StringLiteral *expr) {
1193-
if (!curr_init_type_.empty() && curr_init_type_.back()->isArrayType()) {
1193+
if (IsCodeUnitStringLiteral(expr)) {
1194+
auto arr = GetCodeUnitArrayLiteral(expr);
1195+
StrCat(IsArrayInitContext() ? std::format("Box::from({})", arr)
1196+
: '&' + arr);
1197+
computed_expr_type_ = ComputedExprType::FreshValue;
1198+
return false;
1199+
}
1200+
1201+
if (IsArrayInitContext()) {
11941202
uint64_t pad = 1;
11951203
if (auto *arr_ty = ctx_.getAsConstantArrayType(curr_init_type_.back())) {
11961204
uint64_t arr_size = arr_ty->getSize().getZExtValue();
@@ -1283,7 +1291,11 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
12831291
return false;
12841292
}
12851293
if (IsStringLiteralExpr(sub_expr)) {
1286-
StrCat(std::format("Ptr::from_string_literal({})",
1294+
auto code_unit = ToStringBase(
1295+
ctx_.getAsArrayType(
1296+
sub_expr->IgnoreParens()->IgnoreImplicit()->getType())
1297+
->getElementType());
1298+
StrCat(std::format("Ptr::<{}>::from_string_literal({})", code_unit,
12871299
ToString(sub_expr->IgnoreParens())));
12881300
computed_expr_type_ = ComputedExprType::FreshPointer;
12891301
return false;
@@ -2169,7 +2181,12 @@ std::string ConverterRefCount::ConvertVarInitValue(clang::QualType qual_type,
21692181
}
21702182
if (qual_type.getNonReferenceType()->isArrayType()) {
21712183
if (IsStringLiteralExpr(expr)) {
2172-
return std::format("Ptr::from_string_literal_array({})",
2184+
auto code_unit = ToStringBase(
2185+
ctx_.getAsArrayType(
2186+
expr->IgnoreParens()->IgnoreImplicit()->getType())
2187+
->getElementType());
2188+
return std::format("Ptr::<Box<[{}]>>::from_string_literal_array({})",
2189+
code_unit,
21732190
ToString(expr->IgnoreParens()->IgnoreImplicit()));
21742191
}
21752192
return std::format("({} as {})", ConvertFreshPointer(expr),
@@ -2461,7 +2478,12 @@ void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,
24612478
{
24622479
PushParen paren(*this, is_inner_boxed);
24632480
if (IsStringLiteralExpr(base)) {
2464-
StrCat(std::format("Ptr::from_string_literal({}).offset({})",
2481+
auto code_unit = ToStringBase(
2482+
ctx_.getAsArrayType(
2483+
base->IgnoreParens()->IgnoreImplicit()->getType())
2484+
->getElementType());
2485+
StrCat(std::format("Ptr::<{}>::from_string_literal({}).offset({})",
2486+
code_unit,
24652487
ToString(base->IgnoreParens()->IgnoreImplicit()),
24662488
ConvertSubscriptIndex(idx)));
24672489
} else {

‎libcc2rs/src/cstr.rs‎

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,32 +27,49 @@ impl fmt::Display for Ptr<u8> {
2727
}
2828
}
2929

30-
type StringLiteralMap = HashMap<&'static [u8], Rc<RefCell<Box<[u8]>>>>;
30+
macro_rules! impl_string_literal {
31+
($t:ty, $cache:ident) => {
32+
thread_local! {
33+
static $cache: RefCell<HashMap<&'static [$t], Rc<RefCell<Box<[$t]>>>>> =
34+
RefCell::new(HashMap::new());
35+
}
3136

32-
thread_local! {
33-
static STRING_LITERALS: RefCell<StringLiteralMap> = RefCell::new(HashMap::new());
34-
}
37+
impl Ptr<Box<[$t]>> {
38+
#[inline]
39+
pub fn from_string_literal_array(s: &'static [$t]) -> Self {
40+
$cache.with(|literals| {
41+
let mut literals = literals.borrow_mut();
42+
let weak = Rc::downgrade(literals.entry(s).or_insert_with(|| {
43+
Rc::new(RefCell::new({
44+
let mut v = s.to_vec();
45+
v.push(0);
46+
v.into_boxed_slice()
47+
}))
48+
}));
49+
Ptr {
50+
offset: 0,
51+
kind: PtrKind::StackSingle(weak),
52+
}
53+
})
54+
}
55+
}
3556

36-
impl Ptr<Box<[u8]>> {
37-
#[inline]
38-
pub fn from_string_literal_array(s: &'static [u8]) -> Self {
39-
STRING_LITERALS.with(|literals| {
40-
let mut literals = literals.borrow_mut();
41-
let weak = Rc::downgrade(literals.entry(s).or_insert_with(|| {
42-
Rc::new(RefCell::new({
43-
let mut v = s.to_vec();
44-
v.push(0);
45-
v.into_boxed_slice()
46-
}))
47-
}));
48-
Ptr {
49-
offset: 0,
50-
kind: PtrKind::StackSingle(weak),
57+
impl Ptr<$t> {
58+
#[inline]
59+
pub fn from_string_literal(s: &'static [$t]) -> Self {
60+
Ptr::<Box<[$t]>>::from_string_literal_array(s)
61+
.to_strong()
62+
.as_pointer()
5163
}
52-
})
53-
}
64+
}
65+
};
5466
}
5567

68+
impl_string_literal!(u8, STRING_LITERALS_U8);
69+
impl_string_literal!(u16, STRING_LITERALS_U16);
70+
impl_string_literal!(u32, STRING_LITERALS_U32);
71+
impl_string_literal!(i32, STRING_LITERALS_I32);
72+
5673
impl Ptr<u8> {
5774
#[allow(clippy::explicit_counter_loop)]
5875
pub fn memcpy(&self, src: &Self, len: usize) {
@@ -104,13 +121,6 @@ impl Ptr<u8> {
104121
0
105122
}
106123

107-
#[inline]
108-
pub fn from_string_literal(s: &'static [u8]) -> Self {
109-
Ptr::<Box<[u8]>>::from_string_literal_array(s)
110-
.to_strong()
111-
.as_pointer()
112-
}
113-
114124
pub fn to_c_string_iterator(&self) -> CStringIterator {
115125
CStringIterator { ptr: self.clone() }
116126
}

‎libcc2rs/src/libc_shims/time.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl Tm {
3737
let zone: &'static [u8] = b"GMT";
3838
#[cfg(target_os = "macos")]
3939
let zone: &'static [u8] = b"UTC";
40-
*tm.tm_zone.borrow_mut() = Ptr::from_string_literal(zone);
40+
*tm.tm_zone.borrow_mut() = Ptr::<u8>::from_string_literal(zone);
4141
tm
4242
}
4343

‎rules/locale/tgt_refcount.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ use libcc2rs::*;
88
// TODO: we need to track ourselves the locale settings and change the behavior of the relevant
99
// functions based on the set locale.
1010
fn f1(a0: i32, a1: Ptr<u8>) -> Ptr<u8> {
11-
Ptr::from_string_literal(b"C")
11+
Ptr::<u8>::from_string_literal(b"C")
1212
}

‎tests/ub/out/refcount/fd_double_close.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main_0() -> i32 {
1717
None => nix::sys::stat::Mode::empty(),
1818
};
1919
match nix::fcntl::open(
20-
Ptr::from_string_literal(b"/dev/null")
20+
Ptr::<u8>::from_string_literal(b"/dev/null")
2121
.to_rust_string()
2222
.as_str(),
2323
nix::fcntl::OFlag::from_bits_retain(::libc::O_RDONLY),

‎tests/ub/out/refcount/fd_use_after_close.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main_0() -> i32 {
1717
None => nix::sys::stat::Mode::empty(),
1818
};
1919
match nix::fcntl::open(
20-
Ptr::from_string_literal(b"/dev/null")
20+
Ptr::<u8>::from_string_literal(b"/dev/null")
2121
.to_rust_string()
2222
.as_str(),
2323
nix::fcntl::OFlag::from_bits_retain(::libc::O_RDONLY),

0 commit comments

Comments
 (0)