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
60 changes: 35 additions & 25 deletions c2rust-transpile/src/c_ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ impl TypedAstContext {
use SomeId::*;
match id {
Stmt(id) => self.index(id).loc,
Expr(id) => self.index(id).loc,
Expr(id) => self.index_unwrap_parens(id).loc,
Decl(id) => self.index(id).loc,
Type(id) => self.index(id).loc,
}
Expand Down Expand Up @@ -487,7 +487,7 @@ impl TypedAstContext {

pub fn is_null_expr(&self, expr_id: CExprId) -> bool {
use CExprKind::*;
match self[expr_id].kind {
match self.index_unwrap_parens(expr_id).kind {
ExplicitCast(_, _, CastKind::NullToPointer, _, _)
| ImplicitCast(_, _, CastKind::NullToPointer, _, _) => true,

Expand Down Expand Up @@ -673,17 +673,30 @@ impl TypedAstContext {
}

/// Returns the expression inside any number of nested parentheses.
pub fn resolve_parens(&self, mut expr_id: CExprId) -> CExprId {
while let CExprKind::Paren(_, subexpr) = self.index(expr_id).kind {
pub fn unwrap_parens(&self, mut expr_id: CExprId) -> CExprId {
while let CExprKind::Paren(_, subexpr) = self[expr_id].kind {
expr_id = subexpr;
}

expr_id
}

/// Same as the index operator, but unwraps `Paren` expressions.
pub fn index_unwrap_parens(&self, expr_id: CExprId) -> &CExpr {
static BADEXPR: CExpr = Located {
loc: None,
kind: CExprKind::BadExpr,
};
self.c_exprs
.get(&self.unwrap_parens(expr_id))
.unwrap_or(&BADEXPR)
}

/// Returns the expression inside an `__extension__` operator.
pub fn resolve_extension(&self, expr_id: CExprId) -> CExprId {
if let CExprKind::Unary(_, CUnOp::Extension, subexpr, _) = self.index(expr_id).kind {
if let CExprKind::Unary(_, CUnOp::Extension, subexpr, _) =
self.index_unwrap_parens(expr_id).kind
{
subexpr
} else {
expr_id
Expand All @@ -692,9 +705,9 @@ impl TypedAstContext {

/// Unwraps a predefined expression, if there is one.
pub fn unwrap_predefined_ident(&self, mut expr_id: CExprId) -> CExprId {
expr_id = self.resolve_extension(self.resolve_parens(expr_id));
expr_id = self.resolve_extension(self.unwrap_parens(expr_id));

if let CExprKind::Predefined(_, subexpr) = self.index(expr_id).kind {
if let CExprKind::Predefined(_, subexpr) = self.index_unwrap_parens(expr_id).kind {
subexpr
} else {
expr_id
Expand All @@ -705,7 +718,7 @@ impl TypedAstContext {
pub fn unwrap_cast_expr(&self, mut expr_id: CExprId) -> CExprId {
while let CExprKind::Paren(_, subexpr)
| CExprKind::ImplicitCast(_, subexpr, _, _, _)
| CExprKind::ExplicitCast(_, subexpr, _, _, _) = self.index(expr_id).kind
| CExprKind::ExplicitCast(_, subexpr, _, _, _) = self[expr_id].kind
{
expr_id = subexpr;
}
Expand All @@ -715,7 +728,9 @@ impl TypedAstContext {

/// Unwraps the underlying expression beneath any implicit casts.
pub fn unwrap_implicit_cast_expr(&self, mut expr_id: CExprId) -> CExprId {
while let CExprKind::ImplicitCast(_, subexpr, _, _, _) = self.index(expr_id).kind {
while let CExprKind::ImplicitCast(_, subexpr, _, _, _) =
self.index_unwrap_parens(expr_id).kind
{
expr_id = subexpr;
}

Expand All @@ -725,7 +740,7 @@ impl TypedAstContext {
/// Resolve true expression type, iterating through any casts and variable
/// references.
pub fn resolve_expr_type_id(&self, expr_id: CExprId) -> Option<(CExprId, CTypeId)> {
let expr = &self.index(expr_id).kind;
let expr = &self[expr_id].kind;
let mut ty = expr.get_type();
use CExprKind::*;
match expr {
Expand Down Expand Up @@ -804,9 +819,10 @@ impl TypedAstContext {
/// Looks for ImplicitCast(FunctionToPointerDecay, DeclRef(function_decl))
pub fn fn_declref_decl(&self, func_expr: CExprId) -> Option<&CDeclKind> {
use CastKind::FunctionToPointerDecay;
if let CExprKind::ImplicitCast(_, fexp, FunctionToPointerDecay, _, _) = self[func_expr].kind
if let CExprKind::ImplicitCast(_, fexp, FunctionToPointerDecay, _, _) =
self.index_unwrap_parens(func_expr).kind
{
if let CExprKind::DeclRef(_ty, decl_id, _rv) = &self[fexp].kind {
if let CExprKind::DeclRef(_ty, decl_id, _rv) = &self.index_unwrap_parens(fexp).kind {
let decl = &self.index(*decl_id).kind;
assert!(matches!(decl, CDeclKind::Function { .. }));
return Some(decl);
Expand Down Expand Up @@ -868,7 +884,7 @@ impl TypedAstContext {
pub fn is_expr_pure(&self, expr: CExprId) -> bool {
use CExprKind::*;
let pure = |expr| self.is_expr_pure(expr);
match self.index(expr).kind {
match self[expr].kind {
BadExpr |
ShuffleVector(..) |
ConvertVector(..) |
Expand Down Expand Up @@ -912,12 +928,12 @@ impl TypedAstContext {
/// Pessimistically try to check if an expression doesn't return.
/// If it does, or we can't tell that it doesn't, return `false`.
pub fn expr_diverges(&self, expr_id: CExprId) -> bool {
let func_id = match self.index(expr_id).kind {
let func_id = match self.index_unwrap_parens(expr_id).kind {
CExprKind::Call(_, func_id, _) => func_id,
_ => return false,
};

let type_id = match self[func_id].kind.get_type() {
let type_id = match self.index_unwrap_parens(func_id).kind.get_type() {
None => return false,
Some(t) => t,
};
Expand Down Expand Up @@ -1174,7 +1190,7 @@ impl TypedAstContext {
}

Expr(expr_id) => {
let expr = self.index(expr_id);
let expr = self.index_unwrap_parens(expr_id);
if let Some(macs) = self.macro_invocations.get(&expr_id) {
for mac_id in macs {
if wanted.insert(*mac_id) {
Expand Down Expand Up @@ -1254,7 +1270,7 @@ impl TypedAstContext {
_ => return,
};

let new_ty = match self.ast_context.c_exprs[&e].kind {
let new_ty = match self.ast_context[e].kind {
CExprKind::Conditional(_ty, _cond, lhs, rhs) => {
let lhs_type_id =
self.ast_context.c_exprs[&lhs].kind.get_qual_type().unwrap();
Expand Down Expand Up @@ -1502,21 +1518,15 @@ impl Index<CTypeId> for TypedAstContext {

impl Index<CExprId> for TypedAstContext {
type Output = CExpr;

fn index(&self, index: CExprId) -> &CExpr {
static BADEXPR: CExpr = Located {
loc: None,
kind: CExprKind::BadExpr,
};
match self.c_exprs.get(&index) {
None => &BADEXPR, // panic!("Could not find {:?} in TypedAstContext", index),
Some(e) => {
// Transparently index through Paren expressions
if let CExprKind::Paren(_, subexpr) = e.kind {
self.index(subexpr)
} else {
e
}
}
Some(e) => e,
}
}
}
Expand Down
32 changes: 25 additions & 7 deletions c2rust-transpile/src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,11 @@ impl CfgBuilder {
.discard_unsafe();
wip.extend(stmts);

let cond_val = translator.ast_context[scrutinee].kind.get_bool();
let cond_val = translator
.ast_context
.index_unwrap_parens(scrutinee)
.kind
.get_bool();
self.add_wip_block(
wip,
match cond_val {
Expand Down Expand Up @@ -1520,7 +1524,11 @@ impl CfgBuilder {
let (stmts, val) = translator
.convert_condition(ctx, true, condition)?
.discard_unsafe();
let cond_val = translator.ast_context[condition].kind.get_bool();
let cond_val = translator
.ast_context
.index_unwrap_parens(condition)
.kind
.get_bool();
let mut cond_wip = self.new_wip_block(cond_entry.clone());
cond_wip.extend(stmts);

Expand Down Expand Up @@ -1595,7 +1603,11 @@ impl CfgBuilder {
let (stmts, val) = translator
.convert_condition(ctx, true, condition)?
.discard_unsafe();
let cond_val = translator.ast_context[condition].kind.get_bool();
let cond_val = translator
.ast_context
.index_unwrap_parens(condition)
.kind
.get_bool();
let mut cond_wip = self.new_wip_block(cond_entry);
cond_wip.extend(stmts);
self.add_wip_block(
Expand Down Expand Up @@ -1646,7 +1658,11 @@ impl CfgBuilder {
let (stmts, val) = translator
.convert_condition(ctx, true, cond)?
.discard_unsafe();
let cond_val = translator.ast_context[cond].kind.get_bool();
let cond_val = translator
.ast_context
.index_unwrap_parens(cond)
.kind
.get_bool();
let mut cond_wip = slf.new_wip_block(cond_entry.clone());
cond_wip.extend(stmts);
slf.add_wip_block(
Expand Down Expand Up @@ -1772,9 +1788,11 @@ impl CfgBuilder {
// We simply inline the common statement at this point rather
// than to try and create new control-flow blocks.
let blk_or_wip = if let CExprKind::Unary(_, CUnOp::Extension, sube, _) =
translator.ast_context[expr].kind
translator.ast_context.index_unwrap_parens(expr).kind
{
if let CExprKind::Statements(_, stmtid) = translator.ast_context[sube].kind {
if let CExprKind::Statements(_, stmtid) =
translator.ast_context.index_unwrap_parens(sube).kind
{
let comp_entry = self.fresh_label();
self.add_wip_block(wip, Jump(comp_entry.clone()));
let next_lbl = self.convert_stmt_help(
Expand Down Expand Up @@ -1858,7 +1876,7 @@ impl CfgBuilder {

// Case
let resolved = translator.ast_context.unwrap_cast_expr(case_expr);
let branch = match translator.ast_context.index(resolved).kind {
let branch = match translator.ast_context.index_unwrap_parens(resolved).kind {
CExprKind::Literal(..) | CExprKind::ConstantExpr(_, _, Some(_)) => {
match translator
.convert_expr(ctx.used(), resolved, None)?
Expand Down
16 changes: 11 additions & 5 deletions c2rust-transpile/src/translator/atomics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ impl<'c> Translation<'c> {

fn convert_constant_bool(&self, expr: CExprId) -> Option<bool> {
let val = self.ast_context.unwrap_cast_expr(expr);
match self.ast_context.index(val).kind {
match self.ast_context.index_unwrap_parens(val).kind {
CExprKind::Literal(_, CLiteral::Integer(i, _)) => Some(i != 0),
_ => None,
}
}

fn convert_memordering(&self, expr: CExprId) -> Option<Ordering> {
let memorder = &self.ast_context[expr];
let memorder = &self.ast_context.index_unwrap_parens(expr);
let i = match memorder.kind {
CExprKind::Literal(_, CLiteral::Integer(i, _)) => Some(i),
CExprKind::DeclRef(_, decl_id, LRValue::RValue) => {
Expand Down Expand Up @@ -295,8 +295,12 @@ impl<'c> Translation<'c> {
}
.ok_or_else(|| {
format_translation_err!(
self.ast_context
.display_loc(&self.ast_context[order_fail_id.unwrap()].loc),
self.ast_context.display_loc(
&self
.ast_context
.index_unwrap_parens(order_fail_id.unwrap())
.loc
),
"Invalid failure memory ordering",
)
})?;
Expand Down Expand Up @@ -337,7 +341,9 @@ impl<'c> Translation<'c> {
let order = static_order(order);
let val =
val1.expect("__atomic arithmetic operations must have a val argument");
let val_type_id = self.ast_context[val1_id.unwrap()]
let val_type_id = self
.ast_context
.index_unwrap_parens(val1_id.unwrap())
.kind
.get_qual_type()
.ok_or_else(|| format_err!("bad val1 type"))?;
Expand Down
10 changes: 7 additions & 3 deletions c2rust-transpile/src/translator/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'c> Translation<'c> {
fexp: CExprId,
args: &[CExprId],
) -> TranslationResult<WithStmts<Box<Expr>>> {
let expr = &self.ast_context[fexp];
let expr = &self.ast_context.index_unwrap_parens(fexp);
let src_loc = &expr.loc;
let decl_id = match expr.kind {
CExprKind::DeclRef(_, decl_id, _) => decl_id,
Expand Down Expand Up @@ -590,7 +590,9 @@ impl<'c> Translation<'c> {
if let Some(atomic_op) = CAtomicBinOp::from_sync_builtin_fn(builtin_name) {
let arg0 = self.convert_expr(ctx.used(), args[0], None)?;
let arg1 = self.convert_expr(ctx.used(), args[1], None)?;
let arg1_type_id = self.ast_context[args[1]]
let arg1_type_id = self
.ast_context
.index_unwrap_parens(args[1])
.kind
.get_qual_type()
.ok_or_else(|| format_err!("bad arg1 type"))?;
Expand All @@ -611,7 +613,9 @@ impl<'c> Translation<'c> {
}

fn import_num_traits(&self, arg_id: CExprId) -> TranslationResult<()> {
let arg_type_id = self.ast_context[arg_id]
let arg_type_id = self
.ast_context
.index_unwrap_parens(arg_id)
.kind
.get_qual_type()
.ok_or_else(|| format_err!("bad arg type"))?;
Expand Down
4 changes: 2 additions & 2 deletions c2rust-transpile/src/translator/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl<'c> Translation<'c> {
val: Box<Expr>,
) -> TranslationResult<Box<Expr>> {
if let Some(expr) = expr {
match self.ast_context[expr].kind {
match self.ast_context.index_unwrap_parens(expr).kind {
// This is the case of finding a variable which is an `EnumConstant` of the same
// enum we are casting to. Here, we can just remove the extraneous cast instead of
// generating a new one.
Expand All @@ -112,7 +112,7 @@ impl<'c> Translation<'c> {

CExprKind::Unary(_, CUnOp::Negate, subexpr_id, _) => {
if let &CExprKind::Literal(_, CLiteral::Integer(i, _)) =
&self.ast_context[subexpr_id].kind
&self.ast_context.index_unwrap_parens(subexpr_id).kind
{
return Ok(self.enum_for_i64(enum_type_id, -(i as i64)));
}
Expand Down
15 changes: 10 additions & 5 deletions c2rust-transpile/src/translator/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,8 @@ impl<'c> Translation<'c> {
let fn_ty = self
.ast_context
.get_pointee_qual_type(
self.ast_context[func]
self.ast_context
.index_unwrap_parens(func)
.kind
.get_type()
.ok_or_else(|| format_err!("Invalid callee expression {:?}", func))?,
Expand All @@ -384,12 +385,12 @@ impl<'c> Translation<'c> {
None
};

let func = match self.ast_context[func].kind {
let func = match self.ast_context.index_unwrap_parens(func).kind {
// Direct function call
CExprKind::ImplicitCast(_, fexp, CastKind::FunctionToPointerDecay, _, _)
// Only a direct function call with pointer decay if the
// callee is a declref
if matches!(self.ast_context[fexp].kind, CExprKind::DeclRef(..)) =>
if matches!(self.ast_context.index_unwrap_parens(fexp).kind, CExprKind::DeclRef(..)) =>
{
self.convert_expr(ctx.used(), fexp, None)?
}
Expand Down Expand Up @@ -507,8 +508,12 @@ impl<'c> Translation<'c> {
) -> TranslationResult<WithStmts<Box<Expr>>> {
let mut val;

if (self.ast_context.index(expr_id).kind.get_qual_type())
.map_or(false, |qtype| self.ast_context.is_va_list(qtype.ctype))
if (self
.ast_context
.index_unwrap_parens(expr_id)
.kind
.get_qual_type())
.map_or(false, |qtype| self.ast_context.is_va_list(qtype.ctype))
{
// No `override_ty` to avoid unwanted casting.
val = self.convert_expr(ctx, expr_id, None)?;
Expand Down
Loading
Loading