Skip to content
Open
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
7 changes: 6 additions & 1 deletion c2rust-ast-exporter/src/AstExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2625,11 +2625,16 @@ class TranslateASTVisitor final

void TypeEncoder::VisitEnumType(const EnumType *T) {
auto ed = T->getDecl()->getDefinition();

if (!ed) {
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.

Could you use stacked PRs to make this easier to review? I already looked at these lines in the other PR. Thanks!

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.

On second thought, do we support stacked PRs in our repo? It seems the feature is not public yet.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I haven't seen that feature anywhere yet.

ed = T->getDecl()->getCanonicalDecl();
}

encodeType(T, TagEnumType, [T, ed](CborEncoder *local) {
cbor_encode_uint(local, uintptr_t(ed));
});

if (ed != nullptr) astEncoder->TraverseDecl(ed);
astEncoder->TraverseDecl(ed);
}

void TypeEncoder::VisitRecordType(const RecordType *T) {
Expand Down
9 changes: 9 additions & 0 deletions c2rust-refactor/src/transform/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ impl Transform for RenameUnnamed {
renamer
.new_idents
.insert(cx.hir_map().node_to_hir_id(i.id), new_name);

if let ItemKind::Struct(variant_data, _) | ItemKind::Union(variant_data, _) = &i.kind {
if let Some(ctor_id) = variant_data.ctor_id() {
renamer
.new_idents
.insert(cx.hir_map().node_to_hir_id(ctor_id), new_name);
}
}

renamer.new_to_old.insert(new_name, i.ident);
counter += 1;
smallvec![i.map(|i| Item {
Expand Down
39 changes: 38 additions & 1 deletion c2rust-refactor/src/transform/reorganize_definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, item_to_string, PrintState};
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_hir::def::{DefKind, Namespace, PerNS, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, Node};
use rustc_middle::metadata::ModChild;
use rustc_middle::ty::{self, ParamEnv};
Expand Down Expand Up @@ -122,6 +122,7 @@ impl<'a, 'tcx> Reorganizer<'a, 'tcx> {
self.update_module_info_items(krate);

self.move_items(header_decls, krate);
self.add_ctor_mappings();

self.update_paths(krate)
}
Expand Down Expand Up @@ -765,6 +766,42 @@ impl<'a, 'tcx> Reorganizer<'a, 'tcx> {
});
}

fn add_ctor_mappings(&mut self) {
let get_ctor = |def_id: DefId| -> Option<LocalDefId> {
self.cx.hir_map().get_if_local(def_id).and_then(|node| {
let item = match node {
hir::Node::Item(item) => item,
_ => return None,
};
let hir_id = match &item.kind {
hir::ItemKind::Struct(variant_data, _)
| hir::ItemKind::Union(variant_data, _) => variant_data.ctor_hir_id()?,
_ => return None,
};
self.cx.hir_map().opt_local_def_id(hir_id)
})
};

let ctor_mapping: HashMap<DefId, Replacement> = self
.path_mapping
.iter()
.filter_map(|(&def_id, replacement)| {
Some((
get_ctor(def_id)?.to_def_id(),
Replacement {
def: replacement
.def
.and_then(|def| get_ctor(def))
.map(LocalDefId::to_def_id),
..replacement.clone()
},
))
})
.collect();

self.path_mapping.extend(ctor_mapping);
}

/// Update paths to moved items and remove redundant imports.
fn update_paths(&self, krate: &mut Crate) {
let tcx = self.cx.ty_ctxt();
Expand Down
92 changes: 77 additions & 15 deletions c2rust-transpile/src/c_ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,54 @@ impl TypedAstContext {
}
}

/// Identifies typedefs that name unnamed types.
/// Later, the two declarations can be collapsed into a single name and declaration,
/// eliminating the typedef altogether.
pub fn set_prenamed_decls(&mut self) {
let mut prenamed_decls: IndexMap<CDeclId, CDeclId> = IndexMap::new();

for (&decl_id, decl) in self.iter_decls() {
if let CDeclKind::Typedef { ref name, typ, .. } = decl.kind {
if let Some(subdecl_id) = self.resolve_type(typ.ctype).kind.as_underlying_decl() {
use CDeclKind::*;
let is_unnamed = match self[subdecl_id].kind {
Struct { name: None, .. }
| Union { name: None, .. }
| Enum { name: None, .. } => true,

// Detect case where typedef and struct share the same name.
// In this case the purpose of the typedef was simply to eliminate
// the need for the 'struct' tag when referring to the type name.
Struct {
name: Some(ref target_name),
..
}
| Union {
name: Some(ref target_name),
..
}
| Enum {
name: Some(ref target_name),
..
} => name == target_name,

_ => false,
};

if is_unnamed
&& !prenamed_decls
.values()
.any(|decl_id| *decl_id == subdecl_id)
{
prenamed_decls.insert(decl_id, subdecl_id);
}
}
}
}

self.prenamed_decls = prenamed_decls;
}

pub fn prune_unwanted_decls(&mut self, want_unused_functions: bool) {
// Starting from a set of root declarations, walk each one to find declarations it
// depends on. Then walk each of those, recursively.
Expand Down Expand Up @@ -1105,19 +1153,20 @@ impl TypedAstContext {
}
}

// Unset c_main if we are not retaining its declaration
if let Some(main_id) = self.c_main {
if !wanted.contains(&main_id) {
self.c_main = None;
}
}

// Prune any declaration that isn't considered live
self.c_decls
.retain(|&decl_id, _decl| wanted.contains(&decl_id));

// Prune top declarations that are not considered live
self.c_decls_top.retain(|x| wanted.contains(x));
// Remove references to removed decls that are held elsewhere.
self.c_decls_top.retain(|x| self.c_decls.contains_key(x));
self.prenamed_decls
.retain(|x, _| self.c_decls.contains_key(x));

if let Some(main_id) = self.c_main {
if !self.c_decls.contains_key(&main_id) {
self.c_main = None;
}
}
}

/// Bubble types of unary and binary operators up from their args into the expression type.
Expand Down Expand Up @@ -1803,37 +1852,46 @@ impl CastKind {

(CTypeKind::Function(..), CTypeKind::Pointer(..)) => CastKind::FunctionToPointerDecay,

(_, CTypeKind::Pointer(..)) if source_ty_kind.is_integral_type() => {
(_, CTypeKind::Pointer(..)) if source_ty_kind.is_enum_or_integral_type() => {
CastKind::IntegralToPointer
}

(CTypeKind::Pointer(..), CTypeKind::Bool) => CastKind::PointerToBoolean,

(CTypeKind::Pointer(..), _) if target_ty_kind.is_integral_type() => {
(CTypeKind::Pointer(..), _) if target_ty_kind.is_enum_or_integral_type() => {
CastKind::PointerToIntegral
}

(_, CTypeKind::Bool) if source_ty_kind.is_integral_type() => {
(_, CTypeKind::Bool) if source_ty_kind.is_enum_or_integral_type() => {
CastKind::IntegralToBoolean
}

(CTypeKind::Bool, _) if target_ty_kind.is_signed_integral_type() => {
CastKind::BooleanToSignedIntegral
}

(_, _) if source_ty_kind.is_integral_type() && target_ty_kind.is_integral_type() => {
(_, _)
if source_ty_kind.is_enum_or_integral_type()
&& target_ty_kind.is_enum_or_integral_type() =>
{
CastKind::IntegralCast
}

(_, _) if source_ty_kind.is_integral_type() && target_ty_kind.is_floating_type() => {
(_, _)
if source_ty_kind.is_enum_or_integral_type()
&& target_ty_kind.is_floating_type() =>
{
CastKind::IntegralToFloating
}

(_, CTypeKind::Bool) if source_ty_kind.is_floating_type() => {
CastKind::FloatingToBoolean
}

(_, _) if source_ty_kind.is_floating_type() && target_ty_kind.is_integral_type() => {
(_, _)
if source_ty_kind.is_floating_type()
&& target_ty_kind.is_enum_or_integral_type() =>
{
CastKind::FloatingToIntegral
}

Expand Down Expand Up @@ -2684,6 +2742,10 @@ impl CTypeKind {
matches!(*self, Self::Enum { .. })
}

pub fn is_enum_or_integral_type(&self) -> bool {
self.is_integral_type() || self.is_enum()
}

pub fn is_integral_type(&self) -> bool {
self.is_unsigned_integral_type() || self.is_signed_integral_type()
}
Expand Down
Loading
Loading