Skip to content

Commit 9d525db

Browse files
committed
Finalize first draft of Rule 21.6.2
1 parent 3e795fa commit 9d525db

File tree

3 files changed

+103
-53
lines changed

3 files changed

+103
-53
lines changed

cpp/misra/src/rules/RULE-21-6-2/DynamicMemoryManagedManually.ql

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import cpp
1515
import codingstandards.cpp.misra
16+
import codingstandards.cpp.SmartPointers
1617

1718
/**
1819
* A function that has namespace `std` and has name `allocate` or `deallocate`, including but not limited to:
@@ -45,18 +46,26 @@ class MemoryManagementExpr extends Expr {
4546
}
4647
}
4748

48-
from Expr expr
49+
from Expr expr, string message
4950
where
5051
not isExcluded(expr, Memory5Package::dynamicMemoryManagedManuallyQuery()) and
5152
(
5253
/* ===== 1. The expression is a use of non-placement `new`/ `new[]`, or a `delete`. ===== */
53-
/* ===== 2. The expression is a call to malloc / calloc / or to `free`. ===== */
54-
expr instanceof MemoryManagementExpr
54+
/* ===== 2. The expression is a call to `malloc` / `calloc` / `aligned_alloc` or to `free`. ===== */
55+
expr instanceof MemoryManagementExpr and
56+
message = "This expression dynamically allocates or deallocates memory."
5557
or
5658
/* ===== 3. The expression is a call to a member function named `allocate` or `deallocate` in namespace `std`. ===== */
57-
expr.(FunctionCall).getTarget() instanceof AllocateOrDeallocateStdlibMemberFunction
59+
exists(AllocateOrDeallocateStdlibMemberFunction allocateOrDeallocate |
60+
expr.(FunctionCall).getTarget() = allocateOrDeallocate and
61+
message =
62+
"This expression uses a standard library function `" +
63+
allocateOrDeallocate.getQualifiedName() + "` that manages memory manually."
64+
)
5865
or
59-
/* ===== 4. The expression is a ==== */
60-
none()
66+
/* ===== 4. The expression is a call to `std::unique_ptr::release`. ==== */
67+
exists(AutosarUniquePointer uniquePtr | expr = uniquePtr.getAReleaseCall()) and
68+
message =
69+
"This expression is a call to `std::unique_ptr::release` that manages memory manually."
6170
)
62-
select expr, "TODO"
71+
select expr, message
Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,42 @@
1-
No expected results have yet been specified
1+
| test.cpp:17:12:17:17 | new | This expression dynamically allocates or deallocates memory. |
2+
| test.cpp:22:12:22:17 | new | This expression dynamically allocates or deallocates memory. |
3+
| test.cpp:23:3:23:11 | call to operator delete | This expression dynamically allocates or deallocates memory. |
4+
| test.cpp:23:3:23:11 | delete | This expression dynamically allocates or deallocates memory. |
5+
| test.cpp:30:7:30:17 | call to malloc | This expression dynamically allocates or deallocates memory. |
6+
| test.cpp:32:7:32:12 | call to malloc | This expression dynamically allocates or deallocates memory. |
7+
| test.cpp:37:7:37:17 | call to calloc | This expression dynamically allocates or deallocates memory. |
8+
| test.cpp:38:30:38:35 | call to calloc | This expression dynamically allocates or deallocates memory. |
9+
| test.cpp:43:13:43:23 | call to malloc | This expression dynamically allocates or deallocates memory. |
10+
| test.cpp:44:14:44:25 | call to realloc | This expression dynamically allocates or deallocates memory. |
11+
| test.cpp:45:14:45:20 | call to realloc | This expression dynamically allocates or deallocates memory. |
12+
| test.cpp:50:14:50:31 | call to aligned_alloc | This expression dynamically allocates or deallocates memory. |
13+
| test.cpp:52:14:52:26 | call to aligned_alloc | This expression dynamically allocates or deallocates memory. |
14+
| test.cpp:59:7:59:17 | call to malloc | This expression dynamically allocates or deallocates memory. |
15+
| test.cpp:60:3:60:11 | call to free | This expression dynamically allocates or deallocates memory. |
16+
| test.cpp:61:3:61:6 | call to free | This expression dynamically allocates or deallocates memory. |
17+
| test.cpp:69:18:69:25 | call to allocate | This expression uses a standard library function `std::allocator<C1>::allocate` that manages memory manually. |
18+
| test.cpp:70:9:70:18 | call to deallocate | This expression uses a standard library function `std::allocator<C1>::deallocate` that manages memory manually. |
19+
| test.cpp:77:12:77:27 | call to allocate | This expression uses a standard library function `std::allocator_traits<allocator<C1>>::allocate` that manages memory manually. |
20+
| test.cpp:79:3:79:20 | call to deallocate | This expression uses a standard library function `std::allocator_traits<allocator<C1>>::deallocate` that manages memory manually. |
21+
| test.cpp:85:10:85:17 | call to allocate | This expression uses a standard library function `std::pmr::memory_resource::allocate` that manages memory manually. |
22+
| test.cpp:86:6:86:15 | call to deallocate | This expression uses a standard library function `std::pmr::memory_resource::deallocate` that manages memory manually. |
23+
| test.cpp:88:17:88:24 | call to allocate | This expression uses a standard library function `std::pmr::memory_resource::allocate` that manages memory manually. |
24+
| test.cpp:91:6:91:15 | call to deallocate | This expression uses a standard library function `std::pmr::memory_resource::deallocate` that manages memory manually. |
25+
| test.cpp:99:18:99:25 | call to allocate | This expression uses a standard library function `std::pmr::polymorphic_allocator<C1>::allocate` that manages memory manually. |
26+
| test.cpp:100:9:100:18 | call to deallocate | This expression uses a standard library function `std::pmr::polymorphic_allocator<C1>::deallocate` that manages memory manually. |
27+
| test.cpp:107:17:107:24 | call to allocate | This expression uses a standard library function `std::pmr::memory_resource::allocate` that manages memory manually. |
28+
| test.cpp:109:6:109:15 | call to deallocate | This expression uses a standard library function `std::pmr::memory_resource::deallocate` that manages memory manually. |
29+
| test.cpp:115:26:115:33 | call to allocate | This expression uses a standard library function `std::pmr::memory_resource::allocate` that manages memory manually. |
30+
| test.cpp:117:15:117:24 | call to deallocate | This expression uses a standard library function `std::pmr::memory_resource::deallocate` that manages memory manually. |
31+
| test.cpp:122:24:122:31 | call to allocate | This expression uses a standard library function `std::pmr::memory_resource::allocate` that manages memory manually. |
32+
| test.cpp:124:13:124:22 | call to deallocate | This expression uses a standard library function `std::pmr::memory_resource::deallocate` that manages memory manually. |
33+
| test.cpp:133:13:133:20 | call to allocate | This expression uses a standard library function `std::scoped_allocator_adaptor<allocator<C1>>::allocate` that manages memory manually. |
34+
| test.cpp:134:9:134:18 | call to deallocate | This expression uses a standard library function `std::scoped_allocator_adaptor<allocator<C1>>::deallocate` that manages memory manually. |
35+
| test.cpp:142:17:142:23 | call to release | This expression is a call to `std::unique_ptr::release` that manages memory manually. |
36+
| test.cpp:143:3:143:13 | call to operator delete | This expression dynamically allocates or deallocates memory. |
37+
| test.cpp:143:3:143:13 | delete | This expression dynamically allocates or deallocates memory. |
38+
| test.cpp:148:10:148:16 | call to release | This expression is a call to `std::unique_ptr::release` that manages memory manually. |
39+
| test.cpp:149:3:149:15 | call to operator delete[] | This expression dynamically allocates or deallocates memory. |
40+
| test.cpp:149:3:149:15 | delete[] | This expression dynamically allocates or deallocates memory. |
41+
| test.cpp:155:3:155:12 | call to operator delete | This expression dynamically allocates or deallocates memory. |
42+
| test.cpp:155:3:155:12 | delete | This expression dynamically allocates or deallocates memory. |
Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#include <cstdlib>
2-
#include <stdlib.h>
32
#include <memory>
43
#include <memory_resource>
54
#include <scoped_allocator>
5+
#include <stdlib.h>
66

