Skip to content

Commit 8f1f16c

Browse files
RexJaeschkeBillWagner
authored andcommitted
support unsigned right shift operator
1 parent 2bdfe88 commit 8f1f16c

1 file changed

Lines changed: 27 additions & 9 deletions

File tree

standard/expressions.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ The following operations in C# are subject to binding:
6767
- Element access: `e[e₁,...,eᵥ]`
6868
- Object creation: new `C(e₁,...,eᵥ)`
6969
- Overloaded unary operators: `+`, `-`, `!` (logical negation only), `~`, `++`, `--`, `true`, `false`
70-
- Overloaded binary operators: `+`, `-`, `*`, `/`, `%`, `&`, `&&`, `|`, `||`, `??`, `^`, `<<`, `>>`, `==`, `!=`, `>`, `<`, `>=`, `<=`
71-
- Assignment operators: `=`, `= ref`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `??=`
70+
- Overloaded binary operators: `+`, `-`, `*`, `/`, `%`, `&`, `&&`, `|`, `||`, `??`, `^`, `<<`, `>>`, `>>>` (static binding only), `==`, `!=`, `>`, `<`, `>=`, `<=`
71+
- Assignment operators: `=`, `= ref`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, `>>>=` (static binding only), `??=`
7272
- Implicit and explicit conversions
7373

