Detect container action and yield functions (#5117)

* Detect container action and yield functions

* Fix test

* Adapt getUseRetValType() to handle container yield functions
Add TODO

* Handle combined action/yield

* Add Yield::BUFFER

* Remove redundant functions

* Revert "Remove redundant functions"

This reverts commit 4f124a57de5c761ac757ebed83d9f047ef4a1328.

* Add Yield::AT_INDEX

* Add Yield::ITERATOR

* Simplify
This commit is contained in:
chrchr-github 2023-06-09 16:03:47 +02:00 committed by GitHub
parent 2beb46194f
commit bd6c5318ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 19 additions and 38 deletions

View File

@ -6600,12 +6600,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<not-uninit/>
</arg>
</function>
<!-- void clear(); // until C++11 -->
<!-- void clear() noexcept; // since C++11 -->
<function name="std::deque::clear,std::list::clear,std::forward_list::clear,std::map::clear,std::unordered_map::clear,std::queue::clear,std::set::clear,std::unordered_set::clear,std::stack::clear,std::string::clear,std::wstring::clear,std::basic_string::clear,std::vector::clear">
<noreturn>false</noreturn>
<returnValue type="void"/>
</function>
<!-- bool empty() const; // until C++11 -->
<!-- constexpr bool empty() const noexcept; // since C++11 until C++20 -->
<!-- [[nodiscard]] constexpr bool empty() const noexcept; // since C++20 -->
@ -6703,26 +6697,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<not-uninit/>
</arg>
</function>
<function name="std::list::back,std::list::front,std::forward_list::front,std::queue::back,std::queue::front,std::deque::back,std::deque::front,std::vector::back,std::vector::front,std::array::front,std::array::back,std::string::front,std::string::back,std::wstring::front,std::wstring::back,std::string_view::front,std::string_view::back,std::wstring_view::front,std::wstring_view::back,std::span::back,std::span::front">
<use-retval/>
<noreturn>false</noreturn>
</function>
<function name="std::list::begin,std::list::end,std::forward_list::begin,std::forward_list::end,std::deque::begin,std::deque::end,std::vector::begin,std::vector::end,std::array::begin,std::array::end,std::string::begin,std::string::end,std::wstring::begin,std::wstring::end,std::string_view::begin,std::string_view::end,std::wstring_view::begin,std::wstring_view::end,std::span::begin,std::span::end,std::set::begin,std::set::end,std::unordered_set::begin,std::unordered_set::end,std::map::begin,std::map::end,std::unordered_map::begin,std::unordered_map::end">
<use-retval/>
<noreturn>false</noreturn>
</function>
<function name="std::list::cbegin,std::list::cend,std::forward_list::cbegin,std::forward_list::cend,std::deque::cbegin,std::deque::cend,std::vector::cbegin,std::vector::cend,std::array::cbegin,std::array::cend,std::string::cbegin,std::string::cend,std::wstring::cbegin,std::wstring::cend,std::string_view::cbegin,std::string_view::cend,std::wstring_view::cbegin,std::wstring_view::cend,std::span::cbegin,std::span::cend,std::set::cbegin,std::set::cend,std::unordered_set::cbegin,std::unordered_set::cend,std::map::cbegin,std::map::cend,std::unordered_map::cbegin,std::unordered_map::cend">
<use-retval/>
<noreturn>false</noreturn>
</function>
<function name="std::list::rbegin,std::list::rend,std::deque::rbegin,std::deque::rend,std::vector::rbegin,std::vector::rend,std::array::rbegin,std::array::rend,std::string::rbegin,std::string::rend,std::wstring::rbegin,std::wstring::rend,std::string_view::rbegin,std::string_view::rend,std::wstring_view::rbegin,std::wstring_view::rend,std::span::rbegin,std::span::rend,std::set::rbegin,std::set::rend,std::map::rbegin,std::map::rend">
<use-retval/>
<noreturn>false</noreturn>
</function>
<function name="std::list::crbegin,std::list::crend,std::deque::crbegin,std::deque::crend,std::vector::crbegin,std::vector::crend,std::array::crbegin,std::array::crend,std::string::crbegin,std::string::crend,std::wstring::crbegin,std::wstring::crend,std::string_view::crbegin,std::string_view::crend,std::wstring_view::crbegin,std::wstring_view::crend,std::span::crbegin,std::span::crend,std::set::crbegin,std::set::crend,std::map::crbegin,std::map::crend">
<use-retval/>
<noreturn>false</noreturn>
</function>
<function name="std::vector::at,std::array::at,std::string::at,std::wstring::at,std::string_view::at,std::wstring_view::at">
<use-retval/>
<noreturn>false</noreturn>
@ -6768,14 +6742,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<not-uninit/>
</arg>
</function>
<!-- T* std::vector<T,Allocator>::data() noexcept; -->
<!-- const T* std::vector<T,Allocator>::data() const noexcept; -->
<function name="std::array::data,std::vector::data,std::span::data">
<use-retval/>
<const/>
<returnValue type="const T *"/>
<noreturn>false</noreturn>
</function>
<!-- https://en.cppreference.com/w/cpp/container/deque/swap -->
<!-- void std::deque::swap( deque& other ); -->
<!-- https://en.cppreference.com/w/cpp/container/list/swap -->

View File

@ -622,6 +622,14 @@ void CheckFunctions::checkLibraryMatchFunctions()
if (Token::simpleMatch(tok->astTop(), "throw"))
continue;
if (Token::simpleMatch(tok->astParent(), ".")) {
const Token* contTok = tok->astParent()->astOperand1();
if (astContainerAction(contTok) != Library::Container::Action::NO_ACTION)
continue;
if (astContainerYield(contTok) != Library::Container::Yield::NO_YIELD)
continue;
}
if (!mSettings->library.isNotLibraryFunction(tok))
continue;

View File

@ -1358,6 +1358,15 @@ const Library::NonOverlappingData* Library::getNonOverlappingData(const Token *f
Library::UseRetValType Library::getUseRetValType(const Token *ftok) const
{
if (Token::simpleMatch(ftok->astParent(), ".")) {
using Yield = Library::Container::Yield;
using Action = Library::Container::Action;
const Yield yield = astContainerYield(ftok->astParent()->astOperand1());
if (yield == Yield::START_ITERATOR || yield == Yield::END_ITERATOR || yield == Yield::AT_INDEX ||
yield == Yield::SIZE || yield == Yield::EMPTY || yield == Yield::BUFFER || yield == Yield::BUFFER_NT ||
((yield == Yield::ITEM || yield == Yield::ITERATOR) && astContainerAction(ftok->astParent()->astOperand1()) == Action::NO_ACTION))
return Library::UseRetValType::DEFAULT;
}
if (isNotLibraryFunction(ftok))
return Library::UseRetValType::NONE;
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));

View File

@ -4489,7 +4489,7 @@ void getline()
in.close();
}
// cppcheck-suppress passedByValue
// TODO cppcheck-suppress passedByValue
void stream_write(std::ofstream& s, std::vector<char> v) {
if (v.empty()) {}
s.write(v.data(), v.size());

View File

@ -1925,9 +1925,7 @@ private:
" auto x = std::vector<int>(1);\n"
" x.push_back(1);\n"
"}\n", "test.cpp", &s);
TODO_ASSERT_EQUALS("",
"[test.cpp:7]: (information) --check-library: There is no matching configuration for function auto::push_back()\n",
errout.str());
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" auto p(std::make_shared<std::vector<int>>());\n"