@@ -2,9 +2,10 @@ use c2rust_ast_builder::mk;
22use failure:: format_err;
33use log:: { info, trace} ;
44use proc_macro2:: { Span , TokenStream } ;
5+ use std:: collections:: HashMap ;
56use syn:: { Expr , MacroDelimiter } ;
67
7- use crate :: c_ast:: { CDeclId , CExprId , CQualTypeId , CTypeId , CTypeKind } ;
8+ use crate :: c_ast:: { CDeclId , CExprId , CQualTypeId , CTypeKind } ;
89use crate :: diagnostics:: { TranslationError , TranslationResult } ;
910use crate :: translator:: { ConvertedDecl , ConvertedMacro , ExprContext , Translation } ;
1011use crate :: with_stmts:: WithStmts ;
@@ -33,6 +34,15 @@ impl<'c> Translation<'c> {
3334 Ok ( ( replacement, converted) ) => {
3435 trace ! ( " to {:?}" , replacement) ;
3536
37+ for ( expr_id, result) in & converted. expr_results {
38+ if let Err ( err) = result {
39+ info ! (
40+ "Could not convert macro {} for {:?}: {}" ,
41+ name, expr_id, err
42+ ) ;
43+ }
44+ }
45+
3646 let result_type_rs = self . convert_type ( converted. result_type_id ) ?;
3747 self . converted_macros
3848 . borrow_mut ( )
@@ -46,7 +56,7 @@ impl<'c> Translation<'c> {
4656 }
4757 Err ( e) => {
4858 self . converted_macros . borrow_mut ( ) . insert ( decl_id, None ) ;
49- info ! ( "Could not expand macro {}: {}" , name, e) ;
59+ info ! ( "Could not convert macro {}: {}" , name, e) ;
5060 Ok ( ConvertedDecl :: NoItem )
5161 }
5262 }
@@ -68,56 +78,67 @@ impl<'c> Translation<'c> {
6878 ctx : ExprContext ,
6979 expansions : & [ CExprId ] ,
7080 ) -> TranslationResult < ( Box < Expr > , ConvertedMacro ) > {
71- let ( val, result_type_id) = expansions
81+ let mut canonical = None ;
82+ let expr_results: HashMap < _ , _ > = expansions
7283 . iter ( )
73- . try_fold :: < Option < ( WithStmts < Box < Expr > > , CTypeId ) > , _ , _ > (
74- None ,
75- |mut canonical, & expr_id| -> TranslationResult < _ > {
76- self . can_convert_const_macro_expansion ( expr_id) ?;
77-
78- let type_id = self . ast_context [ expr_id]
79- . kind
80- . get_type ( )
81- . ok_or_else ( || format_err ! ( "Invalid expression type" ) ) ?;
82- let val = self . convert_expr ( ctx, expr_id, None ) ?;
83- let new = ( val, type_id) ;
84-
85- // Join ty and cur_ty to the smaller of the two types. If the
86- // types are not cast-compatible, abort the fold.
87- match & mut canonical {
88- Some ( canonical) => {
89- let & mut ( _, canon_type_id) = canonical;
90- let ( _, new_type_id) = new;
91-
92- let canon_type_kind =
93- self . ast_context . resolve_type ( canon_type_id) . kind . clone ( ) ;
94- let new_type_kind =
95- self . ast_context . resolve_type ( new_type_id) . kind . clone ( ) ;
96- let smaller_type_kind = CTypeKind :: smaller_compatible_type (
97- canon_type_kind. clone ( ) ,
98- new_type_kind,
99- ) ;
100- let Some ( smaller_type_kind) = smaller_type_kind else {
101- return Err (
102- format_err ! ( "Not all macro expansions are compatible types" )
103- . into ( )
104- )
105- } ;
106-
107- if smaller_type_kind != canon_type_kind {
108- * canonical = new;
84+ . map ( |& expr_id| {
85+ let result = self
86+ . can_convert_const_macro_expansion ( expr_id)
87+ . and_then ( |_| {
88+ let type_id = self . ast_context [ expr_id]
89+ . kind
90+ . get_type ( )
91+ . ok_or_else ( || format_err ! ( "Invalid expression type" ) ) ?;
92+ let val = self . convert_expr ( ctx, expr_id, None ) ?;
93+ Ok ( ( val, type_id) )
94+ } )
95+ . and_then ( |new| {
96+ // Join ty and cur_ty to the smaller of the two types. If the
97+ // types are not cast-compatible, skip this expansion.
98+ match & mut canonical {
99+ Some ( canonical) => {
100+ let & mut ( _, canon_type_id) = canonical;
101+ let ( _, new_type_id) = new;
102+
103+ let canon_type_kind =
104+ self . ast_context . resolve_type ( canon_type_id) . kind . clone ( ) ;
105+ let new_type_kind =
106+ self . ast_context . resolve_type ( new_type_id) . kind . clone ( ) ;
107+ let smaller_type_kind = CTypeKind :: smaller_compatible_type (
108+ canon_type_kind. clone ( ) ,
109+ new_type_kind,
110+ ) ;
111+ let Some ( smaller_type_kind) = smaller_type_kind else {
112+ return Err (
113+ format_err ! (
114+ "Not all macro expansions are compatible types"
115+ )
116+ . into ( )
117+ )
118+ } ;
119+
120+ if smaller_type_kind != canon_type_kind {
121+ * canonical = new;
122+ }
109123 }
124+
125+ None => canonical = Some ( new) ,
110126 }
111127
112- None => canonical = Some ( new) ,
113- }
128+ Ok ( ( ) )
129+ } ) ;
130+
131+ ( expr_id, result)
132+ } )
133+ . collect ( ) ;
114134
115- Ok ( canonical)
116- } ,
117- ) ?
118- . ok_or_else ( || format_err ! ( "Could not find a valid type for macro" ) ) ?;
135+ let ( val, result_type_id) =
136+ canonical. ok_or_else ( || format_err ! ( "Could not find a valid type for macro" ) ) ?;
119137
120- let converted = ConvertedMacro { result_type_id } ;
138+ let converted = ConvertedMacro {
139+ result_type_id,
140+ expr_results,
141+ } ;
121142 val. wrap_unsafe ( )
122143 . to_pure_expr ( )
123144 . map ( |val| ( val, converted) )
@@ -205,6 +226,11 @@ impl<'c> Translation<'c> {
205226 return Ok ( None ) ;
206227 } ;
207228
229+ if !matches ! ( converted. expr_results. get( & expr_id) , Some ( Ok ( _) ) ) {
230+ // Expansion succeeded in general, but not for this particular expression.
231+ return Ok ( None ) ;
232+ }
233+
208234 let result_type_id = converted. result_type_id ;
209235 let rust_name = self
210236 . renamer
0 commit comments