Skip to content

Commit d8de842

Browse files
Merge pull request #1176 from castler/fix_7_0_1_bool_reference_fp
Fix RULE-7-0-1 false positives for bool-to-reference bindings
2 parents cbebd13 + 6f872c7 commit d8de842

3 files changed

Lines changed: 56 additions & 0 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
- `RULE-7-0-1` - `NoConversionFromBool.ql`:
2+
- Fixed false positives where a `bool` value is bound to a reference whose
3+
referenced type is also `bool` (e.g. `bool&`, `const bool&`), including
4+
when this happens via a generic/forwarding-reference parameter (e.g.
5+
`template<class T> void f(T&& t)`, or class template forwarding
6+
constructors such as `std::pair`'s `pair(U1&&, U2&&)`) that happens to be
7+
instantiated with `bool`. Binding a value to a reference of its own type
8+
does not change the type or representation of the value, so this is not
9+
a conversion from `bool` in the sense intended by the rule.

cpp/misra/src/rules/RULE-7-0-1/NoConversionFromBool.ql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ where
2323
conv = e.getConversion() and
2424
conv.getExpr().getType().stripTopLevelSpecifiers() instanceof BoolType and
2525
not conv.getType().stripTopLevelSpecifiers() instanceof BoolType and
26+
// Exclude conversions that only bind a `bool` value to a reference to `bool`
27+
// (e.g. `bool&`, `const bool&`). Binding a value to a reference of its own
28+
// type does not change the type or representation of the value, so this is
29+
// not a "conversion from bool" in the sense intended by the rule. This
30+
// commonly occurs when a `bool` argument is forwarded through a generic
31+
// `bool&`/`const bool&` parameter (e.g. logging helpers, `std::pair`-style
32+
// structured bindings/aggregates).
33+
not conv.getType()
34+
.stripTopLevelSpecifiers()
35+
.(ReferenceType)
36+
.getBaseType()
37+
.stripTopLevelSpecifiers() instanceof BoolType and
2638
// Exclude cases that are explicitly allowed
2739
not (
2840
// Exception: equality operators with both bool operands

cpp/misra/test/rules/RULE-7-0-1/test.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,39 @@ void test_bool_conversion_compliant() {
122122

123123
// Bit-field assignment exception - compliant
124124
bf.bit = b1; // COMPLIANT
125+
}
126+
127+
void f3(bool &b) {}
128+
void f4(const bool &b) {}
129+
130+
template <typename T> void f5(T &&t) {}
131+
132+
template <typename T1, typename T2> struct Pair {
133+
template <typename U1, typename U2> Pair(U1 &&x, U2 &&y) : a(x), b(y) {}
134+
T1 a;
135+
T2 b;
136+
};
137+
138+
void test_bool_reference_conversion_compliant() {
139+
bool b1 = true;
140+
141+
// Binding a bool lvalue to a bool reference parameter - compliant, no
142+
// actual type conversion takes place.
143+
f3(b1); // COMPLIANT
144+
145+
// Binding a bool value to a const bool reference parameter - compliant.
146+
f4(b1); // COMPLIANT
147+
f4(true); // COMPLIANT
148+
149+
// Binding a bool value to a forwarding reference parameter deduced as
150+
// bool - compliant.
151+
f5(b1); // COMPLIANT
152+
f5(true); // COMPLIANT
153+
154+
// Binding a bool value through a generic forwarding-reference constructor,
155+
// where the second template parameter is deduced as bool - compliant. This
156+
// mirrors idiomatic `return {value, overflow_flag};` and structured-binding
157+
// patterns (e.g. std::pair and std::map::insert()'s return value).
158+
Pair<int, bool> p1{1, true}; // COMPLIANT
159+
Pair<int, bool> p2 = {1, b1}; // COMPLIANT
125160
}

0 commit comments

Comments
 (0)