mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2025-01-01 13:29:32 +00:00
Add lint check for implicit conversions that change a constant's value.
This occurs when the constant value is out of range of the type being assigned to. This is likely indicative of an error, or of code that assumes types have larger ranges than they do in ORCA/C (e.g. 32-bit int). This intentionally does not report cases where a value is assigned to a signed type but is within the range of the corresponding unsigned type, or vice versa. These may be done intentionally, e.g. setting an unsigned value to "-1" or setting a signed value using a hex constant with the high bit set. Also, only conversions to 8-bit or 16-bit integer types are currently checked.
This commit is contained in:
parent
9f36e99194
commit
245dd0a3f4
2
CC.rez
2
CC.rez
@ -11,5 +11,5 @@ resource rVersion(1) {
|
||||
verUS, /* Region code */
|
||||
"ORCA/C", /* Short version number */
|
||||
"Copyright 1997, Byte Works, Inc.\n" /* Long version number */
|
||||
"Updated 2022"
|
||||
"Updated 2023"
|
||||
};
|
||||
|
@ -95,6 +95,7 @@ const
|
||||
lintC99Syntax = $0040; {check for syntax that C99 disallows}
|
||||
lintReturn = $0080; {flag issues with how functions return}
|
||||
lintUnused = $0100; {check for unused variables}
|
||||
lintConstantRange = $0200; {check for out-of-range constants}
|
||||
|
||||
{bit masks for GetLInfo flags}
|
||||
{----------------------------}
|
||||
|
@ -610,6 +610,41 @@ var
|
||||
baseType1,baseType2: baseTypeEnum; {temp variables (for speed)}
|
||||
kind1,kind2: typeKind; {temp variables (for speed)}
|
||||
|
||||
|
||||
procedure CheckConstantRange(t1: typePtr; value: longint);
|
||||
|
||||
{ Check for situations where an implicit conversion will }
|
||||
{ change the value of a constant. }
|
||||
{ }
|
||||
{ Note: This currently only addresses conversions to 8-bit }
|
||||
{ or 16-bit integer types, and intentionally does not }
|
||||
{ distinguish between signed and unsigned types. }
|
||||
|
||||
var
|
||||
min,max: longint; {min/max allowed values}
|
||||
|
||||
begin {CheckConstantRange}
|
||||
if t1^.cType = ctBool then begin
|
||||
min := 0;
|
||||
max := 1;
|
||||
end {if}
|
||||
else if t1^.baseType in [cgByte,cgUByte] then begin
|
||||
min := -128;
|
||||
max := 255;
|
||||
end {else if}
|
||||
else if t1^.baseType in [cgWord,cgUWord] then begin
|
||||
min := -32768;
|
||||
max := 65536;
|
||||
end {else if}
|
||||
else begin
|
||||
min := -maxint4-1;
|
||||
max := maxint4;
|
||||
end; {else}
|
||||
if (value < min) or (value > max) then
|
||||
Error(186);
|
||||
end; {CheckConstantRange}
|
||||
|
||||
|
||||
begin {AssignmentConversion}
|
||||
kind1 := t1^.kind;
|
||||
kind2 := t2^.kind;
|
||||
@ -630,6 +665,9 @@ else if kind2 in
|
||||
case kind1 of
|
||||
|
||||
scalarType: begin
|
||||
if ((lint & lintConstantRange) <> 0) then
|
||||
if isConstant then
|
||||
CheckConstantRange(t1, value);
|
||||
baseType1 := t1^.baseType;
|
||||
if baseType1 in [cgReal,cgDouble,cgComp] then
|
||||
baseType1 := cgExtended;
|
||||
@ -701,6 +739,9 @@ else if kind2 in
|
||||
|
||||
enumType: begin
|
||||
if kind2 = scalarType then begin
|
||||
if ((lint & lintConstantRange) <> 0) then
|
||||
if isConstant then
|
||||
CheckConstantRange(intPtr, value);
|
||||
baseType2 := t2^.baseType;
|
||||
if baseType2 in [cgString,cgVoid] then
|
||||
Error(47)
|
||||
|
@ -202,7 +202,7 @@ const
|
||||
{----}
|
||||
defaultName = '13:ORCACDefs:Defaults.h'; {default include file name}
|
||||
maxErr = 10; {max errors on one line}
|
||||
maxLint = 185; {maximum lint error code}
|
||||
maxLint = 186; {maximum lint error code}
|
||||
|
||||
type
|
||||
errorType = record {record of a single error}
|
||||
@ -801,6 +801,7 @@ if list or (numErr <> 0) then begin
|
||||
183: msg := @'array index out of bounds';
|
||||
184: msg := @'segment exceeds bank size';
|
||||
185: msg := @'lint: unused variable: ';
|
||||
186: msg := @'lint: implicit conversion changes value of constant';
|
||||
otherwise: Error(57);
|
||||
end; {case}
|
||||
if extraStr <> nil then begin
|
||||
@ -4530,7 +4531,7 @@ strictMode := false; {...with extensions}
|
||||
{error codes for lint messages}
|
||||
{if changed, also change maxLint}
|
||||
lintErrors :=
|
||||
[51,104,105,110,124,125,128,129,130,147,151,152,153,154,155,170,185];
|
||||
[51,104,105,110,124,125,128,129,130,147,151,152,153,154,155,170,185,186];
|
||||
|
||||
spaceStr := ' '; {strings used in stringization}
|
||||
quoteStr := '"';
|
||||
|
4
cc.notes
4
cc.notes
@ -761,6 +761,10 @@ If #pragma lint bit 7 (a value of 128) is set, ORCA/C detects some situations wh
|
||||
|
||||
If #pragma lint bit 8 (a value of 256) is set, ORCA/C checks for variables that are declared but never subsequently used. This covers local variables in functions, as well as file-scope static variables.
|
||||
|
||||
* Checking for implicit conversions that change the value of a constant:
|
||||
|
||||
If #pragma lint bit 9 (a value of 512) is set, ORCA/C checks for certain situations where an implicit conversion will change the value of a constant. Implicit conversions occur in assignments, where the value of the expression is converted to the type of the location being assigned to. They also occur in some related situations like initializers and return statements. This lint check identifies cases where a constant is used in such a situation, but its value is outside the range of the type it is converted to, and therefore the value will be changed by the implicit conversion. This may be indicative of a programming error, or of code written with the assumption that types have larger ranges than they do in ORCA/C. This check currently only identifies cases where out-of-range integer values are converted to an 8-bit or 16-bit integer type.
|
||||
|
||||
|
||||
#pragma extensions
|
||||
------------------
|
||||
|
Loading…
Reference in New Issue
Block a user