- Notifications
You must be signed in to change notification settings - Fork70
Implement "Statements" package#938
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
Show all changes
55 commits Select commitHold shift + click to select a range
c8f559c Generate query files for "Statements" package
jeongsoolee09ffcb432 Add agent-generated first draft
jeongsoolee09221b9b2 Add some test cases
jeongsoolee09fabb7e5 Finish first draft
jeongsoolee096909528 Add test case for Rule 9.5.2
jeongsoolee090b5250f Minor
jeongsoolee09b239862 Update test case for Rule 9.5.2
jeongsoolee09a013388 Add first draft of `ForRangeInitializerAtMostOneFunctionCall`
jeongsoolee091c623f4 Add test cases
jeongsoolee09b792897 Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee090d38cd7 Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee09c2cbed3 Update unit test
jeongsoolee09b7ae38e Add more cases and more vocabularies to reason about them
jeongsoolee0986aaa0e Fix labeling of two cases
jeongsoolee0949bdc07 Add cases of addresses taken as part of non-const declaration or expr…
jeongsoolee0901e3276 Finish first draft
jeongsoolee099cab1f5 Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee092f6fc3d Finish first draft
jeongsoolee09999e870 Tidy up, refine a bit more, add a series of test cases
jeongsoolee09562c7be Add two more cases
jeongsoolee096855e6a Add QLDocs to two helper predicates
jeongsoolee095e24d1b Introduce `from` variables and fix logical operator association
jeongsoolee0918daff7 Introduce newtype
jeongsoolee0955b8476 Split cases `5-1` and `5-2`
jeongsoolee09662f51f Debug 5-1-2 and 5-2-2 not being reported
jeongsoolee09a653b66 Add LegacyForLoopUpdateExpression and test cases
jeongsoolee09c8c0770 Separate out helper classes into libraries
jeongsoolee092227255 Finish draft of `LegacyForStatementsShouldBeSimple`
jeongsoolee0938b5fbc Decouple ForStmt from `Increment.qll` and rewrite `getLoopStepOfForStmt`
jeongsoolee0923aa711 Update expected result of `RULE-9-5-1`
jeongsoolee09f0b53e2 Update expected results of `RULE-9-5-2`
jeongsoolee097d5f08b Count in typedefs and cv-qualifiers
jeongsoolee09e135fe6 Fix cross-join issue in `TLoopCounterUpdatedNotByCrementOrAddSubAssig…
jeongsoolee09b13ffd2 Slightly change wording in the message
jeongsoolee0982f9adc Make the loop counter detection more relaxed
jeongsoolee092116400 Refine `LegacyForLoopCondition`
jeongsoolee091f8083a Change phrasing of message from `TNoRelationalOperatorInLoopCondition`
jeongsoolee091355eff Use `upperbound/0` and `getFullyConverted/0` to more precisely infer …
jeongsoolee093ad5ef2 Apply suggestion from @Copilot
jeongsoolee09fb20065 Apply suggestion from @Copilot
jeongsoolee09bce38a0 Reformat test cases of 9-4-2 and 9-5-2
jeongsoolee0932c36fe Merge branch 'jeongsoolee09/MISRA-C++-2023-Statements' of github.com:…
jeongsoolee09c0a8253 Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee0959a4096 Update expected results coming from change in message
jeongsoolee09d37bc70 Use different range predicate and update tests
jeongsoolee0925e29e4 Refine `TLoopCounterMutatedInLoopBody`
jeongsoolee0901216fa Add more candidate exprs and remove duplicate reportings on compound …
jeongsoolee090f998ea Add more test cases
jeongsoolee0987a5158 Fix loop counter -> loop bound
jeongsoolee092aed0f1 Add const-but-mutable pointer examples
jeongsoolee0933222ae Debug loopVariableAssignedToNonConstPointOrReferenceType
jeongsoolee093dca053 Update expected results of 9-5-1
jeongsoolee0915be010 Enforce loop counter to be variable access and add tests
jeongsoolee096ffd229 Expose mutating / assignment rhs expressions
jeongsoolee092163c54 Merge branch 'main' into jeongsoolee09/MISRA-C++-2023-Statements
jeongsoolee09File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
37 changes: 37 additions & 0 deletionscpp/common/src/codingstandards/cpp/Loops.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
76 changes: 76 additions & 0 deletionscpp/common/src/codingstandards/cpp/ast/Increment.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,76 @@ | ||
| /** | ||
| * Provides a library for working with expressions that update the value | ||
| * of a numeric variable by incrementing or decrementing it by a certain | ||
| * amount. | ||
| */ | ||
| import cpp | ||
| private class AssignAddOrSubExpr extends AssignArithmeticOperation { | ||
| AssignAddOrSubExpr() { | ||
| this instanceof AssignAddExpr or | ||
| this instanceof AssignSubExpr | ||
| } | ||
| } | ||
| private class AddOrSubExpr extends BinaryArithmeticOperation { | ||
| AddOrSubExpr() { | ||
| this instanceof AddExpr or | ||
| this instanceof SubExpr | ||
| } | ||
| } | ||
| /** | ||
| * An expression that updates a numeric variable by adding to or subtracting | ||
| * from it a certain amount. | ||
| */ | ||
| abstract class StepCrementUpdateExpr extends Expr { | ||
| /** | ||
| * The expression in the abstract syntax tree that represents the amount of | ||
| * value by which the variable is updated. | ||
| */ | ||
| abstract Expr getAmountExpr(); | ||
| } | ||
| /** | ||
| * An increment or decrement operator application, either postfix or prefix. | ||
| */ | ||
| class PostfixOrPrefixCrementExpr extends CrementOperation, StepCrementUpdateExpr { | ||
| override Expr getAmountExpr() { none() } | ||
| } | ||
| /** | ||
| * An add-then-assign or subtract-then-assign expression in a shortened form, | ||
| * i.e. `+=` or `-=`. | ||
| */ | ||
| class AssignAddOrSubUpdateExpr extends AssignAddOrSubExpr, StepCrementUpdateExpr { | ||
| override Expr getAmountExpr() { result = this.getRValue() } | ||
| } | ||
| /** | ||
| * An add-then-assign expression or a subtract-then-assign expression, i.e. | ||
| * `x = x + E` or `x = x - E`, where `x` is some variable and `E` an | ||
| * arbitrary expression. | ||
| */ | ||
| class AddOrSubThenAssignExpr extends AssignExpr, StepCrementUpdateExpr { | ||
| /** The `x` as in the left-hand side of `x = x + E`. */ | ||
| VariableAccess lvalueVariable; | ||
| /** The `x + E` as in `x = x + E`. */ | ||
| AddOrSubExpr addOrSubExpr; | ||
| /** The `E` as in `x = x + E`. */ | ||
| Expr amountExpr; | ||
| AddOrSubThenAssignExpr() { | ||
| this.getLValue() = lvalueVariable and | ||
| this.getRValue() = addOrSubExpr and | ||
| exists(VariableAccess lvalueVariableAsRvalue | | ||
| lvalueVariableAsRvalue = addOrSubExpr.getAnOperand() and | ||
| amountExpr = addOrSubExpr.getAnOperand() and | ||
| lvalueVariableAsRvalue != amountExpr | ||
| | | ||
| lvalueVariable.getTarget() = lvalueVariableAsRvalue.(VariableAccess).getTarget() | ||
| ) | ||
| } | ||
| override Expr getAmountExpr() { result = amountExpr } | ||
| } |
3 changes: 3 additions & 0 deletionscpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.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
61 changes: 61 additions & 0 deletionscpp/common/src/codingstandards/cpp/exclusions/cpp/Statements.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,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())) | ||
| } | ||
| } |
92 changes: 92 additions & 0 deletionscpp/misra/src/rules/RULE-9-4-2/AppropriateStructureOfSwitchStatement.ql
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,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 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 + "." |
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
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.