@@ -890,12 +890,15 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
890
890
///
891
891
/// This should ideally be less tightly tied to `_match`.
892
892
pub fn trans_switch < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > ,
893
- r : & Repr < ' tcx > , scrutinee : ValueRef )
893
+ r : & Repr < ' tcx > ,
894
+ scrutinee : ValueRef ,
895
+ range_assert : bool )
894
896
-> ( _match:: BranchKind , Option < ValueRef > ) {
895
897
match * r {
896
898
CEnum ( ..) | General ( ..) |
897
899
RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
898
- ( _match:: Switch , Some ( trans_get_discr ( bcx, r, scrutinee, None ) ) )
900
+ ( _match:: Switch , Some ( trans_get_discr ( bcx, r, scrutinee, None ,
901
+ range_assert) ) )
899
902
}
900
903
Univariant ( ..) => {
901
904
// N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
@@ -916,14 +919,18 @@ pub fn is_discr_signed<'tcx>(r: &Repr<'tcx>) -> bool {
916
919
917
920
/// Obtain the actual discriminant of a value.
918
921
pub fn trans_get_discr < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > , r : & Repr < ' tcx > ,
919
- scrutinee : ValueRef , cast_to : Option < Type > )
922
+ scrutinee : ValueRef , cast_to : Option < Type > ,
923
+ range_assert : bool )
920
924
-> ValueRef {
921
925
debug ! ( "trans_get_discr r: {:?}" , r) ;
922
926
let val = match * r {
923
- CEnum ( ity, min, max) => load_discr ( bcx, ity, scrutinee, min, max) ,
927
+ CEnum ( ity, min, max) => {
928
+ load_discr ( bcx, ity, scrutinee, min, max, range_assert)
929
+ }
924
930
General ( ity, ref cases, _) => {
925
931
let ptr = StructGEP ( bcx, scrutinee, 0 ) ;
926
- load_discr ( bcx, ity, ptr, Disr ( 0 ) , Disr ( cases. len ( ) as u64 - 1 ) )
932
+ load_discr ( bcx, ity, ptr, Disr ( 0 ) , Disr ( cases. len ( ) as u64 - 1 ) ,
933
+ range_assert)
927
934
}
928
935
Univariant ( ..) => C_u8 ( bcx. ccx ( ) , 0 ) ,
929
936
RawNullablePointer { nndiscr, nnty, .. } => {
@@ -950,7 +957,8 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &Disc
950
957
}
951
958
952
959
/// Helper for cases where the discriminant is simply loaded.
953
- fn load_discr ( bcx : Block , ity : IntType , ptr : ValueRef , min : Disr , max : Disr )
960
+ fn load_discr ( bcx : Block , ity : IntType , ptr : ValueRef , min : Disr , max : Disr ,
961
+ range_assert : bool )
954
962
-> ValueRef {
955
963
let llty = ll_inttype ( bcx. ccx ( ) , ity) ;
956
964
assert_eq ! ( val_ty( ptr) , llty. ptr_to( ) ) ;
@@ -960,7 +968,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
960
968
let mask = Disr ( !0u64 >> ( 64 - bits) ) ;
961
969
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
962
970
// However, that is fine here (it would still represent the full range),
963
- if max. wrapping_add ( Disr ( 1 ) ) & mask == min & mask {
971
+ if max. wrapping_add ( Disr ( 1 ) ) & mask == min & mask || !range_assert {
964
972
// i.e., if the range is everything. The lo==hi case would be
965
973
// rejected by the LLVM verifier (it would mean either an
966
974
// empty set, which is impossible, or the entire range of the
@@ -1239,10 +1247,14 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
1239
1247
// runtime, so the basic block isn't actually unreachable, so we
1240
1248
// need to make it do something with defined behavior. In this case
1241
1249
// we just return early from the function.
1250
+ //
1251
+ // Note that this is also why the `trans_get_discr` below has
1252
+ // `false` to indicate that loading the discriminant should
1253
+ // not have a range assert.
1242
1254
let ret_void_cx = fcx. new_temp_block ( "enum-variant-iter-ret-void" ) ;
1243
1255
RetVoid ( ret_void_cx, DebugLoc :: None ) ;
1244
1256
1245
- let discr_val = trans_get_discr ( bcx, r, value, None ) ;
1257
+ let discr_val = trans_get_discr ( bcx, r, value, None , false ) ;
1246
1258
let llswitch = Switch ( bcx, discr_val, ret_void_cx. llbb , cases. len ( ) ) ;
1247
1259
let bcx_next = fcx. new_temp_block ( "enum-variant-iter-next" ) ;
1248
1260
0 commit comments