about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorCameron Hart <cameron.hart@gmail.com>2017-01-15 09:49:29 +1100
committerCameron Hart <cameron.hart@gmail.com>2017-04-21 07:32:32 +1000
commit4358e35fda66ab7a00215c7f9d50e7c6dc9b801b (patch)
treea25741bc07d2a01d06a99d2135a776c61d42e3d5 /src/libsyntax
parentddc5d7bd4b9ea3e8a8ccf82cb443e950be311d61 (diff)
downloadrust-4358e35fda66ab7a00215c7f9d50e7c6dc9b801b.tar.gz
rust-4358e35fda66ab7a00215c7f9d50e7c6dc9b801b.zip
Implementation of repr struct alignment RFC 1358.
The main changes around rustc::ty::Layout::struct and rustc_trans:adt:
* Added primitive_align field which stores alignment before repr align
* Always emit field padding when generating the LLVM struct fields
* Added methods for adjusting field indexes from the layout index to the
  LLVM struct field index

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.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/attr.rs50
-rw-r--r--src/libsyntax/diagnostic_list.rs2
2 files changed, 45 insertions, 7 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 6f5f52ff1e9..442345ceb3c 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,38 @@ 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 valid_align = false;
+                        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));
+                                    valid_align = true;
+                                }
+                            }
+                        }
+                        if !valid_align {
+                            span_err!(diagnostic, item.span, E0589,
+                                      "align representation must be a u16 power of two");
+                        }
+                    }
+                }
+                if !recognised {
+                    // Not a word we recognize
+                    span_err!(diagnostic, item.span, E0552,
+                              "unrecognized representation hint");
                 }
             }
         }
@@ -986,6 +1023,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..775775875a4 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, // align representation must be a u16 power of two
 }