-
Notifications
You must be signed in to change notification settings - Fork 71
Implement Rule 0-0-1, unreachable statements from DeadCode package #1001
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MichaelRFairhurst
wants to merge
2
commits into
main
Choose a base branch
from
michaelrfairhurst/dead-code-3-unreachable-stmts-0-0-1
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
6 changes: 6 additions & 0 deletions
6
change_notes/2025-12-15-update-catch-block-shadowing-dead-code.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| - `M0-1-1`, `RULE-2-1` - `UnreachableCode.ql`: | ||
| - Updated detection of compiler generated code to include "handler" blocks, part of EDG's IR. | ||
| - "handler" blocks generated for `catch(...)` blocks are not excluded for technical reasons related to how the CFG is constructed. | ||
| - `M15-3-6`, `ERR54-CPP` - `CatchBlockShadowingMisra.ql`, `CathcBlockShadowingCert.ql`: | ||
| - Altered semantics to detect shadowing for a catch block involving type `T` preceding another catch block involving the same type `T`, such as `catch(T&)` shadowing `catch(T)` and vice versa. Previously, the involved types had to have a subtype relationship. | ||
| - Refactored catch block shadowing into a shared library for use in `RULE-0-0-1`. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import cpp | ||
|
|
||
| CatchBlock getEarlierCatchBlock(CatchBlock cb) { | ||
| exists(TryStmt try, int i, int j | | ||
| cb = try.getCatchClause(j) and | ||
| i < j and | ||
| result = try.getCatchClause(i) | ||
| ) | ||
| } | ||
|
|
||
| /** | ||
| * Get the body of a catch block, ie, the block of statements executed when the catch block is | ||
| * entered. | ||
| * | ||
| * This is useful, for instance, for CFG traversal | ||
| */ | ||
| Stmt getCatchBody(CatchBlock cb) { result = cb.getChild(0) } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
cpp/common/src/codingstandards/cpp/exceptions/Shadowing.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| import cpp | ||
| import codingstandards.cpp.ast.Catch | ||
| import codingstandards.cpp.exceptions.ExceptionFlow | ||
|
|
||
| /** | ||
| * A catch block which is shadowed by an earlier catch block for a base type. | ||
| * | ||
| * For example: | ||
| * | ||
| * ```cpp | ||
| * class Base { }; | ||
| * class Derived : public Base { }; | ||
| * | ||
| * try { | ||
| * // ... | ||
| * } catch (const Base& b) { // This catch block shadows the next one | ||
| * // Handle Base | ||
| * } catch (const Derived& d) { // This catch block is shadowed | ||
| * // Handle Derived | ||
| * } | ||
| * ``` | ||
| */ | ||
| class ShadowedCatchBlock extends CatchBlock { | ||
| CatchBlock cbBase; | ||
| Class baseType; | ||
| Class derivedType; | ||
|
|
||
| ShadowedCatchBlock() { | ||
| cbBase = getEarlierCatchBlock(this) and | ||
| baseType = simplifyHandlerType(cbBase.getParameter().getType()) and | ||
| derivedType = simplifyHandlerType(this.getParameter().getType()) and | ||
| baseType.getADerivedClass*() = derivedType | ||
| } | ||
|
|
||
| /** | ||
| * Get the earlier catch block which shadows this catch block. | ||
| */ | ||
| CatchBlock getShadowingBlock() { result = cbBase } | ||
|
|
||
| /** | ||
| * Get the type of this catch block's derived class whose catch block is shadowed by an earlier | ||
| * catch block. | ||
| */ | ||
| Class getShadowedType() { result = derivedType } | ||
|
|
||
| /** | ||
| * Get the type of the base class whose catch block precedes, and thus shadows, this catch block. | ||
| */ | ||
| Class getShadowingType() { result = baseType } | ||
| } |
26 changes: 26 additions & 0 deletions
26
cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode3.qll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| //** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ | ||
| import cpp | ||
| import RuleMetadata | ||
| import codingstandards.cpp.exclusions.RuleMetadata | ||
|
|
||
| newtype DeadCode3Query = TUnreachableStatementQuery() | ||
|
|
||
| predicate isDeadCode3QueryMetadata(Query query, string queryId, string ruleId, string category) { | ||
| query = | ||
| // `Query` instance for the `unreachableStatement` query | ||
| DeadCode3Package::unreachableStatementQuery() and | ||
| queryId = | ||
| // `@id` for the `unreachableStatement` query | ||
| "cpp/misra/unreachable-statement" and | ||
| ruleId = "RULE-0-0-1" and | ||
| category = "required" | ||
| } | ||
|
|
||
| module DeadCode3Package { | ||
| Query unreachableStatementQuery() { | ||
| //autogenerate `Query` type | ||
| result = | ||
| // `Query` type for `unreachableStatement` query | ||
| TQueryCPP(TDeadCode3PackageQuery(TUnreachableStatementQuery())) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| /** | ||
| * @id cpp/misra/unreachable-statement | ||
| * @name RULE-0-0-1: A function shall not contain unreachable statements | ||
| * @description Dead code can indicate a logic error, potentially introduced during code edits, or | ||
| * it may be unnecessary code that can be deleted. | ||
| * @kind problem | ||
| * @precision very-high | ||
| * @problem.severity error | ||
| * @tags external/misra/id/rule-0-0-1 | ||
| * maintainability | ||
| * scope/single-translation-unit | ||
| * external/misra/enforcement/decidable | ||
| * external/misra/obligation/required | ||
| */ | ||
|
|
||
| import cpp | ||
| import codingstandards.cpp.misra | ||
| import codingstandards.cpp.deadcode.UnreachableCode | ||
| import codingstandards.cpp.exceptions.ExceptionFlow | ||
| import codingstandards.cpp.exceptions.ExceptionSpecifications | ||
| import codingstandards.cpp.exceptions.Shadowing | ||
|
|
||
| /** | ||
| * MISRA C++ defines its own notion of unreachable statements, which is similar to, but distinct | ||
| * from, the general concept of unreachable code. | ||
| * | ||
| * This is not a superset of `BasicBlock.isReachable()`, because that includes all catch blocks. | ||
| * However, it is a superset of the transitive closure of blocks reachable from function entry via | ||
| * `getASuccessor`. | ||
| * | ||
| * The superset relationship can be read below, with extra reachable cases added for `&&`, `||`, | ||
| * `?:`, and `constexpr if`, and catch blocks that aren't shadowed by prior catch blocks. | ||
| */ | ||
| predicate isReachable(BasicBlock bb) { | ||
| bb = any(Function f).getEntryPoint() | ||
| or | ||
| isReachable(bb.getAPredecessor()) | ||
| or | ||
| exists(BinaryLogicalOperation op | | ||
| isReachable(op.getBasicBlock()) and | ||
| bb = op.getAnOperand().getBasicBlock() | ||
| ) | ||
| or | ||
| exists(ConditionalExpr cond | | ||
| isReachable(cond.getBasicBlock()) and | ||
| bb = [cond.getThen(), cond.getElse()].getBasicBlock() | ||
| ) | ||
| or | ||
| exists(FunctionCall call, TryStmt try, CatchBlock cb | | ||
| isReachable(call.getBasicBlock()) and | ||
| not isNoExceptTrue(call.getTarget()) and | ||
| try = getNearestTry(call.getEnclosingStmt()) and | ||
| cb = try.getACatchClause() and | ||
| not cb instanceof ShadowedCatchBlock and | ||
| bb = cb.getBasicBlock() | ||
| ) | ||
| or | ||
| exists(ConstexprIfStmt ifStmt | | ||
| isReachable(ifStmt.getBasicBlock()) and | ||
| bb = [ifStmt.getThen(), ifStmt.getElse()].getBasicBlock() | ||
| ) | ||
| } | ||
|
|
||
| from BasicBlock bb | ||
| where | ||
| not isExcluded(bb, DeadCode3Package::unreachableStatementQuery()) and | ||
| not isReachable(bb) and | ||
| not isCompilerGenerated(bb) and | ||
| not affectedByMacro(bb) | ||
| select bb, "Unreachable statement in function '$@'.", bb.getEnclosingFunction(), | ||
| bb.getEnclosingFunction().getName() |
28 changes: 28 additions & 0 deletions
28
cpp/misra/test/rules/RULE-0-0-1/UnreachableStatement.expected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| | test.cpp:7:3:7:12 | declaration | Unreachable statement in function '$@'. | test.cpp:5:6:5:7 | f2 | f2 | | ||
| | test.cpp:18:14:19:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:10:6:10:7 | f3 | f3 | | ||
| | test.cpp:26:10:27:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:10:6:10:7 | f3 | f3 | | ||
| | test.cpp:43:5:43:14 | declaration | Unreachable statement in function '$@'. | test.cpp:40:6:40:7 | f4 | f4 | | ||
| | test.cpp:52:5:52:14 | declaration | Unreachable statement in function '$@'. | test.cpp:40:6:40:7 | f4 | f4 | | ||
| | test.cpp:63:3:63:12 | declaration | Unreachable statement in function '$@'. | test.cpp:40:6:40:7 | f4 | f4 | | ||
| | test.cpp:70:10:71:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:66:6:66:7 | f5 | f5 | | ||
| | test.cpp:75:11:76:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:66:6:66:7 | f5 | f5 | | ||
| | test.cpp:89:10:90:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:88:24:88:24 | f6 | f6 | | ||
| | test.cpp:92:10:93:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:88:24:88:24 | f6 | f6 | | ||
| | test.cpp:114:5:114:14 | declaration | Unreachable statement in function '$@'. | test.cpp:109:6:109:7 | f8 | f8 | | ||
| | test.cpp:119:5:119:14 | declaration | Unreachable statement in function '$@'. | test.cpp:109:6:109:7 | f8 | f8 | | ||
| | test.cpp:131:3:131:12 | declaration | Unreachable statement in function '$@'. | test.cpp:109:6:109:7 | f8 | f8 | | ||
| | test.cpp:135:18:136:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:134:6:134:7 | f9 | f9 | | ||
| | test.cpp:146:5:146:14 | declaration | Unreachable statement in function '$@'. | test.cpp:134:6:134:7 | f9 | f9 | | ||
| | test.cpp:158:3:134:7 | declaration | Unreachable statement in function '$@'. | test.cpp:134:6:134:7 | f9 | f9 | | ||
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| | test.cpp:162:17:163:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:161:6:161:8 | f10 | f10 | | ||
| | test.cpp:173:5:173:14 | declaration | Unreachable statement in function '$@'. | test.cpp:161:6:161:8 | f10 | f10 | | ||
| | test.cpp:185:3:161:8 | declaration | Unreachable statement in function '$@'. | test.cpp:161:6:161:8 | f10 | f10 | | ||
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| | test.cpp:192:3:190:8 | declaration | Unreachable statement in function '$@'. | test.cpp:190:6:190:8 | f11 | f11 | | ||
MichaelRFairhurst marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| | test.cpp:213:30:214:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
| | test.cpp:215:27:216:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
| | test.cpp:217:17:218:14 | <handler> | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
| | test.cpp:225:30:226:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
| | test.cpp:233:30:234:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
| | test.cpp:235:24:236:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
| | test.cpp:237:23:238:14 | { ... } | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
| | test.cpp:246:19:247:16 | <handler> | Unreachable statement in function '$@'. | test.cpp:200:6:200:8 | f12 | f12 | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| rules/RULE-0-0-1/UnreachableStatement.ql |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.