mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2024-09-27 03:54:30 +00:00
Implement stricter type checks for comparisons.
These rules are used if loose type checks are disabled. They are intended to strictly implement the constraints in C17 sections 6.5.9 and 6.5.10. This patch also fixes a bug where object pointer comparisons to "const void *" should be permitted but were not.
This commit is contained in:
parent
2614f10ced
commit
7848e50218
@ -3337,28 +3337,59 @@ var
|
||||
end; {FunctionCall}
|
||||
|
||||
|
||||
procedure CompareCompatible (var t1,t2: typePtr);
|
||||
procedure CompareCompatible (var t1,t2: typePtr; equality: boolean);
|
||||
|
||||
{ Make sure that it is legal to compare t1 to t2 }
|
||||
{ }
|
||||
{ parameters: }
|
||||
{ t1,t2 - the types to compare }
|
||||
{ equality - is this for an (in)equality comparison? }
|
||||
|
||||
begin {CompareCompatible}
|
||||
if (t1^.kind = functionType) or (t2^.kind = functionType) then begin
|
||||
if not CompTypes(t1, t2) then
|
||||
Error(47)
|
||||
else if not looseTypeChecks and not equality then
|
||||
Error(47);
|
||||
end {if}
|
||||
else if t1^.kind in [pointerType,arrayType] then begin
|
||||
if t2^.kind in [pointerType,arrayType] then begin
|
||||
if (t1^.ptype = voidPtr) or (t2^.ptype = voidPtr) then
|
||||
else if not CompTypes(t1^.ptype, t2^.ptype) then
|
||||
if CompTypes(t1^.ptype, t2^.ptype) then begin
|
||||
if not looseTypeChecks and not equality then
|
||||
if t1^.ptype^.kind = functionType then
|
||||
Error(47);
|
||||
end {if}
|
||||
else if (t1^.ptype^.kind=scalarType) and (t1^.ptype^.basetype=cgVoid)
|
||||
then begin
|
||||
if not looseTypeChecks then begin
|
||||
if not equality then
|
||||
Error(47)
|
||||
else if (not tlastwasconst) or (tlastconst <> 0) then
|
||||
if t2^.ptype^.kind = functionType then
|
||||
Error(47);
|
||||
end {if}
|
||||
end {else if}
|
||||
else if (t2^.ptype^.kind=scalarType) and (t2^.ptype^.basetype=cgVoid)
|
||||
then begin
|
||||
if not looseTypeChecks then begin
|
||||
if not equality then
|
||||
Error(47)
|
||||
else if (not lastwasconst) or (lastconst <> 0) then
|
||||
if t1^.ptype^.kind = functionType then
|
||||
Error(47);
|
||||
end {if}
|
||||
end {else if}
|
||||
else
|
||||
Error(47);
|
||||
t2 := ulongPtr;
|
||||
end {if}
|
||||
else if (not lastwasconst) or (lastconst <> 0) then
|
||||
else if (not lastwasconst) or (lastconst <> 0)
|
||||
or (not equality and not looseTypeChecks) then
|
||||
Error(47);
|
||||
t1 := ulongPtr;
|
||||
end {if}
|
||||
else if expressionType^.kind in [pointerType,arrayType] then begin
|
||||
if (not tlastwasconst) or (tlastconst <> 0) then
|
||||
if (not equality) or (not tlastwasconst) or (tlastconst <> 0) then
|
||||
Error(47);
|
||||
t2 := ulongPtr;
|
||||
end; {else if}
|
||||
@ -4269,7 +4300,7 @@ case tree^.token.kind of
|
||||
tlastwasconst := lastwasconst;
|
||||
tlastconst := lastconst;
|
||||
GenerateCode(tree^.right);
|
||||
CompareCompatible(ltype, expressionType);
|
||||
CompareCompatible(ltype, expressionType, true);
|
||||
if tree^.token.kind = eqeqop then
|
||||
Gen0t(pc_equ, UsualBinaryConversions(lType))
|
||||
else
|
||||
@ -4284,7 +4315,7 @@ case tree^.token.kind of
|
||||
GenerateCode(tree^.left);
|
||||
lType := expressionType;
|
||||
GenerateCode(tree^.right);
|
||||
CompareCompatible(ltype, expressionType);
|
||||
CompareCompatible(ltype, expressionType, false);
|
||||
if tree^.token.kind = lteqop then
|
||||
Gen0t(pc_leq, UsualBinaryConversions(lType))
|
||||
else if tree^.token.kind = gteqop then
|
||||
|
6
cc.notes
6
cc.notes
@ -475,13 +475,15 @@ 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 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 three specific situations where bit 5 currently has an effect:
|
||||
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 four 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 type compatibility checks involving function pointers to ignore the prototyped parameter types. If bit 5 is clear, the prototyped parameter types (if available) must be compatible.
|
||||
|
||||
Third, 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:
|
||||
Third, setting bit 5 causes certain comparisons involving pointers to be permitted even though they violate constraints specified in the C standards. If bit 5 is clear, the rules in the standards will be followed strictly.
|
||||
|
||||
Fourth, 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 *. */
|
||||
|
Loading…
Reference in New Issue
Block a user