1- use rustc_abi:: Align ;
1+ use rustc_abi:: { Align , Size } ;
22use rustc_ast:: { IntTy , LitIntType , LitKind , UintTy } ;
33use rustc_hir:: attrs:: { IntType , ReprAttr } ;
44
@@ -229,7 +229,7 @@ fn parse_repr_align<S: Stage>(
229229 return None ;
230230 } ;
231231
232- match parse_alignment ( & lit. kind ) {
232+ match parse_alignment ( & lit. kind , cx ) {
233233 Ok ( literal) => Some ( match align_kind {
234234 AlignKind :: Packed => ReprAttr :: ReprPacked ( literal) ,
235235 AlignKind :: Align => ReprAttr :: ReprAlign ( literal) ,
@@ -248,23 +248,35 @@ fn parse_repr_align<S: Stage>(
248248 }
249249}
250250
251- fn parse_alignment ( node : & LitKind ) -> Result < Align , & ' static str > {
252- if let LitKind :: Int ( literal, LitIntType :: Unsuffixed ) = node {
253- // `Align::from_bytes` accepts 0 as an input, check is_power_of_two() first
254- if literal. get ( ) . is_power_of_two ( ) {
255- // Only possible error is larger than 2^29
256- literal
257- . get ( )
258- . try_into ( )
259- . ok ( )
260- . and_then ( |v| Align :: from_bytes ( v) . ok ( ) )
261- . ok_or ( "larger than 2^29" )
262- } else {
263- Err ( "not a power of two" )
264- }
265- } else {
266- Err ( "not an unsuffixed integer" )
251+ fn parse_alignment < S : Stage > (
252+ node : & LitKind ,
253+ cx : & AcceptContext < ' _ , ' _ , S > ,
254+ ) -> Result < Align , String > {
255+ let LitKind :: Int ( literal, LitIntType :: Unsuffixed ) = node else {
256+ return Err ( "not an unsuffixed integer" . to_string ( ) ) ;
257+ } ;
258+
259+ // `Align::from_bytes` accepts 0 as a valid input,
260+ // so we check if its a power of two first
261+ if !literal. get ( ) . is_power_of_two ( ) {
262+ return Err ( "not a power of two" . to_string ( ) ) ;
263+ }
264+ // lit must be < 2^29
265+ let align = literal
266+ . get ( )
267+ . try_into ( )
268+ . ok ( )
269+ . and_then ( |a| Align :: from_bytes ( a) . ok ( ) )
270+ . ok_or ( "larger than 2^29" . to_string ( ) ) ?;
271+
272+ // alignment must not be larger than the pointer width (`isize::MAX`)
273+ let max = Size :: from_bits ( cx. sess . target . pointer_width ) . signed_int_max ( ) as u64 ;
274+ if align. bytes ( ) > max {
275+ return Err ( format ! (
276+ "alignment larger than `isize::MAX` bytes ({max} for the current target)"
277+ ) ) ;
267278 }
279+ Ok ( align)
268280}
269281
270282/// Parse #[align(N)].
@@ -294,7 +306,7 @@ impl RustcAlignParser {
294306 return ;
295307 } ;
296308
297- match parse_alignment ( & lit. kind ) {
309+ match parse_alignment ( & lit. kind , cx ) {
298310 Ok ( literal) => self . 0 = Ord :: max ( self . 0 , Some ( ( literal, cx. attr_span ) ) ) ,
299311 Err ( message) => {
300312 cx. emit_err ( session_diagnostics:: InvalidAlignmentValue {
0 commit comments