about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-07-05 11:46:02 -0700
committerBrian Anderson <banderson@mozilla.com>2011-07-05 11:46:02 -0700
commit6f8bc404f8ceea0b8981ae2afd5d4414d7a26004 (patch)
treea8d40b3fb3967f6551bdb9dbb0304ad4d3286512
parent4349eaed8417a39eb54ea952ce86c7c585be6e90 (diff)
Error if the link attribute has duplicate items. Issue #614
-rw-r--r--src/comp/back/link.rs12
-rw-r--r--src/comp/front/attr.rs16
-rw-r--r--src/test/compile-fail/dup-link-name.rs7
3 files changed, 29 insertions, 6 deletions
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index 47168a3dd8c..12ada918edb 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -286,19 +286,19 @@ fn build_link_meta(&session::session sess, &ast::crate c,
                               option::t[str] vers,
                               vec[@ast::meta_item] cmh_items);
 
-    fn provided_link_metas(&ast::crate c) -> provided_metas {
+    fn provided_link_metas(&session::session sess,
+                           &ast::crate c) -> provided_metas {
         let option::t[str] name = none;
         let option::t[str] vers = none;
         let vec[@ast::meta_item] cmh_items = [];
-        for (@ast::meta_item meta in
-                 attr::find_linkage_metas(c.node.attrs)) {
+        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)) {
-                    // FIXME: Should probably warn about duplicate name items
                     name = some(v);
                 }
                 case (ast::meta_name_value("vers", ?v)) {
-                    // FIXME: Should probably warn about duplicate value items
                     vers = some(v);
                 }
                 case (_) {
@@ -361,7 +361,7 @@ fn build_link_meta(&session::session sess, &ast::crate c,
         };
     }
 
-    auto provided_metas = provided_link_metas(c);
+    auto provided_metas = provided_link_metas(sess, c);
     auto name = crate_meta_name(sess, c, output, provided_metas);
     auto vers = crate_meta_vers(sess, c, provided_metas);
     auto extras_hash = crate_meta_extras_hash(sha, c, provided_metas);
diff --git a/src/comp/front/attr.rs b/src/comp/front/attr.rs
index 00e64e33f6b..acd24e8353e 100644
--- a/src/comp/front/attr.rs
+++ b/src/comp/front/attr.rs
@@ -1,9 +1,12 @@
 // Functions dealing with attributes and meta_items
 
 import std::vec;
+import std::str;
+import std::map;
 import std::option;
 import syntax::ast;
 import util::common;
+import driver::session;
 
 export attr_metas;
 export find_linkage_metas;
@@ -12,6 +15,7 @@ export find_meta_items_by_name;
 export contains;
 export sort_meta_items;
 export remove_meta_items_by_name;
+export require_unique_names;
 export get_attr_name;
 export mk_name_value_item;
 export mk_list_item;
@@ -168,6 +172,18 @@ fn remove_meta_items_by_name(&vec[@ast::meta_item] items,
     ret vec::filter_map(filter, items);
 }
 
+fn require_unique_names(&session::session sess, &vec[@ast::meta_item] metas) {
+    auto map = map::mk_hashmap[str, ()](str::hash, str::eq);
+    for (@ast::meta_item meta in metas) {
+        auto name = get_meta_item_name(meta);
+        if (map.contains_key(name)) {
+            sess.span_fatal(meta.span, 
+                            #fmt("duplicate meta item `%s`", name));
+        }
+        map.insert(name, ());
+    }
+}
+
 fn span[T](&T item) -> ast::spanned[T] {
     ret rec(node=item, span=rec(lo=0u, hi=0u));
 }
diff --git a/src/test/compile-fail/dup-link-name.rs b/src/test/compile-fail/dup-link-name.rs
new file mode 100644
index 00000000000..7ef6314edb3
--- /dev/null
+++ b/src/test/compile-fail/dup-link-name.rs
@@ -0,0 +1,7 @@
+// xfail-stage0
+// error-pattern:duplicate meta item `name`
+
+#[link(name = "test",
+       name)];
+
+fn main() {}
\ No newline at end of file