]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Validity checking for weak lang items | |
12 | ||
13 | use session::config; | |
14 | use session::Session; | |
92a42be0 | 15 | use middle::cstore::CrateStore; |
1a4d82fc JJ |
16 | use middle::lang_items; |
17 | ||
b039eaaf | 18 | use syntax::ast; |
1a4d82fc JJ |
19 | use syntax::codemap::Span; |
20 | use syntax::parse::token::InternedString; | |
54a0048b SL |
21 | use hir::intravisit::Visitor; |
22 | use hir::intravisit; | |
23 | use hir; | |
1a4d82fc JJ |
24 | |
25 | use std::collections::HashSet; | |
26 | ||
27 | macro_rules! weak_lang_items { | |
28 | ($($name:ident, $item:ident, $sym:ident;)*) => ( | |
29 | ||
30 | struct Context<'a> { | |
31 | sess: &'a Session, | |
32 | items: &'a mut lang_items::LanguageItems, | |
33 | } | |
34 | ||
35 | /// Checks the crate for usage of weak lang items, returning a vector of all the | |
36 | /// language items required by this crate, but not defined yet. | |
e9174d1e | 37 | pub fn check_crate(krate: &hir::Crate, |
1a4d82fc JJ |
38 | sess: &Session, |
39 | items: &mut lang_items::LanguageItems) { | |
40 | // These are never called by user code, they're generated by the compiler. | |
41 | // They will never implicitly be added to the `missing` array unless we do | |
42 | // so here. | |
1a4d82fc JJ |
43 | if items.eh_personality().is_none() { |
44 | items.missing.push(lang_items::EhPersonalityLangItem); | |
45 | } | |
c1a9b12d SL |
46 | if sess.target.target.options.custom_unwind_resume & |
47 | items.eh_unwind_resume().is_none() { | |
48 | items.missing.push(lang_items::EhUnwindResumeLangItem); | |
49 | } | |
1a4d82fc JJ |
50 | |
51 | { | |
52 | let mut cx = Context { sess: sess, items: items }; | |
92a42be0 | 53 | krate.visit_all_items(&mut cx); |
1a4d82fc JJ |
54 | } |
55 | verify(sess, items); | |
56 | } | |
57 | ||
b039eaaf | 58 | pub fn link_name(attrs: &[ast::Attribute]) -> Option<InternedString> { |
1a4d82fc | 59 | lang_items::extract(attrs).and_then(|name| { |
85aaf69f | 60 | $(if &name[..] == stringify!($name) { |
1a4d82fc JJ |
61 | Some(InternedString::new(stringify!($sym))) |
62 | } else)* { | |
63 | None | |
64 | } | |
65 | }) | |
66 | } | |
67 | ||
68 | fn verify(sess: &Session, items: &lang_items::LanguageItems) { | |
69 | // We only need to check for the presence of weak lang items if we're | |
70 | // emitting something that's not an rlib. | |
71 | let needs_check = sess.crate_types.borrow().iter().any(|kind| { | |
72 | match *kind { | |
73 | config::CrateTypeDylib | | |
74 | config::CrateTypeExecutable | | |
75 | config::CrateTypeStaticlib => true, | |
76 | config::CrateTypeRlib => false, | |
77 | } | |
78 | }); | |
79 | if !needs_check { return } | |
80 | ||
81 | let mut missing = HashSet::new(); | |
92a42be0 SL |
82 | for cnum in sess.cstore.crates() { |
83 | for item in sess.cstore.missing_lang_items(cnum) { | |
84 | missing.insert(item); | |
1a4d82fc | 85 | } |
92a42be0 | 86 | } |
1a4d82fc JJ |
87 | |
88 | $( | |
89 | if missing.contains(&lang_items::$item) && items.$name().is_none() { | |
85aaf69f SL |
90 | sess.err(&format!("language item required, but not found: `{}`", |
91 | stringify!($name))); | |
1a4d82fc JJ |
92 | |
93 | } | |
94 | )* | |
95 | } | |
96 | ||
97 | impl<'a> Context<'a> { | |
98 | fn register(&mut self, name: &str, span: Span) { | |
99 | $(if name == stringify!($name) { | |
100 | if self.items.$name().is_none() { | |
101 | self.items.missing.push(lang_items::$item); | |
102 | } | |
103 | } else)* { | |
85aaf69f | 104 | span_err!(self.sess, span, E0264, |
92a42be0 SL |
105 | "unknown external lang item: `{}`", |
106 | name); | |
1a4d82fc JJ |
107 | } |
108 | } | |
109 | } | |
110 | ||
111 | impl<'a, 'v> Visitor<'v> for Context<'a> { | |
e9174d1e | 112 | fn visit_foreign_item(&mut self, i: &hir::ForeignItem) { |
85aaf69f | 113 | match lang_items::extract(&i.attrs) { |
1a4d82fc | 114 | None => {} |
85aaf69f | 115 | Some(lang_item) => self.register(&lang_item, i.span), |
1a4d82fc | 116 | } |
92a42be0 | 117 | intravisit::walk_foreign_item(self, i) |
1a4d82fc JJ |
118 | } |
119 | } | |
120 | ||
121 | ) } | |
122 | ||
123 | weak_lang_items! { | |
c1a9b12d | 124 | panic_fmt, PanicFmtLangItem, rust_begin_unwind; |
1a4d82fc | 125 | eh_personality, EhPersonalityLangItem, rust_eh_personality; |
c1a9b12d | 126 | eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; |
1a4d82fc | 127 | } |