77
class C1 {
88
public:
@@ -12,147 +12,147 @@ class C1 {
1212
// Item 1: Any non-placement form of new or delete
1313

1414
void use_of_new() {
15-
C1 x1; // compliant: no use of new
16-
C1 x2{}; // compliant: no use of new
17-
C1 *x3 = new C1; // non_compliant: use of new
18-
C1 *x4 = new (&x1) C1; // compliant: placement new (but violates Rule 21.6.3)
15+
C1 x1; // COMPLIANT: no use of new
16+
C1 x2{}; // COMPLIANT: no use of new
17+
C1 *x3 = new C1; // NON_COMPLIANT: use of new
18+
C1 *x4 = new (&x1) C1; // COMPLIANT: placement new (but violates Rule 21.6.3)
1919
}
2020

2121
void use_of_delete() {
22-
C1 *x1 = new C1; // non_compliant: use of new
23-
delete x1; // non_compliant: use of delete
22+
C1 *x1 = new C1; // NON_COMPLIANT: use of new
23+
delete x1; // NON_COMPLIANT: use of delete
2424
}
2525

2626
// Item 2: Any of the functions malloc, calloc, realloc, aligned_alloc, free
2727

2828
void use_of_malloc() {
2929
C1 *x1 = static_cast<C1 *>(
30-
std::malloc(sizeof(C1))); // non_compliant: use of malloc
30+
std::malloc(sizeof(C1))); // NON_COMPLIANT: use of malloc
3131
C1 *x2 = static_cast<C1 *>(
32-
malloc(sizeof(C1))); // non_compliant: use of malloc from global namespace
32+
malloc(sizeof(C1))); // NON_COMPLIANT: use of malloc from global namespace
3333
}
3434

