Skip to content
Draft
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c8f559c
Generate query files for "Statements" package
jeongsoolee09 Jul 29, 2025
ffcb432
Add agent-generated first draft
jeongsoolee09 Jul 30, 2025
221b9b2
Add some test cases
jeongsoolee09 Jul 30, 2025
fabb7e5
Finish first draft
jeongsoolee09 Jul 31, 2025
6909528
Add test case for Rule 9.5.2
jeongsoolee09 Aug 1, 2025
0b5250f
Minor
jeongsoolee09 Aug 1, 2025
b239862
Update test case for Rule 9.5.2
jeongsoolee09 Aug 1, 2025
a013388
Add first draft of `ForRangeInitializerAtMostOneFunctionCall`
jeongsoolee09 Aug 1, 2025
1c623f4
Add test cases
jeongsoolee09 Aug 8, 2025
b792897
Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee09 Aug 8, 2025
0d38cd7
Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee09 Aug 8, 2025
c2cbed3
Update unit test
jeongsoolee09 Aug 18, 2025
b7ae38e
Add more cases and more vocabularies to reason about them
jeongsoolee09 Aug 27, 2025
86aaa0e
Fix labeling of two cases
jeongsoolee09 Sep 8, 2025
49bdc07
Add cases of addresses taken as part of non-const declaration or expr…
jeongsoolee09 Sep 8, 2025
01e3276
Finish first draft
jeongsoolee09 Sep 9, 2025
9cab1f5
Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee09 Sep 9, 2025
2f6fc3d
Finish first draft
jeongsoolee09 Sep 10, 2025
999e870
Tidy up, refine a bit more, add a series of test cases
jeongsoolee09 Sep 17, 2025
562c7be
Add two more cases
jeongsoolee09 Sep 17, 2025
6855e6a
Add QLDocs to two helper predicates
jeongsoolee09 Sep 17, 2025
5e24d1b
Introduce `from` variables and fix logical operator association
jeongsoolee09 Sep 22, 2025
18daff7
Introduce newtype
jeongsoolee09 Sep 22, 2025
55b8476
Split cases `5-1` and `5-2`
jeongsoolee09 Sep 22, 2025
662f51f
Debug 5-1-2 and 5-2-2 not being reported
jeongsoolee09 Sep 22, 2025
a653b66
Add LegacyForLoopUpdateExpression and test cases
jeongsoolee09 Sep 23, 2025
c8c0770
Separate out helper classes into libraries
jeongsoolee09 Sep 24, 2025
2227255
Finish draft of `LegacyForStatementsShouldBeSimple`
jeongsoolee09 Sep 24, 2025
38b5fbc
Decouple ForStmt from `Increment.qll` and rewrite `getLoopStepOfForStmt`
jeongsoolee09 Sep 24, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import SideEffects1
import SideEffects2
import SmartPointers1
import SmartPointers2
import Statements
import Strings
import Templates
import Toolchain
Expand Down Expand Up @@ -106,6 +107,7 @@ newtype TCPPQuery =
TSideEffects2PackageQuery(SideEffects2Query q) or
TSmartPointers1PackageQuery(SmartPointers1Query q) or
TSmartPointers2PackageQuery(SmartPointers2Query q) or
TStatementsPackageQuery(StatementsQuery q) or
TStringsPackageQuery(StringsQuery q) or
TTemplatesPackageQuery(TemplatesQuery q) or
TToolchainPackageQuery(ToolchainQuery q) or
Expand Down Expand Up @@ -163,6 +165,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
isSideEffects2QueryMetadata(query, queryId, ruleId, category) or
isSmartPointers1QueryMetadata(query, queryId, ruleId, category) or
isSmartPointers2QueryMetadata(query, queryId, ruleId, category) or
isStatementsQueryMetadata(query, queryId, ruleId, category) or
isStringsQueryMetadata(query, queryId, ruleId, category) or
isTemplatesQueryMetadata(query, queryId, ruleId, category) or
isToolchainQueryMetadata(query, queryId, ruleId, category) or
Expand Down
61 changes: 61 additions & 0 deletions cpp/common/src/codingstandards/cpp/exclusions/cpp/Statements.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
import cpp
import RuleMetadata
import codingstandards.cpp.exclusions.RuleMetadata

newtype StatementsQuery =
TAppropriateStructureOfSwitchStatementQuery() or
TLegacyForStatementsShouldBeSimpleQuery() or
TForRangeInitializerAtMostOneFunctionCallQuery()

