@@ -519,52 +519,53 @@ impl TypedAstContext {
519
519
}
520
520
}
521
521
522
- pub fn prune_unused_decls ( & mut self ) {
522
+ pub fn prune_unwanted_decls ( & mut self , want_unused_functions : bool ) {
523
523
// Starting from a set of root declarations, walk each one to find declarations it
524
524
// depends on. Then walk each of those, recursively.
525
525
526
- // Declarations we still need to walk. Everything in here is also in `used `.
526
+ // Declarations we still need to walk. Everything in here is also in `wanted `.
527
527
let mut to_walk: Vec < CDeclId > = Vec :: new ( ) ;
528
528
// Declarations accessible from a root.
529
- let mut used : HashSet < CDeclId > = HashSet :: new ( ) ;
529
+ let mut wanted : HashSet < CDeclId > = HashSet :: new ( ) ;
530
530
531
- // Mark all the roots as used . Roots are all top-level functions and variables that might
531
+ // Mark all the roots as wanted . Roots are all top-level functions and variables that might
532
532
// be visible from another compilation unit.
533
+ //
534
+ // In addition, mark any other (unused) function wanted if configured.
533
535
for & decl_id in & self . c_decls_top {
534
536
let decl = self . index ( decl_id) ;
535
- match decl. kind {
537
+ let is_wanted = match decl. kind {
536
538
CDeclKind :: Function {
537
539
body : Some ( _) ,
538
540
is_global : true ,
539
541
is_inline,
540
542
is_inline_externally_visible,
541
543
..
542
- } if !is_inline || is_inline_externally_visible => {
543
544
// Depending on the C specification and dialect, an inlined function
544
545
// may be externally visible. We rely on clang to determine visibility.
545
- to_walk. push ( decl_id) ;
546
- used. insert ( decl_id) ;
547
- }
546
+ } if !is_inline || is_inline_externally_visible => true ,
547
+ CDeclKind :: Function {
548
+ body : Some ( _) ,
549
+ ..
550
+ } if want_unused_functions => true ,
548
551
CDeclKind :: Variable {
549
552
is_defn : true ,
550
553
is_externally_visible : true ,
551
554
..
552
- } => {
553
- to_walk. push ( decl_id) ;
554
- used. insert ( decl_id) ;
555
- }
555
+ } => true ,
556
556
CDeclKind :: Variable { ref attrs, .. } | CDeclKind :: Function { ref attrs, .. }
557
- if attrs. contains ( & Attribute :: Used ) =>
558
- {
559
- to_walk. push ( decl_id) ;
560
- used. insert ( decl_id) ;
561
- }
562
- _ => { }
557
+ if attrs. contains ( & Attribute :: Used ) => true ,
558
+ _ => false ,
559
+ } ;
560
+
561
+ if is_wanted {
562
+ to_walk. push ( decl_id) ;
563
+ wanted. insert ( decl_id) ;
563
564
}
564
565
}
565
566
566
- // Add all referenced macros to the set of used decls
567
- // used .extend(self.macro_expansions.values().flatten());
567
+ // Add all referenced macros to the set of wanted decls
568
+ // wanted .extend(self.macro_expansions.values().flatten());
568
569
569
570
while let Some ( enclosing_decl_id) = to_walk. pop ( ) {
570
571
for some_id in DFNodes :: new ( self , SomeId :: Decl ( enclosing_decl_id) ) {
@@ -573,13 +574,13 @@ impl TypedAstContext {
573
574
match self . c_types [ & type_id] . kind {
574
575
// This is a reference to a previously declared type. If we look
575
576
// through it we should(?) get something that looks like a declaration,
576
- // which we can mark as used .
577
+ // which we can mark as wanted .
577
578
CTypeKind :: Elaborated ( decl_type_id) => {
578
579
let decl_id = self . c_types [ & decl_type_id]
579
580
. kind
580
581
. as_decl_or_typedef ( )
581
582
. expect ( "target of CTypeKind::Elaborated isn't a decl?" ) ;
582
- if used . insert ( decl_id) {
583
+ if wanted . insert ( decl_id) {
583
584
to_walk. push ( decl_id) ;
584
585
}
585
586
}
@@ -594,20 +595,20 @@ impl TypedAstContext {
594
595
let expr = self . index ( expr_id) ;
595
596
if let Some ( macs) = self . macro_invocations . get ( & expr_id) {
596
597
for mac_id in macs {
597
- if used . insert ( * mac_id) {
598
+ if wanted . insert ( * mac_id) {
598
599
to_walk. push ( * mac_id) ;
599
600
}
600
601
}
601
602
}
602
603
if let CExprKind :: DeclRef ( _, decl_id, _) = & expr. kind {
603
- if used . insert ( * decl_id) {
604
+ if wanted . insert ( * decl_id) {
604
605
to_walk. push ( * decl_id) ;
605
606
}
606
607
}
607
608
}
608
609
609
610
SomeId :: Decl ( decl_id) => {
610
- if used . insert ( decl_id) {
611
+ if wanted . insert ( decl_id) {
611
612
to_walk. push ( decl_id) ;
612
613
}
613
614
@@ -616,7 +617,7 @@ impl TypedAstContext {
616
617
// Special case for enums. The enum constant is used, so the whole
617
618
// enum is also used.
618
619
let parent_id = self . parents [ & decl_id] ;
619
- if used . insert ( parent_id) {
620
+ if wanted . insert ( parent_id) {
620
621
to_walk. push ( parent_id) ;
621
622
}
622
623
}
@@ -633,17 +634,17 @@ impl TypedAstContext {
633
634
634
635
// Unset c_main if we are not retaining its declaration
635
636
if let Some ( main_id) = self . c_main {
636
- if !used . contains ( & main_id) {
637
+ if !wanted . contains ( & main_id) {
637
638
self . c_main = None ;
638
639
}
639
640
}
640
641
641
642
// Prune any declaration that isn't considered live
642
643
self . c_decls
643
- . retain ( |& decl_id, _decl| used . contains ( & decl_id) ) ;
644
+ . retain ( |& decl_id, _decl| wanted . contains ( & decl_id) ) ;
644
645
645
646
// Prune top declarations that are not considered live
646
- self . c_decls_top . retain ( |x| used . contains ( x) ) ;
647
+ self . c_decls_top . retain ( |x| wanted . contains ( x) ) ;
647
648
}
648
649
649
650
pub fn sort_top_decls ( & mut self ) {
0 commit comments