@@ -258,7 +258,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
258
258
val
259
259
} ;
260
260
match self . mode {
261
- PassMode :: Ignore => { } ,
261
+ PassMode :: Ignore ( _ ) => { }
262
262
PassMode :: Pair ( ..) => {
263
263
OperandValue :: Pair ( next ( ) , next ( ) ) . store ( bx, dst) ;
264
264
}
@@ -507,6 +507,14 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
507
507
}
508
508
} ;
509
509
510
+ // Store the index of the last argument. This is useful for working with
511
+ // C-compatible variadic arguments.
512
+ let last_arg_idx = if sig. inputs ( ) . is_empty ( ) {
513
+ None
514
+ } else {
515
+ Some ( sig. inputs ( ) . len ( ) - 1 )
516
+ } ;
517
+
510
518
let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | {
511
519
let is_return = arg_idx. is_none ( ) ;
512
520
let mut arg = mk_arg_type ( ty, arg_idx) ;
@@ -516,7 +524,30 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
516
524
// The same is true for s390x-unknown-linux-gnu
517
525
// and sparc64-unknown-linux-gnu.
518
526
if is_return || rust_abi || ( !win_x64_gnu && !linux_s390x && !linux_sparc64) {
519
- arg. mode = PassMode :: Ignore ;
527
+ arg. mode = PassMode :: Ignore ( IgnoreMode :: Zst ) ;
528
+ }
529
+ }
530
+
531
+ // If this is a C-variadic function, this is not the return value,
532
+ // and there is one or more fixed arguments; ensure that the `VaList`
533
+ // is ignored as an argument.
534
+ if sig. variadic {
535
+ match ( last_arg_idx, arg_idx) {
536
+ ( Some ( last_idx) , Some ( cur_idx) ) if last_idx == cur_idx => {
537
+ let va_list_did = match cx. tcx . lang_items ( ) . va_list ( ) {
538
+ Some ( did) => did,
539
+ None => bug ! ( "`va_list` lang item required for C-variadic functions" ) ,
540
+ } ;
541
+ match ty. sty {
542
+ ty:: Adt ( def, _) if def. did == va_list_did => {
543
+ // This is the "spoofed" `VaList`. Set the arguments mode
544
+ // so that it will be ignored.
545
+ arg. mode = PassMode :: Ignore ( IgnoreMode :: CVarArgs ) ;
546
+ } ,
547
+ _ => ( ) ,
548
+ }
549
+ }
550
+ _ => { }
520
551
}
521
552
}
522
553
@@ -646,7 +677,9 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
646
677
) ;
647
678
648
679
let llreturn_ty = match self . ret . mode {
649
- PassMode :: Ignore => cx. type_void ( ) ,
680
+ PassMode :: Ignore ( IgnoreMode :: Zst ) => cx. type_void ( ) ,
681
+ PassMode :: Ignore ( IgnoreMode :: CVarArgs ) =>
682
+ bug ! ( "`va_list` should never be a return type" ) ,
650
683
PassMode :: Direct ( _) | PassMode :: Pair ( ..) => {
651
684
self . ret . layout . immediate_llvm_type ( cx)
652
685
}
@@ -664,7 +697,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
664
697
}
665
698
666
699
let llarg_ty = match arg. mode {
667
- PassMode :: Ignore => continue ,
700
+ PassMode :: Ignore ( _ ) => continue ,
668
701
PassMode :: Direct ( _) => arg. layout . immediate_llvm_type ( cx) ,
669
702
PassMode :: Pair ( ..) => {
670
703
llargument_tys. push ( arg. layout . scalar_pair_element_llvm_type ( cx, 0 , true ) ) ;
@@ -733,7 +766,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
733
766
apply ( & ArgAttributes :: new ( ) ) ;
734
767
}
735
768
match arg. mode {
736
- PassMode :: Ignore => { }
769
+ PassMode :: Ignore ( _ ) => { }
737
770
PassMode :: Direct ( ref attrs) |
738
771
PassMode :: Indirect ( ref attrs, None ) => apply ( attrs) ,
739
772
PassMode :: Indirect ( ref attrs, Some ( ref extra_attrs) ) => {
@@ -780,7 +813,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
780
813
apply ( & ArgAttributes :: new ( ) ) ;
781
814
}
782
815
match arg. mode {
783
- PassMode :: Ignore => { }
816
+ PassMode :: Ignore ( _ ) => { }
784
817
PassMode :: Direct ( ref attrs) |
785
818
PassMode :: Indirect ( ref attrs, None ) => apply ( attrs) ,
786
819
PassMode :: Indirect ( ref attrs, Some ( ref extra_attrs) ) => {
0 commit comments