Skip to content

Commit

Permalink
Partial fix for #12695 FP assertWithSideEffect with library functions (
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github authored May 2, 2024
1 parent a91edcf commit 50dc589
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 0 deletions.
3 changes: 3 additions & 0 deletions cfg/gtk.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,7 @@
</function>
<!-- guint g_list_length (GList *list); -->
<function name="g_list_length">
<pure/>
<leak-ignore/>
<noreturn>false</noreturn>
<returnValue type="guint"/>
Expand Down Expand Up @@ -1679,6 +1680,7 @@
</function>
<!-- guint g_slist_length (GSList *list); -->
<function name="g_slist_length">
<pure/>
<leak-ignore/>
<noreturn>false</noreturn>
<returnValue type="guint"/>
Expand Down Expand Up @@ -4039,6 +4041,7 @@
</function>
<!-- gboolean g_str_equal (gconstpointer v1, gconstpointer v2); -->
<function name="g_str_equal">
<pure/>
<leak-ignore/>
<noreturn>false</noreturn>
<returnValue type="gboolean"/>
Expand Down
1 change: 1 addition & 0 deletions cfg/opengl.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@
<!-- https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIsEnabled.xml -->
<!-- GLboolean glIsEnabled( GLenum cap ); -->
<function name="glIsEnabled">
<pure/>
<noreturn>false</noreturn>
<returnValue type="GLboolean"/>
<use-retval/>
Expand Down
1 change: 1 addition & 0 deletions cfg/qt.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
</function>
<!-- const T &qBound(const T &min, const T &val, const T &max) -->
<function name="qBound">
<pure/>
<noreturn>false</noreturn>
<use-retval/>
<arg nr="1" direction="in">
Expand Down
2 changes: 2 additions & 0 deletions cfg/sqlite3.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@
<!-- https://www.sqlite.org/capi3ref.html#sqlite3_mutex_held -->
<!-- int sqlite3_mutex_held(sqlite3_mutex*); -->
<function name="sqlite3_mutex_held">
<pure/>
<noreturn>false</noreturn>
<returnValue type="int"/>
<use-retval/>
Expand All @@ -988,6 +989,7 @@
<!-- https://www.sqlite.org/capi3ref.html#sqlite3_mutex_held -->
<!-- int sqlite3_mutex_notheld(sqlite3_mutex*); -->
<function name="sqlite3_mutex_notheld">
<pure/>
<noreturn>false</noreturn>
<returnValue type="int"/>
<use-retval/>
Expand Down
9 changes: 9 additions & 0 deletions cfg/std.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4806,6 +4806,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
</function>
<!-- char * strchr(const char *cs, int c); -->
<function name="strchr,std::strchr">
<pure/>
<use-retval/>
<returnValue type="char *"/>
<noreturn>false</noreturn>
Expand Down Expand Up @@ -5119,6 +5120,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
</function>
<!-- char* strstr(const char *s1, const char *s2); -->
<function name="strstr,std::strstr">
<pure/>
<use-retval/>
<returnValue type="char *"/>
<noreturn>false</noreturn>
Expand Down Expand Up @@ -5377,6 +5379,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<!-- const char * strrchr(const char * str, int character);-->
<!-- char * strrchr(char * str, int character); -->
<function name="strrchr,std::strrchr">
<pure/>
<use-retval/>
<returnValue type="char *"/>
<noreturn>false</noreturn>
Expand Down Expand Up @@ -5620,6 +5623,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
</function>
<!-- int tolower(int c); -->
<function name="tolower,std::tolower">
<pure/>
<use-retval/>
<returnValue type="int">arg1 &lt; 'A' || arg1 &gt; 'Z' ? arg1 : arg1 + 32</returnValue>
<noreturn>false</noreturn>
Expand Down Expand Up @@ -8129,6 +8133,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<!-- template< class T1, class T2 > std::pair<V1,V2> make_pair( T1&& t, T2&& u ); // since C++11 until C++14 -->
<!-- template< class T1, class T2 > constexpr std::pair<V1,V2> make_pair( T1&& t, T2&& u ); // since C++14 -->
<function name="std::make_pair">
<pure/>
<noreturn>false</noreturn>
<use-retval/>
<arg nr="1"/>
Expand Down Expand Up @@ -8171,6 +8176,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
</function>
<!--#define offsetof(type, member) /*implementation-defined*/-->
<function name="offsetof">
<pure/>
<noreturn>false</noreturn>
<returnValue type="std::size_t"/>
<use-retval/>
Expand Down Expand Up @@ -8217,6 +8223,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
</arg>
</function>
<function name="std::size">
<pure/>
<noreturn>false</noreturn>
<use-retval/>
<leak-ignore/>
Expand Down Expand Up @@ -8667,6 +8674,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
</arg>
</function>
<function name="std::exception::what,std::logic_error::what,std::invalid_argument::what,std::domain_error::what,std::length_error::what,std::out_of_range::what,std::future_error::what,std::runtime_error::what,std::range_error::what,std::overflow_error::what,std::underflow_error::what,std::regex_error::what,std::system_error::what,std::ios_base::failure::what,std::filesystem::filesystem_error::what,std::nonexistent_local_time::what,std::ambiguous_local_time::what,std::format_error::what,std::bad_typeid::what,std::bad_cast::what,std::bad_any_cast::what,std::bad_optional_access::what,std::bad_expected_access::what,std::bad_weak_ptr::what,std::bad_function_call::what,std::bad_alloc::what,std::bad_array_new_length::what,std::bad_exception::what,std::bad_variant_access::what">
<const/>
<noreturn>false</noreturn>
<use-retval/>
<returnValue type="const char *"/>
Expand Down Expand Up @@ -8815,6 +8823,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<function name="emplace" action="push"/>
<function name="try_emplace" action="push"/>
<function name="insert_or_assign" action="push"/>
<function name="at" yields="at_index"/>
</access>
</container>
<container id="stdList" startPattern="std :: list|forward_list &lt;" inherits="stdContainer">
Expand Down
5 changes: 5 additions & 0 deletions lib/checkassert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ void CheckAssert::assertWithSideEffects()
return ac.second.iteratorInfo.container > 0; // bailout, takes iterators -> assume read access
}))
continue;
if (tmp->str() == "get" && Token::simpleMatch(tmp->astParent(), ".") && astIsSmartPointer(tmp->astParent()->astOperand1()))
continue;
if (f->containerYield == Library::Container::Yield::START_ITERATOR || // bailout for std::begin/end
f->containerYield == Library::Container::Yield::END_ITERATOR)
continue;
sideEffectInAssertError(tmp, mSettings->library.getFunctionName(tmp));
}
continue;
Expand Down
19 changes: 19 additions & 0 deletions test/cfg/std.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5022,3 +5022,22 @@ void assertWithSideEffect_system()
// cppcheck-suppress [assertWithSideEffect,checkLibraryNoReturn] // TODO: #8329
assert(std::system("abc"));
}

void assertWithSideEffect_std_map_at(const std::map<int, int>& m) // #12695
{
// cppcheck-suppress checkLibraryNoReturn
assert(m.at(0));
}

void assertWithSideEffect_std_unique_ptr_get(std::unique_ptr<int>& p)
{
// cppcheck-suppress checkLibraryNoReturn
assert(p.get());
}

void assertWithSideEffect_std_begin(const std::vector<std::string>& v) {
// cppcheck-suppress checkLibraryFunction // TODO
assert(std::is_sorted(std::begin(v), std::end(v), [](const std::string& a, const std::string& b) {
return a.size() < b.size();
})); // cppcheck-suppress checkLibraryNoReturn
}

0 comments on commit 50dc589

Please sign in to comment.