Skip to content
Draft
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
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions c2rust-transpile/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ c2rust-ast-printer = { path = "../c2rust-ast-printer", version = "0.22.1" }
c2rust-bitfields = { path = "../c2rust-bitfields", version = "0.22.1" }
c2rust-rust-tools = { path = "../c2rust-rust-tools", version = "0.22.1" }
colored = "2.0"
dashmap = "4.0"
dtoa = "1.0"
failure = "0.1.5"
fern = { version = "0.6", features = ["colored"] }
Expand Down
32 changes: 27 additions & 5 deletions c2rust-transpile/src/c_ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub type CEnumConstantId = CDeclId; // Enum's need to point to child 'DeclKind::
pub struct TypedAstContext {
main_file: PathBuf,

c_types: HashMap<CTypeId, CType>,
c_types: dashmap::DashMap<CTypeId, CType>,
c_exprs: HashMap<CExprId, CExpr>,
c_stmts: HashMap<CStmtId, CStmt>,

Expand Down Expand Up @@ -716,9 +716,26 @@ impl TypedAstContext {
}

pub fn type_for_kind(&self, kind: &CTypeKind) -> Option<CTypeId> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function doesn't actually return None anymore, that I can see?

self.c_types
let ro = self.c_types.clone().into_read_only();
if let Some(ty) = ro
.iter()
.find_map(|(id, k)| if kind == &k.kind { Some(*id) } else { None })
{
return Some(ty);
}
let max_type_id = ro
.keys()
.max_by_key(|id| id.0)
.expect("expected non-empty AstContext::c_types");
let new_id = CTypeId(max_type_id.0 + 1);
self.c_types.insert(
new_id,
Located {
loc: None,
kind: kind.clone(),
},
);
Some(new_id)
}

pub fn resolve_type_id(&self, typ: CTypeId) -> CTypeId {
Expand Down Expand Up @@ -1050,11 +1067,16 @@ impl TypedAstContext {
use SomeId::*;
match some_id {
Type(type_id) => {
if let CTypeKind::Elaborated(decl_type_id) = self.c_types[&type_id].kind {
if let CTypeKind::Elaborated(decl_type_id) =
self.c_types.get(&type_id).unwrap().kind
{
// This is a reference to a previously declared type. If we look
// through it we should(?) get something that looks like a declaration,
// which we can mark as wanted.
let decl_id = self.c_types[&decl_type_id]
let decl_id = self
.c_types
.get(&decl_type_id)
.unwrap()
.kind
.as_decl_or_typedef()
.expect("target of CTypeKind::Elaborated isn't a decl?");
Expand Down Expand Up @@ -1388,7 +1410,7 @@ impl Index<CTypeId> for TypedAstContext {
fn index(&self, index: CTypeId) -> &CType {
match self.c_types.get(&index) {
None => panic!("Could not find {:?} in TypedAstContext", index),
Some(ty) => ty,
Some(ty) => Box::leak(Box::new(ty.clone())),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions c2rust-transpile/src/c_ast/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,10 +697,10 @@ impl<W: Write> Printer<W> {
let ty = context
.c_types
.get(&type_id)
.map(|l| &l.kind)
.map(|l| l.kind.clone())
.unwrap_or_else(|| panic!("Could not find type with ID {:?}", type_id));
use CTypeKind::*;
match ty {
match &ty {
Pointer(ref qual_ty) => {
self.print_qtype(*qual_ty, None, context)?;
self.writer.write_all(b"*")?;
Expand Down
33 changes: 32 additions & 1 deletion c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3778,10 +3778,41 @@ impl<'c> Translation<'c> {
return self.convert_expr(ctx, expr, override_ty);
}
}
if kind == CastKind::ArrayToPointerDecay && override_ty.is_some() {
let target_elem = match &self
.ast_context
.resolve_type(override_ty.unwrap().ctype)
.kind
{
CTypeKind::Pointer(qtype) => qtype.ctype,
k => panic!("ArrayToPointerDecay producing non-pointer type {k:?}"),
};
let new_array_override_ty_kind =
match &self.ast_context.resolve_type(source_ty.ctype).kind {
CTypeKind::ConstantArray(_elem, len) => {
CTypeKind::ConstantArray(target_elem, *len)
}
CTypeKind::VariableArray(_elem, len) => {
CTypeKind::VariableArray(target_elem, *len)
}
k => panic!("ArrayToPointerDecay on non-array type {k:?}"),
};
//
// && Some(source_ty.ctype) != override_ty.map(|x| x.ctype)
let new_array_override_ty = self
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than trying to synthesize a completely new array type here, could convert_array_to_pointer_decay not be modified to take an element type instead of source and target types, and then called directly?

.ast_context
.type_for_kind(&new_array_override_ty_kind)
.expect(&format!(
"type id did not already exist for {:?}",
new_array_override_ty_kind
));

self.convert_expr(ctx, expr, Some(CQualTypeId::new(new_array_override_ty)))?
}
// LValueToRValue casts don't actually change the type, so it still makes sense
// to translate their inner expression with the expected type from outside the
// cast.
if kind == CastKind::LValueToRValue
else if kind == CastKind::LValueToRValue
&& Some(source_ty.ctype) != override_ty.map(|x| x.ctype)
{
self.convert_expr(ctx, expr, override_ty)?
Expand Down
Loading