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)} otherch, {other non-whitespace char (pp-token)}
eolsy,eofsy, {control characters} eolsy,eofsy, {control characters}
typedef, {user types} typedef, {user types}
uminus,uand,uasterisk, {converted operations} {converted operations}
uminus,uplus,uand,uasterisk,
parameteroper,castoper,opplusplus,opminusminus,compoundliteral, parameteroper,castoper,opplusplus,opminusminus,compoundliteral,
macroParm); {macro language} macroParm); {macro language}

View File

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

View File

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

View File

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

View File

@ -311,7 +311,8 @@ charSym start single character symbols
enum (bareqop,poundpoundop,dotdotdotsy) enum (bareqop,poundpoundop,dotdotdotsy)
enum (eolsy,eofsy) control characters enum (eolsy,eofsy) control characters
enum (typedef) user types enum (typedef) user types
enum (uminus,uand,uasterisk) converted operations ! converted operations
enum (uminus,uplus,uand,uasterisk)
enum (parameteroper,castoper,opplusplus,opminusminus,compoundliteral) enum (parameteroper,castoper,opplusplus,opminusminus,compoundliteral)
enum (macroParm) macro language enum (macroParm) macro language
@ -470,6 +471,7 @@ icp start in-coming priority for expression
dc i1'200' eofsy dc i1'200' eofsy
dc i1'200' typedef dc i1'200' typedef
dc i1'16' uminus dc i1'16' uminus
dc i1'16' uplus
dc i1'16' uand dc i1'16' uand
dc i1'16' uasterisk dc i1'16' uasterisk
dc i1'200' parameteroper dc i1'200' parameteroper
@ -647,6 +649,7 @@ isp start in stack priority for expression
dc i1'0' eofsy dc i1'0' eofsy
dc i1'0' typedef dc i1'0' typedef
dc i1'16' uminus dc i1'16' uminus
dc i1'16' uplus
dc i1'16' uand dc i1'16' uand
dc i1'16' uasterisk dc i1'16' uasterisk
dc i1'0' parameteroper 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. 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 ----------------------------------- -- Bugs from C 2.1.0 that have been fixed -----------------------------------
1. In some situations, fread() reread the first 1K or so of the file. 1. In some situations, fread() reread the first 1K or so of the file.