7474
When no dynamic expressions are involved, C# defaults to static binding, which means that the compile-time types of subexpressions are used in the selection process. However, when one of the subexpressions in the operations listed above is a dynamic expression, the operation is instead dynamically bound.
@@ -160,7 +160,7 @@ The precedence of an operator is established by the definition of its associated
160160
> | [§12.12](expressions.md#1212-switch-expression) | Switch | `switch { … }` |
161161
> | [§12.13](expressions.md#1213-arithmetic-operators) | Multiplicative | `*` `/` `%` |
162162
> | [§12.13](expressions.md#1213-arithmetic-operators) | Additive | `+` `-` |
163-
> | [§12.14](expressions.md#1214-shift-operators) | Shift | `<<` `>>` |
163+
> | [§12.14](expressions.md#1214-shift-operators) | Shift | `<<` `>>` `>>>` |
164164
> | [§12.15](expressions.md#1215-relational-and-type-testing-operators) | Relational and type-testing | `<` `>` `<=` `>=` `is` `as` |
165165
> | [§12.15](expressions.md#1215-relational-and-type-testing-operators) | Equality | `==` `!=` |
166166
> | [§12.16](expressions.md#1216-logical-operators) | Logical AND | `&` |
@@ -170,7 +170,7 @@ The precedence of an operator is established by the definition of its associated
170170
> | [§12.17](expressions.md#1217-conditional-logical-operators) | Conditional OR | `\|\|` |
171171
> | [§12.18](expressions.md#1218-the-null-coalescing-operator) and12.19](expressions.md#1219-the-throw-expression-operator) | Null coalescing and throw expression | `??` `throw x` |
172172
> |12.21](expressions.md#1221-conditional-operator) | Conditional | `?:` |
173-
> |12.24](expressions.md#1224-assignment-operators) and12.22](expressions.md#1222-anonymous-function-expressions) | Assignment and lambda expression | `=` `= ref` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `&=` `^=` `\|=` `=>` `??=` |
173+
> |12.24](expressions.md#1224-assignment-operators) and12.22](expressions.md#1222-anonymous-function-expressions) | Assignment and lambda expression | `=` `= ref` `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `\|=` `=>` `??=` |
174174
>
175175
> *end note*
176176
@@ -201,7 +201,7 @@ Only the operators listed above can be overloaded. In particular, it is not poss
201201
202202
The ***overloadable binary operator***s are:
203203
204-
> `+ - * / % & | ^ << >> == != > < <= >=`
204+
> `+ - * / % & | ^ << >> >>> == != > < <= >=`
205205
206206
Only the operators listed above can be overloaded. In particular, it is not possible to overload member access, method invocation, or the `..`, `=`, `&&`, `||`, `??`, `?:`, `=>`, `checked`, `unchecked`, `new`, `typeof`, `default`, `as`, and `isoperators.
207207
@@ -359,7 +359,7 @@ In both of the above cases, a cast expression can be used to explicitly convert
359359
A ***lifted operator*** permits predefined and user-defined operators that operate on a non-nullable value type to also be used with the nullable form of that type. Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following:
360360
361361
- For the unary operators `+`, `++`, `-`, `--`, `!` (logical negation), `^`, and `~`, a lifted form of an operator exists if the operand and result types are both non-nullable value types. The lifted form is constructed by adding a single `?modifier to the operand and result types. The lifted operator produces a `null` value if the operand is `null`. Otherwise, the lifted operator unwraps the operand, applies the underlying operator, and wraps the result.
362-
- For the binary operators `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `..`, `<<`, and `>>`, a lifted form of an operator exists if the operand and result types are all non-nullable value types. The lifted form is constructed by adding a single `?modifier to each operand and result type. The lifted operator produces a `null` value if one or both operands are `null` (an exception being the `&` and `|operators of the `bool?` type, as described in12.16.5](expressions.md#12165-nullable-boolean--and--operators)). Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.
362+
- For the binary operators `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `..`, `<<`, `>>`, and `>>>`, a lifted form of an operator exists if the operand and result types are all non-nullable value types. The lifted form is constructed by adding a single `?modifier to each operand and result type. The lifted operator produces a `null` value if one or both operands are `null` (an exception being the `&` and `|operators of the `bool?` type, as described in12.16.5](expressions.md#12165-nullable-boolean--and--operators)). Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.
363363
- For the equality operators `==` and `!=`, a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is `bool`. The lifted form is constructed by adding a single `?modifier to each operand type. The lifted operator considers two `null` values equal, and a `null` value unequal to any non-`null` value. If both operands are non-`null`, the lifted operator unwraps the operands and applies the underlying operator to produce the `bool` result.
364364
- For the relational operators `<`, `>`, `<=`, and `>=`, a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is `bool`. The lifted form is constructed by adding a single `?modifier to each operand type. The lifted operator produces the value `false` if one or both operands are `null`. Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce the `bool` result.
365365
@@ -4497,22 +4497,29 @@ Lifted ([§12.4.8](expressions.md#1248-lifted-operators)) forms of the unlifted
44974497
44984498
## 12.14 Shift operators
44994499
4500-
The `<<` and `>>` operators are used to perform bit-shifting operations.
4500+
The `<<`, `>>`, and `>>>` operators are used to perform bit-shifting operations.
45014501
45024502
```ANTLR
45034503
shift_expression
45044504
: additive_expression
45054505
| shift_expression '<<' additive_expression
45064506
| shift_expression right_shift additive_expression
4507+
| shift_expression unsigned_right_shift additive_expression
45074508
;
45084509
```
45094510
45104511
If an operand of a *shift_expression* has the compile-time type `dynamic`, then the expression is dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)). In this case, the compile-time type of the expression is `dynamic`, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type `dynamic`.
45114512

4512-
For an operation of the form `x << count` or `x >> count`, binary operator overload resolution ([§12.4.5](expressions.md#1245-binary-operator-overload-resolution)) is applied to select a specific operator implementation. The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
4513+
Dynamic binding uses values of type `enum System.Linq.Expressions.ExpressionType` to communicate binary operator kind to the runtime binder. As there is no enum member specifically representing an unsigned right shift operator, dynamic binding for `>>>` is not supported.
4514+
4515+
For an operation of the form `x << count`, `x >> count`, or `X >>> count`, binary operator overload resolution ([§12.4.5](expressions.md#1245-binary-operator-overload-resolution)) is applied to select a specific operator implementation. The left operand is converted to type `T`, where `T` is the first of `int`, `uint`, `long`, and `ulong` that can fully represent all possible values of the operand. The operation is then performed using the precision of type `T`, and the type of the result is `T`.
45134516

45144517
When declaring an overloaded shift operator, the type of the first operand shall always be the class or struct containing the operator declaration, and the type of the second operand shall always be `int`.
45154518

4519+
The *unsigned_right_shift* operator (`>>>`) shall not be present in an expression tree.
4520+
4521+
> *Note*: The semantics of the predefined `>>>` operator on signed types cannot be accurately represented without adding conversions to an unsigned type and back. *end note*
4522+
45164523
The predefined shift operators are listed below.
45174524

45184525
- Shift left:
@@ -4538,6 +4545,12 @@ The predefined shift operators are listed below.
45384545
nuint operator >>(nuint x, int count);
45394546
long operator >>(long x, int count);
45404547
ulong operator >>(ulong x, int count);
4548+
int operator >>>(int x, int count);
4549+
uint operator >>>(uint x, int count);
4550+
nint operator >>>(nint x, int count);
4551+
nuint operator >>>(nuint x, int count);
4552+
long operator >>>(long x, int count);
4553+
ulong operator >>>(ulong x, int count);
45414554
```
45424555

45434556
The `>>` operator shifts `x` right by a number of bits computed as described below.
@@ -4546,6 +4559,8 @@ The predefined shift operators are listed below.
45464559

45474560
When `x` is of type `uint`, `nuint`, or `ulong`, the low-order bits of `x` are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.
45484561

4562+
The `>>>` operator shifts `x` right by a number of bits computed as follows: The low-order bits of `x` are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.
4563+
45494564
For the predefined operators, the number of bits to shift is computed as follows:
45504565

45514566
- When the type of `x` is `int` or `uint`, the shift count is given by the low-order five bits of `count`. In other words, the shift count is computed from `count & 0x1F`. This also applies when the type of `x` is `nint` or `nuint`, and those types have the same size and representation as `int` and `uint`, respectively.
@@ -7022,6 +7037,9 @@ assignment
70227037
| simple_assignment
70237038
| compound_assignment
70247039
| ref_assignment
7040+
| right_shift_assignment
7041+
| unsigned_right_shift_assignment
7042+
: unary_expression assignment_operator expression
70257043
;
70267044
```
70277045

@@ -7501,7 +7519,7 @@ Only the following constructs are permitted in constant expressions:
75017519
- `checked` and `unchecked` expressions.
75027520
- `nameof` expressions.
75037521
- The predefined `+`, `-`, `!` (logical negation) and `~` unary operators.
7504-
- The predefined `+`, `-`, `*`, `/`, `%`, `<<`, `>>`, `&`, `|`, `^`, `&&`, `||`, `==`, `!=`, `<`, `>`, `<=`, and `>=` binary operators.
7522+
- The predefined `+`, `-`, `*`, `/`, `%`, `<<`, `>>`, `>>>`, `&`, `|`, `^`, `&&`, `||`, `==`, `!=`, `<`, `>`, `<=`, and `>=` binary operators.
75057523
- The `?:` conditional operator.
75067524
- The `!` null-forgiving operator ([§12.8.9](expressions.md#1289-null-forgiving-expressions)).
75077525
- `sizeof` expressions, provided the unmanaged-type is one of the types specified in [§24.6.9](unsafe-code.md#2469-the-sizeof-operator) for which `sizeof` returns a constant value.

0 commit comments

Comments
 (0)