Give an error for pointer assignments that discard qualifiers.

This is controlled by #pragma ignore bit 5, which is now a more general "loose type checks" bit.
This commit is contained in:
Stephen Heumann 2021-09-09 21:39:29 -05:00
parent 2f7e71cd24
commit a8682e28d3
5 changed files with 25 additions and 14 deletions

View File

@ -633,12 +633,18 @@ else if kind2 in
pointerType: begin
if kind2 = pointerType then begin
if not CompTypes(t1, t2) then
Error(47);
Error(47)
else if not looseTypeChecks then
if not (t1^.ptype^.qualifiers >= t2^.ptype^.qualifiers) then
Error(163);
end {if}
else if kind2 = arrayType then begin
if not CompTypes(t1^.ptype, t2^.atype) then
if t1^.ptype^.baseType <> cgVoid then
Error(47);
if not CompTypes(t1^.ptype, t2^.atype) and
(t1^.ptype^.baseType <> cgVoid) then
Error(47)
else if not looseTypeChecks then
if not (t1^.ptype^.qualifiers >= t2^.atype^.qualifiers) then
Error(163);
end {if}
else if kind2 = scalarType then begin
if isConstant and (value = 0) then begin

View File

@ -877,7 +877,7 @@ procedure EndInclude {chPtr: ptr};
| (ord(allowTokensAfterEndif) << 2)
| (ord(allowSlashSlashComments) << 3)
| (ord(allowMixedDeclarations) << 4)
| (ord(looseCharTypeChecks) << 5));
| (ord(looseTypeChecks) << 5));
p_segment: begin
for i := 1 to 10 do begin
@ -1537,7 +1537,7 @@ var
allowSlashSlashComments := odd(i >> 3);
allowMixedDeclarations := odd(i >> 4);
c99Scope := allowMixedDeclarations;
looseCharTypeChecks := odd(i >> 5);
looseTypeChecks := odd(i >> 5);
end;
p_segment: begin

View File

@ -89,7 +89,7 @@ var
{Note: The following two are set together}
allowMixedDeclarations: boolean; {allow mixed declarations & stmts (C99)?}
c99Scope: boolean; {follow C99 rules for block scopes?}
looseCharTypeChecks: boolean; {treat char and unsigned char as compatible?}
looseTypeChecks: boolean; {loosen some standard type checks?}
{---------------------------------------------------------------}
@ -719,6 +719,7 @@ if list or (numErr <> 0) then begin
160: msg := @'no matching association in _Generic expression';
161: msg := @'illegal operator in a constant expression';
162: msg := @'invalid escape sequence';
163: msg := @'pointer assignment discards qualifier(s)';
otherwise: Error(57);
end; {case}
writeln(msg^);
@ -3077,7 +3078,7 @@ if ch in ['a','d','e','i','l','p','u','w'] then begin
{ 4 - allow tokens after #endif }
{ 8 - allow // comments }
{ 16 - allow mixed decls & use C99 scope rules }
{ 32 - treat char and unsigned char as compatible }
{ 32 - loosen some standard type checks }
FlagPragmas(p_ignore);
NumericDirective;
if expressionType^.kind = scalarType then
@ -3089,7 +3090,7 @@ if ch in ['a','d','e','i','l','p','u','w'] then begin
allowTokensAfterEndif := odd(val >> 2);
allowSlashSlashComments := odd(val >> 3);
allowMixedDeclarations := odd(val >> 4);
looseCharTypeChecks := odd(val >> 5);
looseTypeChecks := odd(val >> 5);
if allowMixedDeclarations <> c99Scope then begin
if doingFunction then
Error(126)
@ -3875,7 +3876,7 @@ allowTokensAfterEndif := false; {allow tokens after #endif}
allowSlashSlashComments := true; {allow // comments}
allowMixedDeclarations := true; {allow mixed declarations & stmts (C99)}
c99Scope := true; {follow C99 rules for block scopes}
looseCharTypeChecks := true; {make char and unsigned char compatible}
looseTypeChecks := true; {loosen some standard type checks}
foundFunction := false; {no functions found so far}
fileList := nil; {no included files}
gettingFileName := false; {not in GetFileName}

View File

@ -412,7 +412,7 @@ else
if kind2 = scalarType then begin
CompTypes := t1^.baseType = t2^.baseType;
if t1^.cType <> t2^.cType then
if not (looseCharTypeChecks
if not (looseTypeChecks
and (t1^.cType in [ctChar, ctUChar])
and (t2^.cType in [ctChar, ctUChar])) then
CompTypes := false;

View File

@ -178,7 +178,7 @@ See "// Comments," below, for a complete description of // comments.
Bit 4 controls whether C99-style scope rules are followed and whether mixed statements and declarations are allowed in blocks. See "New Language Features," below.
Bit 5 controls whether the types "char" and "unsigned char" are treated as compatible with each other. See "Additions to #pragma ignore," below.
Bit 5 controls whether type compatibility checks should strictly follow the C standards, or whether looser rules should be used in certain cases. See "Additions to #pragma ignore," below.
p. 259
@ -475,12 +475,16 @@ Bit 2 (a value of 4) controls whether spurious tokens are allowed after an #endi
Bit 4 (a value of 16) controls whether ORCA/C follows C99-style rules for declaration placement and block scopes. See "New Language Features," above.
Bit 5 (a value of 32) controls whether the types "char" and "unsigned char" are treated as compatible with each other. These types have the same representation in ORCA/C, but the C standards specify that they are nonetheless two distinct types and are not mutually compatible. Therefore, any standard-conforming C compiler should produce a diagnostic message if these two types or types derived from them are used in a situation where the types are required to be compatible, as in the following example:
Bit 5 (a value of 32) controls whether type compatibility checks should strictly follow the C standards, or whether looser rules should be used in certain cases. If this bit is set, the looser rules will be followed, matching ORCA/C's historical behavior. Bit 5 is currently set by default, but new code should avoid relying on this. There are two specific situations where bit 5 currently has an effect:
First, setting bit 5 causes pointer assignments that discard type qualifiers to be allowed. For example, this affects an assignment from an expression of type "const int *" to a variable of type "int *", because it discards the "const" qualifier from the type pointed to. These assignments are prohibited by the C standards, but ORCA/C historically allowed them. If bit 5 is set it will still allow them, but if bit 5 is clear it will give an error.
Second, setting bit 5 causes the types "char" and "unsigned char" to be treated as compatible with each other for most purposes. These types have the same representation in ORCA/C, but the C standards specify that they are nonetheless two distinct types and are not mutually compatible. Therefore, any standard-conforming C compiler should produce a diagnostic message if these two types or types derived from them are used in a situation where the types are required to be compatible, as in the following example:
unsigned char uc;
char *p = &uc; /* &uc has type unsigned char *, incompatible with char *. */
If bit 5 is set, it causes the "char" and "unsigned char" types to be treated as compatible for most purposes, matching ORCA/C's historical behavior and permitting code like the above example. If this bit is clear, the types will be treated as incompatible, as required by the C standards. This will make ORCA/C give a "type conflict" error for code like the example above. Currently, this bit is set by default, giving the more permissive behavior, but new code should avoid relying on this.
ORCA/C historically permitted code like the above, and when bit 5 is set it will still do so. If bit 5 is clear, it will give a "type conflict" error.
(Mike Westerfield, Kelvin Sherlock, Stephen Heumann)