Fix #9104 reopened Improve check: missing virtual destructor (#5110)

* Fix #9104 reopened Improve check: missing virtual destructor

* Add support for missing container members

* Add more stuff

* Improve qt.cfg

* Improve wxwidgets.cfg, qt.cfg
This commit is contained in:
chrchr-github 2023-06-02 15:24:18 +02:00 committed by GitHub
parent 52c0f10fa1
commit 7c56514bd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 109 additions and 13 deletions

View File

@ -885,11 +885,21 @@
<use-retval/>
<const/>
</function>
<!-- iterator QVector::..() -->
<function name="QVector::begin,QVector::end,QVector::cbegin,QVector::cend,QVector::constBegin,QVector::constEnd,QVector::rbegin,QVector::rend,QVector::crbegin,QVector::crend">
<noreturn>false</noreturn>
<use-retval/>
</function>
<!-- iterator QList::..() -->
<function name="QList::begin,QList::end,QList::cbegin,QList::cend,QList::constBegin,QList::constEnd,QList::rbegin,QList::rend,QList::crbegin,QList::crend">
<noreturn>false</noreturn>
<use-retval/>
</function>
<!-- iterator QLinkedList::..() -->
<function name="QLinkedList::begin,QLinkedList::end,QLinkedList::cbegin,QLinkedList::cend,QLinkedList::constBegin,QLinkedList::constEnd,QLinkedList::rbegin,QLinkedList::rend,QLinkedList::crbegin,QLinkedList::crend">
<noreturn>false</noreturn>
<use-retval/>
</function>
<!-- iterator QString::..() -->
<function name="QString::begin,QString::end,QString::cbegin,QString::cend,QString::constBegin,QString::constEnd,QString::rbegin,QString::rend,QString::crbegin,QString::crend">
<noreturn>false</noreturn>
@ -900,6 +910,11 @@
<noreturn>false</noreturn>
<use-retval/>
</function>
<!-- iterator QStack::..() -->
<function name="QStack::begin,QStack::end,QStack::cbegin,QStack::cend,QStack::constBegin,QStack::constEnd,QStack::rbegin,QStack::rend,QStack::crbegin,QStack::crend">
<noreturn>false</noreturn>
<use-retval/>
</function>
<!-- QStandardItem *QStandardItem::child(int row, int column = 0) const -->
<function name="QStandardItem::child">
<noreturn>false</noreturn>
@ -935,7 +950,7 @@
</arg>
</function>
<!-- void QString::clear() -->
<function name="QList::clear,QString::clear">
<function name="QList::clear,QLinkedList::clear,QString::clear">
<noreturn>false</noreturn>
</function>
<!-- int QString::compare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) //static -->
@ -1132,7 +1147,8 @@
<!-- int QStringList::count() const -->
<!-- int QStringList::length() const -->
<!-- int QStringList::size() const -->
<function name="QList::count,QList::length,QList::size,QString::count,QString::length,QString::size,QStringList::count,QStringList::length,QStringList::size">
<!-- int QByteArray::size() const -->
<function name="QList::count,QList::length,QList::size,QString::count,QString::length,QString::size,QStringList::count,QStringList::length,QStringList::size,QByteArray::size,QByteArray::length,QByteArray::count">
<noreturn>false</noreturn>
<use-retval/>
<returnValue type="signed int"/>
@ -4075,10 +4091,16 @@
</function>
<!-- T *QVector::data() -->
<!-- const T *QVector::data() const -->
<function name="QVector::data,QStack::data">
<function name="QVector::data,QStack::data,QByteArray::data">
<noreturn>false</noreturn>
<use-retval/>
</function>
<!-- const T *QVector::constData() const -->
<function name="QVector::constData,QStack::constData,QByteArray::constData">
<noreturn>false</noreturn>
<use-retval/>
<const/>
</function>
<!-- bool QVector::empty() const -->
<function name="QVector::empty,QStack::empty">
<noreturn>false</noreturn>

