Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/ShellCheck/Analytics.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5049,6 +5049,10 @@ prop_checkCommandIsUnreachable2 = verify checkCommandIsUnreachable "die() { exit
prop_checkCommandIsUnreachable3 = verifyNot checkCommandIsUnreachable "foo; bar || exit; baz"
prop_checkCommandIsUnreachable4 = verifyNot checkCommandIsUnreachable "f() { foo; }; # Maybe sourced"
prop_checkCommandIsUnreachable5 = verify checkCommandIsUnreachable "f() { foo; }; exit # Not sourced"
prop_checkCommandIsUnreachable6 = verifyNot checkCommandIsUnreachable "return || true; echo 'reachable'"
prop_checkCommandIsUnreachable7 = verifyNot checkCommandIsUnreachable "return 2>/dev/null ||:"
prop_checkCommandIsUnreachable8 = verifyNot checkCommandIsUnreachable "return; echo 'reachable when not in function'"
prop_checkCommandIsUnreachable9 = verify checkCommandIsUnreachable "f() { return; echo unreachable; }"
checkCommandIsUnreachable params t =
case t of
T_Pipeline {} -> sequence_ $ do
Expand Down
13 changes: 10 additions & 3 deletions src/ShellCheck/CFG.hs
Original file line number Diff line number Diff line change
Expand Up @@ -983,13 +983,20 @@ handleCommand cmd vars args literalCmd = do

handleReturn = do
returnTarget <- reader cfReturnTarget
case returnTarget of
Nothing -> error $ pleaseReport "missing return target"
Just target -> do
isFunction <- reader cfIsFunction
case (returnTarget, isFunction) of
(Nothing, _) -> error $ pleaseReport "missing return target"
(Just target, True) -> do
-- In a function: return actually returns, making subsequent code unreachable
ret <- newNode CFStructuralNode
link ret target CFEFlow
unreachable <- newNode CFUnreachable
return $ Range ret unreachable
(Just _, False) -> do
-- Not in a function: return will fail and execution continues
-- Treat it like a regular command that sets exit code
ret <- newNodeRange $ CFSetExitCode (getId cmd)
return ret

handleUnset (cmd NE.:| args) = do
case () of
Expand Down