Treat unary + as an actual operator, not a no-op.

This is necessary both to detect errors (using unary + on non-arithmetic types) and to correctly perform the integer promotions when unary + is used (which can be detected with sizeof or _Generic).
This commit is contained in:
Stephen Heumann 2022-12-09 19:03:38 -06:00
parent f027286b6a
commit e71fe5d785
6 changed files with 35 additions and 9 deletions

View File

@ -202,7 +202,8 @@ type
otherch, {other non-whitespace char (pp-token)}
eolsy,eofsy, {control characters}
typedef, {user types}
uminus,uand,uasterisk, {converted operations}
{converted operations}
uminus,uplus,uand,uasterisk,
parameteroper,castoper,opplusplus,opminusminus,compoundliteral,
macroParm); {macro language}

View File

@ -1659,6 +1659,7 @@ var
tildech, {~}
excch, {!}
uminus, {unary -}
uplus, {unary +}
uand, {unary &}
uasterisk: begin {unary *}
op^.left := Pop;
@ -1810,6 +1811,7 @@ var
ekind := intconst;
end;
uminus : op1 := -op1; {unary -}
uplus : ; {unary +}
uasterisk : Error(79); {unary *}
otherwise: Error(57);
end; {case}
@ -1852,6 +1854,7 @@ var
if llop1.lo = 0 then
llop1.hi := llop1.hi + 1;
end;
uplus : ; {unary +}
uasterisk : Error(79); {unary *}
otherwise: Error(57);
end; {case}
@ -1880,6 +1883,11 @@ var
op^.token.kind := ekind;
op^.token.rval := -rop1;
end;
uplus : begin {unary +}
op^.token.class := realConstant;
op^.token.kind := ekind;
op^.token.rval := rop1;
end;
excch : begin {!}
op^.token.class := intConstant;
op^.token.kind := intconst;
@ -2278,10 +2286,7 @@ if token.kind in startExpression then begin
asteriskch: token.kind := uasterisk;
minusch : token.kind := uminus;
andch : token.kind := uand;
plusch : begin
NextToken;
goto 2;
end;
plusch : token.kind := uplus;
otherwise : Error(57);
end; {case}
if icp[token.kind] = notAnOperation then
@ -2305,7 +2310,7 @@ if token.kind in startExpression then begin
end; {if}
if token.kind in {make sure we get what we want}
[plusplusop,minusminusop,sizeofsy,_Alignofsy,tildech,excch,
uasterisk,uminus,uand] then begin
uasterisk,uminus,uplus,uand] then begin
if not expectingTerm then begin
Error(38);
Skip;
@ -4485,6 +4490,19 @@ case tree^.token.kind of
end; {case}
end; {case uminus}
uplus: begin {unary +}
GenerateCode(tree^.left);
if expressionType^.kind <> scalarType then
error(66)
else case UsualUnaryConversions of
cgByte,cgUByte,cgWord,cgUWord,cgLong,cgULong,cgQuad,cgUQuad,
cgReal,cgDouble,cgComp,cgExtended:
;
otherwise:
error(66);
end; {case}
end; {case uplus}
tildech: begin {~}
GenerateCode(tree^.left);
if expressionType^.kind <> scalarType then

View File

@ -18,7 +18,7 @@ uses CCommon, MM, Scanner, Symbol, CGI;
{$segment 'HEADER'}
const
symFileVersion = 35; {version number of .sym file format}
symFileVersion = 36; {version number of .sym file format}
var
inhibitHeader: boolean; {should .sym includes be blocked?}

View File

@ -1060,7 +1060,9 @@ case token.kind of
uminus: write('-');
uand: write('+');
uplus: write('+');
uand: write('&');
uasterisk: write('*');

View File

@ -311,7 +311,8 @@ charSym start single character symbols
enum (bareqop,poundpoundop,dotdotdotsy)
enum (eolsy,eofsy) control characters
enum (typedef) user types
enum (uminus,uand,uasterisk) converted operations
! converted operations
enum (uminus,uplus,uand,uasterisk)
enum (parameteroper,castoper,opplusplus,opminusminus,compoundliteral)
enum (macroParm) macro language
@ -470,6 +471,7 @@ icp start in-coming priority for expression
dc i1'200' eofsy
dc i1'200' typedef
dc i1'16' uminus
dc i1'16' uplus
dc i1'16' uand
dc i1'16' uasterisk
dc i1'200' parameteroper
@ -647,6 +649,7 @@ isp start in stack priority for expression
dc i1'0' eofsy
dc i1'0' typedef
dc i1'16' uminus
dc i1'16' uplus
dc i1'16' uand
dc i1'16' uasterisk
dc i1'0' parameteroper

View File

@ -2049,6 +2049,8 @@ int foo(int[42]);
225. According to the C99 and later standards, a line continuation with \ should let a // comment continue to the next line. ORCA/C now behaves accordingly.
226. The unary + operator should apply the integer promotions to its operand, e.g. promoting char to int. This can affect the value of sizeof(+expression).
-- Bugs from C 2.1.0 that have been fixed -----------------------------------
1. In some situations, fread() reread the first 1K or so of the file.