View File

@ -6609,7 +6609,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<!-- 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 -->
<function name="std::array::empty,std::deque::empty,std::list::empty,std::forward_list::empty,std::map::empty,std::unordered_map::empty,std::queue::empty,std::set::empty,std::unordered_set::empty,std::stack::empty,std::string::empty,std::wstring::empty,std::basic_string::empty,std::vector::empty">
<function name="std::array::empty,std::deque::empty,std::list::empty,std::forward_list::empty,std::map::empty,std::unordered_map::empty,std::queue::empty,std::set::empty,std::unordered_set::empty,std::stack::empty,std::string::empty,std::wstring::empty,std::basic_string::empty,std::vector::empty,std::span::empty">
<use-retval/>
<const/>
<returnValue type="bool"/>
@ -6682,7 +6682,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<not-uninit/>
</arg>
</function>
<function name="std::deque::size,std::deque::max_size,std::list::size,std::list::max_size,std::map::size,std::map::max_size,std::unordered_map::size,std::unordered_map::max_size,std::queue::size,std::set::size,std::set::max_size,std::unordered_set::size,std::unordered_set::max_size,std::stack::size,std::string::size,std::wstring::size,std::vector::size,std::vector::capacity,std::vector::max_size,std::array::size,std::array::max_size">
<function name="std::deque::size,std::deque::max_size,std::list::size,std::list::max_size,std::map::size,std::map::max_size,std::unordered_map::size,std::unordered_map::max_size,std::queue::size,std::set::size,std::set::max_size,std::unordered_set::size,std::unordered_set::max_size,std::stack::size,std::string::size,std::wstring::size,std::vector::size,std::vector::capacity,std::vector::max_size,std::array::size,std::array::max_size,std::span::size,std::span::size_bytes">
<use-retval/>
<const/>
<returnValue type="std::size_t"/>
@ -6703,11 +6703,23 @@ 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::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">
<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::queue::begin,std::queue::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">
<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>
@ -6756,6 +6768,14 @@ 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="void *"/>
<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 -->
@ -7352,6 +7372,12 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<not-uninit/>
</arg>
</function>
<!-- void std::ifstream::close(); -->
<function name="std::ifstream::close">
<noreturn>false</noreturn>
<leak-ignore/>
<returnValue type="void"/>
</function>
<!-- void std::fstream::open(const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out); -->
<!-- void std::fstream::open(const std::string& filename, ios_base::openmode mode = ios_base::in | ios_base::out); -->
<function name="std::fstream::open">
@ -8370,7 +8396,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
</function>
<!-- void std::string::shrink_to_fit(void) ; (since C++11) -->
<!-- void std::wstring::shrink_to_fit(void) ; (since C++11) -->
<function name="std::string::shrink_to_fit,std::wstring::shrink_to_fit">
<function name="std::string::shrink_to_fit,std::wstring::shrink_to_fit,std::vector::shrink_to_fit">
<noreturn>false</noreturn>
<returnValue type="void"/>
<leak-ignore/>

View File

@ -5485,7 +5485,7 @@
<!-- http://docs.wxwidgets.org/trunk/classwx_string.html#ab20a87ca731a52c36ec674dae2213ad8 -->
<!-- size_t wxString::Len () const -->
<!-- size_t wxString::length () const -->
<function name="wxString::Len,wxString::length">
<function name="wxString::Len,wxString::length,wxString::size">
<noreturn>false</noreturn>
<leak-ignore/>
<const/>
@ -8953,6 +8953,22 @@
<not-bool/>
</arg>
</function>
<!-- void wxString::Clear () -->
<function name="wxString::Clear">
<noreturn>false</noreturn>
<returnValue type="void"/>
</function>
<!-- void wxString::c_str () -->
<function name="wxString::c_str">
<noreturn>false</noreturn>
<leak-ignore/>
<const/>
<returnValue type="const char*"/>
</function>
<function name="wxString::begin,wxString::end">
<use-retval/>
<noreturn>false</noreturn>
</function>
<!-- void wxBitmap::SetMask( wxMask * mask ) -->
<function name="wxBitmap::SetMask">
<noreturn>false</noreturn>
@ -14219,7 +14235,7 @@ wxItemKind kind = wxITEM_NORMAL) -->
<arg nr="2" direction="in" default="0">
<not-uninit/>
</arg>
<arg nr="3" direction="in" default="std::wxString::npos">
<arg nr="3" direction="in" default="wxString::npos">
<not-uninit/>
</arg>
</function>

