Skip to content

Commit 2f996c7

Browse files
committed
Merge branch 'master' of https://github.com/immunant/c2rust into raw-borrow
2 parents c693c8d + cbf4e0a commit 2f996c7

File tree

15 files changed

+316
-193
lines changed

15 files changed

+316
-193
lines changed

c2rust-ast-exporter/src/AstExporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2537,7 +2537,7 @@ void TypeEncoder::VisitEnumType(const EnumType *T) {
25372537
cbor_encode_uint(local, uintptr_t(ed));
25382538
});
25392539

2540-
if (ed != nullptr) astEncoder->VisitEnumDecl(ed);
2540+
if (ed != nullptr) astEncoder->TraverseDecl(ed);
25412541
}
25422542

25432543
void TypeEncoder::VisitRecordType(const RecordType *T) {

c2rust-transpile/src/c_ast/mod.rs

Lines changed: 144 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::c_ast::iterators::{immediate_children_all_types, NodeVisitor};
2+
use crate::iterators::{DFNodes, SomeId};
13
use c2rust_ast_exporter::clang_ast::LRValue;
24
use indexmap::{IndexMap, IndexSet};
35
use std::cell::RefCell;
@@ -9,8 +11,14 @@ use std::ops::Index;
911
use std::path::{Path, PathBuf};
1012
use std::rc::Rc;
1113

14+
pub use self::conversion::*;
15+
pub use self::print::Printer;
1216
pub use c2rust_ast_exporter::clang_ast::{BuiltinVaListKind, SrcFile, SrcLoc, SrcSpan};
1317

18+
mod conversion;
19+
pub mod iterators;
20+
mod print;
21+
1422
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Copy, Clone)]
1523
pub struct CTypeId(pub u64);
1624

@@ -33,15 +41,6 @@ pub type CTypedefId = CDeclId; // Typedef types need to point to 'DeclKind::Type
3341
pub type CEnumId = CDeclId; // Enum types need to point to 'DeclKind::Enum'
3442
pub type CEnumConstantId = CDeclId; // Enum's need to point to child 'DeclKind::EnumConstant's
3543

