diff --git a/change_notes/2024-02-26-exclusion-M5-14-1.md b/change_notes/2024-02-26-exclusion-M5-14-1.md new file mode 100644 index 0000000000..e60ccd0319 --- /dev/null +++ b/change_notes/2024-02-26-exclusion-M5-14-1.md @@ -0,0 +1,2 @@ +- `M5-14-1` - `RightHandOperandOfALogicalAndOperatorsContainSideEffects.ql`: + - Fix FP reported in #375. Addresses incorrect detection of side effects in unevaluated contexts. \ No newline at end of file diff --git a/cpp/autosar/src/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.ql b/cpp/autosar/src/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.ql index 0819259a25..871e9828c8 100644 --- a/cpp/autosar/src/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.ql +++ b/cpp/autosar/src/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.ql @@ -18,11 +18,13 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.SideEffect import codingstandards.cpp.sideeffect.DefaultEffects +import codingstandards.cpp.Expr from BinaryLogicalOperation op, Expr rhs where not isExcluded(op, SideEffects1Package::rightHandOperandOfALogicalAndOperatorsContainSideEffectsQuery()) and rhs = op.getRightOperand() and - hasSideEffect(rhs) + hasSideEffect(rhs) and + not rhs instanceof UnevaluatedExprExtension select op, "The $@ may have a side effect that is not always evaluated.", rhs, "right-hand operand" diff --git a/cpp/autosar/test/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.expected b/cpp/autosar/test/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.expected index f693f1a4be..75b3a45304 100644 --- a/cpp/autosar/test/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.expected +++ b/cpp/autosar/test/rules/M5-14-1/RightHandOperandOfALogicalAndOperatorsContainSideEffects.expected @@ -1,3 +1,4 @@ | test.cpp:15:7:15:14 | ... \|\| ... | The $@ may have a side effect that is not always evaluated. | test.cpp:15:12:15:14 | ... ++ | right-hand operand | | test.cpp:18:7:18:21 | ... \|\| ... | The $@ may have a side effect that is not always evaluated. | test.cpp:18:13:18:20 | ... == ... | right-hand operand | | test.cpp:21:7:21:15 | ... \|\| ... | The $@ may have a side effect that is not always evaluated. | test.cpp:21:12:21:13 | call to f1 | right-hand operand | +| test.cpp:40:7:40:41 | ... \|\| ... | The $@ may have a side effect that is not always evaluated. | test.cpp:40:26:40:26 | call to operator== | right-hand operand | diff --git a/cpp/autosar/test/rules/M5-14-1/test.cpp b/cpp/autosar/test/rules/M5-14-1/test.cpp index 2833b4fd44..76fd08c2ca 100644 --- a/cpp/autosar/test/rules/M5-14-1/test.cpp +++ b/cpp/autosar/test/rules/M5-14-1/test.cpp @@ -23,4 +23,20 @@ void f3(bool b) { if (b || f2()) { // COMPLIANT, f2 has local side-effects } +} + +int g1 = 0; +int f4() { return g1++; } +int f5() { return 1; } + +#include + +void f6() { + if (1 && sizeof(f4())) { + } // COMPLIANT - sizeof operands not evaluated + if (1 &&noexcept(f4()) &&noexcept(f4())) { + } // COMPLIANT - noexcept operands not evaluated + + if (1 || (typeid(f5()) == typeid(f4()))) { + } // NON_COMPLIANT - typeid operands not evaluated, but the ==operator is } \ No newline at end of file diff --git a/cpp/common/src/codingstandards/cpp/Expr.qll b/cpp/common/src/codingstandards/cpp/Expr.qll index 86d04e70df..029a5b7c03 100644 --- a/cpp/common/src/codingstandards/cpp/Expr.qll +++ b/cpp/common/src/codingstandards/cpp/Expr.qll @@ -189,3 +189,17 @@ module MisraExpr { CValue() { isCValue(this) } } } + +/** + * an operator that does not evaluate its operand + */ +class UnevaluatedExprExtension extends Expr { + UnevaluatedExprExtension() { + this.getAChild().isUnevaluated() + or + exists(FunctionCall declval | + declval.getTarget().hasQualifiedName("std", "declval") and + declval.getAChild() = this + ) + } +} diff --git a/cpp/common/test/includes/standard-library/typeinfo.h b/cpp/common/test/includes/standard-library/typeinfo.h index dbe2d07503..6be058f090 100644 --- a/cpp/common/test/includes/standard-library/typeinfo.h +++ b/cpp/common/test/includes/standard-library/typeinfo.h @@ -4,5 +4,6 @@ namespace std { struct type_info { const char *name() const noexcept; std::size_t hash_code() const noexcept; + bool operator==(const type_info &rhs) const; }; } // namespace std \ No newline at end of file