View File

@ -1250,7 +1250,7 @@ bool Library::matchArguments(const Token *ftok, const std::string &functionName)
const int callargs = numberOfArgumentsWithoutAst(ftok);
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(functionName);
if (it == functions.cend())
return (callargs == 0);
return false;
int args = 0;
int firstOptionalArg = -1;
for (const std::pair<const int, Library::ArgumentChecks> & argCheck : it->second.argumentChecks) {

View File

@ -28,6 +28,7 @@ int valid_code_do_crypt(char *outfile)
FILE *out;
ctx = EVP_CIPHER_CTX_new();
// cppcheck-suppress checkLibraryFunction
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, intext, strlen(intext))) {

View File

@ -441,6 +441,7 @@ void validCode(int * pIntPtr, QString & qstrArg, double d)
printf(QT_TR_NOOP("Hi"));
// cppcheck-suppress checkLibraryFunction
Q_DECLARE_LOGGING_CATEGORY(logging_category_test);
QT_FORWARD_DECLARE_CLASS(forwardDeclaredClass);
QT_FORWARD_DECLARE_STRUCT(forwardDeclaredStruct);

View File

@ -4489,6 +4489,7 @@ void getline()
in.close();
}
// cppcheck-suppress passedByValue
void stream_write(std::ofstream& s, std::vector<char> v) {
if (v.empty()) {}
s.write(v.data(), v.size());
@ -4634,18 +4635,26 @@ void stdspan()
// cppcheck-suppress unreadVariable
std::span spn2 = spn;
//cppcheck-suppress ignoredReturnValue
spn.begin();
//cppcheck-suppress ignoredReturnValue
spn.end();
//cppcheck-suppress ignoredReturnValue
spn.rbegin();
spn.end();
//cppcheck-suppress ignoredReturnValue
spn.front();
//cppcheck-suppress ignoredReturnValue
spn.back();
//cppcheck-suppress constStatement
spn[0];
//cppcheck-suppress ignoredReturnValue
spn.data();
//cppcheck-suppress ignoredReturnValue
spn.size();
//cppcheck-suppress ignoredReturnValue
spn.size_bytes();
//cppcheck-suppress ignoredReturnValue
spn.empty();
//cppcheck-suppress ignoredReturnValue
spn.first(2);

View File

@ -2630,6 +2630,27 @@ private:
" delete p;\n"
"}");
ASSERT_EQUALS("[test.cpp:7]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
checkVirtualDestructor("using namespace std;\n"
"struct A\n"
"{\n"
" A() { cout << \"A is constructing\\n\"; }\n"
" ~A() { cout << \"A is destructing\\n\"; }\n"
"};\n"
" \n"
"struct Base {};\n"
" \n"
"struct Derived : Base\n"
"{\n"
" A a;\n"
"};\n"
" \n"
"int main(void)\n"
"{\n"
" Base* p = new Derived();\n"
" delete p;\n"
"}");
ASSERT_EQUALS("[test.cpp:8]: (error) Class 'Base' which is inherited by class 'Derived' does not have a virtual destructor.\n", errout.str());
}
void virtualDestructor3() {

View File

@ -1823,7 +1823,7 @@ private:
check("void f() {\n"
" lib_func();"
"}", "test.cpp", &s);
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (information) --check-library: There is no matching configuration for function lib_func()\n", errout.str());
check("void f(void* v) {\n"
" lib_func(v);"