11use rustc_abi:: { Align , Size } ;
22use rustc_ast:: { IntTy , LitIntType , LitKind , UintTy } ;
3- use rustc_hir:: attrs:: { IntType , ReprAttr } ;
3+ use rustc_hir:: attrs:: IntType :: { SignedInt , UnsignedInt } ;
4+ use rustc_hir:: attrs:: ReprAttr ;
45
56use super :: prelude:: * ;
6- use crate :: session_diagnostics:: { self , IncorrectReprFormatGenericCause } ;
7+ use crate :: session_diagnostics;
78
89/// Parse #[repr(...)] forms.
910///
10- /// Valid repr contents: any of the primitive integral type names (see
11- /// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
12- /// the same discriminant size that the corresponding C enum would or C
13- /// structure layout, `packed` to remove padding, and `transparent` to delegate representation
14- /// concerns to the only non-ZST field.
15- // FIXME(jdonszelmann): is a vec the right representation here even? isn't it just a struct?
11+ /// Valid repr contents:
12+ /// * any of the primitive integral type names to specify enum discriminant type
13+ /// * `Rust`, to use the default `Rust` layout of the type
14+ /// * `C`, to use the same layout for the type that C would use
15+ /// * `align(...)`, to change the alignment requirements of the type
16+ /// * `packed`, to remove padding
17+ /// * `transparent`, to delegate representation concerns to the only non-ZST field.
1618pub ( crate ) struct ReprParser ;
1719
1820impl CombineAttributeParser for ReprParser {
1921 type Item = ( ReprAttr , Span ) ;
2022 const PATH : & [ Symbol ] = & [ sym:: repr] ;
2123 const CONVERT : ConvertFn < Self :: Item > =
2224 |items, first_span| AttributeKind :: Repr { reprs : items, first_span } ;
23- // FIXME(jdonszelmann): never used
2425 const TEMPLATE : AttributeTemplate = template ! (
2526 List : & [ "C" , "Rust" , "transparent" , "align(...)" , "packed(...)" , "<integer type>" ] ,
2627 "https://doc.rust-lang.org/reference/type-layout.html#representations"
@@ -30,29 +31,24 @@ impl CombineAttributeParser for ReprParser {
3031 cx : & mut AcceptContext < ' _ , ' _ > ,
3132 args : & ArgParser ,
3233 ) -> impl IntoIterator < Item = Self :: Item > {
33- let mut reprs = Vec :: new ( ) ;
34-
3534 let Some ( list) = cx. expect_list ( args, cx. attr_span ) else {
36- return reprs ;
35+ return vec ! [ ] ;
3736 } ;
3837
3938 if list. is_empty ( ) {
4039 let attr_span = cx. attr_span ;
4140 cx. adcx ( ) . warn_empty_attribute ( attr_span) ;
42- return reprs ;
41+ return vec ! [ ] ;
4342 }
4443
44+ let mut reprs = Vec :: new ( ) ;
4545 for param in list. mixed ( ) {
46- if let Some ( _ ) = param. as_lit ( ) {
47- cx. emit_err ( session_diagnostics :: ReprIdent { span : cx . attr_span } ) ;
46+ let Some ( item ) = param. meta_item ( ) else {
47+ cx. adcx ( ) . expected_identifier ( param . span ( ) ) ;
4848 continue ;
49- }
50-
51- reprs. extend (
52- param. meta_item ( ) . and_then ( |mi| parse_repr ( cx, & mi) ) . map ( |r| ( r, param. span ( ) ) ) ,
53- ) ;
49+ } ;
50+ reprs. extend ( parse_repr ( cx, & item) . map ( |r| ( r, param. span ( ) ) ) ) ;
5451 }
55-
5652 reprs
5753 }
5854
@@ -61,122 +57,69 @@ impl CombineAttributeParser for ReprParser {
6157 const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( ALL_TARGETS ) ;
6258}
6359
64- macro_rules! int_pat {
65- ( ) => {
66- sym:: i8
67- | sym:: u8
68- | sym:: i16
69- | sym:: u16
70- | sym:: i32
71- | sym:: u32
72- | sym:: i64
73- | sym:: u64
74- | sym:: i128
75- | sym:: u128
76- | sym:: isize
77- | sym:: usize
78- } ;
79- }
80-
81- fn int_type_of_word ( s : Symbol ) -> Option < IntType > {
82- use IntType :: * ;
83-
84- match s {
85- sym:: i8 => Some ( SignedInt ( IntTy :: I8 ) ) ,
86- sym:: u8 => Some ( UnsignedInt ( UintTy :: U8 ) ) ,
87- sym:: i16 => Some ( SignedInt ( IntTy :: I16 ) ) ,
88- sym:: u16 => Some ( UnsignedInt ( UintTy :: U16 ) ) ,
89- sym:: i32 => Some ( SignedInt ( IntTy :: I32 ) ) ,
90- sym:: u32 => Some ( UnsignedInt ( UintTy :: U32 ) ) ,
91- sym:: i64 => Some ( SignedInt ( IntTy :: I64 ) ) ,
92- sym:: u64 => Some ( UnsignedInt ( UintTy :: U64 ) ) ,
93- sym:: i128 => Some ( SignedInt ( IntTy :: I128 ) ) ,
94- sym:: u128 => Some ( UnsignedInt ( UintTy :: U128 ) ) ,
95- sym:: isize => Some ( SignedInt ( IntTy :: Isize ) ) ,
96- sym:: usize => Some ( UnsignedInt ( UintTy :: Usize ) ) ,
97- _ => None ,
98- }
99- }
100-
101- fn parse_repr ( cx : & AcceptContext < ' _ , ' _ > , param : & MetaItemParser ) -> Option < ReprAttr > {
60+ fn parse_repr ( cx : & mut AcceptContext < ' _ , ' _ > , param : & MetaItemParser ) -> Option < ReprAttr > {
10261 use ReprAttr :: * ;
10362
104- // FIXME(jdonszelmann): invert the parsing here to match on the word first and then the
105- // structure.
106- let ( name, ident_span) = if let Some ( ident) = param. path ( ) . word ( ) {
107- ( Some ( ident. name ) , ident. span )
108- } else {
109- ( None , DUMMY_SP )
110- } ;
111-
112- let args = param. args ( ) ;
113-
114- match ( name, args) {
115- ( Some ( sym:: align) , ArgParser :: NoArgs ) => {
116- cx. emit_err ( session_diagnostics:: InvalidReprAlignNeedArg { span : ident_span } ) ;
117- None
118- }
119- ( Some ( sym:: align) , ArgParser :: List ( l) ) => {
120- parse_repr_align ( cx, l, param. span ( ) , AlignKind :: Align )
121- }
122-
123- ( Some ( sym:: packed) , ArgParser :: NoArgs ) => Some ( ReprPacked ( Align :: ONE ) ) ,
124- ( Some ( sym:: packed) , ArgParser :: List ( l) ) => {
125- parse_repr_align ( cx, l, param. span ( ) , AlignKind :: Packed )
126- }
127-
128- ( Some ( name @ sym:: align | name @ sym:: packed) , ArgParser :: NameValue ( l) ) => {
129- cx. emit_err ( session_diagnostics:: IncorrectReprFormatGeneric {
130- span : param. span ( ) ,
131- // FIXME(jdonszelmann) can just be a string in the diag type
132- repr_arg : name,
133- cause : IncorrectReprFormatGenericCause :: from_lit_kind (
134- param. span ( ) ,
135- & l. value_as_lit ( ) . kind ,
136- name,
137- ) ,
138- } ) ;
139- None
140- }
141-
142- ( Some ( sym:: Rust ) , ArgParser :: NoArgs ) => Some ( ReprRust ) ,
143- ( Some ( sym:: C ) , ArgParser :: NoArgs ) => Some ( ReprC ) ,
144- ( Some ( sym:: simd) , ArgParser :: NoArgs ) => Some ( ReprSimd ) ,
145- ( Some ( sym:: transparent) , ArgParser :: NoArgs ) => Some ( ReprTransparent ) ,
146- ( Some ( name @ int_pat ! ( ) ) , ArgParser :: NoArgs ) => {
147- // int_pat!() should make sure it always parses
148- Some ( ReprInt ( int_type_of_word ( name) . unwrap ( ) ) )
149- }
63+ macro_rules! no_args {
64+ ( $constructor: expr) => { {
65+ cx. expect_no_args( param. args( ) ) ?;
66+ Some ( $constructor)
67+ } } ;
68+ }
15069
151- (
152- Some (
153- name @ sym:: Rust
154- | name @ sym:: C
155- | name @ sym:: simd
156- | name @ sym:: transparent
157- | name @ int_pat ! ( ) ,
158- ) ,
159- ArgParser :: NameValue ( _) ,
160- ) => {
161- cx. emit_err ( session_diagnostics:: InvalidReprHintNoValue { span : param. span ( ) , name } ) ;
162- None
163- }
164- (
165- Some (
166- name @ sym:: Rust
167- | name @ sym:: C
168- | name @ sym:: simd
169- | name @ sym:: transparent
170- | name @ int_pat ! ( ) ,
171- ) ,
172- ArgParser :: List ( _) ,
173- ) => {
174- cx. emit_err ( session_diagnostics:: InvalidReprHintNoParen { span : param. span ( ) , name } ) ;
175- None
70+ match param. path ( ) . word_sym ( ) {
71+ Some ( sym:: align) => {
72+ let l = cx. expect_list ( param. args ( ) , param. span ( ) ) ?;
73+ parse_repr_align ( cx, l, AlignKind :: Align )
17674 }
177-
75+ Some ( sym:: packed) => match param. args ( ) {
76+ ArgParser :: NoArgs => Some ( ReprPacked ( Align :: ONE ) ) ,
77+ ArgParser :: List ( l) => parse_repr_align ( cx, l, AlignKind :: Packed ) ,
78+ ArgParser :: NameValue ( _) => {
79+ cx. adcx ( ) . expected_list_or_no_args ( param. span ( ) ) ;
80+ None
81+ }
82+ } ,
83+ Some ( sym:: Rust ) => no_args ! ( ReprRust ) ,
84+ Some ( sym:: C ) => no_args ! ( ReprC ) ,
85+ Some ( sym:: simd) => no_args ! ( ReprSimd ) ,
86+ Some ( sym:: transparent) => no_args ! ( ReprTransparent ) ,
87+ Some ( sym:: i8) => no_args ! ( ReprInt ( SignedInt ( IntTy :: I8 ) ) ) ,
88+ Some ( sym:: u8) => no_args ! ( ReprInt ( UnsignedInt ( UintTy :: U8 ) ) ) ,
89+ Some ( sym:: i16) => no_args ! ( ReprInt ( SignedInt ( IntTy :: I16 ) ) ) ,
90+ Some ( sym:: u16) => no_args ! ( ReprInt ( UnsignedInt ( UintTy :: U16 ) ) ) ,
91+ Some ( sym:: i32) => no_args ! ( ReprInt ( SignedInt ( IntTy :: I32 ) ) ) ,
92+ Some ( sym:: u32) => no_args ! ( ReprInt ( UnsignedInt ( UintTy :: U32 ) ) ) ,
93+ Some ( sym:: i64) => no_args ! ( ReprInt ( SignedInt ( IntTy :: I64 ) ) ) ,
94+ Some ( sym:: u64) => no_args ! ( ReprInt ( UnsignedInt ( UintTy :: U64 ) ) ) ,
95+ Some ( sym:: i128) => no_args ! ( ReprInt ( SignedInt ( IntTy :: I128 ) ) ) ,
96+ Some ( sym:: u128) => no_args ! ( ReprInt ( UnsignedInt ( UintTy :: U128 ) ) ) ,
97+ Some ( sym:: isize) => no_args ! ( ReprInt ( SignedInt ( IntTy :: Isize ) ) ) ,
98+ Some ( sym:: usize) => no_args ! ( ReprInt ( UnsignedInt ( UintTy :: Usize ) ) ) ,
17899 _ => {
179- cx. emit_err ( session_diagnostics:: UnrecognizedReprHint { span : param. span ( ) } ) ;
100+ cx. adcx ( ) . expected_specific_argument (
101+ param. span ( ) ,
102+ & [
103+ sym:: align,
104+ sym:: packed,
105+ sym:: Rust ,
106+ sym:: C ,
107+ sym:: simd,
108+ sym:: transparent,
109+ sym:: i8,
110+ sym:: u8,
111+ sym:: i16,
112+ sym:: u16,
113+ sym:: i32,
114+ sym:: u32,
115+ sym:: i64,
116+ sym:: u64,
117+ sym:: i128,
118+ sym:: u128,
119+ sym:: isize,
120+ sym:: usize,
121+ ] ,
122+ ) ;
180123 None
181124 }
182125 }
@@ -188,44 +131,17 @@ enum AlignKind {
188131}
189132
190133fn parse_repr_align (
191- cx : & AcceptContext < ' _ , ' _ > ,
134+ cx : & mut AcceptContext < ' _ , ' _ > ,
192135 list : & MetaItemListParser ,
193- param_span : Span ,
194136 align_kind : AlignKind ,
195137) -> Option < ReprAttr > {
196- use AlignKind :: * ;
197-
198138 let Some ( align) = list. as_single ( ) else {
199- match align_kind {
200- Packed => {
201- cx. emit_err ( session_diagnostics:: IncorrectReprFormatPackedOneOrZeroArg {
202- span : param_span,
203- } ) ;
204- }
205- Align => {
206- cx. emit_err ( session_diagnostics:: IncorrectReprFormatAlignOneArg {
207- span : param_span,
208- } ) ;
209- }
210- }
211-
139+ cx. adcx ( ) . expected_single_argument ( list. span , list. len ( ) ) ;
212140 return None ;
213141 } ;
214142
215143 let Some ( lit) = align. as_lit ( ) else {
216- match align_kind {
217- Packed => {
218- cx. emit_err ( session_diagnostics:: IncorrectReprFormatPackedExpectInteger {
219- span : align. span ( ) ,
220- } ) ;
221- }
222- Align => {
223- cx. emit_err ( session_diagnostics:: IncorrectReprFormatExpectInteger {
224- span : align. span ( ) ,
225- } ) ;
226- }
227- }
228-
144+ cx. adcx ( ) . expected_integer_literal ( align. span ( ) ) ;
229145 return None ;
230146 } ;
231147
@@ -235,12 +151,8 @@ fn parse_repr_align(
235151 AlignKind :: Align => ReprAttr :: ReprAlign ( literal) ,
236152 } ) ,
237153 Err ( message) => {
238- cx. emit_err ( session_diagnostics:: InvalidReprGeneric {
154+ cx. emit_err ( session_diagnostics:: InvalidAlignmentValue {
239155 span : lit. span ,
240- repr_arg : match align_kind {
241- Packed => "packed" . to_string ( ) ,
242- Align => "align" . to_string ( ) ,
243- } ,
244156 error_part : message,
245157 } ) ;
246158 None
@@ -294,10 +206,7 @@ impl RustcAlignParser {
294206 } ;
295207
296208 let Some ( lit) = align. as_lit ( ) else {
297- cx. emit_err ( session_diagnostics:: IncorrectReprFormatExpectInteger {
298- span : align. span ( ) ,
299- } ) ;
300-
209+ cx. adcx ( ) . expected_integer_literal ( align. span ( ) ) ;
301210 return ;
302211 } ;
303212
0 commit comments