3535
void use_of_calloc() {
3636
C1 *x1 = static_cast<C1 *>(
37-
std::calloc(1, sizeof(C1))); // non_compliant: use of calloc
37+
std::calloc(1, sizeof(C1))); // NON_COMPLIANT: use of calloc
3838
C1 *x2 = static_cast<C1 *>(calloc(
39-
1, sizeof(C1))); // non_compliant: use of calloc from global namespace
39+
1, sizeof(C1))); // NON_COMPLIANT: use of calloc from global namespace
4040
}
4141

4242
void use_of_realloc() {
43-
void *p = std::malloc(sizeof(C1)); // non_compliant: use of malloc
44-
void *q1 = std::realloc(p, sizeof(C1) * 2); // non_compliant: use of realloc
43+
void *p = std::malloc(sizeof(C1)); // NON_COMPLIANT: use of malloc
44+
void *q1 = std::realloc(p, sizeof(C1) * 2); // NON_COMPLIANT: use of realloc
4545
void *q2 = realloc(
46-
p, sizeof(C1) * 2); // non_compliant: use of realloc from global namespace
46+
p, sizeof(C1) * 2); // NON_COMPLIANT: use of realloc from global namespace
4747
}
4848

4949
void use_of_aligned_alloc() {
5050
void *x1 = std::aligned_alloc(
51-
alignof(C1), sizeof(C1)); // non_compliant: use of aligned_alloc
51+
alignof(C1), sizeof(C1)); // NON_COMPLIANT: use of aligned_alloc
5252
void *x2 = aligned_alloc(
5353
alignof(C1),
54-
sizeof(C1)); // non_compliant: use of aligned_alloc from global namespace
54+
sizeof(C1)); // NON_COMPLIANT: use of aligned_alloc from global namespace
5555
}
5656

