mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2024-06-10 22:29:27 +00:00
Fix so the type of shift expressions depends only on the (promoted) type of their left operand.
This is as required by the C standards: the type of the right operand should not affect the result type. The following program demonstrates problems with the old behavior: #include <stdio.h> int main(void) { unsigned long ul; long l; unsigned u; int i; ul = 0x8000 << 1L; /* should be 0 */ printf("%lx\n", ul); l = -1 >> 1U; /* should be -1 */ printf("%ld\n", l); u = 0xFF10; l = 8; ul = u << l; /* should be 0x1000 */ printf("%lx\n", ul); l = -4; ul = 1; l = l >> ul; /* should be -2 */ printf("%ld\n", l); }
This commit is contained in:
parent
5618b2810e
commit
af48935d43
|
@ -1061,11 +1061,17 @@ var
|
||||||
op1 := ord(op1 >= op2);
|
op1 := ord(op1 >= op2);
|
||||||
ekind := intconst;
|
ekind := intconst;
|
||||||
end;
|
end;
|
||||||
ltltop : op1 := op1 << op2; {<<}
|
ltltop : begin {<<}
|
||||||
gtgtop : if unsigned1 then {>>}
|
op1 := op1 << op2;
|
||||||
|
ekind := kindLeft;
|
||||||
|
end;
|
||||||
|
gtgtop : begin {>>}
|
||||||
|
if unsigned1 then
|
||||||
op1 := lshr(op1,op2)
|
op1 := lshr(op1,op2)
|
||||||
else
|
else
|
||||||
op1 := op1 >> op2;
|
op1 := op1 >> op2;
|
||||||
|
ekind := kindLeft;
|
||||||
|
end;
|
||||||
plusch : op1 := op1 + op2; {+}
|
plusch : op1 := op1 + op2; {+}
|
||||||
minusch : op1 := op1 - op2; {-}
|
minusch : op1 := op1 - op2; {-}
|
||||||
asteriskch : if unsigned then {*}
|
asteriskch : if unsigned then {*}
|
||||||
|
@ -3199,9 +3205,16 @@ case tree^.token.kind of
|
||||||
|
|
||||||
ltltop: begin {<<}
|
ltltop: begin {<<}
|
||||||
GenerateCode(tree^.left);
|
GenerateCode(tree^.left);
|
||||||
|
et := UsualUnaryConversions;
|
||||||
lType := expressionType;
|
lType := expressionType;
|
||||||
GenerateCode(tree^.right);
|
GenerateCode(tree^.right);
|
||||||
case UsualBinaryConversions(lType) of
|
if (expressionType^.kind <> scalarType)
|
||||||
|
or not (expressionType^.baseType in
|
||||||
|
[cgByte,cgUByte,cgWord,cgUWord,cgLong,cgULong]) then
|
||||||
|
error(66);
|
||||||
|
if expressionType^.baseType <> et then
|
||||||
|
Gen2(pc_cnv, ord(expressionType^.baseType), ord(et));
|
||||||
|
case et of
|
||||||
cgByte,cgUByte,cgWord,cgUWord:
|
cgByte,cgUByte,cgWord,cgUWord:
|
||||||
Gen0(pc_shl);
|
Gen0(pc_shl);
|
||||||
cgLong,cgULong:
|
cgLong,cgULong:
|
||||||
|
@ -3209,13 +3222,21 @@ case tree^.token.kind of
|
||||||
otherwise:
|
otherwise:
|
||||||
error(66);
|
error(66);
|
||||||
end; {case}
|
end; {case}
|
||||||
|
expressionType := lType;
|
||||||
end; {case ltltop}
|
end; {case ltltop}
|
||||||
|
|
||||||
gtgtop: begin {>>}
|
gtgtop: begin {>>}
|
||||||
GenerateCode(tree^.left);
|
GenerateCode(tree^.left);
|
||||||
|
et := UsualUnaryConversions;
|
||||||
lType := expressionType;
|
lType := expressionType;
|
||||||
GenerateCode(tree^.right);
|
GenerateCode(tree^.right);
|
||||||
case UsualBinaryConversions(lType) of
|
if (expressionType^.kind <> scalarType)
|
||||||
|
or not (expressionType^.baseType in
|
||||||
|
[cgByte,cgUByte,cgWord,cgUWord,cgLong,cgULong]) then
|
||||||
|
error(66);
|
||||||
|
if expressionType^.baseType <> et then
|
||||||
|
Gen2(pc_cnv, ord(expressionType^.baseType), ord(et));
|
||||||
|
case et of
|
||||||
cgByte,cgWord:
|
cgByte,cgWord:
|
||||||
Gen0(pc_shr);
|
Gen0(pc_shr);
|
||||||
cgUByte,cgUWord:
|
cgUByte,cgUWord:
|
||||||
|
@ -3227,6 +3248,7 @@ case tree^.token.kind of
|
||||||
otherwise:
|
otherwise:
|
||||||
error(66);
|
error(66);
|
||||||
end; {case}
|
end; {case}
|
||||||
|
expressionType := lType;
|
||||||
end; {case gtgtop}
|
end; {case gtgtop}
|
||||||
|
|
||||||
plusch: begin {+}
|
plusch: begin {+}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user