mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2024-06-05 21:29:26 +00:00
Check for non-void functions that execute to the end without returning a value.
This generalizes the heuristic approach for checking whether _Noreturn functions could execute to the end of the function, extending it to apply to any function with a non-void return type. These checks use the same #pragma lint bit but give different messages depending on the situation.
This commit is contained in:
parent
77dcfdf3ee
commit
c84c4d9c5c
|
@ -92,7 +92,7 @@ const
|
||||||
lintPrintf = $0010; {check printf/scanf format flags}
|
lintPrintf = $0010; {check printf/scanf format flags}
|
||||||
lintOverflow = $0020; {check for overflows}
|
lintOverflow = $0020; {check for overflows}
|
||||||
lintC99Syntax = $0040; {check for syntax that C99 disallows}
|
lintC99Syntax = $0040; {check for syntax that C99 disallows}
|
||||||
lintNoreturn = $0080; {check for return in _Noreturn funcs}
|
lintReturn = $0080; {flag issues with how functions return}
|
||||||
|
|
||||||
{bit masks for GetLInfo flags}
|
{bit masks for GetLInfo flags}
|
||||||
{----------------------------}
|
{----------------------------}
|
||||||
|
@ -505,6 +505,7 @@ var
|
||||||
wait: boolean; {wait for keypress after errors?}
|
wait: boolean; {wait for keypress after errors?}
|
||||||
lintIsError: boolean; {treat lint messages as errors?}
|
lintIsError: boolean; {treat lint messages as errors?}
|
||||||
fIsNoreturn: boolean; {is the current function _Noreturn?}
|
fIsNoreturn: boolean; {is the current function _Noreturn?}
|
||||||
|
doingMain: boolean; {are we processing the main function?}
|
||||||
|
|
||||||
{syntactic classes of tokens}
|
{syntactic classes of tokens}
|
||||||
{---------------------------}
|
{---------------------------}
|
||||||
|
|
31
DAG.pas
31
DAG.pas
|
@ -4823,9 +4823,10 @@ var
|
||||||
end; {Generate}
|
end; {Generate}
|
||||||
|
|
||||||
|
|
||||||
procedure CheckNoreturn;
|
procedure CheckReturn;
|
||||||
|
|
||||||
{ Check if a noreturn function looks like it might return. }
|
{ Check if a noreturn function looks like it might return, }
|
||||||
|
{ or if a non-void function might return with no value. }
|
||||||
{ }
|
{ }
|
||||||
{ This uses a heuristic of basically looking for code at the }
|
{ This uses a heuristic of basically looking for code at the }
|
||||||
{ end of the function that would lead to it returning if }
|
{ end of the function that would lead to it returning if }
|
||||||
|
@ -4838,17 +4839,22 @@ var
|
||||||
var
|
var
|
||||||
code: icptr;
|
code: icptr;
|
||||||
|
|
||||||
begin {CheckNoreturn}
|
begin {CheckReturn}
|
||||||
code := DAGhead;
|
code := DAGhead;
|
||||||
while code^.opcode in [pc_nop,pc_ret,pc_lnm,dc_lab,dc_loc,pc_add] do
|
while code^.opcode in [pc_lnm,dc_lab,dc_loc,pc_add] do
|
||||||
code := code^.next;
|
code := code^.next;
|
||||||
while code^.opcode = pc_pop do
|
while code^.opcode = pc_pop do
|
||||||
code := code^.left;
|
code := code^.left;
|
||||||
while code^.opcode = pc_bno do
|
while code^.opcode = pc_bno do
|
||||||
code := code^.right;
|
code := code^.right;
|
||||||
if not (code^.opcode in [pc_fjp,pc_tjp,pc_ujp,pc_xjp,pc_cui,pc_cup,pc_tl1])
|
if not (code^.opcode in [pc_fjp,pc_tjp,pc_ujp,pc_xjp,pc_cui,pc_cup,pc_tl1])
|
||||||
then Error(154);
|
then begin
|
||||||
end; {CheckNoreturn}
|
if fIsNoreturn then
|
||||||
|
Error(154)
|
||||||
|
else
|
||||||
|
Error(155);
|
||||||
|
end;
|
||||||
|
end; {CheckReturn}
|
||||||
|
|
||||||
|
|
||||||
procedure Push (code: icptr);
|
procedure Push (code: icptr);
|
||||||
|
@ -4938,9 +4944,17 @@ case code^.opcode of
|
||||||
pc_gil, pc_gli, pc_gdl, pc_gld, pc_lil, pc_lli, pc_ldl, pc_lld,
|
pc_gil, pc_gli, pc_gdl, pc_gld, pc_lil, pc_lli, pc_ldl, pc_lld,
|
||||||
pc_lad, pc_lao, pc_lca, pc_lda, pc_ldc, pc_ldo, pc_lod, pc_nop,
|
pc_lad, pc_lao, pc_lca, pc_lda, pc_ldc, pc_ldo, pc_lod, pc_nop,
|
||||||
dc_cns, dc_glb, dc_dst, pc_lnm, pc_nam, pc_nat, dc_lab, pc_add,
|
dc_cns, dc_glb, dc_dst, pc_lnm, pc_nam, pc_nat, dc_lab, pc_add,
|
||||||
pc_ujp, dc_pin, pc_ent, pc_ret, dc_sym:
|
pc_ujp, dc_pin, pc_ent, dc_sym:
|
||||||
Push(code);
|
Push(code);
|
||||||
|
|
||||||
|
pc_ret:
|
||||||
|
begin
|
||||||
|
if (lint & lintReturn) <> 0 then
|
||||||
|
if fIsNoreturn or ((code^.optype <> cgVoid) and not doingMain) then
|
||||||
|
CheckReturn;
|
||||||
|
Push(code);
|
||||||
|
end;
|
||||||
|
|
||||||
pc_cnn:
|
pc_cnn:
|
||||||
begin
|
begin
|
||||||
code^.opcode := pc_cnv;
|
code^.opcode := pc_cnv;
|
||||||
|
@ -4968,9 +4982,6 @@ case code^.opcode of
|
||||||
end;
|
end;
|
||||||
|
|
||||||
dc_enp: begin
|
dc_enp: begin
|
||||||
if fIsNoreturn then
|
|
||||||
if (lint & lintNoreturn) <> 0 then
|
|
||||||
CheckNoreturn;
|
|
||||||
Push(code);
|
Push(code);
|
||||||
Reverse;
|
Reverse;
|
||||||
Generate;
|
Generate;
|
||||||
|
|
|
@ -151,7 +151,6 @@ type
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
doingMain: boolean; {are we processing the main function?}
|
|
||||||
firstCompoundStatement: boolean; {are we doing a function level compound statement?}
|
firstCompoundStatement: boolean; {are we doing a function level compound statement?}
|
||||||
fType: typePtr; {return type of the current function}
|
fType: typePtr; {return type of the current function}
|
||||||
isForwardDeclared: boolean; {is the field list component }
|
isForwardDeclared: boolean; {is the field list component }
|
||||||
|
@ -739,7 +738,7 @@ var
|
||||||
|
|
||||||
begin {ReturnStatement}
|
begin {ReturnStatement}
|
||||||
if fIsNoreturn then
|
if fIsNoreturn then
|
||||||
if (lint & lintNoreturn) <> 0 then
|
if (lint & lintReturn) <> 0 then
|
||||||
Error(153);
|
Error(153);
|
||||||
NextToken; {skip the 'return' token}
|
NextToken; {skip the 'return' token}
|
||||||
if token.kind <> semicolonch then {if present, evaluate the return value}
|
if token.kind <> semicolonch then {if present, evaluate the return value}
|
||||||
|
@ -770,7 +769,7 @@ var
|
||||||
end {if}
|
end {if}
|
||||||
else begin
|
else begin
|
||||||
if (fType^.kind <> scalarType) or (fType^.baseType <> cgVoid) then
|
if (fType^.kind <> scalarType) or (fType^.baseType <> cgVoid) then
|
||||||
if (lint & lintC99Syntax) <> 0 then
|
if ((lint & lintC99Syntax) <> 0) or ((lint & lintReturn) <> 0) then
|
||||||
Error(152);
|
Error(152);
|
||||||
end; {else}
|
end; {else}
|
||||||
Gen1(pc_ujp, returnLabel); {branch to the exit point}
|
Gen1(pc_ujp, returnLabel); {branch to the exit point}
|
||||||
|
|
|
@ -183,7 +183,7 @@ const
|
||||||
{----}
|
{----}
|
||||||
defaultName = '13:ORCACDefs:Defaults.h'; {default include file name}
|
defaultName = '13:ORCACDefs:Defaults.h'; {default include file name}
|
||||||
maxErr = 10; {max errors on one line}
|
maxErr = 10; {max errors on one line}
|
||||||
maxLint = 154; {maximum lint error code}
|
maxLint = 155; {maximum lint error code}
|
||||||
|
|
||||||
type
|
type
|
||||||
errorType = record {record of a single error}
|
errorType = record {record of a single error}
|
||||||
|
@ -682,6 +682,7 @@ if list or (numErr <> 0) then begin
|
||||||
152: msg := @'lint: return with no value in non-void function';
|
152: msg := @'lint: return with no value in non-void function';
|
||||||
153: msg := @'lint: return statement in function declared _Noreturn';
|
153: msg := @'lint: return statement in function declared _Noreturn';
|
||||||
154: msg := @'lint: function declared _Noreturn can return or has unreachable code';
|
154: msg := @'lint: function declared _Noreturn can return or has unreachable code';
|
||||||
|
155: msg := @'lint: non-void function may not return a value or has unreachable code';
|
||||||
otherwise: Error(57);
|
otherwise: Error(57);
|
||||||
end; {case}
|
end; {case}
|
||||||
writeln(msg^);
|
writeln(msg^);
|
||||||
|
@ -3683,7 +3684,7 @@ lintIsError := true; {lint messages are considered errors}
|
||||||
|
|
||||||
{error codes for lint messages}
|
{error codes for lint messages}
|
||||||
{if changed, also change maxLint}
|
{if changed, also change maxLint}
|
||||||
lintErrors := [51,104,105,110,124,125,128,129,130,147,151,152,153,154];
|
lintErrors := [51,104,105,110,124,125,128,129,130,147,151,152,153,154,155];
|
||||||
|
|
||||||
spaceStr := ' '; {strings used in stringization}
|
spaceStr := ' '; {strings used in stringization}
|
||||||
quoteStr := '"';
|
quoteStr := '"';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user