5757
void use_of_free() {
5858
C1 *c1 = static_cast<C1 *>(
59-
std::malloc(sizeof(C1))); // non_compliant: use of malloc
60-
std::free(c1); // non_compliant: use of free
61-
free(c1); // non_compliant: use of free from global namespace
59+
std::malloc(sizeof(C1))); // NON_COMPLIANT: use of malloc
60+
std::free(c1); // NON_COMPLIANT: use of free
61+
free(c1); // NON_COMPLIANT: use of free from global namespace
6262
}
6363

6464
// Item 3: Any member function named allocate or deallocate enclosed by
6565
// namespace std
6666

6767
void use_of_std_allocator() {
6868
std::allocator<C1> alloc;
69-
C1 *p1 = alloc.allocate(1); // non_compliant: std::allocator::allocate
70-
alloc.deallocate(p1, 1); // non_compliant: std::allocator::deallocate
69+
C1 *p1 = alloc.allocate(1); // NON_COMPLIANT: std::allocator::allocate
70+
alloc.deallocate(p1, 1); // NON_COMPLIANT: std::allocator::deallocate
7171
}
7272

7373
void use_of_allocator_traits() {
7474
std::allocator<C1> alloc;
7575
using Traits = std::allocator_traits<std::allocator<C1>>;
7676

7777
C1 *p1 = Traits::allocate(
78-
alloc, 1); // non_compliant: std::allocator_traits::allocate
78+
alloc, 1); // NON_COMPLIANT: std::allocator_traits::allocate
7979
Traits::deallocate(alloc, p1,
80-
1); // non_compliant: std::allocator_traits::deallocate
80+
1); // NON_COMPLIANT: std::allocator_traits::deallocate
8181
}
8282

8383
void use_of_memory_resource(std::pmr::memory_resource &mr) {
8484
void *p1 =
85-
mr.allocate(sizeof(C1)); // non_compliant: memory_resource::allocate
86-
mr.deallocate(p1, sizeof(C1)); // non_compliant: memory_resource::deallocate
85+
mr.allocate(sizeof(C1)); // NON_COMPLIANT: memory_resource::allocate
86+
mr.deallocate(p1, sizeof(C1)); // NON_COMPLIANT: memory_resource::deallocate
8787

8888
void *p2 = mr.allocate(
8989
sizeof(C1),
90-
alignof(C1)); // non_compliant: memory_resource::allocate (with alignment)
90+
alignof(C1)); // NON_COMPLIANT: memory_resource::allocate (with alignment)
9191
mr.deallocate(
9292
p2, sizeof(C1),
9393
alignof(
94-
C1)); // non_compliant: memory_resource::deallocate (with alignment)
94+
C1)); // NON_COMPLIANT: memory_resource::deallocate (with alignment)
9595
}
9696

9797
void use_of_polymorphic_allocator() {
9898
std::pmr::polymorphic_allocator<C1> alloc;
99-
C1 *p1 = alloc.allocate(1); // non_compliant: polymorphic_allocator::allocate
100-
alloc.deallocate(p1, 1); // non_compliant: polymorphic_allocator::deallocate
99+
C1 *p1 = alloc.allocate(1); // NON_COMPLIANT: polymorphic_allocator::allocate
100+
alloc.deallocate(p1, 1); // NON_COMPLIANT: polymorphic_allocator::deallocate
101101
}
102102

