@@ -20,6 +20,7 @@ use metadata::cstore::{CStore, CrateSource, MetadataBlob};
20
20
use metadata:: decoder;
21
21
use metadata:: loader;
22
22
use metadata:: loader:: CratePaths ;
23
+ use util:: nodemap:: FnvHashMap ;
23
24
24
25
use std:: cell:: RefCell ;
25
26
use std:: path:: PathBuf ;
@@ -40,6 +41,7 @@ use log;
40
41
pub struct CrateReader < ' a > {
41
42
sess : & ' a Session ,
42
43
next_crate_num : ast:: CrateNum ,
44
+ foreign_item_map : FnvHashMap < String , Vec < ast:: NodeId > > ,
43
45
}
44
46
45
47
impl < ' a , ' v > visit:: Visitor < ' v > for CrateReader < ' a > {
@@ -150,6 +152,7 @@ impl<'a> CrateReader<'a> {
150
152
CrateReader {
151
153
sess : sess,
152
154
next_crate_num : sess. cstore . next_crate_num ( ) ,
155
+ foreign_item_map : FnvHashMap ( ) ,
153
156
}
154
157
}
155
158
@@ -167,6 +170,7 @@ impl<'a> CrateReader<'a> {
167
170
for & ( ref name, kind) in & self . sess . opts . libs {
168
171
register_native_lib ( self . sess , None , name. clone ( ) , kind) ;
169
172
}
173
+ self . register_statically_included_foreign_items ( ) ;
170
174
}
171
175
172
176
fn process_crate ( & self , c : & ast:: Crate ) {
@@ -223,80 +227,65 @@ impl<'a> CrateReader<'a> {
223
227
None => ( )
224
228
}
225
229
}
226
- ast:: ItemForeignMod ( ref fm) => {
227
- if fm . abi == abi :: Rust || fm . abi == abi :: RustIntrinsic {
228
- return ;
229
- }
230
+ ast:: ItemForeignMod ( ref fm) => self . process_foreign_mod ( i , fm ) ,
231
+ _ => { }
232
+ }
233
+ }
230
234
231
- // First, add all of the custom link_args attributes
232
- let link_args = i. attrs . iter ( )
233
- . filter_map ( |at| if at. name ( ) == "link_args" {
234
- Some ( at)
235
- } else {
236
- None
237
- } )
238
- . collect :: < Vec < & ast:: Attribute > > ( ) ;
239
- for m in & link_args {
240
- match m. value_str ( ) {
241
- Some ( linkarg) => self . sess . cstore . add_used_link_args ( & linkarg) ,
242
- None => { /* fallthrough */ }
243
- }
244
- }
235
+ fn process_foreign_mod ( & mut self , i : & ast:: Item , fm : & ast:: ForeignMod ) {
236
+ if fm. abi == abi:: Rust || fm. abi == abi:: RustIntrinsic {
237
+ return ;
238
+ }
245
239
246
- // Next, process all of the #[link(..)]-style arguments
247
- let link_args = i. attrs . iter ( )
248
- . filter_map ( |at| if at. name ( ) == "link" {
249
- Some ( at)
250
- } else {
251
- None
252
- } )
253
- . collect :: < Vec < & ast:: Attribute > > ( ) ;
254
- for m in & link_args {
255
- match m. meta_item_list ( ) {
256
- Some ( items) => {
257
- let kind = items. iter ( ) . find ( |k| {
258
- k. name ( ) == "kind"
259
- } ) . and_then ( |a| a. value_str ( ) ) ;
260
- let kind = match kind {
261
- Some ( k) => {
262
- if k == "static" {
263
- cstore:: NativeStatic
264
- } else if self . sess . target . target . options . is_like_osx
265
- && k == "framework" {
266
- cstore:: NativeFramework
267
- } else if k == "framework" {
268
- cstore:: NativeFramework
269
- } else if k == "dylib" {
270
- cstore:: NativeUnknown
271
- } else {
272
- self . sess . span_err ( m. span ,
273
- & format ! ( "unknown kind: `{}`" ,
274
- k) ) ;
275
- cstore:: NativeUnknown
276
- }
277
- }
278
- None => cstore:: NativeUnknown
279
- } ;
280
- let n = items. iter ( ) . find ( |n| {
281
- n. name ( ) == "name"
282
- } ) . and_then ( |a| a. value_str ( ) ) ;
283
- let n = match n {
284
- Some ( n) => n,
285
- None => {
286
- self . sess . span_err ( m. span ,
287
- "#[link(...)] specified without \
288
- `name = \" foo\" `") ;
289
- InternedString :: new ( "foo" )
290
- }
291
- } ;
292
- register_native_lib ( self . sess , Some ( m. span ) ,
293
- n. to_string ( ) , kind) ;
294
- }
295
- None => { }
296
- }
297
- }
240
+ // First, add all of the custom #[link_args] attributes
241
+ for m in i. attrs . iter ( ) . filter ( |a| a. check_name ( "link_args" ) ) {
242
+ if let Some ( linkarg) = m. value_str ( ) {
243
+ self . sess . cstore . add_used_link_args ( & linkarg) ;
298
244
}
299
- _ => { }
245
+ }
246
+
247
+ // Next, process all of the #[link(..)]-style arguments
248
+ for m in i. attrs . iter ( ) . filter ( |a| a. check_name ( "link" ) ) {
249
+ let items = match m. meta_item_list ( ) {
250
+ Some ( item) => item,
251
+ None => continue ,
252
+ } ;
253
+ let kind = items. iter ( ) . find ( |k| {
254
+ k. check_name ( "kind" )
255
+ } ) . and_then ( |a| a. value_str ( ) ) ;
256
+ let kind = match kind. as_ref ( ) . map ( |s| & s[ ..] ) {
257
+ Some ( "static" ) => cstore:: NativeStatic ,
258
+ Some ( "dylib" ) => cstore:: NativeUnknown ,
259
+ Some ( "framework" ) => cstore:: NativeFramework ,
260
+ Some ( k) => {
261
+ self . sess . span_err ( m. span , & format ! ( "unknown kind: `{}`" , k) ) ;
262
+ cstore:: NativeUnknown
263
+ }
264
+ None => cstore:: NativeUnknown
265
+ } ;
266
+ let n = items. iter ( ) . find ( |n| {
267
+ n. check_name ( "name" )
268
+ } ) . and_then ( |a| a. value_str ( ) ) ;
269
+ let n = match n {
270
+ Some ( n) => n,
271
+ None => {
272
+ self . sess . span_err ( m. span , "#[link(...)] specified without \
273
+ `name = \" foo\" `") ;
274
+ InternedString :: new ( "foo" )
275
+ }
276
+ } ;
277
+ register_native_lib ( self . sess , Some ( m. span ) , n. to_string ( ) , kind) ;
278
+ }
279
+
280
+ // Finally, process the #[linked_from = "..."] attribute
281
+ for m in i. attrs . iter ( ) . filter ( |a| a. check_name ( "linked_from" ) ) {
282
+ let lib_name = match m. value_str ( ) {
283
+ Some ( name) => name,
284
+ None => continue ,
285
+ } ;
286
+ let list = self . foreign_item_map . entry ( lib_name. to_string ( ) )
287
+ . or_insert ( Vec :: new ( ) ) ;
288
+ list. extend ( fm. items . iter ( ) . map ( |it| it. id ) ) ;
300
289
}
301
290
}
302
291
@@ -592,6 +581,20 @@ impl<'a> CrateReader<'a> {
592
581
_ => None ,
593
582
}
594
583
}
584
+
585
+ fn register_statically_included_foreign_items ( & mut self ) {
586
+ let libs = self . sess . cstore . get_used_libraries ( ) ;
587
+ for ( lib, list) in self . foreign_item_map . iter ( ) {
588
+ let is_static = libs. borrow ( ) . iter ( ) . any ( |& ( ref name, kind) | {
589
+ lib == name && kind == cstore:: NativeStatic
590
+ } ) ;
591
+ if is_static {
592
+ for id in list {
593
+ self . sess . cstore . add_statically_included_foreign_item ( * id) ;
594
+ }
595
+ }
596
+ }
597
+ }
595
598
}
596
599
597
600
/// Imports the codemap from an external crate into the codemap of the crate
0 commit comments