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