Skip to content

Commit 2c81e6f

Browse files
committed
Merge branch 'master' into safe-cstring
2 parents 6355eac + 12c7116 commit 2c81e6f

37 files changed

Lines changed: 1163 additions & 77 deletions

‎cpp2rust/converter/converter.cpp‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,11 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
891891
}
892892
}
893893

894+
EmitRustStructOrUnion(decl);
895+
} else if (decl->isUnion()) {
896+
if (!record_decls_.MarkDefined(GetRecordName(decl))) {
897+
return false;
898+
}
894899
EmitRustStructOrUnion(decl);
895900
} else {
896901
// FIXME: improve error handling
@@ -2084,8 +2089,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
20842089
bool dest_pointee_const =
20852090
expr->getType()->getPointeeType().isConstQualified();
20862091
Convert(sub_expr);
2087-
if (clang::isa<clang::StringLiteral>(sub_expr) ||
2088-
clang::isa<clang::PredefinedExpr>(sub_expr)) {
2092+
if (IsStringLiteralExpr(sub_expr)) {
20892093
StrCat(".as_ptr()");
20902094
if (!dest_pointee_const) {
20912095
StrCat(".cast_mut()");

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ bool IsUnionArrayMember(const clang::Expr *base) {
140140
return false;
141141
}
142142

143+
bool IsStringLiteralExpr(const clang::Expr *expr) {
144+
const auto *stripped = expr->IgnoreParens()->IgnoreImplicit();
145+
return clang::isa<clang::StringLiteral>(stripped) ||
146+
clang::isa<clang::PredefinedExpr>(stripped);
147+
}
148+
143149
bool IsUserDefinedDecl(const clang::Decl *decl) {
144150
const auto &ctx = decl->getASTContext();
145151
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
@@ -42,6 +42,8 @@ bool IsInMainFile(const clang::Decl *decl);
4242

4343
bool IsUnionArrayMember(const clang::Expr *base);
4444

45+
bool IsStringLiteralExpr(const clang::Expr *expr);
46+
4547
bool IsUserDefinedDecl(const clang::Decl *decl);
4648

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

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 81 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,14 @@ bool ConverterRefCount::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
417417
return false;
418418
}
419419

420+
bool ConverterRefCount::VisitOffsetOfExpr(clang::OffsetOfExpr *expr) {
421+
clang::Expr::EvalResult result;
422+
ENSURE(expr->EvaluateAsInt(result, ctx_));
423+
StrCat(std::format("{}_usize", result.Val.getInt().getZExtValue()));
424+
computed_expr_type_ = ComputedExprType::FreshValue;
425+
return false;
426+
}
427+
420428
void ConverterRefCount::ConvertOrdAndPartialOrdTraits(
421429
const clang::CXXRecordDecl *decl, const clang::FunctionDecl *op) {
422430
std::string first_branch, second_branch, first_return, second_return;
@@ -723,10 +731,10 @@ void ConverterRefCount::EmitHoistedInArmAssignment(clang::VarDecl *decl) {
723731
if (!decl->hasInit()) {
724732
return;
725733
}
726-
PushConversionKind push(*this, ConversionKind::Unboxed);
734+
PushConversionKind push(*this, ConversionKind::FullRefCount);
727735
StrCat(token::kStar, GetNamedDeclAsString(decl), ".borrow_mut()",
728736
token::kAssign);
729-
Convert(decl->getInit());
737+
StrCat(ConvertVarInitValue(decl->getType(), decl->getInit()));
730738
StrCat(token::kSemiColon);
731739
}
732740

@@ -1173,6 +1181,8 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
11731181
->getPointeeType()
11741182
->getAsArrayTypeUnsafe()
11751183
->getElementType())));
1184+
} else if (IsStringLiteralExpr(sub_expr)) {
1185+
StrCat(std::format("{}.to_any()", ConvertFreshPointer(sub_expr)));
11761186
} else {
11771187
StrCat(std::format("({} as {}).to_any()", ConvertFreshPointer(sub_expr),
11781188
ToString(sub_expr->getType())));
@@ -1212,9 +1222,9 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
12121222
Convert(sub_expr);
12131223
return false;
12141224
}
1215-
if (clang::isa<clang::StringLiteral>(sub_expr) ||
1216-
clang::isa<clang::PredefinedExpr>(sub_expr)) {
1217-
StrCat(std::format("Ptr::from_string_literal({})", ToString(sub_expr)));
1225+
if (IsStringLiteralExpr(sub_expr)) {
1226+
StrCat(std::format("Ptr::from_string_literal({})",
1227+
ToString(sub_expr->IgnoreParens())));
12181228
return false;
12191229
} else {
12201230
// we need to write (var.as_pointer as Ptr<T>) because Rust isn't
@@ -1318,6 +1328,7 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
13181328
return false;
13191329
}
13201330
if (expr->getCastKind() == clang::CK_NullToPointer) {
1331+
PushConversionKind push(*this, ConversionKind::Unboxed);
13211332
StrCat(GetDefaultAsString(expr->getType()));
13221333
computed_expr_type_ = ComputedExprType::FreshPointer;
13231334
return false;
@@ -1333,8 +1344,29 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) {
13331344
return false;
13341345
case clang::Stmt::CStyleCastExprClass:
13351346
case clang::Stmt::CXXStaticCastExprClass:
1347+
if (expr->getCastKind() == clang::CastKind::CK_PointerToIntegral ||
1348+
expr->getCastKind() == clang::CastKind::CK_IntegralToPointer) {
1349+
std::string dst_type;
1350+
{
1351+
PushConversionKind push(*this, ConversionKind::Unboxed);
1352+
dst_type = ToString(expr->getType());
1353+
}
1354+
if (expr->getCastKind() == clang::CastKind::CK_PointerToIntegral) {
1355+
StrCat(std::format("{}.to_int()", ToString(expr->getSubExpr())));
1356+
computed_expr_type_ = ComputedExprType::FreshValue;
1357+
} else {
1358+
StrCat(std::format("<{}>::from_int({})", dst_type,
1359+
ToString(expr->getSubExpr())));
1360+
computed_expr_type_ = ComputedExprType::FreshPointer;
1361+
}
1362+
return false;
1363+
}
1364+
13361365
if (!VisitFunctionPointerCast(expr)) {
13371366
return false;
1367+
} else if (expr->getSubExpr()->getType()->isVoidPointerType() &&
1368+
expr->getType()->isVoidPointerType()) {
1369+
return Convert(expr->getSubExpr());
13381370
} else if (expr->getSubExpr()->getType()->isVoidPointerType() &&
13391371
expr->getType()->isPointerType()) {
13401372
Convert(expr->getSubExpr());
@@ -1889,7 +1921,9 @@ ConverterRefCount::GetArrayDefaultAsString(clang::QualType qual_type) {
18891921
const auto &size = array_type->getSize();
18901922
auto size_as_string = GetNumAsString(size);
18911923
auto element_type = array_type->getElementType();
1892-
PushConversionKind push(*this, ConversionKind::Unboxed);
1924+
PushConversionKind push(*this, element_type->isArrayType()
1925+
? ConversionKind::FullRefCount
1926+
: ConversionKind::Unboxed);
18931927
auto element_type_as_string = ToString(element_type);
18941928
auto default_as_string = GetDefaultAsString(element_type);
18951929
return std::format("(0..{}).map(|_| {}).collect::<Box<[{}]>>()",
@@ -1957,35 +1991,34 @@ ConverterRefCount::GetStructAttributes(const clang::RecordDecl *decl) {
19571991
return attrs;
19581992
}
19591993

1960-
void ConverterRefCount::ConvertVarInit(clang::QualType qual_type,
1961-
clang::Expr *expr) {
1994+
std::string ConverterRefCount::ConvertVarInitValue(clang::QualType qual_type,
1995+
clang::Expr *expr) {
19621996
if (auto lambda = clang::dyn_cast<clang::LambdaExpr>(
19631997
expr->IgnoreUnlessSpelledInSource())) {
1964-
std::string str;
1965-
{
1966-
Buffer buf(*this);
1967-
PushConversionKind push(*this, ConversionKind::Unboxed);
1968-
if (qual_type->isFunctionPointerType() && lambda->capture_size() == 0) {
1969-
StrCat("FnPtr::new(");
1970-
VisitLambdaExpr(lambda);
1971-
StrCat(')');
1972-
} else {
1973-
VisitLambdaExpr(lambda);
1974-
}
1975-
str = std::move(buf).str();
1998+
Buffer buf(*this);
1999+
PushConversionKind push(*this, ConversionKind::Unboxed);
2000+
if (qual_type->isFunctionPointerType() && lambda->capture_size() == 0) {
2001+
StrCat("FnPtr::new(");
2002+
VisitLambdaExpr(lambda);
2003+
StrCat(')');
2004+
} else {
2005+
VisitLambdaExpr(lambda);
19762006
}
1977-
StrCat(BoxValue(std::move(str)));
1978-
return;
2007+
return std::move(buf).str();
19792008
}
19802009

1981-
bool is_ref = qual_type->isReferenceType();
1982-
PushConversionKind push(*this, ConversionKind::Unboxed, is_ref);
19832010
PushInitType init_type(*this, qual_type);
1984-
if (is_ref || qual_type->isFunctionPointerType()) {
1985-
StrCat(BoxValue(ConvertFreshPointer(expr)));
1986-
} else {
1987-
StrCat(BoxValue(ConvertFreshRValue(expr, qual_type)));
2011+
if (qual_type->isReferenceType() || qual_type->isFunctionPointerType()) {
2012+
return ConvertFreshPointer(expr);
19882013
}
2014+
return ConvertFreshRValue(expr, qual_type);
2015+
}
2016+
2017+
void ConverterRefCount::ConvertVarInit(clang::QualType qual_type,
2018+
clang::Expr *expr) {
2019+
bool is_ref = qual_type->isReferenceType();
2020+
PushConversionKind push(*this, ConversionKind::Unboxed, is_ref);
2021+
StrCat(BoxValue(ConvertVarInitValue(qual_type, expr)));
19892022
}
19902023

19912024
void ConverterRefCount::EmitSetOrAssign(clang::Expr *lhs,
@@ -2157,7 +2190,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
21572190
pending_deref_.set(std::format("({} as {}).offset({})",
21582191
ConvertObject(expr->getArg(0)),
21592192
ConvertPtrType(expr->getArg(0)->getType()),
2160-
ConvertRValue(expr->getArg(1))),
2193+
ConvertSubscriptIndex(expr->getArg(1))),
21612194
expr);
21622195
break;
21632196
}
@@ -2177,7 +2210,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
21772210
StrCat(std::format("({} as {}).offset({})",
21782211
ConvertObject(expr->getArg(0)),
21792212
ConvertPtrType(expr->getArg(0)->getType()),
2180-
ConvertRValue(expr->getArg(1))));
2213+
ConvertSubscriptIndex(expr->getArg(1))));
21812214

21822215
if (is_inner_boxed) {
21832216
StrCat(GetPointerDerefSuffix(expr->getType()), ".as_pointer()");
@@ -2212,6 +2245,14 @@ void ConverterRefCount::ConvertFunctionParameters(clang::FunctionDecl *decl) {
22122245
}
22132246
}
22142247

2248+
std::string ConverterRefCount::ConvertSubscriptIndex(clang::Expr *idx) {
2249+
auto str = ConvertRValue(idx);
2250+
if (idx->getType()->isEnumeralType()) {
2251+
return std::format("({}) as isize", str);
2252+
}
2253+
return str;
2254+
}
2255+
22152256
void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,
22162257
clang::Expr *idx,
22172258
clang::QualType type) {
@@ -2225,10 +2266,16 @@ void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,
22252266

22262267
{
22272268
PushParen paren(*this, is_inner_boxed);
2228-
StrCat(std::format("({} as {}).offset({})",
2229-
ToString(base->IgnoreImplicit()),
2230-
ConvertPtrType(base->IgnoreImplicit()->getType()),
2231-
ConvertRValue(idx)));
2269+
if (IsStringLiteralExpr(base)) {
2270+
StrCat(std::format("Ptr::from_string_literal({}).offset({})",
2271+
ToString(base->IgnoreParens()->IgnoreImplicit()),
2272+
ConvertSubscriptIndex(idx)));
2273+
} else {
2274+
StrCat(std::format("({} as {}).offset({})",
2275+
ToString(base->IgnoreImplicit()),
2276+
ConvertPtrType(base->IgnoreImplicit()->getType()),
2277+
ConvertSubscriptIndex(idx)));
2278+
}
22322279

22332280
if (is_inner_boxed) {
22342281
StrCat(GetPointerDerefSuffix(type), ".as_pointer()");

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class ConverterRefCount final : public Converter {
2828

2929
bool VisitCXXRecordDecl(clang::CXXRecordDecl *decl) override;
3030

31+
bool VisitOffsetOfExpr(clang::OffsetOfExpr *expr) override;
32+
3133
void EmitRustUnion(clang::RecordDecl *decl) override;
3234

3335
bool EmitsReprCForRecords() const override { return false; }
@@ -167,6 +169,8 @@ class ConverterRefCount final : public Converter {
167169

168170
void ConvertVarInit(clang::QualType qual_type, clang::Expr *expr) override;
169171

172+
std::string ConvertVarInitValue(clang::QualType qual_type, clang::Expr *expr);
173+
170174
void ConvertAssignment(clang::Expr *lhs, clang::Expr *rhs,
171175
std::string_view assign_operator) override;
172176

@@ -242,6 +246,8 @@ class ConverterRefCount final : public Converter {
242246
std::string ConvertPtrType(clang::QualType type);
243247
std::string ConvertPointeeType(clang::QualType ptr_type) override;
244248

249+
std::string ConvertSubscriptIndex(clang::Expr *idx);
250+
245251
std::string GetSafeTypeAsString(clang::QualType qual_type) const;
246252

247253
/// The kind of conversion that should be performed.

‎libcc2rs/src/compat.rs‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
// Copyright (c) 2022-present INESC-ID.
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

4+
use std::cell::RefCell;
45
use std::ffi::c_void;
6+
use std::rc::Rc;
7+
8+
use crate::rc::Ptr;
9+
use crate::{AsPointer, Value};
510

611
unsafe extern "C" {
712
#[cfg(target_os = "linux")]
@@ -40,6 +45,14 @@ pub unsafe fn malloc_usable_size(ptr: *mut c_void) -> usize {
4045
/// # Safety
4146
///
4247
/// Invokes the platform specific errno.
43-
pub unsafe fn cpp2rust_errno() -> *mut i32 {
48+
pub unsafe fn cpp2rust_errno_unsafe() -> *mut i32 {
4449
unsafe { platform_errno_location() }
4550
}
51+
52+
thread_local! {
53+
static ERRNO: Value<i32> = Rc::new(RefCell::new(0));
54+
}
55+
56+
pub fn cpp2rust_errno() -> Ptr<i32> {
57+
ERRNO.with(AsPointer::as_pointer)
58+
}

‎libcc2rs/src/rc.rs‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,30 @@ impl<T: ?Sized> AsPointerDyn<T> for Rc<RefCell<T>> {
12211221
impl<T: 'static> ByteRepr for Ptr<T> {}
12221222
impl ByteRepr for AnyPtr {}
12231223

1224+
impl<T: 'static> Ptr<T> {
1225+
pub fn to_int(&self) -> usize {
1226+
let mut buf = vec![0u8; Self::byte_size()];
1227+
self.to_bytes(&mut buf);
1228+
usize::from_bytes(&buf[..std::mem::size_of::<usize>()])
1229+
}
1230+
1231+
pub fn from_int(value: usize) -> Self {
1232+
let mut buf = vec![0u8; Self::byte_size()];
1233+
value.to_bytes(&mut buf[..std::mem::size_of::<usize>()]);
1234+
Self::from_bytes(&buf)
1235+
}
1236+
}
1237+
1238+
impl AnyPtr {
1239+
pub fn to_int(&self) -> usize {
1240+
self.reinterpret_cast::<u8>().to_int()
1241+
}
1242+
1243+
pub fn from_int(value: usize) -> Self {
1244+
Ptr::<u8>::from_int(value).to_any()
1245+
}
1246+
}
1247+
12241248
#[cfg(test)]
12251249
mod tests {
12261250
use super::*;

‎rules/errno/tgt_refcount.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2022-present INESC-ID.
2+
// Distributed under the MIT license that can be found in the LICENSE file.
3+
4+
use libcc2rs::*;
5+
6+
fn f1() -> Ptr<i32> {
7+
libcc2rs::cpp2rust_errno()
8+
}

‎rules/errno/tgt_unsafe.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
// Distributed under the MIT license that can be found in the LICENSE file.
33

44
unsafe fn f1() -> *mut i32 {
5-
libcc2rs::cpp2rust_errno()
5+
libcc2rs::cpp2rust_errno_unsafe()
66
}

‎rules/src/modules.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub mod deque_tgt_refcount;
4040
pub mod deque_tgt_unsafe;
4141
#[path = r#"../dirent/tgt_unsafe.rs"#]
4242
pub mod dirent_tgt_unsafe;
43+
#[path = r#"../errno/tgt_refcount.rs"#]
44+
pub mod errno_tgt_refcount;
4345
#[path = r#"../errno/tgt_unsafe.rs"#]
4446
pub mod errno_tgt_unsafe;
4547
#[path = r#"../eventfd/tgt_unsafe.rs"#]

0 commit comments

Comments
 (0)