diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs index a0bb27d3280fe..5c9c10ec3bfd5 100644 --- a/src/comp/back/link.rs +++ b/src/comp/back/link.rs @@ -14,6 +14,7 @@ import std::sha1::sha1; import std::sort; import trans::crate_ctxt; import syntax::ast; +import syntax::print::pprust; import lib::llvm::llvm::ModuleRef; import lib::llvm::llvm::ValueRef; import lib::llvm::mk_pass_manager; @@ -294,16 +295,18 @@ fn build_link_meta(&session::session sess, &ast::crate c, auto linkage_metas = attr::find_linkage_metas(c.node.attrs); attr::require_unique_names(sess, linkage_metas); for (@ast::meta_item meta in linkage_metas) { - alt (meta.node) { - case (ast::meta_name_value("name", ?v)) { - name = some(v); + if (attr::get_meta_item_name(meta) == "name") { + alt (attr::get_meta_item_value_str(meta)) { + case (some(?v)) { name = some(v); } + case (none) { cmh_items += [meta]; } } - case (ast::meta_name_value("vers", ?v)) { - vers = some(v); - } - case (_) { - cmh_items += [meta]; + } else if (attr::get_meta_item_name(meta) == "vers") { + alt (attr::get_meta_item_value_str(meta)) { + case (some(?v)) { vers = some(v); } + case (none) { cmh_items += [meta]; } } + } else { + cmh_items += [meta]; } } ret rec(name = name, @@ -317,6 +320,10 @@ fn build_link_meta(&session::session sess, &ast::crate c, fn len_and_str(&str s) -> str { ret #fmt("%u_%s", str::byte_len(s), s); } + + fn len_and_str_lit(&ast::lit l) -> str { + ret len_and_str(pprust::lit_to_str(@l)); + } auto cmh_items = attr::sort_meta_items(metas.cmh_items); @@ -326,7 +333,7 @@ fn build_link_meta(&session::session sess, &ast::crate c, alt (m.node) { case (ast::meta_name_value(?key, ?value)) { sha.input_str(len_and_str(key)); - sha.input_str(len_and_str(value)); + sha.input_str(len_and_str_lit(value)); } case (ast::meta_word(?name)) { sha.input_str(len_and_str(name)); diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index ce422742b45a7..5f410678fdf49 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -48,7 +48,7 @@ fn default_configuration(session::session sess, str argv0, str input) -> case (_) { "libc.so" } }; - auto mk = attr::mk_name_value_item; + auto mk = attr::mk_name_value_item_str; ret [ // Target bindings. mk("target_os", std::os::target_os()), diff --git a/src/comp/front/attr.rs b/src/comp/front/attr.rs index acd24e8353ee4..37bcd0bb8b821 100644 --- a/src/comp/front/attr.rs +++ b/src/comp/front/attr.rs @@ -8,6 +8,7 @@ import syntax::ast; import util::common; import driver::session; +export attr_meta; export attr_metas; export find_linkage_metas; export find_attrs_by_name; @@ -17,6 +18,9 @@ export sort_meta_items; export remove_meta_items_by_name; export require_unique_names; export get_attr_name; +export get_meta_item_name; +export get_meta_item_value_str; +export mk_name_value_item_str; export mk_name_value_item; export mk_list_item; export mk_word_item; @@ -78,9 +82,25 @@ fn get_meta_item_name(&@ast::meta_item meta) -> ast::ident { } } +// Gets the string value if the meta_item is a meta_name_value variant +// containing a string, otherwise none +fn get_meta_item_value_str(&@ast::meta_item meta) -> option::t[str] { + alt (meta.node) { + case (ast::meta_name_value(_, ?v)) { + alt (v.node) { + case (ast::lit_str(?s, _)) { + option::some(s) + } + case (_) { option::none } + } + } + case (_) { option::none } + } +} + fn attr_meta(&ast::attribute attr) -> @ast::meta_item { @attr.node.value } -// Get the meta_items from inside an attribute +// Get the meta_items from inside a vector of attributes fn attr_metas(&vec[ast::attribute] attrs) -> vec[@ast::meta_item] { ret vec::map(attr_meta, attrs); } @@ -95,7 +115,9 @@ fn eq(@ast::meta_item a, @ast::meta_item b) -> bool { } case (ast::meta_name_value(?na, ?va)) { alt (b.node) { - case (ast::meta_name_value(?nb, ?vb)) { na == nb && va == vb } + case (ast::meta_name_value(?nb, ?vb)) { + na == nb && va.node == vb.node + } case (_) { false } } } @@ -188,7 +210,12 @@ fn span[T](&T item) -> ast::spanned[T] { ret rec(node=item, span=rec(lo=0u, hi=0u)); } -fn mk_name_value_item(ast::ident name, str value) -> @ast::meta_item { +fn mk_name_value_item_str(ast::ident name, str value) -> @ast::meta_item { + auto value_lit = span(ast::lit_str(value, ast::sk_rc)); + ret mk_name_value_item(name, value_lit); +} + +fn mk_name_value_item(ast::ident name, ast::lit value) -> @ast::meta_item { ret @span(ast::meta_name_value(name, value)); } diff --git a/src/comp/metadata/creader.rs b/src/comp/metadata/creader.rs index 308a59101d4c9..f2f9a358713b2 100644 --- a/src/comp/metadata/creader.rs +++ b/src/comp/metadata/creader.rs @@ -64,8 +64,8 @@ fn find_library_crate(&session::session sess, &ast::ident ident, auto name_items = attr::find_meta_items_by_name(metas, "name"); alt (vec::last(name_items)) { case (some(?i)) { - alt (i.node) { - case (ast::meta_name_value(_, ?v)) { v } + alt (attr::get_meta_item_value_str(i)) { + case (some(?n)) { n } case (_) { // FIXME: Probably want a warning here since the user // is using the wrong type of meta item @@ -180,17 +180,13 @@ fn visit_item(env e, &@ast::item i) { if (!e.sess.add_used_library(m.native_name)) { ret; } - for (ast::attribute a in i.attrs) { - auto v = a.node.value.node; - alt (v) { - case (ast::meta_name_value(?i, ?s)) { - if (i != "link_args") { - cont; - } - e.sess.add_used_link_args(s); - } - case (_) { + for (ast::attribute a in + attr::find_attrs_by_name(i.attrs, "link_args")) { + alt (attr::get_meta_item_value_str(attr::attr_meta(a))) { + case (some(?linkarg)) { + e.sess.add_used_link_args(linkarg); } + case (none) { /* fallthrough */ } } } } diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index 14d4035185f0b..7bcb9e48bf863 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -276,7 +276,9 @@ fn get_meta_items(&ebml::doc md) -> vec[@ast::meta_item] { auto vd = ebml::get_doc(meta_item_doc, tag_meta_item_value); auto n = str::unsafe_from_bytes(ebml::doc_data(nd)); auto v = str::unsafe_from_bytes(ebml::doc_data(vd)); - items += [attr::mk_name_value_item(n, v)]; + // FIXME (#611): Should be able to decode meta_name_value variants, + // but currently they can't be encoded + items += [attr::mk_name_value_item_str(n, v)]; } for each (ebml::doc meta_item_doc in ebml::tagged_docs(md, tag_meta_item_list)) { diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index 4526e515f7987..cc3d44399c8b9 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -429,14 +429,19 @@ fn encode_meta_item(&ebml::writer ebml_w, &meta_item mi) { ebml::end_tag(ebml_w); } case (meta_name_value(?name, ?value)) { - ebml::start_tag(ebml_w, tag_meta_item_name_value); - ebml::start_tag(ebml_w, tag_meta_item_name); - ebml_w.writer.write(str::bytes(name)); - ebml::end_tag(ebml_w); - ebml::start_tag(ebml_w, tag_meta_item_value); - ebml_w.writer.write(str::bytes(value)); - ebml::end_tag(ebml_w); - ebml::end_tag(ebml_w); + alt (value.node) { + case (lit_str(?value, _)) { + ebml::start_tag(ebml_w, tag_meta_item_name_value); + ebml::start_tag(ebml_w, tag_meta_item_name); + ebml_w.writer.write(str::bytes(name)); + ebml::end_tag(ebml_w); + ebml::start_tag(ebml_w, tag_meta_item_value); + ebml_w.writer.write(str::bytes(value)); + ebml::end_tag(ebml_w); + ebml::end_tag(ebml_w); + } + case (_) { /* FIXME (#611) */ } + } } case (meta_list(?name, ?items)) { ebml::start_tag(ebml_w, tag_meta_item_list); @@ -475,10 +480,10 @@ fn synthesize_crate_attrs(&@crate_ctxt cx, assert cx.link_meta.name != ""; assert cx.link_meta.vers != ""; - auto name_item = attr::mk_name_value_item("name", - cx.link_meta.name); - auto vers_item = attr::mk_name_value_item("vers", - cx.link_meta.vers); + auto name_item = attr::mk_name_value_item_str("name", + cx.link_meta.name); + auto vers_item = attr::mk_name_value_item_str("vers", + cx.link_meta.vers); auto other_items = { auto tmp = attr::remove_meta_items_by_name(items, "name"); diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 7d1bb124c4e53..5f8e301d6e201 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -104,7 +104,7 @@ type meta_item = spanned[meta_item_]; tag meta_item_ { meta_word(ident); meta_list(ident, vec[@meta_item]); - meta_name_value(ident, str); + meta_name_value(ident, lit); } type block = spanned[block_]; diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index e852fdcb0af92..b671e9eaa69be 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -2172,17 +2172,9 @@ fn parse_meta_item(&parser p) -> @ast::meta_item { alt (p.peek()) { case (token::EQ) { p.bump(); - alt (p.peek()) { - case (token::LIT_STR(?s)) { - p.bump(); - auto value = p.get_str(s); - auto hi = p.get_hi_pos(); - ret @spanned(lo, hi, ast::meta_name_value(ident, value)); - } - case (_) { - p.fatal("Metadata items must be string literals"); - } - } + auto lit = parse_lit(p); + auto hi = p.get_hi_pos(); + ret @spanned(lo, hi, ast::meta_name_value(ident, lit)); } case (token::LPAREN) { auto inner_items = parse_meta_seq(p); diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index e69c089323edd..b5f83c2009c7a 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -1103,7 +1103,7 @@ fn print_meta_item(&ps s, &@ast::meta_item item) { case (ast::meta_name_value(?name, ?value)) { word_space(s, name); word_space(s, "="); - print_string(s, value); + print_literal(s, @value); } case (ast::meta_list(?name, ?items)) { word(s.s, name); diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index c66a41e8d0be7..be43623d8a831 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -204,6 +204,20 @@ mod test_native_items { } } +mod test_literals { + #[str = "s"]; + #[char = 'c']; + #[int = 100]; + #[uint = 100u]; + #[mach_int = 100u32]; + #[float = 1.0]; + #[mach_float = 1.0f32]; + // FIXME (#622): Can't parse a nil literal here + //#[nil = ()]; + #[bool = true]; + mod m {} +} + fn main() { }