@@ -1228,6 +1228,20 @@ fn arrange_header(t: &Translation, is_binary: bool) -> (Vec<syn::Attribute>, Vec
12281228 out_attrs. push ( attr) ;
12291229 }
12301230
1231+ if t. tcfg . cross_checks {
1232+ let xcheck_plugin_args = t
1233+ . tcfg
1234+ . cross_check_configs
1235+ . iter ( )
1236+ . map ( |config_file| mk ( ) . meta_namevalue ( "config_file" , mk ( ) . str_lit ( config_file) ) )
1237+ . collect :: < Vec < _ > > ( ) ;
1238+ let xcheck_plugin_item = mk ( ) . meta_list ( "c2rust_xcheck_plugin" , xcheck_plugin_args) ;
1239+ let plugin_args = vec ! [ xcheck_plugin_item] ;
1240+ let plugin_item = mk ( ) . meta_list ( "plugin" , plugin_args) ;
1241+ let attr = mk ( ) . attribute ( AttrStyle :: Inner ( Default :: default ( ) ) , plugin_item) ;
1242+ out_attrs. push ( attr) ;
1243+ }
1244+
12311245 if t. tcfg . emit_no_std {
12321246 let meta = mk ( ) . meta_path ( "no_std" ) ;
12331247 let attr = mk ( ) . attribute ( AttrStyle :: Inner ( Default :: default ( ) ) , meta) ;
@@ -1247,6 +1261,24 @@ fn arrange_header(t: &Translation, is_binary: bool) -> (Vec<syn::Attribute>, Vec
12471261 }
12481262 }
12491263
1264+ if t. tcfg . cross_checks {
1265+ out_items. push (
1266+ mk ( ) . single_attr ( "macro_use" )
1267+ . extern_crate_item ( "c2rust_xcheck_derive" , None ) ,
1268+ ) ;
1269+ out_items. push (
1270+ mk ( ) . single_attr ( "macro_use" )
1271+ . extern_crate_item ( "c2rust_xcheck_runtime" , None ) ,
1272+ ) ;
1273+ // When cross-checking, always use the system allocator
1274+ let sys_alloc_path = vec ! [ "" , "std" , "alloc" , "System" ] ;
1275+ out_items. push ( mk ( ) . single_attr ( "global_allocator" ) . static_item (
1276+ "C2RUST_ALLOC" ,
1277+ mk ( ) . path_ty ( sys_alloc_path. clone ( ) ) ,
1278+ mk ( ) . path_expr ( sys_alloc_path) ,
1279+ ) ) ;
1280+ }
1281+
12501282 // TODO: switch to `#[expect(unused_imports, reason = ...)]` once
12511283 // we upgrade to a newer nightly (Rust 1.81) that supports it.
12521284 out_items. push (
@@ -1432,6 +1464,10 @@ impl<'c> Translation<'c> {
14321464 "unused_assignments" ,
14331465 ] ,
14341466 ) ] ;
1467+ if self . tcfg . cross_checks {
1468+ features. append ( & mut vec ! [ "plugin" ] ) ;
1469+ pragmas. push ( ( "cross_check" , vec ! [ "yes" ] ) ) ;
1470+ }
14351471
14361472 if self . features . borrow ( ) . contains ( "register_tool" ) {
14371473 pragmas. push ( ( "register_tool" , vec ! [ "c2rust" ] ) ) ;
@@ -1465,6 +1501,14 @@ impl<'c> Translation<'c> {
14651501 ) )
14661502 }
14671503
1504+ fn mk_cross_check ( & self , mk : Builder , args : Vec < & str > ) -> Builder {
1505+ if self . tcfg . cross_checks {
1506+ mk. call_attr ( "cross_check" , args)
1507+ } else {
1508+ mk
1509+ }
1510+ }
1511+
14681512 fn static_initializer_is_unsafe ( & self , expr_id : Option < CExprId > , qty : CQualTypeId ) -> bool {
14691513 // SIMD types are always unsafe in statics
14701514 match self . ast_context . resolve_type ( qty. ctype ) . kind {
@@ -1660,7 +1704,11 @@ impl<'c> Translation<'c> {
16601704 let fn_decl = mk ( ) . fn_decl ( fn_name. clone ( ) , vec ! [ ] , None , fn_ty. clone ( ) ) ;
16611705 let fn_bare_decl = ( vec ! [ ] , None , fn_ty) ;
16621706 let fn_block = mk ( ) . block ( sectioned_static_initializers) ;
1663- let fn_item = mk ( ) . unsafe_ ( ) . extern_ ( "C" ) . fn_item ( fn_decl, fn_block) ;
1707+ let fn_attributes = self . mk_cross_check ( mk ( ) , vec ! [ "none" ] ) ;
1708+ let fn_item = fn_attributes
1709+ . unsafe_ ( )
1710+ . extern_ ( "C" )
1711+ . fn_item ( fn_decl, fn_block) ;
16641712
16651713 let static_attributes = mk ( )
16661714 . single_attr ( "used" )
@@ -2418,7 +2466,10 @@ impl<'c> Translation<'c> {
24182466
24192467 // Only add linkage attributes if the function is `extern`
24202468 let mut mk_ = if is_main {
2421- mk ( )
2469+ // Cross-check this function as if it was called `main`
2470+ // FIXME: pass in a vector of NestedMetaItem elements,
2471+ // but strings have to do for now
2472+ self . mk_cross_check ( mk ( ) , vec ! [ "entry(djb2=\" main\" )" , "exit(djb2=\" main\" )" ] )
24222473 } else if ( is_global && !is_inline) || is_extern_inline {
24232474 mk_linkage ( false , new_name, name) . extern_ ( "C" ) . pub_ ( )
24242475 } else if self . cur_file . get ( ) . is_some ( ) {
0 commit comments