Make lint report some more cases where noreturn functions may return.
This uses a heuristic that may produce both false positives and false negatives, but any false positives should reflect extraneous code at the end of the function that is not actually reachable.
This commit is contained in:
parent
76eb476809
commit
bc951b6735
|
@ -504,6 +504,7 @@ var
|
|||
useGlobalPool: boolean; {use global (or local) string pool?}
|
||||
wait: boolean; {wait for keypress after errors?}
|
||||
lintIsError: boolean; {treat lint messages as errors?}
|
||||
fIsNoreturn: boolean; {is the current function _Noreturn?}
|
||||
|
||||
{syntactic classes of tokens}
|
||||
{---------------------------}
|
||||
|
|
31
DAG.pas
31
DAG.pas
|
@ -4821,6 +4821,34 @@ var
|
|||
DumpLoopLists;
|
||||
DAGhead := nil; {reset the DAG pointers}
|
||||
end; {Generate}
|
||||
|
||||
|
||||
procedure CheckNoreturn;
|
||||
|
||||
{ Check if a noreturn function looks like it might return. }
|
||||
{ }
|
||||
{ This uses a heuristic of basically looking for code at the }
|
||||
{ end of the function that would lead to it returning if }
|
||||
{ executed. Control flow operations are optimistically }
|
||||
{ assumed not to lead to a return. This may produce both }
|
||||
{ false positives and false negative, but any false }
|
||||
{ positives should reflect extraneous code that is not }
|
||||
{ actually reachable (which is dubious in its own right). }
|
||||
|
||||
var
|
||||
code: icptr;
|
||||
|
||||
begin {CheckNoreturn}
|
||||
code := DAGhead;
|
||||
while code^.opcode in [pc_nop,pc_ret,pc_lnm,dc_lab,dc_loc,pc_add] do
|
||||
code := code^.next;
|
||||
while code^.opcode = pc_pop do
|
||||
code := code^.left;
|
||||
while code^.opcode = pc_bno do
|
||||
code := code^.right;
|
||||
if not (code^.opcode in [pc_fjp,pc_tjp,pc_ujp,pc_xjp,pc_cui,pc_cup,pc_tl1])
|
||||
then Error(154);
|
||||
end; {CheckNoreturn}
|
||||
|
||||
|
||||
procedure Push (code: icptr);
|
||||
|
@ -4940,6 +4968,9 @@ case code^.opcode of
|
|||
end;
|
||||
|
||||
dc_enp: begin
|
||||
if fIsNoreturn then
|
||||
if (lint & lintNoreturn) <> 0 then
|
||||
CheckNoreturn;
|
||||
Push(code);
|
||||
Reverse;
|
||||
Generate;
|
||||
|
|
|
@ -154,7 +154,6 @@ var
|
|||
doingMain: boolean; {are we processing the main function?}
|
||||
firstCompoundStatement: boolean; {are we doing a function level compound statement?}
|
||||
fType: typePtr; {return type of the current function}
|
||||
fIsNoreturn: boolean; {is the current function _Noreturn?}
|
||||
isForwardDeclared: boolean; {is the field list component }
|
||||
{ referencing a forward struct/union? }
|
||||
isFunction: boolean; {is the declaration a function?}
|
||||
|
@ -352,6 +351,7 @@ if not doingFunction then begin {if so, finish it off}
|
|||
dumpLocal := true; {dump the local pool}
|
||||
nameFound := false; {no pc_nam for the next function (yet)}
|
||||
volatile := savedVolatile; {local volatile vars are out of scope}
|
||||
fIsNoreturn := false; {not doing a noreturn function}
|
||||
end; {if}
|
||||
PopTable; {remove this symbol table}
|
||||
dispose(stPtr); {dump the record}
|
||||
|
@ -4364,6 +4364,7 @@ nameFound := false; {no pc_nam generated yet}
|
|||
statementList := nil; {no open statements}
|
||||
codegenStarted := false; {code generator is not started}
|
||||
doingForLoopClause1 := false; {not doing a for loop}
|
||||
fIsNoreturn := false; {not doing a noreturn function}
|
||||
|
||||
{init syntactic classes of tokens}
|
||||
{See C17 section 6.7 ff.}
|
||||
|
|
|
@ -182,7 +182,7 @@ const
|
|||
{----}
|
||||
defaultName = '13:ORCACDefs:Defaults.h'; {default include file name}
|
||||
maxErr = 10; {max errors on one line}
|
||||
maxLint = 153; {maximum lint error code}
|
||||
maxLint = 154; {maximum lint error code}
|
||||
|
||||
type
|
||||
errorType = record {record of a single error}
|
||||
|
@ -680,6 +680,7 @@ if list or (numErr <> 0) then begin
|
|||
151: msg := @'lint: type specifier missing';
|
||||
152: msg := @'lint: return with no value in non-void function';
|
||||
153: msg := @'lint: return statement in function declared _Noreturn';
|
||||
154: msg := @'lint: function declared _Noreturn can return or has unreachable code';
|
||||
otherwise: Error(57);
|
||||
end; {case}
|
||||
writeln(msg^);
|
||||
|
@ -3653,7 +3654,7 @@ lintIsError := true; {lint messages are considered errors}
|
|||
|
||||
{error codes for lint messages}
|
||||
{if changed, also change maxLint}
|
||||
lintErrors := [51,104,105,110,124,125,128,129,130,147,151,152,153];
|
||||
lintErrors := [51,104,105,110,124,125,128,129,130,147,151,152,153,154];
|
||||
|
||||
spaceStr := ' '; {strings used in stringization}
|
||||
quoteStr := '"';
|
||||
|
|
Loading…
Reference in New Issue