From a5cd9116f7b1fd1f33e1371c088bd44588e5ff96 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 13:27:54 +0100 Subject: [PATCH 1/2] Fix signed printing of integers --- cpp2rust/converter/converter.cpp | 7 +++++-- cpp2rust/converter/converter_lib.cpp | 16 ++++++++-------- tests/unit/size_t_template_param.cpp | 10 ++++++++++ tests/unit/string_literal_interior_null.cpp | 3 +++ 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index b63c7fcb3..d31c661c2 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2533,8 +2533,11 @@ bool Converter::VisitStringLiteral(clang::StringLiteral *expr) { } if (expr->getString().contains('\0')) { std::string out = "(&["; - for (unsigned char c : expr->getString()) { - out += getTypedLiteral(std::to_string(c).c_str(), CharRustType()) + ", "; + for (char c : expr->getString()) { + auto value = CharRustTypeIsSigned() + ? std::to_string(static_cast(c)) + : std::to_string(static_cast(c)); + out += getTypedLiteral(value.c_str(), CharRustType()) + ", "; } out += getTypedLiteral("0", CharRustType()) + "])"; StrCat(out); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 1aa18fea3..a6259f7ef 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -319,15 +319,15 @@ llvm::APSInt GetIntegerLiteralValue(const clang::ASTContext &ctx, const clang::QualType *type, bool char_is_signed) { auto value = expr->getValue(); + auto target = type ? *type : expr->getType(); bool is_signed = false; - if (type && (*type)->isBuiltinType() && (*type)->isIntegerType() && - !(*type)->isBooleanType()) { - value = value.zextOrTrunc(ctx.getIntWidth(*type)); - is_signed = - (*type)->isSpecificBuiltinType(clang::BuiltinType::Char_S) || - (*type)->isSpecificBuiltinType(clang::BuiltinType::Char_U) - ? char_is_signed - : (*type)->isSignedIntegerType(); + if (target->isBuiltinType() && target->isIntegerType() && + !target->isBooleanType()) { + value = value.zextOrTrunc(ctx.getIntWidth(target)); + is_signed = target->isSpecificBuiltinType(clang::BuiltinType::Char_S) || + target->isSpecificBuiltinType(clang::BuiltinType::Char_U) + ? char_is_signed + : target->isSignedIntegerType(); } return llvm::APSInt(value, !is_signed); } diff --git a/tests/unit/size_t_template_param.cpp b/tests/unit/size_t_template_param.cpp index d8bf3e7d1..bde5c9160 100644 --- a/tests/unit/size_t_template_param.cpp +++ b/tests/unit/size_t_template_param.cpp @@ -16,6 +16,12 @@ template struct RefCtor { RefCtor(const T &x) : v(x + 1) {} }; +template static long long neg_ll() { return N; } + +template static char neg_char() { return C; } + +template static int neg_int() { return N; } + int main() { size_t a1[] = {1, 2, 3}; assert(array_ref(a1) == 3); @@ -28,5 +34,9 @@ int main() { size_t v1 = 6; RefCtor rc(v1); assert(rc.v == 7); + + assert(neg_ll<-9000000>() == -9000000); + assert(neg_char<'\x80'>() == '\x80'); + assert(neg_int<-1>() == -1); return 0; } diff --git a/tests/unit/string_literal_interior_null.cpp b/tests/unit/string_literal_interior_null.cpp index a922a3649..241774410 100644 --- a/tests/unit/string_literal_interior_null.cpp +++ b/tests/unit/string_literal_interior_null.cpp @@ -18,6 +18,9 @@ int main() { assert(a == b); assert(a == 1); + int high = sum_bytes("\xc2\x00\x41", 3); + assert(high == 0xc2 + 0x41); + int c = "\r\n.\r\n"[0] + "\r\n.\r\n"[3]; assert(c == '\r' + '\r'); From 13b97477d4f77dc5304c46a5c0175ca3d1e63c32 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 18:53:05 +0100 Subject: [PATCH 2/2] Update tests --- cpp2rust/converter/converter_lib.cpp | 9 +++++---- tests/unit/out/refcount/size_t_template_param.rs | 12 ++++++++++++ .../out/refcount/string_literal_interior_null.rs | 2 ++ tests/unit/out/unsafe/size_t_template_param.rs | 12 ++++++++++++ .../unit/out/unsafe/string_literal_interior_null.rs | 13 +++++++++++++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index a6259f7ef..dc57d3afa 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -324,10 +324,11 @@ llvm::APSInt GetIntegerLiteralValue(const clang::ASTContext &ctx, if (target->isBuiltinType() && target->isIntegerType() && !target->isBooleanType()) { value = value.zextOrTrunc(ctx.getIntWidth(target)); - is_signed = target->isSpecificBuiltinType(clang::BuiltinType::Char_S) || - target->isSpecificBuiltinType(clang::BuiltinType::Char_U) - ? char_is_signed - : target->isSignedIntegerType(); + is_signed = + target->isSpecificBuiltinType(clang::BuiltinType::Char_S) || + target->isSpecificBuiltinType(clang::BuiltinType::Char_U) + ? char_is_signed + : target->isSignedIntegerType(); } return llvm::APSInt(value, !is_signed); } diff --git a/tests/unit/out/refcount/size_t_template_param.rs b/tests/unit/out/refcount/size_t_template_param.rs index 1a9e536f3..0af31c771 100644 --- a/tests/unit/out/refcount/size_t_template_param.rs +++ b/tests/unit/out/refcount/size_t_template_param.rs @@ -36,6 +36,15 @@ impl RefCtor_unsigned_long_ { } } } +pub fn neg_ll_1() -> i64 { + return -9000000_i64; +} +pub fn neg_char_2() -> i8 { + return (b'\x80' as i8); +} +pub fn neg_int_3() -> i32 { + return -1; +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -54,6 +63,9 @@ fn main_0() -> i32 { let mut rc: RefCtor_unsigned_long_ = RefCtor_unsigned_long_::new({ (v1.as_pointer()).reinterpret_cast::() }); assert!((rc.v == 7_u64)); + assert!((({ neg_ll_1() }) == (-9000000_i32 as i64))); + assert!(((({ neg_char_2() }) as i32) == ((b'\x80' as i8) as i32))); + assert!((({ neg_int_3() }) == -1_i32)); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/string_literal_interior_null.rs b/tests/unit/out/refcount/string_literal_interior_null.rs index 91b5cb253..d6ecad545 100644 --- a/tests/unit/out/refcount/string_literal_interior_null.rs +++ b/tests/unit/out/refcount/string_literal_interior_null.rs @@ -28,6 +28,8 @@ fn main_0() -> i32 { let mut b: i32 = ({ sum_bytes_0((*g_packet_1.with(Value::clone).borrow()).clone(), 2_u32) }); assert!((a == b)); assert!((a == 1)); + let mut high: i32 = ({ sum_bytes_0(Ptr::::from_string_literal(b"\xc2\0A"), 3_u32) }); + assert!((high == (194 + 65))); let mut c: i32 = ((b"\r\n.\r\n"[(0) as usize] as i32) + (b"\r\n.\r\n"[(3) as usize] as i32)); assert!((c == ((('\r' as i8) as i32) + (('\r' as i8) as i32)))); let mut idx: i32 = 1; diff --git a/tests/unit/out/unsafe/size_t_template_param.rs b/tests/unit/out/unsafe/size_t_template_param.rs index 08c778229..25a1d13f7 100644 --- a/tests/unit/out/unsafe/size_t_template_param.rs +++ b/tests/unit/out/unsafe/size_t_template_param.rs @@ -36,6 +36,15 @@ impl RefCtor_unsigned_long_ { this } } +pub unsafe fn neg_ll_1() -> i64 { + return -9000000_i64; +} +pub unsafe fn neg_char_2() -> libc::c_char { + return (b'\x80' as libc::c_char); +} +pub unsafe fn neg_int_3() -> i32 { + return -1; +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -55,6 +64,9 @@ unsafe fn main_0() -> i32 { let mut rc: RefCtor_unsigned_long_ = RefCtor_unsigned_long_::new({ &*(&raw const v1).cast::() }); assert!(((rc.v) == (7_u64))); + assert!(((unsafe { neg_ll_1() }) == (-9000000_i32 as i64))); + assert!((((unsafe { neg_char_2() }) as i32) == ((b'\x80' as libc::c_char) as i32))); + assert!(((unsafe { neg_int_3() }) == (-1_i32))); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/string_literal_interior_null.rs b/tests/unit/out/unsafe/string_literal_interior_null.rs index c514daddb..83b4e96c9 100644 --- a/tests/unit/out/unsafe/string_literal_interior_null.rs +++ b/tests/unit/out/unsafe/string_literal_interior_null.rs @@ -50,6 +50,19 @@ unsafe fn main_0() -> i32 { }); assert!(((a) == (b))); assert!(((a) == (1))); + let mut high: i32 = (unsafe { + sum_bytes_0( + (&[ + (-62 as libc::c_char), + (0 as libc::c_char), + (65 as libc::c_char), + (0 as libc::c_char), + ]) + .as_ptr(), + 3_u32, + ) + }); + assert!(((high) == ((194) + (65)))); let mut c: i32 = (((*c"\r\n.\r\n".as_ptr().offset((0) as isize)) as i32) + ((*c"\r\n.\r\n".as_ptr().offset((3) as isize)) as i32)); assert!(((c) == ((('\r' as libc::c_char) as i32) + (('\r' as libc::c_char) as i32))));