103103
void use_of_monotonic_buffer_resource() {
104104
char buffer[1024];
105105
std::pmr::monotonic_buffer_resource mr{buffer, sizeof(buffer)};
106106

107107
void *p1 = mr.allocate(
108-
sizeof(C1)); // non_compliant: monotonic_buffer_resource::allocate
108+
sizeof(C1)); // NON_COMPLIANT: monotonic_buffer_resource::allocate
109109
mr.deallocate(
110-
p1, sizeof(C1)); // non_compliant: monotonic_buffer_resource::deallocate
110+
p1, sizeof(C1)); // NON_COMPLIANT: monotonic_buffer_resource::deallocate
111111
}
112112

113113
void use_of_pool_resources() {
114114
std::pmr::unsynchronized_pool_resource unsync_pool;
115115
void *p1 = unsync_pool.allocate(
116-
sizeof(C1)); // non_compliant: unsynchronized_pool_resource::allocate
116+
sizeof(C1)); // NON_COMPLIANT: unsynchronized_pool_resource::allocate
117117
unsync_pool.deallocate(
118118
p1,
119-
sizeof(C1)); // non_compliant: unsynchronized_pool_resource::deallocate
119+
sizeof(C1)); // NON_COMPLIANT: unsynchronized_pool_resource::deallocate
120120

121121
std::pmr::synchronized_pool_resource sync_pool;
122122
void *p2 = sync_pool.allocate(
123-
sizeof(C1)); // non_compliant: synchronized_pool_resource::allocate
123+
sizeof(C1)); // NON_COMPLIANT: synchronized_pool_resource::allocate
124124
sync_pool.deallocate(
125-
p2, sizeof(C1)); // non_compliant: synchronized_pool_resource::deallocate
125+
p2, sizeof(C1)); // NON_COMPLIANT: synchronized_pool_resource::deallocate
126126
}
127127

128128
void use_of_scoped_allocator_adaptor() {
129129
using Alloc = std::scoped_allocator_adaptor<std::allocator<C1>>;
130130
Alloc alloc;
131131

132132
C1 *p1 =
133-
alloc.allocate(1); // non_compliant: scoped_allocator_adaptor::allocate
133+
alloc.allocate(1); // NON_COMPLIANT: scoped_allocator_adaptor::allocate
134134
alloc.deallocate(p1,
135-
1); // non_compliant: scoped_allocator_adaptor::deallocate
135+
1); // NON_COMPLIANT: scoped_allocator_adaptor::deallocate
136136
}
137137

138138
// Item 4: std::unique_ptr::release
139139

140140
void use_of_unique_ptr_release() {
141-
auto p1 = std::make_unique<C1>(); // compliant: smart pointer creation
142-
C1 *raw1 = p1.release(); // non_compliant: std::unique_ptr::release
143-
delete raw1; // non_compliant: use of delete
141+
auto p1 = std::make_unique<C1>(); // COMPLIANT: smart pointer creation
142+
C1 *raw1 = p1.release(); // NON_COMPLIANT: std::unique_ptr::release
143+
delete raw1; // NON_COMPLIANT: use of delete
144144

145145
auto p2 =
146-
std::make_unique<C1[]>(10); // compliant: smart pointer array creation
146+
std::make_unique<C1[]>(10); // COMPLIANT: smart pointer array creation
147147
C1 *raw2 =
148-
p2.release(); // non_compliant: std::unique_ptr::release (array form)
149-
delete[] raw2; // non_compliant: use of delete[]
148+
p2.release(); // NON_COMPLIANT: std::unique_ptr::release (array form)
149+
delete[] raw2; // NON_COMPLIANT: use of delete[]
150150
}
151151

152152
void delete_via_get() {
153153
auto p1 = std::make_unique<C1>();
154-
C1 *raw = p1.get(); // compliant: get() is fine
155-
delete raw; // non_compliant: use of delete (causes double-free!)
154+
C1 *raw = p1.get(); // COMPLIANT: get() is fine
155+
delete raw; // NON_COMPLIANT: use of delete (causes double-free!)
156156
}
157157

158158
int main() { return 0; }

0 commit comments

Comments
 (0)