36-
pub use self::conversion::*;
37-
pub use self::print::Printer;
38-
39-
mod conversion;
40-
pub mod iterators;
41-
mod print;
42-
43-
use iterators::{DFNodes, SomeId};
44-
4544
/// AST context containing all of the nodes in the Clang AST
4645
#[derive(Debug, Clone)]
4746
pub struct TypedAstContext {
@@ -638,12 +637,10 @@ impl TypedAstContext {
638637
// Unary ops should be `const`.
639638
// TODO handle `f128` or use the primitive type.
640639
Unary(_, _, expr, _) => is_const(expr),
641-
UnaryType(_, _, _, _) => false, // TODO disabled for now as tests are broken
642640
// Not sure what a `None` `CExprId` means here
643641
// or how to detect a `sizeof` of a VLA, which is non-`const`,
644642
// although it seems we don't handle `sizeof(VLAs)`
645643
// correctly in macros elsewhere already.
646-
#[allow(unreachable_patterns)]
647644
UnaryType(_, _, expr, _) => expr.map_or(true, is_const),
648645
// Not sure what a `OffsetOfKind::Variable` means.
649646
OffsetOf(_, _) => true,
@@ -652,7 +649,6 @@ impl TypedAstContext {
652649
// TODO `f128` is not yet handled, as we should eventually
653650
// switch to the (currently unstable) `f128` primitive type (#1262).
654651
Binary(_, _, lhs, rhs, _, _) => is_const(lhs) && is_const(rhs),
655-
ImplicitCast(_, _, CastKind::ArrayToPointerDecay, _, _) => false, // TODO disabled for now as tests are broken
656652
// `as` casts are always `const`.
657653
ImplicitCast(_, expr, _, _, _) => is_const(expr),
658654
// `as` casts are always `const`.
@@ -691,9 +687,61 @@ impl TypedAstContext {
691687
}
692688
}
693689

694-
pub fn is_const_stmt(&self, _stmt: CStmtId) -> bool {
695-
// TODO
696-
false
690+
pub fn is_const_stmt(&self, stmt: CStmtId) -> bool {
691+
let is_const = |stmt| self.is_const_stmt(stmt);
692+
let is_const_expr = |expr| self.is_const_expr(expr);
693+
694+
use CStmtKind::*;
695+
match self[stmt].kind {
696+
Case(expr, stmt, _const_expr) => is_const_expr(expr) && is_const(stmt),
697+
Default(stmt) => is_const(stmt),
698+
Compound(ref stmts) => stmts.iter().copied().all(is_const),
699+
Expr(expr) => is_const_expr(expr),
700+
Empty => true,
701+
If {
702+
scrutinee,
703+
true_variant,
704+
false_variant,
705+
} => {
706+
is_const_expr(scrutinee)
707+
&& is_const(true_variant)
708+
&& false_variant.map_or(true, is_const)
709+
}
710+
Switch { scrutinee, body } => is_const_expr(scrutinee) && is_const(body),
711+
While { condition, body } => is_const_expr(condition) && is_const(body),
712+
DoWhile { body, condition } => is_const(body) && is_const_expr(condition),
713+
ForLoop {
714+
init,
715+
condition,
716+
increment,
717+
body,
718+
} => {
719+
init.map_or(true, is_const)
720+
&& condition.map_or(true, is_const_expr)
721+
&& increment.map_or(true, is_const_expr)
722+
&& is_const(body)
723+
}
724+
Break => true,
725+
Continue => true,
726+
Return(expr) => expr.map_or(true, is_const_expr),
727+
Decls(ref _decls) => true,
728+
Asm { .. } => false,
729+
Attributed {
730+
attributes: _,
731+
substatement,
732+
} => is_const(substatement),
733+
// `goto`s are tricky, because they can be non-local
734+
// and jump out of the context of the macro.
735+
// A `goto` and its labels are `const` if the whole state machine
736+
// we compile to has all `const` statements,
737+
// but determining what that is exactly is trickier,
738+
// and might depend on the context in which the macro is used.
739+
// This is probably fairly uncommon, so we just assume it's not `const` for now.
740+
// Note that in C, labels are for `goto`s.
741+
// There are no labeled `break`s and `continue`s.
742+
Label(_stmt) => false,
743+
Goto(_label) => false,
744+
}
697745
}
698746

699747
pub fn prune_unwanted_decls(&mut self, want_unused_functions: bool) {
@@ -836,76 +884,90 @@ impl TypedAstContext {
836884
ast_context: &'a mut TypedAstContext,
837885
}
838886

839-
use iterators::{immediate_children_all_types, NodeVisitor};
840887
impl<'a> NodeVisitor for BubbleExprTypes<'a> {
841888
fn children(&mut self, id: SomeId) -> Vec<SomeId> {
842889
immediate_children_all_types(self.ast_context, id)
843890
}
891+
844892
fn post(&mut self, id: SomeId) {
845-
if let SomeId::Expr(e) = id {
846-
let new_ty = match self.ast_context.c_exprs[&e].kind {
847-
CExprKind::Conditional(_ty, _cond, lhs, rhs) => {
848-
let lhs_type_id =
849-
self.ast_context.c_exprs[&lhs].kind.get_qual_type().unwrap();
850-
let rhs_type_id =
851-
self.ast_context.c_exprs[&rhs].kind.get_qual_type().unwrap();
893+
let e = match id {
894+
SomeId::Expr(e) => e,
895+
_ => return,
896+
};
897+
898+
let new_ty = match self.ast_context.c_exprs[&e].kind {
899+
CExprKind::Conditional(_ty, _cond, lhs, rhs) => {
900+
let lhs_type_id =
901+
self.ast_context.c_exprs[&lhs].kind.get_qual_type().unwrap();
902+
let rhs_type_id =
903+
self.ast_context.c_exprs[&rhs].kind.get_qual_type().unwrap();
904+
905+
let lhs_resolved_ty = self.ast_context.resolve_type(lhs_type_id.ctype);
906+
let rhs_resolved_ty = self.ast_context.resolve_type(rhs_type_id.ctype);
907+
908+
if CTypeKind::PULLBACK_KINDS.contains(&lhs_resolved_ty.kind) {
909+
Some(lhs_type_id)
910+
} else if CTypeKind::PULLBACK_KINDS.contains(&rhs_resolved_ty.kind) {
911+
Some(rhs_type_id)
912+
} else {
913+
None
914+
}
915+
}
916+
CExprKind::Binary(_ty, op, lhs, rhs, _, _) => {
917+
let rhs_type_id =
918+
self.ast_context.c_exprs[&rhs].kind.get_qual_type().unwrap();
919+
let lhs_kind = &self.ast_context.c_exprs[&lhs].kind;
920+
let lhs_type_id = lhs_kind.get_qual_type().unwrap();
921+
922+
let lhs_resolved_ty = self.ast_context.resolve_type(lhs_type_id.ctype);
923+
let rhs_resolved_ty = self.ast_context.resolve_type(rhs_type_id.ctype);
852924

853-
let lhs_resolved_ty = self.ast_context.resolve_type(lhs_type_id.ctype);
854-
let rhs_resolved_ty = self.ast_context.resolve_type(rhs_type_id.ctype);
925+
let neither_ptr = !lhs_resolved_ty.kind.is_pointer()
926+
&& !rhs_resolved_ty.kind.is_pointer();
855927

928+
if op.all_types_same() && neither_ptr {
856929
if CTypeKind::PULLBACK_KINDS.contains(&lhs_resolved_ty.kind) {
857930
Some(lhs_type_id)
858-
} else if CTypeKind::PULLBACK_KINDS.contains(&rhs_resolved_ty.kind) {
859-
Some(rhs_type_id)
860-
} else {
861-
None
862-
}
863-
}
864-
CExprKind::Binary(_ty, op, lhs, rhs, _, _) => {
865-
let rhs_type_id =
866-
self.ast_context.c_exprs[&rhs].kind.get_qual_type().unwrap();
867-
let lhs_kind = &self.ast_context.c_exprs[&lhs].kind;
868-
let lhs_type_id = lhs_kind.get_qual_type().unwrap();
869-
870-
let lhs_resolved_ty = self.ast_context.resolve_type(lhs_type_id.ctype);
871-
let rhs_resolved_ty = self.ast_context.resolve_type(rhs_type_id.ctype);
872-
873-
let neither_ptr = !lhs_resolved_ty.kind.is_pointer()
874-
&& !rhs_resolved_ty.kind.is_pointer();
875-
876-
if op.all_types_same() && neither_ptr {
877-
if CTypeKind::PULLBACK_KINDS.contains(&lhs_resolved_ty.kind) {
878-
Some(lhs_type_id)
879-
} else {
880-
Some(rhs_type_id)
881-
}
882-
} else if op == BinOp::ShiftLeft || op == BinOp::ShiftRight {
883-
Some(lhs_type_id)
884931
} else {
885-
return;
932+
Some(rhs_type_id)
886933
}
934+
} else if op == BinOp::ShiftLeft || op == BinOp::ShiftRight {
935+
Some(lhs_type_id)
936+
} else {
937+
return;
887938
}
888-
CExprKind::Unary(_ty, op, e, _idk) => op.expected_result_type(
889-
self.ast_context,
890-
self.ast_context.c_exprs[&e].kind.get_qual_type().unwrap(),
891-
),
892-
CExprKind::Paren(_ty, e) => {
893-
self.ast_context.c_exprs[&e].kind.get_qual_type()
894-
}
895-
_ => return,
896-
};
897-
if let (Some(ty), Some(new_ty)) = (
898-
self.ast_context
899-
.c_exprs
900-
.get_mut(&e)
901-
.and_then(|e| e.kind.get_qual_type_mut()),
902-
new_ty,
903-
) {
904-
*ty = new_ty;
905-
};
906-
}
939+
}
940+
CExprKind::Unary(_ty, op, e, _idk) => op.expected_result_type(
941+
self.ast_context,
942+
self.ast_context.c_exprs[&e].kind.get_qual_type().unwrap(),
943+
),
944+
CExprKind::Paren(_ty, e) => self.ast_context.c_exprs[&e].kind.get_qual_type(),
945+
CExprKind::UnaryType(_, op, _, _) => {
946+
// All of these `UnTypeOp`s should return `size_t`.
947+
let kind = match op {
948+
UnTypeOp::SizeOf => CTypeKind::Size,
949+
UnTypeOp::AlignOf => CTypeKind::Size,
950+
UnTypeOp::PreferredAlignOf => CTypeKind::Size,
951+
};
952+
let ty = self
953+
.ast_context
954+
.type_for_kind(&kind)
955+
.expect("CTypeKind::Size should be size_t");
956+
Some(CQualTypeId::new(ty))
957+
}
958+
_ => return,
959+
};
960+
let ty = self
961+
.ast_context
962+
.c_exprs
963+
.get_mut(&e)
964+
.and_then(|e| e.kind.get_qual_type_mut());
965+
if let (Some(ty), Some(new_ty)) = (ty, new_ty) {
966+
*ty = new_ty;
967+
};
907968
}
908969
}
970+
909971
for decl in self.c_decls_top.clone() {
910972
BubbleExprTypes { ast_context: self }.visit_tree(SomeId::Decl(decl));
911973
}
@@ -2267,6 +2329,17 @@ impl CTypeKind {
22672329
};
22682330
Some(ty)
22692331
}
2332+
2333+
/// Return the element type of a pointer or array
2334+
pub fn element_ty(&self) -> Option<CTypeId> {
2335+
Some(match *self {
2336+
Self::Pointer(ty) => ty.ctype,
2337+
Self::ConstantArray(ty, _) => ty,
2338+
Self::IncompleteArray(ty) => ty,
2339+
Self::VariableArray(ty, _) => ty,
2340+
_ => return None,
2341+
})
2342+
}
22702343
}
22712344

22722345
#[cfg(test)]

0 commit comments

Comments
 (0)