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
2 changes: 2 additions & 0 deletions change_notes/2026-02-10-share-autosar-0-1-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- `A0-1-2` - `UnusedReturnValue.ql`:
- Refactors the rule implementation into a shared library for usage in MISRA C++ ruleset. No externally visible changes expected.
35 changes: 5 additions & 30 deletions cpp/autosar/src/rules/A0-1-2/UnusedReturnValue.ql
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,10 @@

import cpp
import codingstandards.cpp.autosar
import codingstandards.cpp.Operator
import cpp
import codingstandards.cpp.rules.unusedreturnvalueshared.UnusedReturnValueShared

/*
* This query performs a simple syntactic check to ensure that the return value of the function is
* not completely ignored. This matches the examples given in the rule, although the text itself is
* not entirely clear. This means it will not find cases where something is done with the return
* value, but it is not meaningfully read. For example: `int ret_val = f();`, with no subsequent
* access of `ret_val`. However, such a case _would_ be flagged by A0-1-1 - Useless assignment.
*/
module UnusedReturnValueConfig implements UnusedReturnValueSharedConfigSig {
Query getQuery() { result = DeadCodePackage::unusedReturnValueQuery() }
}

from FunctionCall fc, Function f
where
not isExcluded(fc, DeadCodePackage::unusedReturnValueQuery()) and
// Find function calls in `ExprStmt`s, which indicate the return value is ignored
fc.getParent() instanceof ExprStmt and
// Ignore calls to void functions, which don't return values
not fc.getUnderlyingType() instanceof VoidType and
// Get the function target
f = fc.getTarget() and
// Overloaded (i.e. user defined) operators should behave in the same way as built-in operators,
// so the rule does not require the use of the return value
not f instanceof Operator and
// Exclude cases where the function call is generated within a macro, as the user of the macro is
// not necessarily able to address those results
not fc.isAffectedByMacro() and
// Rule allows disabling this rule where a static_cast<void> or a C-style cast to void is applied
not exists(Cast cast | cast instanceof StaticCast or cast instanceof CStyleCast |
fc.getExplicitlyConverted() = cast and
cast.getActualType() instanceof VoidType
)
select fc, "Return value from call to $@ is unused.", f, f.getName()
import UnusedReturnValueShared<UnusedReturnValueConfig>
1 change: 0 additions & 1 deletion cpp/autosar/test/rules/A0-1-2/UnusedReturnValue.expected

This file was deleted.

1 change: 0 additions & 1 deletion cpp/autosar/test/rules/A0-1-2/UnusedReturnValue.qlref

This file was deleted.

1 change: 1 addition & 0 deletions cpp/autosar/test/rules/A0-1-2/UnusedReturnValue.testref
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cpp/common/test/rules/unusedreturnvalueshared/UnusedReturnValueShared.ql
26 changes: 26 additions & 0 deletions cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode6.qll
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 DeadCode6Query = TUnusedReturnValueMisraCppQuery()

predicate isDeadCode6QueryMetadata(Query query, string queryId, string ruleId, string category) {
query =
// `Query` instance for the `unusedReturnValueMisraCpp` query
DeadCode6Package::unusedReturnValueMisraCppQuery() and
queryId =
// `@id` for the `unusedReturnValueMisraCpp` query
"cpp/misra/unused-return-value-misra-cpp" and
ruleId = "RULE-0-1-2" and
category = "required"
}

