Skip to content

Commit a013388

Browse files
committed
Add first draft of ForRangeInitializerAtMostOneFunctionCall
1 parent b239862 commit a013388

File tree

3 files changed

+43
-28
lines changed

3 files changed

+43
-28
lines changed

cpp/misra/src/rules/RULE-9-5-2/ForRangeInitializerAtMostOneFunctionCall.ql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import cpp
2020
import codingstandards.cpp.misra
2121

22-
from
22+
from RangeBasedForStmt foreach, string message
2323
where
24-
not isExcluded(x, StatementsPackage::forRangeInitializerAtMostOneFunctionCallQuery()) and
25-
select
24+
not isExcluded(foreach, StatementsPackage::forRangeInitializerAtMostOneFunctionCallQuery()) and
25+
count(Call call | call = foreach.getRange().getAChild*() | call) >= 2 and
26+
message = "has nested call expression in its initializer"
27+
select foreach, "Range-based for loop " + message + "."
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1-
No expected results have yet been specified
1+
| test.cpp:48:3:49:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |
2+
| test.cpp:56:3:59:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |
3+
| test.cpp:71:3:73:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |
4+
| test.cpp:95:3:97:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |
5+
| test.cpp:99:3:101:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |
6+
| test.cpp:103:3:107:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |
7+
| test.cpp:116:3:119:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |
8+
| test.cpp:121:3:124:3 | for(...:...) ... | Range-based for loop has nested call expression in its initializer. |

cpp/misra/test/rules/RULE-9-5-2/test.cpp

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include <vector>
21
#include <array>
2+
#include <vector>
33

44
/* Helper functions */
55
std::vector<int> getData() { return {1, 2, 3}; }
@@ -10,8 +10,8 @@ class MyContainer {
1010
public:
1111
MyContainer() = default;
1212
MyContainer(std::vector<int> data) : data_(data) {}
13-
std::vector<int>::const_iterator begin() const { return data_.begin(); }
14-
std::vector<int>::const_iterator end() const { return data_.end(); }
13+
std::vector<int>::iterator begin() { return data_.begin(); }
14+
std::vector<int>::iterator end() { return data_.end(); }
1515

1616
private:
1717
std::vector<int> data_{7, 8, 9};
@@ -20,15 +20,16 @@ class MyContainer {
2020
class ConvertibleToVector {
2121
public:
2222
operator std::vector<int>() const { return {7, 8, 9}; }
23-
std::array<int, 3>::const_iterator begin() const { return data_.begin(); }
24-
std::array<int, 3>::const_iterator end() const { return data_.end(); }
23+
std::array<int, 3>::iterator begin() { return data_.begin(); }
24+
std::array<int, 3>::iterator end() { return data_.end(); }
25+
std::array<int, 3>::const_iterator begin() const { return data_.cbegin(); }
26+
std::array<int, 3>::const_iterator end() const { return data_.cend(); }
2527

2628
private:
2729
std::array<int, 3> data_{7, 8, 9};
2830
};
2931

30-
std::vector<int> operator+(std::vector<int> a,
31-
std::vector<int> b) {
32+
std::vector<int> operator+(std::vector<int> a, std::vector<int> b) {
3233
std::vector<int> result = a;
3334
result.insert(result.end(), b.begin(), b.end());
3435
return result;
@@ -49,8 +50,12 @@ int main() {
4950

5051
/* ========== 2. OBJECT CREATION (CONSTRUCTOR CALLS) ========== */
5152

53+
for (auto x : std::vector<int>(3)) { // COMPLIANT: 1 constructor call only
54+
}
55+
5256
for (auto x :
53-
std::vector<int>{1, 2, 3}) { // COMPLIANT: 1 constructor call only
57+
std::vector<int>{1, 2, 3}) { // NON_COMPLIANT: 2 constructor call to
58+
// `vector` and `initializer_list`, respectively
5459
}
5560

5661
for (auto x : MyContainer()) { // COMPLIANT: 1 constructor call only
@@ -77,12 +82,22 @@ int main() {
7782

7883
/* ========== 3. OPERATOR OVERLOADING ========== */
7984

85+
std::vector<int> vec1 = {1}, vec2 = {2}, vec3 = {3};
86+
std::vector<int> appendedVector = (vec1 + vec2) + vec3;
87+
for (auto x : appendedVector) { // COMPLIANT: 0 calls
88+
}
89+
90+
std::vector<int> appendedVector2 = getData() + processData(localVec);
91+
for (auto x : appendedVector2) { // COMPLIANT: 0 calls
92+
}
93+
8094
std::vector<int> anotherVec = {4, 5, 6};
81-
for (auto x : localVec + anotherVec) { // COMPLIANT: 1 operator+ call only
95+
for (auto x : localVec + anotherVec) { // NON_COMPLIANT: 2 calls to vector's
96+
// constructor, 1 operator+ call
8297
}
8398

84-
std::vector<int> vec1 = {1}, vec2 = {2}, vec3 = {3};
85-
for (auto x : (vec1 + vec2) + vec3) { // NON-COMPLIANT: 2 operator+ calls
99+
for (auto x : (vec1 + vec2) + vec3) { // NON-COMPLIANT: 3 calls to vector's
100+
// constructor, 2 operator+ calls
86101
}
87102

88103
for (auto x :
@@ -91,18 +106,11 @@ int main() {
91106
localVec)) { // NON-COMPLIANT: 2 function calls + 1 operator call
92107
}
93108

94-
std::vector<int> appendedVector = (vec1 + vec2) + vec3;
95-
for (auto x : appendedVector) { // COMPLIANT: 0 calls
96-
}
97-
98-
std::vector<int> appendedVector2 = getData() + processData(localVec);
99-
for (auto x : appendedVector2) { // COMPLIANT: 0 calls
100-
}
101-
102109
/* ========== 4. IMPLICIT CONVERSIONS ========== */
103110

104111
ConvertibleToVector convertible;
105-
for (int x : convertible) { // COMPLIANT: 1 conversion operator call only
112+
for (int x :
113+
ConvertibleToVector()) { // COMPLIANT: 1 conversion operator call only
106114
}
107115

108116
for (int x :
@@ -116,12 +124,10 @@ int main() {
116124
}
117125

118126
std::vector<int> intVector1 = convertToIntVector(convertible);
119-
for (int x : intVector1) { // NON_COMPLIANT: 1 function call + 1
120-
// conversion operator call
127+
for (int x : intVector1) { // COMPLIANT: 0 function calls
121128
}
122129

123130
std::vector<int> intVector2 = convertToIntVector(convertible);
124-
for (int x : intVector2) { // NON_COMPLIANT: 1 function call + 1
125-
// conversion operator call
131+
for (int x : intVector2) { // COMPLIANT: 0 function calls
126132
}
127133
}

0 commit comments

Comments
 (0)