|
1 | 1 | use crate::c_ast::c_decl::{CDeclId, CDeclKind, CFieldId}; |
2 | | -use crate::c_ast::c_stmt::CStmtId; |
| 2 | +use crate::c_ast::c_stmt::{CStmtId, CStmtKind}; |
3 | 3 | use crate::c_ast::c_type::{CQualTypeId, CTypeId, CTypeKind}; |
4 | 4 | use crate::c_ast::{Located, SomeId, TypedAstContext}; |
5 | 5 | use c2rust_ast_exporter::clang_ast::LRValue; |
@@ -698,6 +698,18 @@ impl TypedAstContext { |
698 | 698 | } |
699 | 699 | } |
700 | 700 |
|
| 701 | + /// Same as the `Index` trait, but doesn't bypass `Paren`. |
| 702 | + pub fn index_expr_raw(&self, index: CExprId) -> &CExpr { |
| 703 | + static BADEXPR: CExpr = Located { |
| 704 | + loc: None, |
| 705 | + kind: CExprKind::BadExpr, |
| 706 | + }; |
| 707 | + match self.c_exprs.get(&index) { |
| 708 | + None => &BADEXPR, |
| 709 | + Some(e) => e, |
| 710 | + } |
| 711 | + } |
| 712 | + |
701 | 713 | pub fn is_null_expr(&self, expr_id: CExprId) -> bool { |
702 | 714 | use CExprKind::*; |
703 | 715 | match self[expr_id].kind { |
@@ -953,6 +965,53 @@ impl TypedAstContext { |
953 | 965 | BadExpr => false, |
954 | 966 | } |
955 | 967 | } |
| 968 | + |
| 969 | + /// Returns whether `expr` is within a conditional context, meaning that it is in a context |
| 970 | + /// where a Rust `bool` will be expected. |
| 971 | + pub fn expr_is_condition(&self, expr: CExprId) -> bool { |
| 972 | + let parent = match self.parent(expr) { |
| 973 | + Some(parent) => parent, |
| 974 | + None => return false, |
| 975 | + }; |
| 976 | + |
| 977 | + match parent { |
| 978 | + SomeId::Stmt(parent_stmt) => match self.c_stmts[&parent_stmt].kind { |
| 979 | + CStmtKind::If { |
| 980 | + scrutinee: condition, |
| 981 | + .. |
| 982 | + } |
| 983 | + | CStmtKind::While { condition, .. } |
| 984 | + | CStmtKind::DoWhile { condition, .. } |
| 985 | + | CStmtKind::ForLoop { |
| 986 | + condition: Some(condition), |
| 987 | + .. |
| 988 | + } => expr == condition, |
| 989 | + _ => false, |
| 990 | + }, |
| 991 | + |
| 992 | + SomeId::Expr(parent_expr) => match self.c_exprs[&parent_expr].kind { |
| 993 | + CExprKind::Paren(..) => self.expr_is_condition(parent_expr), |
| 994 | + CExprKind::Unary(_, CUnOp::Not, arg, _) => expr == arg, |
| 995 | + CExprKind::Binary(_, CBinOp::And | CBinOp::Or, lhs, rhs, _, _) => { |
| 996 | + expr == lhs || expr == rhs |
| 997 | + } |
| 998 | + CExprKind::Conditional(_, condition, _, _) |
| 999 | + | CExprKind::BinaryConditional(_, condition, _) => expr == condition, |
| 1000 | + CExprKind::ImplicitCast(_, arg, kind, _, _) |
| 1001 | + | CExprKind::ExplicitCast(_, arg, kind, _, _) => { |
| 1002 | + matches!( |
| 1003 | + kind, |
| 1004 | + CastKind::IntegralToBoolean |
| 1005 | + | CastKind::FloatingToBoolean |
| 1006 | + | CastKind::PointerToBoolean |
| 1007 | + ) && expr == arg |
| 1008 | + } |
| 1009 | + _ => false, |
| 1010 | + }, |
| 1011 | + |
| 1012 | + _ => false, |
| 1013 | + } |
| 1014 | + } |
956 | 1015 | } |
957 | 1016 |
|
958 | 1017 | impl Index<CExprId> for TypedAstContext { |
|
0 commit comments