]> git.proxmox.com Git - rustc.git/blame - src/librustc_passes/weak_lang_items.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_passes / weak_lang_items.rs
CommitLineData
74b04a01
XL
1//! Validity checking for weak lang items
2
74b04a01
XL
3use rustc_data_structures::fx::FxHashSet;
4use rustc_errors::struct_span_err;
5use rustc_hir as hir;
6use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
3dfed10e 7use rustc_hir::lang_items::{self, LangItem};
74b04a01 8use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
f035d41b 9use rustc_middle::middle::lang_items::required;
ba9703b0 10use rustc_middle::ty::TyCtxt;
f9f354fc 11use rustc_session::config::CrateType;
74b04a01
XL
12use rustc_span::symbol::Symbol;
13use rustc_span::Span;
14
15struct Context<'a, 'tcx> {
16 tcx: TyCtxt<'tcx>,
17 items: &'a mut lang_items::LanguageItems,
18}
19
20/// Checks the crate for usage of weak lang items, returning a vector of all the
21/// language items required by this crate, but not defined yet.
22pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItems) {
23 // These are never called by user code, they're generated by the compiler.
24 // They will never implicitly be added to the `missing` array unless we do
25 // so here.
26 if items.eh_personality().is_none() {
3dfed10e 27 items.missing.push(LangItem::EhPersonality);
74b04a01 28 }
74b04a01
XL
29
30 {
31 let mut cx = Context { tcx, items };
32 tcx.hir().krate().visit_all_item_likes(&mut cx.as_deep_visitor());
33 }
34 verify(tcx, items);
35}
36
37fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
38 // We only need to check for the presence of weak lang items if we're
39 // emitting something that's not an rlib.
f9f354fc
XL
40 let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind {
41 CrateType::Dylib
42 | CrateType::ProcMacro
43 | CrateType::Cdylib
44 | CrateType::Executable
45 | CrateType::Staticlib => true,
46 CrateType::Rlib => false,
74b04a01
XL
47 });
48 if !needs_check {
49 return;
50 }
51
52 let mut missing = FxHashSet::default();
53 for &cnum in tcx.crates().iter() {
54 for &item in tcx.missing_lang_items(cnum).iter() {
55 missing.insert(item);
56 }
57 }
58
59 for (name, &item) in WEAK_ITEMS_REFS.iter() {
f035d41b 60 if missing.contains(&item) && required(tcx, item) && items.require(item).is_err() {
3dfed10e 61 if item == LangItem::PanicImpl {
74b04a01 62 tcx.sess.err("`#[panic_handler]` function required, but not found");
3dfed10e 63 } else if item == LangItem::Oom {
74b04a01
XL
64 tcx.sess.err("`#[alloc_error_handler]` function required, but not found");
65 } else {
66 tcx.sess.err(&format!("language item required, but not found: `{}`", name));
67 }
68 }
69 }
70}
71
72impl<'a, 'tcx> Context<'a, 'tcx> {
3dfed10e 73 fn register(&mut self, name: Symbol, span: Span) {
74b04a01
XL
74 if let Some(&item) = WEAK_ITEMS_REFS.get(&name) {
75 if self.items.require(item).is_err() {
76 self.items.missing.push(item);
77 }
78 } else {
79 struct_span_err!(self.tcx.sess, span, E0264, "unknown external lang item: `{}`", name)
80 .emit();
81 }
82 }
83}
84
85impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
ba9703b0 86 type Map = intravisit::ErasedMap<'v>;
74b04a01 87
ba9703b0 88 fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
74b04a01
XL
89 NestedVisitorMap::None
90 }
91
92 fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
3dfed10e
XL
93 let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
94 if let Some((lang_item, _)) = lang_items::extract(check_name, &i.attrs) {
95 self.register(lang_item, i.span);
74b04a01
XL
96 }
97 intravisit::walk_foreign_item(self, i)
98 }
99}