From 478a024efe2dc363cc8ebbb1e67ad6cec8eb61fe Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Tue, 7 Apr 2026 16:44:00 -0400 Subject: [PATCH 1/6] Add and fix stubs --- .../test/includes/standard-library/fstream.h | 26 +++++- .../includes/standard-library/functional.h | 2 + .../test/includes/standard-library/istream.h | 2 +- cpp/common/test/includes/standard-library/map | 12 ++- .../test/includes/standard-library/memory.h | 84 ++++++++----------- .../test/includes/standard-library/optional | 2 +- cpp/common/test/includes/standard-library/set | 12 ++- .../test/includes/standard-library/sstream.h | 31 ++++++- .../test/includes/standard-library/string | 4 + .../test/includes/standard-library/tuple.h | 8 +- .../test/includes/standard-library/utility.h | 4 + 11 files changed, 126 insertions(+), 61 deletions(-) diff --git a/cpp/common/test/includes/standard-library/fstream.h b/cpp/common/test/includes/standard-library/fstream.h index 02086ad379..8df67497a4 100644 --- a/cpp/common/test/includes/standard-library/fstream.h +++ b/cpp/common/test/includes/standard-library/fstream.h @@ -10,12 +10,36 @@ class basic_fstream : public std::basic_iostream { // constructors basic_fstream(); explicit basic_fstream(const char *s); + basic_fstream(const basic_fstream &); + basic_fstream(basic_fstream &&); // members bool is_open() const; void open(const string &s); void close(); }; + +template class basic_ifstream { +public: + basic_ifstream(); + basic_ifstream(const basic_ifstream &); + basic_ifstream(basic_ifstream &&); + basic_ifstream(const char *); +}; + +template class basic_ofstream { +public: + basic_ofstream(); + basic_ofstream(const basic_ofstream &); + basic_ofstream(basic_ofstream &&); + basic_ofstream(const char *); +}; + using fstream = basic_fstream; +using wfstream = basic_fstream; +using ifstream = basic_ifstream; +using wifstream = basic_ifstream; +using ofstream = basic_ofstream; +using wofstream = basic_ofstream; } // namespace std -#endif // _GHLIBCPP_FSTREAM \ No newline at end of file +#endif // _GHLIBCPP_FSTREAM diff --git a/cpp/common/test/includes/standard-library/functional.h b/cpp/common/test/includes/standard-library/functional.h index 00dd2016bd..a042293973 100644 --- a/cpp/common/test/includes/standard-library/functional.h +++ b/cpp/common/test/includes/standard-library/functional.h @@ -45,7 +45,9 @@ template binder1st bind1st(const F &f, const T &x); template binder2nd bind2nd(const F &f, const T &x); template class reference_wrapper { +public: reference_wrapper(T &ref) : ref(addressof(ref)) {} + reference_wrapper(const reference_wrapper&); reference_wrapper(T &&ref) = delete; operator T &() const { return *ref; } diff --git a/cpp/common/test/includes/standard-library/istream.h b/cpp/common/test/includes/standard-library/istream.h index f56e67b8c5..de65766d0b 100644 --- a/cpp/common/test/includes/standard-library/istream.h +++ b/cpp/common/test/includes/standard-library/istream.h @@ -92,4 +92,4 @@ getline(basic_istream &is, typedef basic_istream istream; } // namespace std -#endif // _LIBCPP_ISTREAM \ No newline at end of file +#endif // _LIBCPP_ISTREAM diff --git a/cpp/common/test/includes/standard-library/map b/cpp/common/test/includes/standard-library/map index af6f47ca47..50ea3d92c7 100644 --- a/cpp/common/test/includes/standard-library/map +++ b/cpp/common/test/includes/standard-library/map @@ -10,6 +10,10 @@ template , typename _Alloc = std::allocator<_Key>> class multimap { public: + multimap(); + multimap(const multimap&); + multimap(multimap&&); + multimap(std::initializer_list>); typedef std::pair value_type; typedef std::__iterator iterator; typedef std::__iterator const_iterator; @@ -18,14 +22,16 @@ public: iterator end(); const_iterator cbegin(); const_iterator cend(); - - multimap(); }; template , typename _Alloc = std::allocator<_Key>> class map { public: + map(); + map(const map&); + map(map&&); + map(std::initializer_list>); typedef std::pair value_type; typedef std::__iterator iterator; typedef std::__iterator const_iterator; @@ -34,7 +40,5 @@ public: iterator end(); const_iterator cbegin(); const_iterator cend(); - - map(); }; } // namespace std \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/memory.h b/cpp/common/test/includes/standard-library/memory.h index 86e45a3105..2fbba9bcb1 100644 --- a/cpp/common/test/includes/standard-library/memory.h +++ b/cpp/common/test/includes/standard-library/memory.h @@ -35,9 +35,6 @@ class unique_ptr { T *get() { return ptr; } unique_ptr &operator=(const unique_ptr &) = delete; unique_ptr &operator=(unique_ptr &&) { return *this; } - template unique_ptr &operator=(unique_ptr &&) { - return *this; - } private: T *ptr; @@ -185,107 +182,90 @@ template struct allocator_traits { }; // uninitialized_default_construct -template -void uninitialized_default_construct(T1, T1); +template void uninitialized_default_construct(T1, T1); template -void uninitialized_default_construct(T1&&, T2, T2); +void uninitialized_default_construct(T1 &&, T2, T2); // uninitialized_default_construct_n -template -T1 uninitialized_default_construct_n(T1, T2); +template T1 uninitialized_default_construct_n(T1, T2); template -T2 uninitialized_default_construct_n(T1&&, T2, T3); +T2 uninitialized_default_construct_n(T1 &&, T2, T3); // uninitialized_value_construct -template -void uninitialized_value_construct(T1, T1); +template void uninitialized_value_construct(T1, T1); -template -void uninitialized_value_construct(T1&&, T2, T2); +template void uninitialized_value_construct(T1 &&, T2, T2); // uninitialized_value_construct_n -template -T1 uninitialized_value_construct_n(T1, T2); +template T1 uninitialized_value_construct_n(T1, T2); template -T2 uninitialized_value_construct_n(T1&&, T2, T3); +T2 uninitialized_value_construct_n(T1 &&, T2, T3); // uninitialized_copy -template -T2 uninitialized_copy(T1, T1, T2); +template T2 uninitialized_copy(T1, T1, T2); template -T3 uninitialized_copy(T1&&, T2, T2, T3); +T3 uninitialized_copy(T1 &&, T2, T2, T3); // uninitialized_copy_n -template -T3 uninitialized_copy_n(T1, T2, T3); +template T3 uninitialized_copy_n(T1, T2, T3); template -T4 uninitialized_copy_n(T1&&, T2, T3, T4); +T4 uninitialized_copy_n(T1 &&, T2, T3, T4); // uninitialized_move -template -T2 uninitialized_move(T1, T1, T2); +template T2 uninitialized_move(T1, T1, T2); template -T3 uninitialized_move(T1&&, T2, T2, T3); +T3 uninitialized_move(T1 &&, T2, T2, T3); // uninitialized_move_n template pair uninitialized_move_n(T1, T2, T3); template -pair uninitialized_move_n(T1&&, T2, T3, T4); +pair uninitialized_move_n(T1 &&, T2, T3, T4); // uninitialized_fill -template -void uninitialized_fill(T1, T1, const T2&); +template void uninitialized_fill(T1, T1, const T2 &); template -void uninitialized_fill(T1&&, T2, T2, const T3&); +void uninitialized_fill(T1 &&, T2, T2, const T3 &); // uninitialized_fill_n template -T1 uninitialized_fill_n(T1, T2, const T3&); +T1 uninitialized_fill_n(T1, T2, const T3 &); template -T2 uninitialized_fill_n(T1&&, T2, T3, const T4&); +T2 uninitialized_fill_n(T1 &&, T2, T3, const T4 &); // destroy_at -template -void destroy_at(T1*); +template void destroy_at(T1 *); // destroy -template -void destroy(T1, T1); +template void destroy(T1, T1); -template -void destroy(T1&&, T2, T2); +template void destroy(T1 &&, T2, T2); // destroy_n -template -T1 destroy_n(T1, T2); +template T1 destroy_n(T1, T2); -template -T2 destroy_n(T1&&, T2, T3); +template T2 destroy_n(T1 &&, T2, T3); // launder -template -constexpr T1* launder(T1*) noexcept; +template constexpr T1 *launder(T1 *) noexcept; // get_temporary_buffer / return_temporary_buffer (deprecated in C++17) template pair get_temporary_buffer(ptrdiff_t n) noexcept; -template -void return_temporary_buffer(T *p); +template void return_temporary_buffer(T *p); // raw_storage_iterator (deprecated in C++17) -template -class raw_storage_iterator { +template class raw_storage_iterator { public: using iterator_category = output_iterator_tag; using value_type = void; @@ -301,6 +281,16 @@ class raw_storage_iterator { OutputIterator base() const; }; +template class weak_ptr { +public: + weak_ptr(); + weak_ptr(const weak_ptr &); + weak_ptr(weak_ptr &&); + weak_ptr(const shared_ptr &); +}; + +template +shared_ptr allocate_shared(const Alloc &, Args &&...); } // namespace std #endif // _GHLIBCPP_MEMORY diff --git a/cpp/common/test/includes/standard-library/optional b/cpp/common/test/includes/standard-library/optional index 8b129a36cb..d3e7822091 100644 --- a/cpp/common/test/includes/standard-library/optional +++ b/cpp/common/test/includes/standard-library/optional @@ -162,4 +162,4 @@ constexpr optional make_optional(initializer_list ilist, Args &&...args); } // namespace std -#endif // _GHLIBCPP_OPTIONAL \ No newline at end of file +#endif // _GHLIBCPP_OPTIONAL diff --git a/cpp/common/test/includes/standard-library/set b/cpp/common/test/includes/standard-library/set index bb71073096..70f96fc014 100644 --- a/cpp/common/test/includes/standard-library/set +++ b/cpp/common/test/includes/standard-library/set @@ -8,6 +8,10 @@ template , typename _Alloc = std::allocator<_Key>> class set { public: + set(); + set(const set&); + set(set&&); + set(std::initializer_list<_Key>); typedef std::iterator iterator; typedef std::iterator const_iterator; @@ -15,13 +19,15 @@ public: iterator end(); const_iterator cbegin(); const_iterator cend(); - - set(); }; template , typename _Alloc = std::allocator<_Key>> class multiset { public: + multiset(); + multiset(const multiset&); + multiset(multiset&&); + multiset(std::initializer_list<_Key>); typedef std::iterator iterator; typedef std::iterator const_iterator; @@ -29,8 +35,6 @@ public: iterator end(); const_iterator cbegin(); const_iterator cend(); - - multiset(); }; } // namespace std diff --git a/cpp/common/test/includes/standard-library/sstream.h b/cpp/common/test/includes/standard-library/sstream.h index d14c794db4..7d87f1b864 100644 --- a/cpp/common/test/includes/standard-library/sstream.h +++ b/cpp/common/test/includes/standard-library/sstream.h @@ -7,8 +7,35 @@ namespace std { template class basic_stringstream : public basic_iostream { public: - basic_stringstream() {} + basic_stringstream(); + basic_stringstream(const basic_stringstream &); + basic_stringstream(basic_stringstream &&); + basic_stringstream(const CharT *); }; + +template +class basic_istringstream { +public: + basic_istringstream(); + basic_istringstream(const basic_istringstream &); + basic_istringstream(basic_istringstream &&); + basic_istringstream(const CharT *); +}; + +template +class basic_ostringstream { +public: + basic_ostringstream(); + basic_ostringstream(const basic_ostringstream &); + basic_ostringstream(basic_ostringstream &&); +}; + +using stringstream = basic_stringstream; +using wstringstream = basic_stringstream; +using istringstream = basic_istringstream; +using wistringstream = basic_istringstream; +using ostringstream = basic_ostringstream; +using wostringstream = basic_ostringstream; } // namespace std -#endif // _GHLIBCPP_SSTREAM \ No newline at end of file +#endif // _GHLIBCPP_SSTREAM diff --git a/cpp/common/test/includes/standard-library/string b/cpp/common/test/includes/standard-library/string index 52ad4048f3..67eed38e3b 100644 --- a/cpp/common/test/includes/standard-library/string +++ b/cpp/common/test/includes/standard-library/string @@ -250,6 +250,10 @@ public: void reserve(size_type new_cap = 0); }; +using wstring = basic_string; +using u16string = basic_string; +using u32string = basic_string; + template basic_string operator+(const basic_string &lhs, diff --git a/cpp/common/test/includes/standard-library/tuple.h b/cpp/common/test/includes/standard-library/tuple.h index c3eb0e96b8..b13fc819da 100644 --- a/cpp/common/test/includes/standard-library/tuple.h +++ b/cpp/common/test/includes/standard-library/tuple.h @@ -3,7 +3,13 @@ namespace std { // Definition -template class tuple {}; +template class tuple { +public: + tuple(); + tuple(const tuple&); + tuple(tuple&&); + template tuple(UTypes&&...); +}; template std::tuple make_tuple(Types &&...args); struct ignore_t { diff --git a/cpp/common/test/includes/standard-library/utility.h b/cpp/common/test/includes/standard-library/utility.h index 0f347bd013..6edadbbe54 100644 --- a/cpp/common/test/includes/standard-library/utility.h +++ b/cpp/common/test/includes/standard-library/utility.h @@ -24,7 +24,11 @@ template class tuple; template struct pair { T first; U second; + pair(); + pair(const pair&); + pair(pair&&); pair(T t, U u); + template pair(T1&&, U1&&); }; template std::pair make_pair(T &&x, U &&y); From e91aca038a6e6134324fdb46d96ae3e5e10b62cb Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Tue, 7 Apr 2026 16:44:27 -0400 Subject: [PATCH 2/6] Add stubs --- cpp/common/test/includes/standard-library/any | 1 + .../test/includes/standard-library/any.h | 15 +++++ .../test/includes/standard-library/bitset | 1 + .../test/includes/standard-library/bitset.h | 18 ++++++ .../test/includes/standard-library/filesystem | 1 + .../includes/standard-library/filesystem.h | 20 +++++++ .../includes/standard-library/forward_list | 1 + .../includes/standard-library/forward_list.h | 19 +++++++ .../test/includes/standard-library/future | 1 + .../test/includes/standard-library/future.h | 57 +++++++++++++++++++ .../test/includes/standard-library/list | 1 + .../test/includes/standard-library/list.h | 19 +++++++ .../test/includes/standard-library/queue | 1 + .../test/includes/standard-library/queue.h | 24 ++++++++ .../test/includes/standard-library/regex | 1 + .../test/includes/standard-library/regex.h | 14 +++++ .../test/includes/standard-library/stack | 1 + .../test/includes/standard-library/stack.h | 16 ++++++ .../includes/standard-library/unordered_map | 1 + .../includes/standard-library/unordered_map.h | 29 ++++++++++ .../includes/standard-library/unordered_set | 1 + .../includes/standard-library/unordered_set.h | 28 +++++++++ .../test/includes/standard-library/valarray | 1 + .../test/includes/standard-library/valarray.h | 19 +++++++ .../test/includes/standard-library/variant | 1 + .../test/includes/standard-library/variant.h | 17 ++++++ 26 files changed, 308 insertions(+) create mode 100644 cpp/common/test/includes/standard-library/any create mode 100644 cpp/common/test/includes/standard-library/any.h create mode 100644 cpp/common/test/includes/standard-library/bitset create mode 100644 cpp/common/test/includes/standard-library/bitset.h create mode 100644 cpp/common/test/includes/standard-library/filesystem create mode 100644 cpp/common/test/includes/standard-library/filesystem.h create mode 100644 cpp/common/test/includes/standard-library/forward_list create mode 100644 cpp/common/test/includes/standard-library/forward_list.h create mode 100644 cpp/common/test/includes/standard-library/future create mode 100644 cpp/common/test/includes/standard-library/future.h create mode 100644 cpp/common/test/includes/standard-library/list create mode 100644 cpp/common/test/includes/standard-library/list.h create mode 100644 cpp/common/test/includes/standard-library/queue create mode 100644 cpp/common/test/includes/standard-library/queue.h create mode 100644 cpp/common/test/includes/standard-library/regex create mode 100644 cpp/common/test/includes/standard-library/regex.h create mode 100644 cpp/common/test/includes/standard-library/stack create mode 100644 cpp/common/test/includes/standard-library/stack.h create mode 100644 cpp/common/test/includes/standard-library/unordered_map create mode 100644 cpp/common/test/includes/standard-library/unordered_map.h create mode 100644 cpp/common/test/includes/standard-library/unordered_set create mode 100644 cpp/common/test/includes/standard-library/unordered_set.h create mode 100644 cpp/common/test/includes/standard-library/valarray create mode 100644 cpp/common/test/includes/standard-library/valarray.h create mode 100644 cpp/common/test/includes/standard-library/variant create mode 100644 cpp/common/test/includes/standard-library/variant.h diff --git a/cpp/common/test/includes/standard-library/any b/cpp/common/test/includes/standard-library/any new file mode 100644 index 0000000000..6d8dcb9a1f --- /dev/null +++ b/cpp/common/test/includes/standard-library/any @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/any.h b/cpp/common/test/includes/standard-library/any.h new file mode 100644 index 0000000000..de5456c91d --- /dev/null +++ b/cpp/common/test/includes/standard-library/any.h @@ -0,0 +1,15 @@ +#ifndef _GHLIBCPP_ANY +#define _GHLIBCPP_ANY +namespace std { + +class any { +public: + any(); + any(const any &); + any(any &&); + template any(T &&); +}; + +} // namespace std + +#endif // _GHLIBCPP_ANY diff --git a/cpp/common/test/includes/standard-library/bitset b/cpp/common/test/includes/standard-library/bitset new file mode 100644 index 0000000000..39ff9d8cc9 --- /dev/null +++ b/cpp/common/test/includes/standard-library/bitset @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/bitset.h b/cpp/common/test/includes/standard-library/bitset.h new file mode 100644 index 0000000000..95f2c3a56c --- /dev/null +++ b/cpp/common/test/includes/standard-library/bitset.h @@ -0,0 +1,18 @@ +// stubs/bitset + +#ifndef _GHLIBCPP_BITSET +#define _GHLIBCPP_BITSET + +#include + +namespace std { + +template class bitset { +public: + bitset(); + bitset(unsigned long long); +}; + +} // namespace std + +#endif // _GHLIBCPP_BITSET diff --git a/cpp/common/test/includes/standard-library/filesystem b/cpp/common/test/includes/standard-library/filesystem new file mode 100644 index 0000000000..a96ba8e61e --- /dev/null +++ b/cpp/common/test/includes/standard-library/filesystem @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/filesystem.h b/cpp/common/test/includes/standard-library/filesystem.h new file mode 100644 index 0000000000..1a05455bb9 --- /dev/null +++ b/cpp/common/test/includes/standard-library/filesystem.h @@ -0,0 +1,20 @@ +#ifndef _GHLIBCPP_FILESYSTEM +#define _GHLIBCPP_FILESYSTEM + +namespace std { +namespace filesystem { + +class path { +public: + path(); + path(const path&); + path(path&&); + path(const char*); + + path operator/(const path&) const; +}; + +} // namespace filesystem +} // namespace std + +#endif // _GHLIBCPP_FILESYSTEM diff --git a/cpp/common/test/includes/standard-library/forward_list b/cpp/common/test/includes/standard-library/forward_list new file mode 100644 index 0000000000..6dbdc01f28 --- /dev/null +++ b/cpp/common/test/includes/standard-library/forward_list @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/forward_list.h b/cpp/common/test/includes/standard-library/forward_list.h new file mode 100644 index 0000000000..267dd56ac5 --- /dev/null +++ b/cpp/common/test/includes/standard-library/forward_list.h @@ -0,0 +1,19 @@ +#ifndef _GHLIBCPP_FORWARD_LIST +#define _GHLIBCPP_FORWARD_LIST + +#include + +namespace std { + +template +class forward_list { +public: + forward_list(); + forward_list(const forward_list&); + forward_list(forward_list&&); + forward_list(std::initializer_list); +}; + +} // namespace std + +#endif // _GHLIBCPP_FORWARD_LIST diff --git a/cpp/common/test/includes/standard-library/future b/cpp/common/test/includes/standard-library/future new file mode 100644 index 0000000000..1d6724f547 --- /dev/null +++ b/cpp/common/test/includes/standard-library/future @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/future.h b/cpp/common/test/includes/standard-library/future.h new file mode 100644 index 0000000000..9e1f047051 --- /dev/null +++ b/cpp/common/test/includes/standard-library/future.h @@ -0,0 +1,57 @@ +#ifndef _GHLIBCPP_FUTURE +#define _GHLIBCPP_FUTURE + +namespace std { + +enum class launch { + async, + deferred +}; + +template +class future { +public: + future(); + future(const future&); + future(future&&); +}; + +template +class shared_future { +public: + shared_future(); + shared_future(const shared_future&); + shared_future(shared_future&&); + shared_future(future&&); +}; + +template +class promise { +public: + promise(); + promise(const promise&); + promise(promise&&); + future get_future(); +}; + +template +class packaged_task; + +template +class packaged_task { +public: + packaged_task(); + packaged_task(const packaged_task&); + packaged_task(packaged_task&&); + template packaged_task(F&&); +}; + +template +auto async(F&&, Args&&...) -> future()(declval()...))>; + +template +auto async(launch, F&&, Args&&...) -> future()(declval()...))>; + +} // namespace std + +#endif // _GHLIBCPP_FUTURE diff --git a/cpp/common/test/includes/standard-library/list b/cpp/common/test/includes/standard-library/list new file mode 100644 index 0000000000..c1d8a57a9f --- /dev/null +++ b/cpp/common/test/includes/standard-library/list @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/list.h b/cpp/common/test/includes/standard-library/list.h new file mode 100644 index 0000000000..8ae90b0ad8 --- /dev/null +++ b/cpp/common/test/includes/standard-library/list.h @@ -0,0 +1,19 @@ +#ifndef _GHLIBCPP_LIST +#define _GHLIBCPP_LIST + +#include + +namespace std { + +template +class list { +public: + list(); + list(const list&); + list(list&&); + list(std::initializer_list); +}; + +} // namespace std + +#endif // _GHLIBCPP_LIST diff --git a/cpp/common/test/includes/standard-library/queue b/cpp/common/test/includes/standard-library/queue new file mode 100644 index 0000000000..acf6d796f2 --- /dev/null +++ b/cpp/common/test/includes/standard-library/queue @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/queue.h b/cpp/common/test/includes/standard-library/queue.h new file mode 100644 index 0000000000..29c11b3944 --- /dev/null +++ b/cpp/common/test/includes/standard-library/queue.h @@ -0,0 +1,24 @@ +#ifndef _GHLIBCPP_QUEUE +#define _GHLIBCPP_QUEUE + +namespace std { + +template +class queue { +public: + queue(); + queue(const queue&); + queue(queue&&); +}; + +template +class priority_queue { +public: + priority_queue(); + priority_queue(const priority_queue&); + priority_queue(priority_queue&&); +}; + +} // namespace std + +#endif // _GHLIBCPP_QUEUE diff --git a/cpp/common/test/includes/standard-library/regex b/cpp/common/test/includes/standard-library/regex new file mode 100644 index 0000000000..d50a1ed80e --- /dev/null +++ b/cpp/common/test/includes/standard-library/regex @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/regex.h b/cpp/common/test/includes/standard-library/regex.h new file mode 100644 index 0000000000..16d78ad580 --- /dev/null +++ b/cpp/common/test/includes/standard-library/regex.h @@ -0,0 +1,14 @@ +#ifndef _GHLIBCPP_REGEX +#define _GHLIBCPP_REGEX +namespace std { +template class basic_regex { +public: + basic_regex(); + basic_regex(const basic_regex &); + basic_regex(basic_regex &&); + basic_regex(const CharT *); +}; +using regex = basic_regex; +using wregex = basic_regex; +} // namespace std +#endif // _GHLIBCPP_REGEX diff --git a/cpp/common/test/includes/standard-library/stack b/cpp/common/test/includes/standard-library/stack new file mode 100644 index 0000000000..6fa11868e5 --- /dev/null +++ b/cpp/common/test/includes/standard-library/stack @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/stack.h b/cpp/common/test/includes/standard-library/stack.h new file mode 100644 index 0000000000..c9da60fc73 --- /dev/null +++ b/cpp/common/test/includes/standard-library/stack.h @@ -0,0 +1,16 @@ +#ifndef _GHLIBCPP_STACK +#define _GHLIBCPP_STACK + +namespace std { + +template +class stack { +public: + stack(); + stack(const stack&); + stack(stack&&); +}; + +} // namespace std + +#endif // _GHLIBCPP_STACK diff --git a/cpp/common/test/includes/standard-library/unordered_map b/cpp/common/test/includes/standard-library/unordered_map new file mode 100644 index 0000000000..f4cd431367 --- /dev/null +++ b/cpp/common/test/includes/standard-library/unordered_map @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/unordered_map.h b/cpp/common/test/includes/standard-library/unordered_map.h new file mode 100644 index 0000000000..cd36eeeb95 --- /dev/null +++ b/cpp/common/test/includes/standard-library/unordered_map.h @@ -0,0 +1,29 @@ +#ifndef _GHLIBCPP_UNORDERED_MAP +#define _GHLIBCPP_UNORDERED_MAP + +#include +#include + +namespace std { + +template +class unordered_map { +public: + unordered_map(); + unordered_map(const unordered_map&); + unordered_map(unordered_map&&); + unordered_map(std::initializer_list>); +}; + +template +class unordered_multimap { +public: + unordered_multimap(); + unordered_multimap(const unordered_multimap&); + unordered_multimap(unordered_multimap&&); + unordered_multimap(std::initializer_list>); +}; + +} // namespace std + +#endif // _GHLIBCPP_UNORDERED_MAP diff --git a/cpp/common/test/includes/standard-library/unordered_set b/cpp/common/test/includes/standard-library/unordered_set new file mode 100644 index 0000000000..20373b6ddd --- /dev/null +++ b/cpp/common/test/includes/standard-library/unordered_set @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/unordered_set.h b/cpp/common/test/includes/standard-library/unordered_set.h new file mode 100644 index 0000000000..ee94de0e9a --- /dev/null +++ b/cpp/common/test/includes/standard-library/unordered_set.h @@ -0,0 +1,28 @@ +#ifndef _GHLIBCPP_UNORDERED_SET +#define _GHLIBCPP_UNORDERED_SET + +#include + +namespace std { + +template +class unordered_set { +public: + unordered_set(); + unordered_set(const unordered_set&); + unordered_set(unordered_set&&); + unordered_set(std::initializer_list); +}; + +template +class unordered_multiset { +public: + unordered_multiset(); + unordered_multiset(const unordered_multiset&); + unordered_multiset(unordered_multiset&&); + unordered_multiset(std::initializer_list); +}; + +} // namespace std + +#endif // _GHLIBCPP_UNORDERED_SET diff --git a/cpp/common/test/includes/standard-library/valarray b/cpp/common/test/includes/standard-library/valarray new file mode 100644 index 0000000000..0ca8607d31 --- /dev/null +++ b/cpp/common/test/includes/standard-library/valarray @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/valarray.h b/cpp/common/test/includes/standard-library/valarray.h new file mode 100644 index 0000000000..2dd2883158 --- /dev/null +++ b/cpp/common/test/includes/standard-library/valarray.h @@ -0,0 +1,19 @@ +#ifndef _GHLIBCPP_VALARRAY +#define _GHLIBCPP_VALARRAY + +#include + +namespace std { + +template class valarray { +public: + valarray(); + valarray(const valarray &); + valarray(valarray &&); + valarray(std::size_t); + valarray(std::initializer_list); +}; + +} // namespace std + +#endif // _GHLIBCPP_VALARRAY diff --git a/cpp/common/test/includes/standard-library/variant b/cpp/common/test/includes/standard-library/variant new file mode 100644 index 0000000000..a4a3ef1d01 --- /dev/null +++ b/cpp/common/test/includes/standard-library/variant @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/variant.h b/cpp/common/test/includes/standard-library/variant.h new file mode 100644 index 0000000000..a41fea6289 --- /dev/null +++ b/cpp/common/test/includes/standard-library/variant.h @@ -0,0 +1,17 @@ +#ifndef _GHLIBCPP_VARIANT +#define _GHLIBCPP_VARIANT + +namespace std { + +template +class variant { +public: + variant(); + variant(const variant&); + variant(variant&&); + template variant(T&&); +}; + +} // namespace std + +#endif // _GHLIBCPP_VARIANT From ffb3e066dcf8bcf506522c83546a5b634d72bd53 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Tue, 7 Apr 2026 18:56:38 -0400 Subject: [PATCH 3/6] Fix wthe stubs --- cpp/common/test/includes/standard-library/deque.h | 12 +++++++----- .../test/includes/standard-library/forward_list.h | 12 ++++++------ cpp/common/test/includes/standard-library/list.h | 13 +++++++------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/cpp/common/test/includes/standard-library/deque.h b/cpp/common/test/includes/standard-library/deque.h index f16360d7f3..f6380fd206 100644 --- a/cpp/common/test/includes/standard-library/deque.h +++ b/cpp/common/test/includes/standard-library/deque.h @@ -1,10 +1,10 @@ #ifndef _GHLIBCPP_DEQUE #define _GHLIBCPP_DEQUE -#include -#include #include "memory.h" -#include #include +#include +#include +#include namespace std { template > class deque { @@ -14,7 +14,9 @@ template > class deque { typedef value_type &reference; typedef const value_type &const_reference; - deque() = default; + deque(); + deque(const deque &); + deque(deque &&); deque(std::initializer_list, const Allocator & = Allocator()); typedef __iterator iterator; @@ -40,4 +42,4 @@ template > class deque { }; } // namespace std -#endif // _GHLIBCPP_DEQUE \ No newline at end of file +#endif // _GHLIBCPP_DEQUE diff --git a/cpp/common/test/includes/standard-library/forward_list.h b/cpp/common/test/includes/standard-library/forward_list.h index 267dd56ac5..bead950af4 100644 --- a/cpp/common/test/includes/standard-library/forward_list.h +++ b/cpp/common/test/includes/standard-library/forward_list.h @@ -2,16 +2,16 @@ #define _GHLIBCPP_FORWARD_LIST #include +#include namespace std { -template -class forward_list { +template > class forward_list { public: - forward_list(); - forward_list(const forward_list&); - forward_list(forward_list&&); - forward_list(std::initializer_list); + forward_list(); + forward_list(const forward_list &); + forward_list(forward_list &&); + forward_list(std::initializer_list); }; } // namespace std diff --git a/cpp/common/test/includes/standard-library/list.h b/cpp/common/test/includes/standard-library/list.h index 8ae90b0ad8..8d55071403 100644 --- a/cpp/common/test/includes/standard-library/list.h +++ b/cpp/common/test/includes/standard-library/list.h @@ -1,17 +1,18 @@ #ifndef _GHLIBCPP_LIST + #define _GHLIBCPP_LIST #include +#include namespace std { -template -class list { +template > class list { public: - list(); - list(const list&); - list(list&&); - list(std::initializer_list); + list(); + list(const list &); + list(list &&); + list(std::initializer_list); }; } // namespace std From 997cb7ae8b2fd81e844a0f39c777f64e4c9d90b1 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Tue, 7 Apr 2026 18:57:04 -0400 Subject: [PATCH 4/6] Add package files --- .../cpp/exclusions/cpp/Banned7.qll | 26 ++ .../cpp/exclusions/cpp/RuleMetadata.qll | 3 + .../DynamicMemoryShouldNotBeUsed.ql | 244 ++++++++++++ .../DynamicMemoryShouldNotBeUsed.expected | 1 + .../DynamicMemoryShouldNotBeUsed.qlref | 1 + cpp/misra/test/rules/RULE-21-6-1/test.cpp | 351 ++++++++++++++++++ rule_packages/cpp/Banned7.json | 26 ++ rules.csv | 2 +- 8 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 cpp/common/src/codingstandards/cpp/exclusions/cpp/Banned7.qll create mode 100644 cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql create mode 100644 cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected create mode 100644 cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.qlref create mode 100644 cpp/misra/test/rules/RULE-21-6-1/test.cpp create mode 100644 rule_packages/cpp/Banned7.json diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/Banned7.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Banned7.qll new file mode 100644 index 0000000000..1e91a63a18 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Banned7.qll @@ -0,0 +1,26 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Banned7Query = TDynamicMemoryShouldNotBeUsedQuery() + +predicate isBanned7QueryMetadata(Query query, string queryId, string ruleId, string category) { + query = + // `Query` instance for the `dynamicMemoryShouldNotBeUsed` query + Banned7Package::dynamicMemoryShouldNotBeUsedQuery() and + queryId = + // `@id` for the `dynamicMemoryShouldNotBeUsed` query + "cpp/misra/dynamic-memory-should-not-be-used" and + ruleId = "RULE-21-6-1" and + category = "advisory" +} + +module Banned7Package { + Query dynamicMemoryShouldNotBeUsedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `dynamicMemoryShouldNotBeUsed` query + TQueryCPP(TBanned7PackageQuery(TDynamicMemoryShouldNotBeUsedQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll index 3b8175042a..16d200b6ef 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -7,6 +7,7 @@ import Banned1 import Banned2 import Banned3 import Banned4 +import Banned7 import BannedAPIs import BannedFunctions import BannedLibraries @@ -104,6 +105,7 @@ newtype TCPPQuery = TBanned2PackageQuery(Banned2Query q) or TBanned3PackageQuery(Banned3Query q) or TBanned4PackageQuery(Banned4Query q) or + TBanned7PackageQuery(Banned7Query q) or TBannedAPIsPackageQuery(BannedAPIsQuery q) or TBannedFunctionsPackageQuery(BannedFunctionsQuery q) or TBannedLibrariesPackageQuery(BannedLibrariesQuery q) or @@ -201,6 +203,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat isBanned2QueryMetadata(query, queryId, ruleId, category) or isBanned3QueryMetadata(query, queryId, ruleId, category) or isBanned4QueryMetadata(query, queryId, ruleId, category) or + isBanned7QueryMetadata(query, queryId, ruleId, category) or isBannedAPIsQueryMetadata(query, queryId, ruleId, category) or isBannedFunctionsQueryMetadata(query, queryId, ruleId, category) or isBannedLibrariesQueryMetadata(query, queryId, ruleId, category) or diff --git a/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql b/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql new file mode 100644 index 0000000000..5b775c30b3 --- /dev/null +++ b/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql @@ -0,0 +1,244 @@ +/** + * @id cpp/misra/dynamic-memory-should-not-be-used + * @name RULE-21-6-1: Dynamic memory should not be used + * @description Heap allocation is prohibited unless explicitly justified. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-21-6-1 + * scope/single-translation-unit + * correctness + * maintainability + * external/misra/enforcement/undecidable + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.cpp.misra + +class PlacementNewOrNewArrayAllocationFunction extends AllocationFunction { + /* NOTE: Duplicate with RULE-21-6-2 */ + PlacementNewOrNewArrayAllocationFunction() { + this.getName() in ["operator new", "operator new[]"] and + this.getParameter(0).getType().resolveTypedefs*() instanceof Size_t and + this.getAParameter().getUnderlyingType() instanceof VoidPointerType + } +} + +/** + * A function that has namespace `std` and has name `allocate` or `deallocate`, including but not limited to: + * - `std::allocator::allocate(std::size_t)` + * - `std::allocator::dellocate(T*, std::size_t)` + * - `std::pmr::memory_resource::allocate(std::size_t, std::size_t)` + * - `std::pmr::memory_resource::deallocate(void*, std::size_t, std::size_t)` + */ +class AllocateOrDeallocateStdlibMemberFunction extends MemberFunction { + /* NOTE: Duplicate with RULE-21-6-2 */ + AllocateOrDeallocateStdlibMemberFunction() { + this.getName() in ["allocate", "deallocate"] and + this.getNamespace().getParentNamespace*() instanceof StdNamespace + } +} + +/** + * A function that directly or indirectly allocates dynamic memory. + */ +abstract class DynamicMemoryAllocatingFunction extends Function { } + +/** + * A function that directly allocates dynamic memory. + * Includes C allocation functions (malloc, calloc, realloc, aligned_alloc) + * and C++ allocation functions (operator new, operator new[]). + * + * This excludes placement-new operators, as they do not allocate memory themselves. + */ +class DirectDynamicMemoryAllocatingFunction extends DynamicMemoryAllocatingFunction { + DirectDynamicMemoryAllocatingFunction() { + this instanceof AllocationFunction and + not this instanceof PlacementNewOrNewArrayAllocationFunction + } +} + +/** + * A function that indirectly allocates dynamic memory through + * standard library types that use `std::allocator` or operator new internally. + * Includes constructors of containers, strings, streams, regex, and other + * allocating standard library types. + */ +abstract class IndirectDynamicMemoryAllocatingFunction extends DynamicMemoryAllocatingFunction { } + +/** + * A constructor of a standard library container that uses `std::allocator` directly + * as template argument or under the hood as the default value of the template argument. + * Includes `vector`, `deque`, `list`, `forward_list`, `set`, `map`, `multiset`, `multimap`, + * `unordered_set`, `unordered_map`, `unordered_multiset`, `unordered_multimap`, and `valarray`. + */ +class AllocatorContainerConstructor extends IndirectDynamicMemoryAllocatingFunction { + AllocatorContainerConstructor() { + this instanceof Constructor and + this.getDeclaringType() + .hasQualifiedName("std", + [ + "vector", "deque", "list", "forward_list", "set", "map", "multiset", "multimap", + "unordered_set", "unordered_map", "unordered_multiset", "unordered_multimap", "valarray" + ]) + } +} + +/** + * A constructor of a standard library string type that uses std::allocator. + * Includes basic_string and its aliases (string, wstring, u16string, u32string). + */ +class AllocatorStringConstructor extends IndirectDynamicMemoryAllocatingFunction { + AllocatorStringConstructor() { + this instanceof Constructor and + this.getDeclaringType() + .hasQualifiedName("std", ["basic_string", "string", "wstring", "u16string", "u32string"]) + } +} + +/** + * A constructor of a container adaptor that contains an allocating container by default. + * Includes stack (contains deque), queue (contains deque), and priority_queue (contains vector). + */ +class ContainerAdaptorConstructor extends IndirectDynamicMemoryAllocatingFunction { + ContainerAdaptorConstructor() { + this instanceof Constructor and + this.getDeclaringType().hasQualifiedName("std", ["stack", "queue", "priority_queue"]) + } +} + +/** + * A constructor of a string stream that contains std::basic_string for buffer storage. + * Includes `basic_stringstream`, `stringstream`, `wstringstream`, + * `basic_istringstream`, `istringstream`, `wistringstream`, + * `basic_ostringstream`, `ostringstream`, `wostringstream`. + */ +class StringStreamConstructor extends IndirectDynamicMemoryAllocatingFunction { + StringStreamConstructor() { + this instanceof Constructor and + this.getDeclaringType() + .hasQualifiedName("std", + [ + "basic_stringstream", "stringstream", "wstringstream", "basic_istringstream", + "istringstream", "wistringstream", "basic_ostringstream", "ostringstream", + "wostringstream" + ]) + } +} + +/** + * A constructor of a file stream that allocates an internal I/O buffer via `std::basic_filebuf`. + * Includes `basic_fstream`, `fstream`, `wfstream`, + * `basic_ifstream`, `ifstream`, `wifstream`, + * `basic_ofstream`, `ofstream`, `wofstream`. + */ +class FileStreamConstructor extends IndirectDynamicMemoryAllocatingFunction { + FileStreamConstructor() { + this instanceof Constructor and + this.getDeclaringType() + .hasQualifiedName("std", + [ + "basic_fstream", "fstream", "wfstream", "basic_ifstream", "ifstream", "wifstream", + "basic_ofstream", "ofstream", "wofstream" + ]) + } +} + +/** + * A constructor of a regex type that allocates for compiled pattern representation. + * Includes `basic_regex`, `regex`, `wregex`. + */ +class RegexConstructor extends IndirectDynamicMemoryAllocatingFunction { + RegexConstructor() { + this instanceof Constructor and + this.getDeclaringType().hasQualifiedName("std", ["basic_regex", "regex", "wregex"]) + } +} + +/** + * A constructor of a type-erasing wrapper that may allocate via operator new. + * SBO (small buffer optimization) is not guaranteed by the standard. + * Includes `std::function` and `std::any`. + */ +class TypeErasureConstructor extends IndirectDynamicMemoryAllocatingFunction { + TypeErasureConstructor() { + this instanceof Constructor and + this.getDeclaringType().hasQualifiedName("std", ["function", "any"]) + } +} + +/** + * A constructor of a type that heap-allocates shared state for + * cross-object or cross-thread communication. + * Includes promise, future, shared_future, packaged_task, and locale. + */ +class SharedStateConstructor extends IndirectDynamicMemoryAllocatingFunction { + SharedStateConstructor() { + this instanceof Constructor and + this.getDeclaringType() + .hasQualifiedName("std", ["promise", "future", "shared_future", "packaged_task", "locale"]) + } +} + +/** + * A constructor of `std::thread` that heap-allocates callable and arguments + * for transfer to the new thread. + */ +class ThreadConstructor extends IndirectDynamicMemoryAllocatingFunction { + ThreadConstructor() { + this instanceof Constructor and + this.getDeclaringType().hasQualifiedName("std", "thread") + } +} + +/** + * A constructor of `std::filesystem::path` that contains `std::basic_string` for path storage. + */ +class FilesystemPathConstructor extends IndirectDynamicMemoryAllocatingFunction { + FilesystemPathConstructor() { + this instanceof Constructor and + this.getDeclaringType().hasQualifiedName("std::filesystem", "path") + } +} + +/** + * A smart pointer factory function that allocates dynamic memory. + * Includes `make_unique`, `make_shared`, and `allocate_shared`. + */ +class SmartPointerFactoryFunction extends IndirectDynamicMemoryAllocatingFunction { + SmartPointerFactoryFunction() { + this.hasQualifiedName("std", ["make_unique", "make_shared", "allocate_shared"]) + } +} + +/** + * The `std::async` function that allocates callable storage and shared state for the future. + */ +class AsyncFunction extends IndirectDynamicMemoryAllocatingFunction { + AsyncFunction() { this.hasQualifiedName("std", "async") } +} + +/** + * A function that directly or indirectly deallocates dynamic memory. + */ +abstract class DynamicMemoryDeallocatingFunction extends Function { } + +/** + * A function that directly deallocates dynamic memory. + * Includes C allocation functions (`free`) + * and C++ allocation functions (`operator delete`, `operator delete[]`). + */ +class DirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { } + +/** + * A function that indirectly allocates dynamic memory through + * standard library classes and their member functions (e.g. `std::allocator::deallocate`). + */ +class IndirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { } + +from FunctionCall call +where + not isExcluded(call, Banned7Package::dynamicMemoryShouldNotBeUsedQuery()) and + call.getTarget() instanceof DynamicMemoryAllocatingFunction +select call, call.getTarget().toString() diff --git a/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected b/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected new file mode 100644 index 0000000000..2ec1a0ac6c --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected @@ -0,0 +1 @@ +No expected results have yet been specified \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.qlref b/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.qlref new file mode 100644 index 0000000000..261a33cf2c --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.qlref @@ -0,0 +1 @@ +rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql \ No newline at end of file diff --git a/cpp/misra/test/rules/RULE-21-6-1/test.cpp b/cpp/misra/test/rules/RULE-21-6-1/test.cpp new file mode 100644 index 0000000000..0a9a43d8b6 --- /dev/null +++ b/cpp/misra/test/rules/RULE-21-6-1/test.cpp @@ -0,0 +1,351 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void test_new_delete() { + int *p1 = new int; // NON_COMPLIANT: operator new + int *p2 = new int(42); // NON_COMPLIANT: operator new + int *p3 = new int[10]; // NON_COMPLIANT: operator new[] + + delete p1; // NON_COMPLIANT: operator delete + delete p2; // NON_COMPLIANT: operator delete + delete[] p3; // NON_COMPLIANT: operator delete[] +} + +void test_placement_new() { + struct Trivial { + int value; + }; + alignas(Trivial) char buffer[sizeof(Trivial)]; + Trivial *p = new (&buffer[0]) Trivial{ + 42}; // COMPLIANT: placement new uses provided storage, no heap allocation + p->~Trivial(); +} + +void test_c_allocation_std_namespace() { + void *p1 = std::malloc(100); // NON_COMPLIANT: malloc + void *p2 = std::calloc(10, sizeof(int)); // NON_COMPLIANT: calloc + void *p3 = std::realloc(p1, 200); // NON_COMPLIANT: realloc + void *p4 = std::aligned_alloc(16, 64); // NON_COMPLIANT: aligned_alloc + + std::free(p3); // NON_COMPLIANT: free + std::free(p2); // NON_COMPLIANT: free + std::free(p4); // NON_COMPLIANT: free +} + +void test_c_allocation_global_namespace() { + void *p1 = malloc(100); // NON_COMPLIANT: malloc + void *p2 = calloc(10, sizeof(int)); // NON_COMPLIANT: calloc + void *p3 = realloc(p1, 200); // NON_COMPLIANT: realloc + void *p4 = aligned_alloc(16, 64); // NON_COMPLIANT: aligned_alloc + + free(p3); // NON_COMPLIANT: free + free(p2); // NON_COMPLIANT: free + free(p4); // NON_COMPLIANT: free +} + +void test_smart_pointer_factories() { + auto p1 = std::make_unique(42); // NON_COMPLIANT: calls operator new + auto p2 = std::make_unique(10); // NON_COMPLIANT: calls operator new + auto p3 = std::make_shared( + 42); // NON_COMPLIANT: allocates object + control block + + std::allocator alloc; + auto p4 = std::allocate_shared( + alloc, 42); // NON_COMPLIANT: allocates via allocator +} + +void test_smart_pointer_constructors() { + std::unique_ptr p1(new int(42)); // NON_COMPLIANT: operator new + std::shared_ptr p2(new int(42)); // NON_COMPLIANT: operator new + std::weak_ptr p3 = + p2; // COMPLIANT: references existing control block, no new allocation +} + +void test_sequence_containers() { + std::vector v1; // NON_COMPLIANT: uses std::allocator + std::vector v2{1, 2, 3}; // NON_COMPLIANT: uses std::allocator + std::vector v3(10); // NON_COMPLIANT: uses std::allocator + std::vector v4(10, 42); // NON_COMPLIANT: uses std::allocator + + std::deque d1; // NON_COMPLIANT: uses std::allocator + std::deque d2{1, 2, 3}; // NON_COMPLIANT: uses std::allocator + + std::list l1; // NON_COMPLIANT: uses std::allocator + std::list l2{1, 2, 3}; // NON_COMPLIANT: uses std::allocator + + std::forward_list fl1; // NON_COMPLIANT: uses std::allocator + std::forward_list fl2{1, 2, 3}; // NON_COMPLIANT: uses std::allocator +} + +void test_associative_containers() { + std::set s1; // NON_COMPLIANT: uses std::allocator + std::set s2{1, 2, 3}; // NON_COMPLIANT: uses std::allocator + + std::map m1; // NON_COMPLIANT: uses std::allocator + std::map m2{{1, 2}, {3, 4}}; // NON_COMPLIANT: uses std::allocator + + std::multiset ms1; // NON_COMPLIANT: uses std::allocator + std::multiset ms2{1, 1, 2}; // NON_COMPLIANT: uses std::allocator + + std::multimap mm1; // NON_COMPLIANT: uses std::allocator + std::multimap mm2{{1, 2}}; // NON_COMPLIANT: uses std::allocator +} + +void test_unordered_containers() { + std::unordered_set us1; // NON_COMPLIANT: uses std::allocator + std::unordered_set us2{1, 2, 3}; // NON_COMPLIANT: uses std::allocator + + std::unordered_map um1; // NON_COMPLIANT: uses std::allocator + std::unordered_map um2{ + {1, 2}, {3, 4}}; // NON_COMPLIANT: uses std::allocator + + std::unordered_multiset ums1; // NON_COMPLIANT: uses std::allocator + std::unordered_multiset ums2{1, 1, + 2}; // NON_COMPLIANT: uses std::allocator + + std::unordered_multimap umm1; // NON_COMPLIANT: uses std::allocator + std::unordered_multimap umm2{ + {1, 2}}; // NON_COMPLIANT: uses std::allocator +} + +void test_valarray() { + std::valarray va1; // NON_COMPLIANT: allocates for element storage + std::valarray va2(10); // NON_COMPLIANT: allocates for element storage + std::valarray va3{1, 2, + 3}; // NON_COMPLIANT: allocates for element storage +} + +void test_strings() { + std::string s1; // NON_COMPLIANT: uses std::allocator + std::string s2 = "hello"; // NON_COMPLIANT: uses std::allocator + std::string s3("hello"); // NON_COMPLIANT: uses std::allocator + std::string s4(10, 'x'); // NON_COMPLIANT: uses std::allocator + + std::wstring ws1; // NON_COMPLIANT: uses std::allocator + std::wstring ws2 = L"hello"; // NON_COMPLIANT: uses std::allocator + + std::u16string u16s1; // NON_COMPLIANT: uses std::allocator + std::u16string u16s2 = u"hello"; // NON_COMPLIANT: uses std::allocator + + std::u32string u32s1; // NON_COMPLIANT: uses std::allocator + std::u32string u32s2 = U"hello"; // NON_COMPLIANT: uses std::allocator +} + +void test_container_adaptors() { + std::stack st1; // NON_COMPLIANT: contains std::deque + + std::queue q1; // NON_COMPLIANT: contains std::deque + + std::priority_queue pq1; // NON_COMPLIANT: contains std::vector +} + +void test_string_streams() { + std::stringstream ss1; // NON_COMPLIANT: contains std::string + std::stringstream ss2("hello"); // NON_COMPLIANT: contains std::string + + std::istringstream iss1; // NON_COMPLIANT: contains std::string + std::istringstream iss2("hello"); // NON_COMPLIANT: contains std::string + + std::ostringstream oss1; // NON_COMPLIANT: contains std::string + + std::wstringstream wss1; // NON_COMPLIANT: contains std::wstring + std::wistringstream wiss1; // NON_COMPLIANT: contains std::wstring + std::wostringstream woss1; // NON_COMPLIANT: contains std::wstring +} + +void test_file_streams() { + std::fstream fs1; // NON_COMPLIANT: allocates internal buffer + std::fstream fs2("file.txt"); // NON_COMPLIANT: allocates internal buffer + + std::ifstream ifs1; // NON_COMPLIANT: allocates internal buffer + std::ifstream ifs2("file.txt"); // NON_COMPLIANT: allocates internal buffer + + std::ofstream ofs1; // NON_COMPLIANT: allocates internal buffer + std::ofstream ofs2("file.txt"); // NON_COMPLIANT: allocates internal buffer + + std::wfstream wfs1; // NON_COMPLIANT: allocates internal buffer + std::wifstream wifs1; // NON_COMPLIANT: allocates internal buffer + std::wofstream wofs1; // NON_COMPLIANT: allocates internal buffer +} + +void test_regex() { + std::regex r1; // NON_COMPLIANT: allocates compiled pattern + std::regex r2("pattern"); // NON_COMPLIANT: allocates compiled pattern + std::regex r3("[a-z]+"); // NON_COMPLIANT: allocates compiled pattern + + std::wregex wr1; // NON_COMPLIANT: allocates compiled pattern + std::wregex wr2(L"pattern"); // NON_COMPLIANT: allocates compiled pattern +} + +void test_function() { + std::function f1; // NON_COMPLIANT: may allocate via type erasure + std::function f2 = []() { + }; // NON_COMPLIANT: may allocate via type erasure + std::function f3 = [](int x) { + return x; + }; // NON_COMPLIANT: may allocate via type erasure + + int a, b, c, d, e, f, g, h; + std::function f4 = + [=]() { // NON_COMPLIANT: may allocate via type erasure + (void)(a + b + c + d + e + f + g + h); + }; +} + +void test_any() { + std::any a1; // NON_COMPLIANT: may allocate via type erasure + std::any a2 = 42; // NON_COMPLIANT: may allocate via type erasure + std::any a3 = + std::string("hello"); // NON_COMPLIANT: may allocate via type erasure + + struct Large { + char data[1000]; + }; + std::any a4 = Large{}; // NON_COMPLIANT: may allocate via type erasure +} + +void test_promise_future() { + std::promise p1; // NON_COMPLIANT: allocates shared state + std::future f1 = + p1.get_future(); // NON_COMPLIANT: references allocated shared state + + std::promise p2; // NON_COMPLIANT: allocates shared state + std::shared_future sf1 = + std::promise{}.get_future(); // NON_COMPLIANT: allocates shared state + + std::packaged_task pt1( + [] { return 42; }); // NON_COMPLIANT: allocates shared state +} + +void test_locale() { + std::locale loc1; // NON_COMPLIANT: allocates facet storage + std::locale loc2("C"); // NON_COMPLIANT: allocates facet storage + std::locale loc3 = + std::locale::classic(); // NON_COMPLIANT: allocates facet storage +} + +void test_thread() { + std::thread t1([]() {}); // NON_COMPLIANT: allocates callable storage + t1.join(); + + int x = 42; + std::thread t2( + [x]() { (void)x; }); // NON_COMPLIANT: allocates callable storage + t2.join(); +} + +void test_async() { + auto f1 = std::async( + [] { return 42; }); // NON_COMPLIANT: allocates callable + shared state + auto f2 = std::async(std::launch::async, [] { + return 42; + }); // NON_COMPLIANT: allocates callable + shared state + auto f3 = std::async(std::launch::deferred, [] { + return 42; + }); // NON_COMPLIANT: allocates callable + shared state +} + +void test_filesystem() { + std::filesystem::path p1; // NON_COMPLIANT: contains string + std::filesystem::path p2 = "/usr/bin"; // NON_COMPLIANT: contains string + std::filesystem::path p3("file.txt"); // NON_COMPLIANT: contains string + std::filesystem::path p4 = p3 / "sub"; // NON_COMPLIANT: contains string +} + +void test_containers_with_explicit_allocator() { + std::vector> + v1; // NON_COMPLIANT: explicit std::allocator template argument + std::deque> + d1; // NON_COMPLIANT: explicit std::allocator template argument + std::list> + l1; // NON_COMPLIANT: explicit std::allocator template argument + std::forward_list> + fl1; // NON_COMPLIANT: explicit std::allocator template argument +} + +void test_compliant_views() { + std::string_view sv = + "hello"; // COMPLIANT: non-owning view, just pointer + size, no allocation +} + +void test_compliant_stack_allocated() { + std::array arr; // COMPLIANT: fixed-size, elements embedded directly + // in object, no allocator + std::bitset<64> + bs; // COMPLIANT: fixed-size, bits stored internally, no heap allocation +} + +void test_compliant_internal_storage() { + std::optional + opt1; // COMPLIANT: uses aligned internal buffer, no heap allocation + std::optional opt2{ + 42}; // COMPLIANT: uses aligned internal buffer, no heap allocation + + std::variant var1; // COMPLIANT: uses internal buffer sized to + // largest alternative, no heap + std::variant var2 = + 3.14; // COMPLIANT: uses internal buffer sized to largest alternative, no + // heap + + std::pair pair1; // COMPLIANT: simple aggregate, members stored + // directly, no allocation + std::pair pair2{ + 1, + 2}; // COMPLIANT: simple aggregate, members stored directly, no allocation + + std::tuple + tup1; // COMPLIANT: members stored directly in object, no allocation + std::tuple tup2{ + 1, 2.0}; // COMPLIANT: members stored directly in object, no allocation +} + +void test_compliant_reference_wrapper() { + int x = 42; + std::reference_wrapper ref = + x; // COMPLIANT: just wraps a pointer, no ownership, no allocation +} + +void test_compliant_iterators() { + std::array a{1, 2, 3}; + auto it = a.begin(); // COMPLIANT: iterator is typically a pointer or small + // object, no allocation +} + +void test_compliant_pointers() { + int x = 42; + int *p = &x; // COMPLIANT: raw pointer to stack variable, no heap involved + + static int y = 42; + int *q = &y; // COMPLIANT: raw pointer to static storage, no heap involved +} + +int main() { return 0; } diff --git a/rule_packages/cpp/Banned7.json b/rule_packages/cpp/Banned7.json new file mode 100644 index 0000000000..4a98382f3b --- /dev/null +++ b/rule_packages/cpp/Banned7.json @@ -0,0 +1,26 @@ +{ + "MISRA-C++-2023": { + "RULE-21-6-1": { + "properties": { + "enforcement": "undecidable", + "obligation": "advisory" + }, + "queries": [ + { + "description": "Heap allocation is prohibited unless explicitly justified.", + "kind": "problem", + "name": "Dynamic memory should not be used", + "precision": "very-high", + "severity": "warning", + "short_name": "DynamicMemoryShouldNotBeUsed", + "tags": [ + "scope/single-translation-unit", + "correctness", + "maintainability" + ] + } + ], + "title": "Dynamic memory should not be used" + } + } +} diff --git a/rules.csv b/rules.csv index bbbb47f382..e48f496be7 100644 --- a/rules.csv +++ b/rules.csv @@ -978,7 +978,7 @@ cpp,MISRA-C++-2023,RULE-21-2-1,Yes,Required,Decidable,Single Translation Unit,"T cpp,MISRA-C++-2023,RULE-21-2-2,Yes,Required,Decidable,Single Translation Unit,"The string handling functions from , , and shall not be used",M18-0-5,BannedAPIs,Easy, cpp,MISRA-C++-2023,RULE-21-2-3,Yes,Required,Decidable,Single Translation Unit,The library function system from shall not be used,M18-0-3,BannedAPIs,Easy, cpp,MISRA-C++-2023,RULE-21-2-4,Yes,Required,Decidable,Single Translation Unit,The macro offsetof shall not be used,M18-2-1,ImportMisra23,Import, -cpp,MISRA-C++-2023,RULE-21-6-1,Yes,Advisory,Undecidable,Single Translation Unit,Dynamic memory should not be used,DIR-4-12,Banned,Easy, +cpp,MISRA-C++-2023,RULE-21-6-1,Yes,Advisory,Undecidable,Single Translation Unit,Dynamic memory should not be used,DIR-4-12,Banned7,Easy, cpp,MISRA-C++-2023,RULE-21-6-2,Yes,Required,Decidable,Single Translation Unit,Dynamic memory shall be managed automatically,,Memory5,Easy, cpp,MISRA-C++-2023,RULE-21-6-3,Yes,Required,Decidable,Single Translation Unit,Advanced memory management shall not be used,,Memory6,Medium, cpp,MISRA-C++-2023,RULE-21-6-4,Yes,Required,Decidable,System,"If a project defines either a sized or unsized version of a global operator delete, then both shall be defined",A18-5-4,ImportMisra23,Import, From dce0e806104260ab774d4cb90e118b31060947bc Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Wed, 8 Apr 2026 22:34:27 -0400 Subject: [PATCH 5/6] Finalize draft of 21-6-1 and factor out duplicated code --- .../src/codingstandards/cpp/DynamicMemory.qll | 32 +++++ .../DynamicMemoryShouldNotBeUsed.ql | 72 ++++++----- .../DynamicMemoryManagedManually.ql | 29 +---- .../DynamicMemoryShouldNotBeUsed.expected | 121 +++++++++++++++++- cpp/misra/test/rules/RULE-21-6-1/test.cpp | 3 +- 5 files changed, 195 insertions(+), 62 deletions(-) create mode 100644 cpp/common/src/codingstandards/cpp/DynamicMemory.qll diff --git a/cpp/common/src/codingstandards/cpp/DynamicMemory.qll b/cpp/common/src/codingstandards/cpp/DynamicMemory.qll new file mode 100644 index 0000000000..505f133fa9 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/DynamicMemory.qll @@ -0,0 +1,32 @@ +/** Provides classes for modeling dynamic memory allocation and deallocation functions. */ + +import cpp + +/** + * An `operator new` or `operator new[]` allocation function called by a placement-new expression. + * + * The operator functions have a `std::size_t` as their first parameter and a + * `void*` parameter somewhere in the rest of the parameter list. + */ +class PlacementNewOrNewArrayAllocationFunction extends AllocationFunction { + PlacementNewOrNewArrayAllocationFunction() { + this.getName() in ["operator new", "operator new[]"] and + this.getParameter(0).getType().resolveTypedefs*() instanceof Size_t and + this.getAParameter().getUnderlyingType() instanceof VoidPointerType + } +} + +/** + * A function that has namespace `std` and has name `allocate` or `deallocate`, including but + * not limited to: + * - `std::allocator::allocate(std::size_t)` + * - `std::allocator::deallocate(T*, std::size_t)` + * - `std::pmr::memory_resource::allocate(std::size_t, std::size_t)` + * - `std::pmr::memory_resource::deallocate(void*, std::size_t, std::size_t)` + */ +class AllocateOrDeallocateStdlibMemberFunction extends MemberFunction { + AllocateOrDeallocateStdlibMemberFunction() { + this.getName() in ["allocate", "deallocate"] and + this.getNamespace().getParentNamespace*() instanceof StdNamespace + } +} diff --git a/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql b/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql index 5b775c30b3..8ade60f58f 100644 --- a/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql +++ b/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql @@ -15,30 +15,7 @@ import cpp import codingstandards.cpp.misra - -class PlacementNewOrNewArrayAllocationFunction extends AllocationFunction { - /* NOTE: Duplicate with RULE-21-6-2 */ - PlacementNewOrNewArrayAllocationFunction() { - this.getName() in ["operator new", "operator new[]"] and - this.getParameter(0).getType().resolveTypedefs*() instanceof Size_t and - this.getAParameter().getUnderlyingType() instanceof VoidPointerType - } -} - -/** - * A function that has namespace `std` and has name `allocate` or `deallocate`, including but not limited to: - * - `std::allocator::allocate(std::size_t)` - * - `std::allocator::dellocate(T*, std::size_t)` - * - `std::pmr::memory_resource::allocate(std::size_t, std::size_t)` - * - `std::pmr::memory_resource::deallocate(void*, std::size_t, std::size_t)` - */ -class AllocateOrDeallocateStdlibMemberFunction extends MemberFunction { - /* NOTE: Duplicate with RULE-21-6-2 */ - AllocateOrDeallocateStdlibMemberFunction() { - this.getName() in ["allocate", "deallocate"] and - this.getNamespace().getParentNamespace*() instanceof StdNamespace - } -} +import codingstandards.cpp.DynamicMemory /** * A function that directly or indirectly allocates dynamic memory. @@ -56,6 +33,8 @@ class DirectDynamicMemoryAllocatingFunction extends DynamicMemoryAllocatingFunct DirectDynamicMemoryAllocatingFunction() { this instanceof AllocationFunction and not this instanceof PlacementNewOrNewArrayAllocationFunction + or + this.hasGlobalOrStdName("aligned_alloc") } } @@ -226,19 +205,48 @@ abstract class DynamicMemoryDeallocatingFunction extends Function { } /** * A function that directly deallocates dynamic memory. - * Includes C allocation functions (`free`) - * and C++ allocation functions (`operator delete`, `operator delete[]`). + * Includes C deallocation functions (`free`) + * and C++ deallocation functions (`operator delete`, `operator delete[]`). */ -class DirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { } +class DirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { + DirectDynamicMemoryDeallocatingFunction() { + this instanceof DeallocationFunction + } +} /** - * A function that indirectly allocates dynamic memory through + * A function that indirectly deallocates dynamic memory through * standard library classes and their member functions (e.g. `std::allocator::deallocate`). */ -class IndirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { } +class IndirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { + IndirectDynamicMemoryDeallocatingFunction() { + this instanceof AllocateOrDeallocateStdlibMemberFunction and + this.getName() = "deallocate" + } +} -from FunctionCall call +from FunctionCall call, string message where not isExcluded(call, Banned7Package::dynamicMemoryShouldNotBeUsedQuery()) and - call.getTarget() instanceof DynamicMemoryAllocatingFunction -select call, call.getTarget().toString() + ( + // Direct allocation: malloc, calloc, realloc, aligned_alloc, operator new, operator new[] + call.getTarget() instanceof DirectDynamicMemoryAllocatingFunction and + message = + "Call to dynamic memory allocating function '" + call.getTarget().getName() + + "'." + or + // Indirect allocation: std library types that allocate internally + call.getTarget() instanceof IndirectDynamicMemoryAllocatingFunction and + message = + "Call to '" + call.getTarget().getName() + + "' that dynamically allocates memory via the standard library." + or + // Deallocation: free, operator delete, operator delete[], std::allocator::deallocate + // Excludes realloc (already caught as allocation). + call.getTarget() instanceof DynamicMemoryDeallocatingFunction and + not call.getTarget() instanceof DynamicMemoryAllocatingFunction and + message = + "Call to dynamic memory deallocating function '" + call.getTarget().getName() + + "'." + ) +select call, message diff --git a/cpp/misra/src/rules/RULE-21-6-2/DynamicMemoryManagedManually.ql b/cpp/misra/src/rules/RULE-21-6-2/DynamicMemoryManagedManually.ql index 154470ae27..8fb8e6ed0c 100644 --- a/cpp/misra/src/rules/RULE-21-6-2/DynamicMemoryManagedManually.ql +++ b/cpp/misra/src/rules/RULE-21-6-2/DynamicMemoryManagedManually.ql @@ -17,20 +17,7 @@ import cpp import codingstandards.cpp.misra import codingstandards.cpp.SmartPointers - -/** - * An `operator new` or `operator new[]` allocation function called by a placement-new expression. - * - * The operator functions are supposed to have a `std::size_t` as their first parameter and a - * `void*` parameter somewhere in the rest of the parameter list. - */ -class PlacementNewOrNewArrayAllocationFunction extends AllocationFunction { - PlacementNewOrNewArrayAllocationFunction() { - this.getName() in ["operator new", "operator new[]"] and - this.getParameter(0).getType().resolveTypedefs*() instanceof Size_t and - this.getAParameter().getUnderlyingType() instanceof VoidPointerType - } -} +import codingstandards.cpp.DynamicMemory class DynamicMemoryManagementFunction extends Function { DynamicMemoryManagementFunction() { @@ -52,20 +39,6 @@ class DynamicMemoryManagementFunction extends Function { } } -/** - * A function that has namespace `std` and has name `allocate` or `deallocate`, including but not limited to: - * - `std::allocator::allocate(std::size_t)` - * - `std::allocator::dellocate(T*, std::size_t)` - * - `std::pmr::memory_resource::allocate(std::size_t, std::size_t)` - * - `std::pmr::memory_resource::deallocate(void*, std::size_t, std::size_t)` - */ -class AllocateOrDeallocateStdlibMemberFunction extends MemberFunction { - AllocateOrDeallocateStdlibMemberFunction() { - this.getName() in ["allocate", "deallocate"] and - this.getNamespace().getParentNamespace*() instanceof StdNamespace - } -} - /** * The `std::realloc` (``) or `::realloc` (``) function. */ diff --git a/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected b/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected index 2ec1a0ac6c..c6be11acc4 100644 --- a/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected +++ b/cpp/misra/test/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.expected @@ -1 +1,120 @@ -No expected results have yet been specified \ No newline at end of file +| test.cpp:34:13:34:19 | call to operator new | Call to dynamic memory allocating function 'operator new'. | +| test.cpp:35:13:35:23 | call to operator new | Call to dynamic memory allocating function 'operator new'. | +| test.cpp:36:13:36:23 | call to operator new[] | Call to dynamic memory allocating function 'operator new[]'. | +| test.cpp:38:3:38:11 | call to operator delete | Call to dynamic memory deallocating function 'operator delete'. | +| test.cpp:39:3:39:11 | call to operator delete | Call to dynamic memory deallocating function 'operator delete'. | +| test.cpp:40:3:40:13 | call to operator delete[] | Call to dynamic memory deallocating function 'operator delete[]'. | +| test.cpp:54:14:54:24 | call to malloc | Call to dynamic memory allocating function 'malloc'. | +| test.cpp:55:14:55:24 | call to calloc | Call to dynamic memory allocating function 'calloc'. | +| test.cpp:56:14:56:25 | call to realloc | Call to dynamic memory allocating function 'realloc'. | +| test.cpp:57:14:57:31 | call to aligned_alloc | Call to dynamic memory allocating function 'aligned_alloc'. | +| test.cpp:59:3:59:11 | call to free | Call to dynamic memory deallocating function 'free'. | +| test.cpp:60:3:60:11 | call to free | Call to dynamic memory deallocating function 'free'. | +| test.cpp:61:3:61:11 | call to free | Call to dynamic memory deallocating function 'free'. | +| test.cpp:65:14:65:19 | call to malloc | Call to dynamic memory allocating function 'malloc'. | +| test.cpp:66:14:66:19 | call to calloc | Call to dynamic memory allocating function 'calloc'. | +| test.cpp:67:14:67:20 | call to realloc | Call to dynamic memory allocating function 'realloc'. | +| test.cpp:68:14:68:26 | call to aligned_alloc | Call to dynamic memory allocating function 'aligned_alloc'. | +| test.cpp:70:3:70:6 | call to free | Call to dynamic memory deallocating function 'free'. | +| test.cpp:71:3:71:6 | call to free | Call to dynamic memory deallocating function 'free'. | +| test.cpp:72:3:72:6 | call to free | Call to dynamic memory deallocating function 'free'. | +| test.cpp:76:13:76:33 | call to make_unique | Call to 'make_unique' that dynamically allocates memory via the standard library. | +| test.cpp:77:13:77:35 | call to make_unique | Call to 'make_unique' that dynamically allocates memory via the standard library. | +| test.cpp:78:13:78:33 | call to make_shared | Call to 'make_shared' that dynamically allocates memory via the standard library. | +| test.cpp:82:13:82:37 | call to allocate_shared | Call to 'allocate_shared' that dynamically allocates memory via the standard library. | +| test.cpp:87:27:87:37 | call to operator new | Call to dynamic memory allocating function 'operator new'. | +| test.cpp:88:27:88:37 | call to operator new | Call to dynamic memory allocating function 'operator new'. | +| test.cpp:94:20:94:21 | call to vector | Call to 'vector' that dynamically allocates memory via the standard library. | +| test.cpp:95:23:95:30 | call to vector | Call to 'vector' that dynamically allocates memory via the standard library. | +| test.cpp:96:23:96:25 | call to vector | Call to 'vector' that dynamically allocates memory via the standard library. | +| test.cpp:97:23:97:29 | call to vector | Call to 'vector' that dynamically allocates memory via the standard library. | +| test.cpp:99:19:99:20 | call to deque | Call to 'deque' that dynamically allocates memory via the standard library. | +| test.cpp:100:22:100:29 | call to deque | Call to 'deque' that dynamically allocates memory via the standard library. | +| test.cpp:102:18:102:19 | call to list | Call to 'list' that dynamically allocates memory via the standard library. | +| test.cpp:103:21:103:28 | call to list | Call to 'list' that dynamically allocates memory via the standard library. | +| test.cpp:105:26:105:28 | call to forward_list | Call to 'forward_list' that dynamically allocates memory via the standard library. | +| test.cpp:106:30:106:37 | call to forward_list | Call to 'forward_list' that dynamically allocates memory via the standard library. | +| test.cpp:110:17:110:18 | call to set | Call to 'set' that dynamically allocates memory via the standard library. | +| test.cpp:111:20:111:27 | call to set | Call to 'set' that dynamically allocates memory via the standard library. | +| test.cpp:113:22:113:23 | call to map | Call to 'map' that dynamically allocates memory via the standard library. | +| test.cpp:114:25:114:39 | call to map | Call to 'map' that dynamically allocates memory via the standard library. | +| test.cpp:116:22:116:24 | call to multiset | Call to 'multiset' that dynamically allocates memory via the standard library. | +| test.cpp:117:26:117:33 | call to multiset | Call to 'multiset' that dynamically allocates memory via the standard library. | +| test.cpp:119:27:119:29 | call to multimap | Call to 'multimap' that dynamically allocates memory via the standard library. | +| test.cpp:120:31:120:37 | call to multimap | Call to 'multimap' that dynamically allocates memory via the standard library. | +| test.cpp:124:27:124:29 | call to unordered_set | Call to 'unordered_set' that dynamically allocates memory via the standard library. | +| test.cpp:125:31:125:38 | call to unordered_set | Call to 'unordered_set' that dynamically allocates memory via the standard library. | +| test.cpp:127:32:127:34 | call to unordered_map | Call to 'unordered_map' that dynamically allocates memory via the standard library. | +| test.cpp:128:36:129:21 | call to unordered_map | Call to 'unordered_map' that dynamically allocates memory via the standard library. | +| test.cpp:131:32:131:35 | call to unordered_multiset | Call to 'unordered_multiset' that dynamically allocates memory via the standard library. | +| test.cpp:132:37:133:38 | call to unordered_multiset | Call to 'unordered_multiset' that dynamically allocates memory via the standard library. | +| test.cpp:135:37:135:40 | call to unordered_multimap | Call to 'unordered_multimap' that dynamically allocates memory via the standard library. | +| test.cpp:136:42:137:13 | call to unordered_multimap | Call to 'unordered_multimap' that dynamically allocates memory via the standard library. | +| test.cpp:141:22:141:24 | call to valarray | Call to 'valarray' that dynamically allocates memory via the standard library. | +| test.cpp:142:26:142:28 | call to valarray | Call to 'valarray' that dynamically allocates memory via the standard library. | +| test.cpp:143:26:144:27 | call to valarray | Call to 'valarray' that dynamically allocates memory via the standard library. | +| test.cpp:148:15:148:16 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:149:19:149:26 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:150:18:150:25 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:151:18:151:25 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:153:16:153:18 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:154:21:154:29 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:156:18:156:22 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:157:25:157:33 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:159:18:159:22 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:160:25:160:33 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:164:19:164:21 | call to stack | Call to 'stack' that dynamically allocates memory via the standard library. | +| test.cpp:166:19:166:20 | call to queue | Call to 'queue' that dynamically allocates memory via the standard library. | +| test.cpp:168:28:168:30 | call to priority_queue | Call to 'priority_queue' that dynamically allocates memory via the standard library. | +| test.cpp:172:21:172:23 | call to basic_stringstream | Call to 'basic_stringstream' that dynamically allocates memory via the standard library. | +| test.cpp:173:25:173:32 | call to basic_stringstream | Call to 'basic_stringstream' that dynamically allocates memory via the standard library. | +| test.cpp:175:22:175:25 | call to basic_istringstream | Call to 'basic_istringstream' that dynamically allocates memory via the standard library. | +| test.cpp:176:27:176:34 | call to basic_istringstream | Call to 'basic_istringstream' that dynamically allocates memory via the standard library. | +| test.cpp:178:22:178:25 | call to basic_ostringstream | Call to 'basic_ostringstream' that dynamically allocates memory via the standard library. | +| test.cpp:180:22:180:25 | call to basic_stringstream | Call to 'basic_stringstream' that dynamically allocates memory via the standard library. | +| test.cpp:181:23:181:27 | call to basic_istringstream | Call to 'basic_istringstream' that dynamically allocates memory via the standard library. | +| test.cpp:182:23:182:27 | call to basic_ostringstream | Call to 'basic_ostringstream' that dynamically allocates memory via the standard library. | +| test.cpp:186:16:186:18 | call to basic_fstream | Call to 'basic_fstream' that dynamically allocates memory via the standard library. | +| test.cpp:187:20:187:30 | call to basic_fstream | Call to 'basic_fstream' that dynamically allocates memory via the standard library. | +| test.cpp:189:17:189:20 | call to basic_ifstream | Call to 'basic_ifstream' that dynamically allocates memory via the standard library. | +| test.cpp:190:22:190:32 | call to basic_ifstream | Call to 'basic_ifstream' that dynamically allocates memory via the standard library. | +| test.cpp:192:17:192:20 | call to basic_ofstream | Call to 'basic_ofstream' that dynamically allocates memory via the standard library. | +| test.cpp:193:22:193:32 | call to basic_ofstream | Call to 'basic_ofstream' that dynamically allocates memory via the standard library. | +| test.cpp:195:17:195:20 | call to basic_fstream | Call to 'basic_fstream' that dynamically allocates memory via the standard library. | +| test.cpp:196:18:196:22 | call to basic_ifstream | Call to 'basic_ifstream' that dynamically allocates memory via the standard library. | +| test.cpp:197:18:197:22 | call to basic_ofstream | Call to 'basic_ofstream' that dynamically allocates memory via the standard library. | +| test.cpp:201:14:201:15 | call to basic_regex | Call to 'basic_regex' that dynamically allocates memory via the standard library. | +| test.cpp:202:17:202:26 | call to basic_regex | Call to 'basic_regex' that dynamically allocates memory via the standard library. | +| test.cpp:203:17:203:25 | call to basic_regex | Call to 'basic_regex' that dynamically allocates memory via the standard library. | +| test.cpp:205:15:205:17 | call to basic_regex | Call to 'basic_regex' that dynamically allocates memory via the standard library. | +| test.cpp:206:19:206:29 | call to basic_regex | Call to 'basic_regex' that dynamically allocates memory via the standard library. | +| test.cpp:210:25:210:26 | call to function | Call to 'function' that dynamically allocates memory via the standard library. | +| test.cpp:211:29:212:3 | call to function | Call to 'function' that dynamically allocates memory via the standard library. | +| test.cpp:213:31:215:3 | call to function | Call to 'function' that dynamically allocates memory via the standard library. | +| test.cpp:218:29:221:7 | call to function | Call to 'function' that dynamically allocates memory via the standard library. | +| test.cpp:225:12:225:13 | call to any | Call to 'any' that dynamically allocates memory via the standard library. | +| test.cpp:226:16:226:18 | call to any | Call to 'any' that dynamically allocates memory via the standard library. | +| test.cpp:227:16:228:26 | call to any | Call to 'any' that dynamically allocates memory via the standard library. | +| test.cpp:228:7:228:26 | call to basic_string | Call to 'basic_string' that dynamically allocates memory via the standard library. | +| test.cpp:233:16:233:23 | call to any | Call to 'any' that dynamically allocates memory via the standard library. | +| test.cpp:237:21:237:22 | call to promise | Call to 'promise' that dynamically allocates memory via the standard library. | +| test.cpp:242:22:242:23 | call to promise | Call to 'promise' that dynamically allocates memory via the standard library. | +| test.cpp:243:32:244:38 | call to shared_future | Call to 'shared_future' that dynamically allocates memory via the standard library. | +| test.cpp:244:7:244:25 | call to promise | Call to 'promise' that dynamically allocates memory via the standard library. | +| test.cpp:246:33:247:24 | call to packaged_task | Call to 'packaged_task' that dynamically allocates memory via the standard library. | +| test.cpp:251:15:251:18 | call to locale | Call to 'locale' that dynamically allocates memory via the standard library. | +| test.cpp:252:20:252:23 | call to locale | Call to 'locale' that dynamically allocates memory via the standard library. | +| test.cpp:253:21:254:28 | call to locale | Call to 'locale' that dynamically allocates memory via the standard library. | +| test.cpp:258:18:258:25 | call to thread | Call to 'thread' that dynamically allocates memory via the standard library. | +| test.cpp:262:18:263:25 | call to thread | Call to 'thread' that dynamically allocates memory via the standard library. | +| test.cpp:268:13:268:22 | call to async | Call to 'async' that dynamically allocates memory via the standard library. | +| test.cpp:270:13:270:22 | call to async | Call to 'async' that dynamically allocates memory via the standard library. | +| test.cpp:273:13:273:22 | call to async | Call to 'async' that dynamically allocates memory via the standard library. | +| test.cpp:279:25:279:26 | call to path | Call to 'path' that dynamically allocates memory via the standard library. | +| test.cpp:280:29:280:39 | call to path | Call to 'path' that dynamically allocates memory via the standard library. | +| test.cpp:281:28:281:38 | call to path | Call to 'path' that dynamically allocates memory via the standard library. | +| test.cpp:282:35:282:39 | call to path | Call to 'path' that dynamically allocates memory via the standard library. | +| test.cpp:287:7:287:8 | call to vector | Call to 'vector' that dynamically allocates memory via the standard library. | +| test.cpp:289:7:289:8 | call to deque | Call to 'deque' that dynamically allocates memory via the standard library. | +| test.cpp:291:7:291:8 | call to list | Call to 'list' that dynamically allocates memory via the standard library. | +| test.cpp:293:7:293:9 | call to forward_list | Call to 'forward_list' that dynamically allocates memory via the standard library. | diff --git a/cpp/misra/test/rules/RULE-21-6-1/test.cpp b/cpp/misra/test/rules/RULE-21-6-1/test.cpp index 0a9a43d8b6..83fcc29632 100644 --- a/cpp/misra/test/rules/RULE-21-6-1/test.cpp +++ b/cpp/misra/test/rules/RULE-21-6-1/test.cpp @@ -236,7 +236,8 @@ void test_any() { void test_promise_future() { std::promise p1; // NON_COMPLIANT: allocates shared state std::future f1 = - p1.get_future(); // NON_COMPLIANT: references allocated shared state + p1.get_future(); // COMPLIANT: references shared state already allocated + // by promise constructor std::promise p2; // NON_COMPLIANT: allocates shared state std::shared_future sf1 = From cd9a8413ffcacccecb01de7564166e585a453722 Mon Sep 17 00:00:00 2001 From: Jeongsoo Lee Date: Wed, 8 Apr 2026 22:37:45 -0400 Subject: [PATCH 6/6] Fix formatting --- .../RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql b/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql index 8ade60f58f..1dc192eab3 100644 --- a/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql +++ b/cpp/misra/src/rules/RULE-21-6-1/DynamicMemoryShouldNotBeUsed.ql @@ -209,9 +209,7 @@ abstract class DynamicMemoryDeallocatingFunction extends Function { } * and C++ deallocation functions (`operator delete`, `operator delete[]`). */ class DirectDynamicMemoryDeallocatingFunction extends DynamicMemoryDeallocatingFunction { - DirectDynamicMemoryDeallocatingFunction() { - this instanceof DeallocationFunction - } + DirectDynamicMemoryDeallocatingFunction() { this instanceof DeallocationFunction } } /** @@ -231,9 +229,7 @@ where ( // Direct allocation: malloc, calloc, realloc, aligned_alloc, operator new, operator new[] call.getTarget() instanceof DirectDynamicMemoryAllocatingFunction and - message = - "Call to dynamic memory allocating function '" + call.getTarget().getName() + - "'." + message = "Call to dynamic memory allocating function '" + call.getTarget().getName() + "'." or // Indirect allocation: std library types that allocate internally call.getTarget() instanceof IndirectDynamicMemoryAllocatingFunction and @@ -245,8 +241,6 @@ where // Excludes realloc (already caught as allocation). call.getTarget() instanceof DynamicMemoryDeallocatingFunction and not call.getTarget() instanceof DynamicMemoryAllocatingFunction and - message = - "Call to dynamic memory deallocating function '" + call.getTarget().getName() + - "'." + message = "Call to dynamic memory deallocating function '" + call.getTarget().getName() + "'." ) select call, message