Afaik, cardinal is "unsigned" not "positive".
Formally, any value other than zero (0) is signed. Cardinal/word/dword/qword/etc means a non-negative-only value which causes the interpretation of the high bit to change thereby allowing higher magnitudes and, that interpretation is valid because the compiler has been explicitly told that there are no negative values in the type/range. It should also be pointed out that non-negative-only includes zero (0) since it is neither negative nor positive.
In any case, "cardinal" contains 0. Yes, so does (signed-)integer.
Int/Int32/int64/integer also contain zero (0), therefore it is not possible to assign a sign to zero since both "unsigned" and signed data types include that value. It is incorrect to simply choose, or presume, that zero is positive which is what FPC is doing by "concluding" that sign extension should not be done.
In other words, if you see a statement like this:
It is
not possible to state that A is a signed or unsigned data type because zero (0) does not provide enough information to draw a correct conclusion but, FPC
is drawing a conclusion from that case and, as expected, gets it wrong because it cannot be done.
So (for the discussions sake) cardinal is chosen (actually the sub-range 0..0 is chosen, and it is chosen as a subrange of cardinal).
0 is also in a subrange of int16/int32/int64/etc, therefore, it is incorrect to presume it is _only_ in a subrange of an unsigned type such as Cardinal.
SomeCardinal := SomeIntegerVariable // where SomeIntegerVariable = -5
will assign $ffff...fb as a positive SomeCardinal.
Equally you can also assign numbers to a variable of subrange type, even if the number is outside that range.
type TNum = 1..5;
ANum := SomeIntegerVariable // where SomeIntegerVariable = -5
Not tested, but on 64 bit that probably also give $00000000fffffffb
If it does not, that would IMHO be inconsistent.
But in that example, you are declaring a type and in addition to that, you have values other than zero (0) which provide enough information to unambiguously state that the type/range does not include negative values.
That example does _not_ reflect the situation that causes the bug.
Again, I am not saying that I agree with this design decision. Just pointing out my understanding of the current state.
I understand you are not saying you are in agreement with the decision. I am clear on that.
What I'd like to make people understand is
why what FPC is doing is a legitimate bug. It is simply wrong. The "current state", as you put it, is simply incorrect. It's wrong. It's not a matter of choice, being nice, implementation or "undefined territory", it is provably wrong. Zero cannot be presumed to be positive nor negative, it is neither. No type information can be derived from it.
HTH.