I found a inconsistent behaviour for the shr operator: The output of the following program
Smallint: -1 Longint: 2147483647 Int64: 9223372036854775807
Since shr is a logical shift right
Rules:
1. shr operation is always a logical shift (unsigned).
2. shr operation is 32 bits for the size of the operands <= 32 bits and 64 bits otherwise.
Now details:
vs := cs shr 1;
cs is SmallInt ($FFFF) are sign extended to 32 bit ($FFFFFFFF). Now it shifted without sign ($7FFFFFFF). Now it's needed store to SmallInt. If {$RANGECHECKS ON} will be range error (very big for SmallInt), otherwize only last 16 bits saved ($FFFF). Result is -1.
vl := cl shr 1;
cl is not changed (already 32), signed, so simple unsigned shift ($7FFFFFFF). Because result is fit in vl, so it's simple 2147483647.
Same behaviour for 64 bit integer.
It's all Delphi compatible (including range error).
What about vs := vs shr 1? With optimization, compiler coded this as in-place operation (which ignore rule 2), but do range check as by rule 2 (range error). It's NOT Delphi compatible. Delphi always convert to 32 bit (and result is -1). Without optimization FPC result is -1.
PS: for constants shr operation make by compiler itself, and result can be arithmetic shift or using large size operand (not documented and version depended).