diff options
| author | Cameron Hart <cameron.hart@gmail.com> | 2018-02-04 22:10:28 +1100 |
|---|---|---|
| committer | Cameron Hart <cameron.hart@gmail.com> | 2018-04-11 22:13:13 +1000 |
| commit | 15d1c4d2139611fcb87a2c802bd015b5f4f0aed8 (patch) | |
| tree | 5822428a8e6a8ef94f13ea80f22d8ec01545f33b /src/libsyntax | |
| parent | ca26ef321c44358404ef788d315c4557eb015fb2 (diff) | |
| download | rust-15d1c4d2139611fcb87a2c802bd015b5f4f0aed8.tar.gz rust-15d1c4d2139611fcb87a2c802bd015b5f4f0aed8.zip | |
Implementation of `#[repr(packed(n))]` RFC 1399.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/attr.rs | 46 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 19 |
2 files changed, 45 insertions, 20 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 2812e1238e9..c68a743303a 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -993,7 +993,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> let word = &*mi.ident.name.as_str(); let hint = match word { "C" => Some(ReprC), - "packed" => Some(ReprPacked), + "packed" => Some(ReprPacked(1)), "simd" => Some(ReprSimd), "transparent" => Some(ReprTransparent), _ => match int_type_of_word(word) { @@ -1009,27 +1009,41 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> acc.push(h); } } else if let Some((name, value)) = item.name_value_literal() { - if name == "align" { - recognised = true; - let mut align_error = None; - if let ast::LitKind::Int(align, ast::LitIntType::Unsuffixed) = value.node { - if align.is_power_of_two() { + let parse_alignment = |node: &ast::LitKind| -> Result<u32, &'static str> { + if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node { + if literal.is_power_of_two() { // rustc::ty::layout::Align restricts align to <= 2147483647 - if align <= 2147483647 { - acc.push(ReprAlign(align as u32)); + if *literal <= 2147483647 { + Ok(*literal as u32) } else { - align_error = Some("larger than 2147483647"); + Err("larger than 2147483647") } } else { - align_error = Some("not a power of two"); + Err("not a power of two") } } else { - align_error = Some("not an unsuffixed integer"); - } - if let Some(align_error) = align_error { - span_err!(diagnostic, item.span, E0589, - "invalid `repr(align)` attribute: {}", align_error); + Err("not an unsuffixed integer") } + }; + + let mut literal_error = None; + if name == "align" { + recognised = true; + match parse_alignment(&value.node) { + Ok(literal) => acc.push(ReprAlign(literal)), + Err(message) => literal_error = Some(message) + }; + } + else if name == "packed" { + recognised = true; + match parse_alignment(&value.node) { + Ok(literal) => acc.push(ReprPacked(literal)), + Err(message) => literal_error = Some(message) + }; + } + if let Some(literal_error) = literal_error { + span_err!(diagnostic, item.span, E0589, + "invalid `repr(align)` attribute: {}", literal_error); } } if !recognised { @@ -1065,7 +1079,7 @@ fn int_type_of_word(s: &str) -> Option<IntType> { pub enum ReprAttr { ReprInt(IntType), ReprC, - ReprPacked, + ReprPacked(u32), ReprSimd, ReprTransparent, ReprAlign(u32), diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0a3cd66d897..df39757d1eb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -432,6 +432,9 @@ declare_features! ( // Parentheses in patterns (active, pattern_parentheses, "1.26.0", None, None), + // Allows `#[repr(packed)]` attribute on structs + (active, repr_packed, "1.26.0", Some(33158), None), + // `use path as _;` and `extern crate c as _;` (active, underscore_imports, "1.26.0", Some(48216), None), @@ -1439,11 +1442,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - // allow attr_literals in #[repr(align(x))] - let mut is_repr_align = false; + // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))] + let mut allow_attr_literal = false; if attr.path == "repr" { if let Some(content) = attr.meta_item_list() { - is_repr_align = content.iter().any(|c| c.check_name("align")); + allow_attr_literal = content.iter().any( + |c| c.check_name("align") || c.check_name("packed")); } } @@ -1451,7 +1455,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { return } - if !is_repr_align { + if !allow_attr_literal { let meta = panictry!(attr.parse_meta(self.context.parse_sess)); if contains_novel_literal(&meta) { gate_feature_post!(&self, attr_literals, attr.span, @@ -1535,6 +1539,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "the `#[repr(transparent)]` attribute \ is experimental"); } + if let Some((name, _)) = item.name_value_literal() { + if name == "packed" { + gate_feature_post!(&self, repr_packed, attr.span, + "the `#[repr(packed(n))]` attribute \ + is experimental"); + } + } } } } |
