From 80c513bbf22446d456e69c6219c315fadc508953 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Wed, 29 Jan 2020 19:26:45 -0600 Subject: [PATCH] Add a lint flag for checking if _Noreturn functions may return. Currently, this only flags return statements, not cases where they may execute to the end of the function. (Whether the function will actually return is not decidable in general, although it may be in special cases). --- CCommon.pas | 1 + Parser.pas | 5 +++++ Scanner.pas | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CCommon.pas b/CCommon.pas index d327b48..1697b78 100644 --- a/CCommon.pas +++ b/CCommon.pas @@ -92,6 +92,7 @@ const lintPrintf = $0010; {check printf/scanf format flags} lintOverflow = $0020; {check for overflows} lintC99Syntax = $0040; {check for syntax that C99 disallows} + lintNoreturn = $0080; {check for return in _Noreturn funcs} {bit masks for GetLInfo flags} {----------------------------} diff --git a/Parser.pas b/Parser.pas index 44a7544..7adddff 100644 --- a/Parser.pas +++ b/Parser.pas @@ -154,6 +154,7 @@ 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?} @@ -737,6 +738,9 @@ var tk: tokenType; {structure name token} begin {ReturnStatement} + if fIsNoreturn then + if (lint & lintNoreturn) <> 0 then + Error(153); NextToken; {skip the 'return' token} if token.kind <> semicolonch then {if present, evaluate the return value} begin @@ -3568,6 +3572,7 @@ if isFunction then begin ftype := fnType^.ftype; {record the type of the function} while fType^.kind = definedType do fType := fType^.dType; + fIsNoreturn := isNoreturn; {record if function is _Noreturn} variable^.state := defined; {note that the function is defined} pfunc := variable; {set the identifier for parm checks} fnType^.isPascal := isPascal; {note if we have pascal parms} diff --git a/Scanner.pas b/Scanner.pas index fae40d2..16ccf90 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -182,7 +182,7 @@ const {----} defaultName = '13:ORCACDefs:Defaults.h'; {default include file name} maxErr = 10; {max errors on one line} - maxLint = 152; {maximum lint error code} + maxLint = 153; {maximum lint error code} type errorType = record {record of a single error} @@ -677,6 +677,7 @@ if list or (numErr <> 0) then begin 150: msg := @'designated initializers are not supported by ORCA/C'; 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'; otherwise: Error(57); end; {case} writeln(msg^); @@ -3637,7 +3638,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]; +lintErrors := [51,104,105,110,124,125,128,129,130,147,151,152,153]; new(mp); {__LINE__} mp^.name := @'__LINE__';