@@ -100,6 +100,8 @@ enum CItemKind {
100100ImportedExtern , 
101101    /// `extern "C"` function definitions, to be used elsewhere -> IMPROPER_C_FN_DEFINITIONS, 
102102ExportedFunction , 
103+     /// `no_mangle`/`export_name` static variables, assumed to be used from across an FFI boundary, 
104+ ExportedStatic , 
103105    /// `extern "C"` function pointers -> IMPROPER_C_CALLBACKS, 
104106Callback , 
105107} 
@@ -438,6 +440,7 @@ bitflags! {
438440        // unfortunately, "cannot call non-const operator in constants" (bitwise or?). 
439441        const  None  = 0b000000 ; 
440442        const  StaticTy  = 0b000001 ;  //Self::STATIC 
443+         const  ExportedStaticTy  = 0b001001 ;  //Self::STATIC | Self::DEFINED 
441444        const  ArgumentTyInDefinition  = 0b001010 ;  //Self::FUNC | Self::DEFINED 
442445        const  ReturnTyInDefinition  = 0b001110 ;   //Self::FUNC | Self::FN_RETURN | Self::DEFINED 
443446        const  ArgumentTyInDeclaration  = 0b000010 ;   //Self::FUNC 
@@ -1485,6 +1488,14 @@ impl<'tcx> ImproperCTypesLint {
14851488        self . process_ffi_result ( cx,  span,  ffi_res,  CItemKind :: ImportedExtern ) ; 
14861489    } 
14871490
1491+     /// Check that a `#[no_mangle]`/`#[export_name = _]` static variable is of a ffi-safe type. 
1492+ fn  check_exported_static ( & self ,  cx :  & LateContext < ' tcx > ,  id :  hir:: OwnerId ,  span :  Span )  { 
1493+         let  ty = cx. tcx . type_of ( id) . instantiate_identity ( ) ; 
1494+         let  visitor = ImproperCTypesVisitor :: new ( cx) ; 
1495+         let  ffi_res = visitor. check_for_type ( VisitorState :: ExportedStaticTy ,  ty) ; 
1496+         self . process_ffi_result ( cx,  span,  ffi_res,  CItemKind :: ExportedStatic ) ; 
1497+     } 
1498+ 
14881499    /// Check if a function's argument types and result type are "ffi-safe". 
14891500fn  check_foreign_fn ( 
14901501        & mut  self , 
@@ -1585,11 +1596,13 @@ impl<'tcx> ImproperCTypesLint {
15851596        let  lint = match  fn_mode { 
15861597            CItemKind :: ImportedExtern  => IMPROPER_CTYPES , 
15871598            CItemKind :: ExportedFunction  => IMPROPER_C_FN_DEFINITIONS , 
1599+             CItemKind :: ExportedStatic  => IMPROPER_C_VAR_DEFINITIONS , 
15881600            CItemKind :: Callback  => IMPROPER_C_CALLBACKS , 
15891601        } ; 
15901602        let  desc = match  fn_mode { 
15911603            CItemKind :: ImportedExtern  => "`extern` block" , 
15921604            CItemKind :: ExportedFunction  => "`extern` fn" , 
1605+             CItemKind :: ExportedStatic  => "foreign-code-reachable static" , 
15931606            CItemKind :: Callback  => "`extern` callback" , 
15941607        } ; 
15951608        for  reason in  reasons. iter_mut ( )  { 
@@ -1657,6 +1670,25 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesLint {
16571670                    ty, 
16581671                    cx. tcx . type_of ( item. owner_id ) . instantiate_identity ( ) , 
16591672                ) ; 
1673+ 
1674+                 // FIXME: cx.tcx.has_attr no worky 
1675+                 // if matches!(item.kind, hir::ItemKind::Static(..)) 
1676+                 //     && (cx.tcx.has_attr(item.owner_id, sym::no_mangle) 
1677+                 //         || cx.tcx.has_attr(item.owner_id, sym::export_name)) 
1678+                 if  matches ! ( item. kind,  hir:: ItemKind :: Static ( ..) )  { 
1679+                     let  is_exported_static = cx. tcx . get_all_attrs ( item. owner_id ) . iter ( ) . any ( |x| { 
1680+                         matches ! ( 
1681+                             x, 
1682+                             hir:: Attribute :: Parsed ( 
1683+                                 hir:: attrs:: AttributeKind :: NoMangle ( _) 
1684+                                     | hir:: attrs:: AttributeKind :: ExportName  {  .. } 
1685+                             ) 
1686+                         ) 
1687+                     } ) ; 
1688+                     if  is_exported_static { 
1689+                         self . check_exported_static ( cx,  item. owner_id ,  ty. span ) ; 
1690+                     } 
1691+                 } 
16601692            } 
16611693            // See `check_fn` for declarations, `check_foreign_items` for definitions in extern blocks 
16621694            hir:: ItemKind :: Fn  {  .. }  => { } 
@@ -1823,6 +1855,37 @@ declare_lint! {
18231855    "proper use of libc types in foreign item definitions" 
18241856} 
18251857
1858+ declare_lint !  { 
1859+     /// The `improper_c_var_definitions` lint detects incorrect use of 
1860+ /// [`no_mangle`] and [`export_name`] static variable definitions. 
1861+ /// (In other words, static variables accessible by name by foreign code.) 
1862+ /// 
1863+ /// [`no_mangle`]: https://doc.rust-lang.org/stable/reference/abi.html#the-no_mangle-attribute 
1864+ /// [`export_name`]: https://doc.rust-lang.org/stable/reference/abi.html#the-export_name-attribute 
1865+ /// 
1866+ /// ### Example 
1867+ /// 
1868+ /// ```rust 
1869+ /// # #[unsafe(no_mangle)] 
1870+ /// # #[used] 
1871+ /// static mut PLUGIN_ABI_MIN_VERSION: &'static str = "0.0.5"; 
1872+ /// ``` 
1873+ /// 
1874+ /// {{produces}} 
1875+ /// 
1876+ /// ### Explanation 
1877+ /// 
1878+ /// The compiler has several checks to verify that types used in 
1879+ /// static variables exposed to foreign code are safe and follow 
1880+ /// certain rules to ensure proper compatibility with the foreign interfaces. 
1881+ /// This lint is issued when it detects a probable mistake in a definition. 
1882+ /// The lint usually should provide a description of the issue, 
1883+ /// along with possibly a hint on how to resolve it. 
1884+ pub ( crate )  IMPROPER_C_VAR_DEFINITIONS , 
1885+     Warn , 
1886+     "proper use of libc types in foreign-reachable static variable definitions" 
1887+ } 
1888+ 
18261889declare_lint !  { 
18271890    /// The `improper_c_callbacks` lint detects incorrect use of 
18281891/// [`extern` function] pointers. 
@@ -1909,6 +1972,7 @@ declare_lint! {
19091972declare_lint_pass ! ( ImproperCTypesLint  => [ 
19101973    IMPROPER_CTYPES , 
19111974    IMPROPER_C_FN_DEFINITIONS , 
1975+     IMPROPER_C_VAR_DEFINITIONS , 
19121976    IMPROPER_C_CALLBACKS , 
19131977    USES_POWER_ALIGNMENT , 
19141978] ) ; 
0 commit comments