diff options
| author | bors <bors@rust-lang.org> | 2017-04-22 11:50:40 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-04-22 11:50:40 +0000 |
| commit | 6d841da4a0d7629f826117f99052e3d4a7997a7e (patch) | |
| tree | 27e04604a86c867e8146bf75ff0c1ea973aaf47c /src/libsyntax | |
| parent | ff13b7c91813eb178c98a7abc661acaf5c41dc31 (diff) | |
| parent | 946f8e6a59242a8112c6983d1336fef54bc55b9a (diff) | |
| download | rust-6d841da4a0d7629f826117f99052e3d4a7997a7e.tar.gz rust-6d841da4a0d7629f826117f99052e3d4a7997a7e.zip | |
Auto merge of #39999 - bitshifter:struct_align, r=eddyb
Implementation of repr struct alignment RFC 1358. The main changes around rustc::ty::Layout::struct: * Added abi_align field which stores abi alignment before repr align is applied * align field contains transitive repr alignment * Added padding vec which stores padding required after fields The main user of this information is rustc_trans::adt::struct_llfields which determines the LLVM fields to be used by LLVM, including padding fields. A possible future optimisation would be to put the padding Vec in an Option, since it will be unused unless you are using repr align.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/attr.rs | 55 | ||||
| -rw-r--r-- | src/libsyntax/diagnostic_list.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 8 |
3 files changed, 58 insertions, 7 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 6f5f52ff1e9..82492d97627 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -147,6 +147,24 @@ impl NestedMetaItem { self.meta_item().and_then(|meta_item| meta_item.value_str()) } + /// Returns a name and single literal value tuple of the MetaItem. + pub fn name_value_literal(&self) -> Option<(Name, &Lit)> { + self.meta_item().and_then( + |meta_item| meta_item.meta_item_list().and_then( + |meta_item_list| { + if meta_item_list.len() == 1 { + let nested_item = &meta_item_list[0]; + if nested_item.is_literal() { + Some((meta_item.name(), nested_item.literal().unwrap())) + } else { + None + } + } + else { + None + }})) + } + /// Returns a MetaItem if self is a MetaItem with Kind Word. pub fn word(&self) -> Option<&MetaItem> { self.meta_item().and_then(|meta_item| if meta_item.is_word() { @@ -931,6 +949,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> continue } + let mut recognised = false; if let Some(mi) = item.word() { let word = &*mi.name().as_str(); let hint = match word { @@ -941,20 +960,43 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> _ => match int_type_of_word(word) { Some(ity) => Some(ReprInt(ity)), None => { - // Not a word we recognize - span_err!(diagnostic, item.span, E0552, - "unrecognized representation hint"); None } } }; if let Some(h) = hint { + recognised = true; acc.push(h); } - } else { - span_err!(diagnostic, item.span, E0553, - "unrecognized enum representation hint"); + } 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() { + // rustc::ty::layout::Align restricts align to <= 32768 + if align <= 32768 { + acc.push(ReprAlign(align as u16)); + } else { + align_error = Some("larger than 32768"); + } + } else { + align_error = Some("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); + } + } + } + if !recognised { + // Not a word we recognize + span_err!(diagnostic, item.span, E0552, + "unrecognized representation hint"); } } } @@ -986,6 +1028,7 @@ pub enum ReprAttr { ReprExtern, ReprPacked, ReprSimd, + ReprAlign(u16), } #[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 2d59051ec4a..01d1277ea62 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -287,10 +287,10 @@ register_diagnostics! { E0550, // multiple deprecated attributes E0551, // incorrect meta item E0552, // unrecognized representation hint - E0553, // unrecognized enum representation hint E0554, // #[feature] may not be used on the [] release channel E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word E0557, // feature has been removed E0584, // file for module `..` found at both .. and .. + E0589, // invalid `repr(align)` attribute } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 175447e1112..9b55a860b35 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -338,6 +338,9 @@ declare_features! ( // Allows the `catch {...}` expression (active, catch_expr, "1.17.0", Some(31436)), + // Allows `repr(align(u16))` struct attribute (RFC 1358) + (active, repr_align, "1.17.0", Some(33626)), + // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work. (active, rvalue_static_promotion, "1.15.1", Some(38865)), @@ -1189,6 +1192,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { and possibly buggy"); } + if item.check_name("align") { + gate_feature_post!(&self, repr_align, i.span, + "the struct `#[repr(align(u16))]` attribute \ + is experimental"); + } } } } |
