diff options
| author | Jed Davis <jld@panix.com> | 2013-05-24 18:08:45 -0400 |
|---|---|---|
| committer | Jed Davis <jld@panix.com> | 2013-10-29 09:09:19 -0700 |
| commit | f1124a2f55406be8e758488352c59ae9deef17b3 (patch) | |
| tree | 06cd816c346551e82db912d0edc7b4872a36de57 /src/libsyntax/attr.rs | |
| parent | e6650c87a3800264a043b7f129e6a4841c4cc3f7 (diff) | |
| download | rust-f1124a2f55406be8e758488352c59ae9deef17b3.tar.gz rust-f1124a2f55406be8e758488352c59ae9deef17b3.zip | |
Add parser for `#[repr(...)]`; nothing uses it yet.
Also export enum attrs into metadata, and add a convenient interface for obtaining the repr hint from either a local or remote definition.
Diffstat (limited to 'src/libsyntax/attr.rs')
| -rw-r--r-- | src/libsyntax/attr.rs | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 40b7ff29e24..e538e09c056 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -14,7 +14,7 @@ use extra; use ast; use ast::{Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, MetaList}; -use codemap::{Spanned, spanned, dummy_spanned}; +use codemap::{Span, Spanned, spanned, dummy_spanned}; use codemap::BytePos; use diagnostic::span_handler; use parse::comments::{doc_comment_style, strip_doc_comment_decoration}; @@ -363,3 +363,97 @@ pub fn require_unique_names(diagnostic: @mut span_handler, } } } + + +/** + * Fold this over attributes to parse #[repr(...)] forms. + * + * Valid repr contents: any of the primitive integral type names (see + * `int_type_of_word`, below) to specify the discriminant type; and `C`, to use + * the same discriminant size that the corresponding C enum would. These are + * not allowed on univariant or zero-variant enums, which have no discriminant. + * + * If a discriminant type is so specified, then the discriminant will be + * present (before fields, if any) with that type; reprensentation + * optimizations which would remove it will not be done. + */ +pub fn find_repr_attr(diagnostic: @mut span_handler, attr: @ast::MetaItem, acc: ReprAttr) + -> ReprAttr { + let mut acc = acc; + match attr.node { + ast::MetaList(s, ref items) if "repr" == s => { + for item in items.iter() { + match item.node { + ast::MetaWord(word) => { + let word: &str = word; + let hint = match word { + // Can't use "extern" because it's not a lexical identifier. + "C" => ReprExtern, + _ => match int_type_of_word(word) { + Some(ity) => ReprInt(item.span, ity), + None => { + // Not a word we recognize + diagnostic.span_err(item.span, + "unrecognized representation hint"); + ReprAny + } + } + }; + if hint != ReprAny { + if acc == ReprAny { + acc = hint; + } else if acc != hint { + diagnostic.span_warn(item.span, + "conflicting representation hint ignored") + } + } + } + // Not a word: + _ => diagnostic.span_err(item.span, "unrecognized representation hint") + } + } + } + // Not a "repr" hint: ignore. + _ => { } + } + return acc; +} + +fn int_type_of_word(s: &str) -> Option<IntType> { + match s { + "i8" => Some(SignedInt(ast::ty_i8)), + "u8" => Some(UnsignedInt(ast::ty_u8)), + "i16" => Some(SignedInt(ast::ty_i16)), + "u16" => Some(UnsignedInt(ast::ty_u16)), + "i32" => Some(SignedInt(ast::ty_i32)), + "u32" => Some(UnsignedInt(ast::ty_u32)), + "i64" => Some(SignedInt(ast::ty_i64)), + "u64" => Some(UnsignedInt(ast::ty_u64)), + "int" => Some(SignedInt(ast::ty_i)), + "uint" => Some(UnsignedInt(ast::ty_u)), + _ => None + } +} + +#[deriving(Eq)] +pub enum ReprAttr { + ReprAny, + ReprInt(Span, IntType), + ReprExtern +} + +#[deriving(Eq)] +pub enum IntType { + SignedInt(ast::int_ty), + UnsignedInt(ast::uint_ty) +} + +impl IntType { + #[inline] + pub fn is_signed(self) -> bool { + match self { + SignedInt(*) => true, + UnsignedInt(*) => false + } + } +} |