module DeadCode6Package {
Query unusedReturnValueMisraCppQuery() {
//autogenerate `Query` type
result =
// `Query` type for `unusedReturnValueMisraCpp` query
TQueryCPP(TDeadCode6PackageQuery(TUnusedReturnValueMisraCppQuery()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Conversions2
import DeadCode
import DeadCode3
import DeadCode4
import DeadCode6
import Declarations
import ExceptionSafety
import Exceptions1
Expand Down Expand Up @@ -91,6 +92,7 @@ newtype TCPPQuery =
TDeadCodePackageQuery(DeadCodeQuery q) or
TDeadCode3PackageQuery(DeadCode3Query q) or
TDeadCode4PackageQuery(DeadCode4Query q) or
TDeadCode6PackageQuery(DeadCode6Query q) or
TDeclarationsPackageQuery(DeclarationsQuery q) or
TExceptionSafetyPackageQuery(ExceptionSafetyQuery q) or
TExceptions1PackageQuery(Exceptions1Query q) or
Expand Down Expand Up @@ -163,6 +165,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
isDeadCodeQueryMetadata(query, queryId, ruleId, category) or
isDeadCode3QueryMetadata(query, queryId, ruleId, category) or
isDeadCode4QueryMetadata(query, queryId, ruleId, category) or
isDeadCode6QueryMetadata(query, queryId, ruleId, category) or
isDeclarationsQueryMetadata(query, queryId, ruleId, category) or
isExceptionSafetyQueryMetadata(query, queryId, ruleId, category) or
isExceptions1QueryMetadata(query, queryId, ruleId, category) or
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Provides a configurable module UnusedReturnValue with a `problems` predicate
* for the following issue:
* The value returned by a function having a non-void return type that is not an
* overloaded operator shall be used.
*/

import cpp
import codingstandards.cpp.Customizations
import codingstandards.cpp.Exclusions

signature module UnusedReturnValueSharedConfigSig {
Query getQuery();
}

module UnusedReturnValueShared<UnusedReturnValueSharedConfigSig Config> {
/*
* This query performs a simple syntactic check to ensure that the return value of the function is
* not completely ignored. This matches the examples given in the rule, although the text itself is
* not entirely clear. This means it will not find cases where something is done with the return
* value, but it is not meaningfully read. For example: `int ret_val = f();`, with no subsequent
* access of `ret_val`. However, such a case _would_ be flagged by A0-1-1 - Useless assignment.
*/

query predicate problems(FunctionCall fc, string message, Function f, string funcName) {
not isExcluded(fc, Config::getQuery()) and
message = "Return value from call to $@ is unused." and
funcName = f.getName() and
// Find function calls in `ExprStmt`s, which indicate the return value is ignored
fc.getParent() instanceof ExprStmt and
// Ignore calls to void functions, which don't return values
not fc.getUnderlyingType() instanceof VoidType and
// Get the function target
f = fc.getTarget() and
// Overloaded (i.e. user defined) operators should behave in the same way as built-in operators,
// so the rule does not require the use of the return value
not f instanceof Operator and
Comment on lines +35 to +37
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Operator is referenced in not f instanceof Operator, but this file does not import codingstandards.cpp.Operator, so the query will fail to compile. Add the missing import (or replace Operator with the correct type from an already-imported library).

Copilot uses AI. Check for mistakes.
// Exclude cases where the function call is generated within a macro, as the user of the macro is
// not necessarily able to address those results
not fc.isAffectedByMacro() and
// Rule allows disabling this rule where a static_cast<void> or a C-style cast to void is applied
not exists(Cast cast | cast instanceof StaticCast or cast instanceof CStyleCast |
fc.getExplicitlyConverted() = cast and
cast.getActualType() instanceof VoidType
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,11 @@
import cpp
import codingstandards.cpp.CodingStandards
import codingstandards.cpp.exclusions.cpp.RuleMetadata
import codingstandards.cpp.rules.unusedreturnvalueshared.UnusedReturnValueShared

/* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */
/*
* This query performs a simple syntactic check to ensure that the return value of the function is
* not completely ignored. This matches the examples given in the rule, although the text itself is
* not entirely clear. This means it will not find cases where something is done with the return
* value, but it is not meaningfully read. For example: `int ret_val = f();`, with no subsequent
* access of `ret_val`. However, such a case _would_ be flagged by A0-1-1 - Useless assignment.
*/
module UnusedReturnValueConfig implements UnusedReturnValueSharedConfigSig {
Query getQuery() { result = DeadCodePackage::unusedReturnValueQuery() }
}

from FunctionCall fc, Function f
where
not isExcluded(fc, DeadCodePackage::unusedReturnValueQuery()) and
// Find function calls in `ExprStmt`s, which indicate the return value is ignored
fc.getParent() instanceof ExprStmt and
// Ignore calls to void functions, which don't return values
not fc.getType() instanceof VoidType and
// Get the function target
f = fc.getTarget() and
// Overloaded (i.e. user defined) operators should behave in the same way as built-in operators,
// so the rule does not require the use of the return value
not f instanceof Operator and
// Exclude cases where the function call is generated within a macro, as the user of the macro is
// not necessarily able to address thoes results
not fc.isAffectedByMacro() and
// Rule allows disabling this rule where a static_cast<void> is applied
not fc.getExplicitlyConverted().(StaticCast).getActualType() instanceof VoidType
select fc, "Return value from call to $@ is unused.", f, f.getName()
import UnusedReturnValueShared<UnusedReturnValueConfig>
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,11 @@
import cpp
import codingstandards.cpp.CodingStandards
import codingstandards.cpp.exclusions.cpp.RuleMetadata
import codingstandards.cpp.rules.unusedreturnvalueshared.UnusedReturnValueShared

/* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */
/*
* This query performs a simple syntactic check to ensure that the return value of the function is
* not completely ignored. This matches the examples given in the rule, although the text itself is
* not entirely clear. This means it will not find cases where something is done with the return
* value, but it is not meaningfully read. For example: `int ret_val = f();`, with no subsequent
* access of `ret_val`. However, such a case _would_ be flagged by A0-1-1 - Useless assignment.
*/
module UnusedReturnValueConfig implements UnusedReturnValueSharedConfigSig {
Query getQuery() { result = DeadCodePackage::unusedReturnValueQuery() }
}

from FunctionCall fc, Function f
where
not isExcluded(fc, DeadCodePackage::unusedReturnValueQuery()) and
// Find function calls in `ExprStmt`s, which indicate the return value is ignored
fc.getParent() instanceof ExprStmt and
// Ignore calls to void functions, which don't return values
not fc.getType() instanceof VoidType and
// Get the function target
f = fc.getTarget() and
// Overloaded (i.e. user defined) operators should behave in the same way as built-in operators,
// so the rule does not require the use of the return value
not f instanceof Operator and
// Exclude cases where the function call is generated within a macro, as the user of the macro is
// not necessarily able to address thoes results
not fc.isAffectedByMacro() and
// Rule allows disabling this rule where a static_cast<void> is applied
not fc.getExplicitlyConverted().(StaticCast).getActualType() instanceof VoidType
select fc, "Return value from call to $@ is unused.", f, f.getName()
import UnusedReturnValueShared<UnusedReturnValueConfig>
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,11 @@
import cpp
import codingstandards.cpp.CodingStandards
import codingstandards.cpp.exclusions.cpp.RuleMetadata
import codingstandards.cpp.rules.unusedreturnvalueshared.UnusedReturnValueShared

/* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */
/*
* This query performs a simple syntactic check to ensure that the return value of the function is
* not completely ignored. This matches the examples given in the rule, although the text itself is
* not entirely clear. This means it will not find cases where something is done with the return
* value, but it is not meaningfully read. For example: `int ret_val = f();`, with no subsequent
* access of `ret_val`. However, such a case _would_ be flagged by A0-1-1 - Useless assignment.
*/
module UnusedReturnValueConfig implements UnusedReturnValueSharedConfigSig {
Query getQuery() { result = DeadCodePackage::unusedReturnValueQuery() }
}

from FunctionCall fc, Function f
where
not isExcluded(fc, DeadCodePackage::unusedReturnValueQuery()) and
// Find function calls in `ExprStmt`s, which indicate the return value is ignored
fc.getParent() instanceof ExprStmt and
// Ignore calls to void functions, which don't return values
not fc.getType() instanceof VoidType and
// Get the function target
f = fc.getTarget() and
// Overloaded (i.e. user defined) operators should behave in the same way as built-in operators,
// so the rule does not require the use of the return value
not f instanceof Operator and
// Exclude cases where the function call is generated within a macro, as the user of the macro is
// not necessarily able to address thoes results
not fc.isAffectedByMacro() and
// Rule allows disabling this rule where a static_cast<void> is applied
not fc.getExplicitlyConverted().(StaticCast).getActualType() instanceof VoidType
select fc, "Return value from call to $@ is unused.", f, f.getName()
import UnusedReturnValueShared<UnusedReturnValueConfig>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
| test.cpp:15:3:15:3 | call to f | Return value from call to $@ is unused. | test.cpp:3:5:3:5 | f | f |
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// GENERATED FILE - DO NOT MODIFY
import codingstandards.cpp.rules.unusedreturnvalueshared.UnusedReturnValueShared

module TestFileConfig implements UnusedReturnValueSharedConfigSig {
Query getQuery() { result instanceof TestQuery }
}

import UnusedReturnValueShared<TestFileConfig>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ void g(int x);

class A {
public:
A() {
g(2); // Make constructor non-trivial so its call is always extracted.
}
A operator+(const A &other);
};

Expand All @@ -21,6 +24,7 @@ void test_return_val() {
a1 + a2; // COMPLIANT - `+` is a call to operator+, but is permitted by the
// rule

A a3{}; // COMPLIANT - not function call syntax.
(void)f(); // COMPLIANT - explicitly ignoring the return value by C-style cast
// to void.
std::ignore = f(); // COMPLIANT - explicitly ignoring the return value by
Expand Down
23 changes: 23 additions & 0 deletions cpp/misra/src/rules/RULE-0-1-2/UnusedReturnValueMisraCpp.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @id cpp/misra/unused-return-value-misra-cpp
* @name RULE-0-1-2: The value returned by a function shall be used
* @description The result of a non-void function shall be used if called with function call syntax.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/misra/id/rule-0-1-2
* scope/single-translation-unit
* correctness
* external/misra/enforcement/decidable
* external/misra/obligation/required
*/

import cpp
import codingstandards.cpp.misra
import codingstandards.cpp.rules.unusedreturnvalueshared.UnusedReturnValueShared

module UnusedReturnValueMisraCppConfig implements UnusedReturnValueSharedConfigSig {
Query getQuery() { result = DeadCode6Package::unusedReturnValueMisraCppQuery() }
}

import UnusedReturnValueShared<UnusedReturnValueMisraCppConfig>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cpp/common/test/rules/unusedreturnvalueshared/UnusedReturnValueShared.ql
1 change: 1 addition & 0 deletions rule_packages/cpp/DeadCode.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"precision": "very-high",
"severity": "warning",
"short_name": "UnusedReturnValue",
"shared_implementation_short_name": "UnusedReturnValueShared",
"tags": [
"readability",
"maintainability"
Expand Down
26 changes: 26 additions & 0 deletions rule_packages/cpp/DeadCode6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"MISRA-C++-2023": {
"RULE-0-1-2": {
"properties": {
"enforcement": "decidable",
"obligation": "required"
},
"queries": [
{
"description": "The result of a non-void function shall be used if called with function call syntax.",
"kind": "problem",
"name": "The value returned by a function shall be used",
"precision": "very-high",
"severity": "error",
"short_name": "UnusedReturnValueMisraCpp",
"shared_implementation_short_name": "UnusedReturnValueShared",
"tags": [
"scope/single-translation-unit",
"correctness"
]
}
],
"title": "The value returned by a function shall be used"
}
}
}
2 changes: 1 addition & 1 deletion rules.csv
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ c,MISRA-C-2012,RULE-23-8,Yes,Required,,,A default association shall appear as ei
cpp,MISRA-C++-2023,RULE-0-0-1,Yes,Required,Decidable,Single Translation Unit,A function shall not contain unreachable statements,M0-1-1,DeadCode3,Medium,
cpp,MISRA-C++-2023,RULE-0-0-2,Yes,Advisory,Undecidable,System,Controlling expressions should not be invariant,M0-1-2,DeadCode4,Easy,
cpp,MISRA-C++-2023,RULE-0-1-1,Yes,Advisory,Undecidable,System,A value should not be unnecessarily written to a local object,A0-1-1,DeadCode2,Medium,
cpp,MISRA-C++-2023,RULE-0-1-2,Yes,Required,Decidable,Single Translation Unit,The value returned by a function shall be used,A0-1-2,DeadCode2,Easy,
cpp,MISRA-C++-2023,RULE-0-1-2,Yes,Required,Decidable,Single Translation Unit,The value returned by a function shall be used,A0-1-2,DeadCode6,Easy,
cpp,MISRA-C++-2023,RULE-0-2-1,Yes,Advisory,Decidable,Single Translation Unit,Variables with limited visibility should be used at least once,M0-1-3,DeadCode2,Easy,
cpp,MISRA-C++-2023,RULE-0-2-2,Yes,Required,Decidable,Single Translation Unit,A named function parameter shall be used at least once,"A0-1-4, A0-1-5",DeadCode2,Easy,
cpp,MISRA-C++-2023,RULE-0-2-3,Yes,Advisory,Decidable,Single Translation Unit,Types with limited visibility should be used at least once,A0-1-6,DeadCode2,Easy,
Expand Down
Loading