about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-04-22 11:50:40 +0000
committerbors <bors@rust-lang.org>2017-04-22 11:50:40 +0000
commit6d841da4a0d7629f826117f99052e3d4a7997a7e (patch)
tree27e04604a86c867e8146bf75ff0c1ea973aaf47c /src/libsyntax
parentff13b7c91813eb178c98a7abc661acaf5c41dc31 (diff)
parent946f8e6a59242a8112c6983d1336fef54bc55b9a (diff)
downloadrust-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.rs55
-rw-r--r--src/libsyntax/diagnostic_list.rs2
-rw-r--r--src/libsyntax/feature_gate.rs8
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");
+                            }
                         }
                     }
                 }