predicate isStatementsQueryMetadata(Query query, string queryId, string ruleId, string category) {
query =
// `Query` instance for the `appropriateStructureOfSwitchStatement` query
StatementsPackage::appropriateStructureOfSwitchStatementQuery() and
queryId =
// `@id` for the `appropriateStructureOfSwitchStatement` query
"cpp/misra/appropriate-structure-of-switch-statement" and
ruleId = "RULE-9-4-2" and
category = "required"
or
query =
// `Query` instance for the `legacyForStatementsShouldBeSimple` query
StatementsPackage::legacyForStatementsShouldBeSimpleQuery() and
queryId =
// `@id` for the `legacyForStatementsShouldBeSimple` query
"cpp/misra/legacy-for-statements-should-be-simple" and
ruleId = "RULE-9-5-1" and
category = "advisory"
or
query =
// `Query` instance for the `forRangeInitializerAtMostOneFunctionCall` query
StatementsPackage::forRangeInitializerAtMostOneFunctionCallQuery() and
queryId =
// `@id` for the `forRangeInitializerAtMostOneFunctionCall` query
"cpp/misra/for-range-initializer-at-most-one-function-call" and
ruleId = "RULE-9-5-2" and
category = "required"
}

module StatementsPackage {
Query appropriateStructureOfSwitchStatementQuery() {
//autogenerate `Query` type
result =
// `Query` type for `appropriateStructureOfSwitchStatement` query
TQueryCPP(TStatementsPackageQuery(TAppropriateStructureOfSwitchStatementQuery()))
}

Query legacyForStatementsShouldBeSimpleQuery() {
//autogenerate `Query` type
result =
// `Query` type for `legacyForStatementsShouldBeSimple` query
TQueryCPP(TStatementsPackageQuery(TLegacyForStatementsShouldBeSimpleQuery()))
}

Query forRangeInitializerAtMostOneFunctionCallQuery() {
//autogenerate `Query` type
result =
// `Query` type for `forRangeInitializerAtMostOneFunctionCall` query
TQueryCPP(TStatementsPackageQuery(TForRangeInitializerAtMostOneFunctionCallQuery()))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* @id cpp/misra/appropriate-structure-of-switch-statement
* @name RULE-9-4-2: The structure of a switch statement shall be appropriate
* @description A switch statement should have an appropriate structure with proper cases, default
* labels, and break statements to ensure clear control flow and prevent unintended
* fall-through behavior.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-9-4-2
* correctness
* maintainability
* readability
* external/misra/allocated-target/single-translation-unit
* external/misra/enforcement/decidable
* external/misra/obligation/required
*/

import cpp
import codingstandards.cpp.misra
import codingstandards.cpp.SwitchStatement
import codingstandards.cpp.Noreturn

from SwitchStmt switch, string message
where
not isExcluded(switch, StatementsPackage::appropriateStructureOfSwitchStatementQuery()) and
/* 1. There is a statement that appears as an initializer and is not a declaration statement. */
exists(Stmt initializer | initializer = switch.getInitialization() |
not initializer instanceof DeclStmt
) and
message = "contains a statement that that is not a simple declaration"
or
/* 2. There is a switch case label that does not lead a branch (i.e. a switch case label is nested). */
exists(SwitchCase case | case = switch.getASwitchCase() | case instanceof NestedSwitchCase) and
message = "contains a switch label that is not directly within the switch body"
or
/* 3. There is a non-case label in a label group. */
exists(SwitchCase case | case = switch.getASwitchCase() |
case.getAStmt().getChildStmt*() instanceof LabelStmt
) and
message = "contains a statement label that is not a case label"
or
/* 4. There is a statement before the first case label. */
exists(Stmt switchBody | switchBody = switch.getStmt() |
not switchBody.getChild(0) instanceof SwitchCase
) and
message = "has a statement that is not a case label as its first element"
or
/* 5. There is a switch case whose terminator is not one of the allowed kinds. */
exists(SwitchCase case, Stmt lastStmt |
case = switch.getASwitchCase() and lastStmt = case.getLastStmt()
|
not (
lastStmt instanceof BreakStmt or
lastStmt instanceof ReturnStmt or
lastStmt instanceof GotoStmt or
lastStmt instanceof ContinueStmt or
lastStmt.(ExprStmt).getExpr() instanceof ThrowExpr or
lastStmt.(ExprStmt).getExpr().(Call).getTarget() instanceof NoreturnFunction or
lastStmt.getAnAttribute().getName().matches("%fallthrough") // We'd like to consider compiler variants such as `clang::fallthrough`.
)
) and
message = "is missing a terminator that moves the control out of its body"
or
/* 6. The switch statement does not have more than two unique branches. */
count(SwitchCase case |
case = switch.getASwitchCase() and
/*
* If the next switch case is the following statement of this switch case, then the two
* switch cases are consecutive and should be considered as constituting one branch
* together.
*/

not case.getNextSwitchCase() = case.getFollowingStmt()
|
case
) < 2 and
message = "contains less than two branches"
or
/* 7-1. The switch statement is not an enum switch statement and is missing a default case. */
not switch instanceof EnumSwitch and
not switch.hasDefaultCase() and
message = "lacks a default case"
or
/*
* 7-2. The switch statement is an enum switch statement and is missing a branch for a
* variant.
*/

exists(switch.(EnumSwitch).getAMissingCase()) and
message = "lacks a case for one of its variants"
select switch, "Switch statement " + message + "."
Loading
Loading