diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index 8a58a4ce319..b7751fc2303 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -328,6 +328,10 @@ fn list_crate_attributes(&ebml::doc md, io::writer out) { out.write_str("\n\n"); } +fn get_crate_attributes(&vec[u8] data) -> vec[ast::attribute] { + ret get_attributes(ebml::new_doc(data)); +} + fn list_crate_items(vec[u8] bytes, &ebml::doc md, io::writer out) { out.write_str("=Items=\n"); auto paths = ebml::get_doc(md, tag_paths); diff --git a/src/comp/middle/attr.rs b/src/comp/middle/attr.rs new file mode 100644 index 00000000000..45b0ccb7026 --- /dev/null +++ b/src/comp/middle/attr.rs @@ -0,0 +1,74 @@ +import std::vec; +import std::option; +import front::ast; + +export get_linkage_metas; +export find_attrs_by_name; + +// From a list of crate attributes get only the meta_items that impact crate +// linkage +fn find_linkage_metas(vec[ast::attribute] attrs) -> vec[@ast::meta_item] { + let vec[@ast::meta_item] metas = []; + for (ast::attribute attr in find_attrs_by_name(attrs, "link")) { + alt (attr.node.value.node) { + case (ast::meta_list(_, ?items)) { + metas += items; + } + case (_) { + // FIXME: Maybe need a warning that this attr isn't + // being used for linkage + } + } + } + ret metas; +} + +// Search a list of attributes and return only those with a specific name +fn find_attrs_by_name(vec[ast::attribute] attrs, + ast::ident name) -> vec[ast::attribute] { + auto filter = bind fn(&ast::attribute a, + ast::ident name) -> option::t[ast::attribute] { + if (get_attr_name(a) == name) { + option::some(a) + } else { + option::none + } + } (_, name); + ret vec::filter_map(filter, attrs); +} + +fn get_attr_name(&ast::attribute attr) -> ast::ident { + get_meta_item_name(@attr.node.value) +} + +fn find_meta_items_by_name(vec[@ast::meta_item] metas, + ast::ident name) -> vec[@ast::meta_item] { + auto filter = bind fn(&@ast::meta_item m, + ast::ident name) -> option::t[@ast::meta_item] { + if (get_meta_item_name(m) == name) { + option::some(m) + } else { + option::none + } + } (_, name); + ret vec::filter_map(filter, metas); +} + +fn get_meta_item_name(&@ast::meta_item meta) -> ast::ident { + alt (meta.node) { + case (ast::meta_word(?n)) { n } + case (ast::meta_name_value(?n, _)) { n } + case (ast::meta_list(?n, _)) { n } + } +} + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index ac64e7068f2..75af89639ca 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -14,6 +14,7 @@ use std (name = "std", url = "http://rust-lang.org/src/std"); mod middle { + mod attr; mod trans; mod ty; mod walk; diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs deleted file mode 100644 index bb8f068874c..00000000000 --- a/src/test/run-pass/item-attributes.rs +++ /dev/null @@ -1,201 +0,0 @@ -// xfail-stage0 - -// These are attributes of the implicit crate. Really this just needs to parse -// for completeness since .rs files linked from .rc files support this -// notation to specify their module's attributes -#[attr1 = "val"]; -#[attr2 = "val"]; -#[attr3]; -#[attr4(attr5)]; - -// These are are attributes of the following mod -#[attr1 = "val"] -#[attr2 = "val"] -mod test_first_item_in_file_mod { -} - -mod test_single_attr_outer { - - #[attr = "val"] - const int x = 10; - - #[attr = "val"] - fn f() {} - - #[attr = "val"] - mod mod1 { - } - - #[attr = "val"] - native "rust" mod rustrt { } - - #[attr = "val"] - type t = obj { }; - - - #[attr = "val"] - obj o() { } -} - -mod test_multi_attr_outer { - - #[attr1 = "val"] - #[attr2 = "val"] - const int x = 10; - - #[attr1 = "val"] - #[attr2 = "val"] - fn f() {} - - #[attr1 = "val"] - #[attr2 = "val"] - mod mod1 { - } - - #[attr1 = "val"] - #[attr2 = "val"] - native "rust" mod rustrt { } - - #[attr1 = "val"] - #[attr2 = "val"] - type t = obj { }; - - - #[attr1 = "val"] - #[attr2 = "val"] - obj o() { } -} - -mod test_stmt_single_attr_outer { - - fn f() { - - #[attr = "val"] - const int x = 10; - - #[attr = "val"] - fn f() {} - - /* FIXME: Issue #493 - #[attr = "val"] - mod mod1 { - } - - #[attr = "val"] - native "rust" mod rustrt { - } - */ - - #[attr = "val"] - type t = obj { }; - - #[attr = "val"] - obj o() { } - - } -} - -mod test_stmt_multi_attr_outer { - - fn f() { - - #[attr1 = "val"] - #[attr2 = "val"] - const int x = 10; - - #[attr1 = "val"] - #[attr2 = "val"] - fn f() {} - - /* FIXME: Issue #493 - #[attr1 = "val"] - #[attr2 = "val"] - mod mod1 { - } - - #[attr1 = "val"] - #[attr2 = "val"] - native "rust" mod rustrt { - } - */ - - #[attr1 = "val"] - #[attr2 = "val"] - type t = obj { }; - - #[attr1 = "val"] - #[attr2 = "val"] - obj o() { } - - } -} - -mod test_attr_inner { - - mod m { - // This is an attribute of mod m - #[attr = "val"]; - } -} - -mod test_attr_inner_then_outer { - - mod m { - // This is an attribute of mod m - #[attr = "val"]; - // This is an attribute of fn f - #[attr = "val"] - fn f() { - } - } -} - -mod test_attr_inner_then_outer_multi { - mod m { - // This is an attribute of mod m - #[attr1 = "val"]; - #[attr2 = "val"]; - // This is an attribute of fn f - #[attr1 = "val"] - #[attr2 = "val"] - fn f() { - } - } -} - -mod test_distinguish_syntax_ext { - - use std; - - fn f() { - #fmt("test%s", "s"); - #[attr = "val"] - fn g() { - } - } -} - -mod test_other_forms { - #[attr] - #[attr(word)] - #[attr(attr(word))] - #[attr(key1 = "val", - key2 = "val", - attr)] - fn f() { - } -} - -fn main() { -} - -// -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: -//