diff --git a/change_notes/2024-04-12-fix-fp-m9-3-3.md b/change_notes/2024-04-12-fix-fp-m9-3-3.md new file mode 100644 index 0000000000..bbc9fb9ab0 --- /dev/null +++ b/change_notes/2024-04-12-fix-fp-m9-3-3.md @@ -0,0 +1,2 @@ +`M9-3-3`: `MemberFunctionConstIfPossible.ql`: + - Fix FP reported in 381. Omit member functions that return nonconst reference types. \ No newline at end of file diff --git a/cpp/autosar/src/rules/M9-3-3/MemberFunctionConstIfPossible.ql b/cpp/autosar/src/rules/M9-3-3/MemberFunctionConstIfPossible.ql index 66a3affa24..3c8bab4d1f 100644 --- a/cpp/autosar/src/rules/M9-3-3/MemberFunctionConstIfPossible.ql +++ b/cpp/autosar/src/rules/M9-3-3/MemberFunctionConstIfPossible.ql @@ -37,6 +37,13 @@ class NonConstMemberFunction extends MemberFunction { NonConstMemberFunction() { not this.hasSpecifier("const") } } +/** + * References that are not const + */ +class NonConstReferenceType extends ReferenceType { + NonConstReferenceType() { not this.isConst() } +} + /** * `MemberFunction`s that are not const * and not `Constructor`s ect as const constructors are @@ -57,7 +64,9 @@ class ConstMemberFunctionCandidate extends NonConstMemberFunction { this.hasDefinition() and // For uninstantiated templates we have only partial information that prevents us from determining // if the candidate calls non-const functions. Therefore we exclude these. - not this.isFromUninstantiatedTemplate(_) + not this.isFromUninstantiatedTemplate(_) and + // Cannot recommend const if it returns a non-const reference. + not this.getType() instanceof NonConstReferenceType } /** diff --git a/cpp/autosar/test/rules/M9-3-3/test.cpp b/cpp/autosar/test/rules/M9-3-3/test.cpp index 704a4ae5fd..5469b41d5c 100644 --- a/cpp/autosar/test/rules/M9-3-3/test.cpp +++ b/cpp/autosar/test/rules/M9-3-3/test.cpp @@ -193,3 +193,25 @@ void test_template() { class Z3 { void f(int) = delete; // COMPLIANT }; + +class Z4 { +public: + int values[128]; + template + void fill(const T &val) { // COMPLIANT[FALSE_NEGATIVE|TRUE_NEGATIVE] - + // exception not specified in the + // standard, we opt to not raise an issue because the template can be both + // compliant and non-compliant depending on instantiations. + for (auto &elem : values) { + elem = val; + } + } + constexpr int &front() noexcept { return values[0]; } // COMPLIANT +}; + +void fp_reported_in_381() { + // added to test template initialization effects/lack thereof + Z4 z; + int i = z.front(); + z.fill(i); +} \ No newline at end of file