Skip to content

Commit 50dc589

Browse files
Partial fix for #12695 FP assertWithSideEffect with library functions (#6373)
1 parent a91edcf commit 50dc589

7 files changed

Lines changed: 40 additions & 0 deletions

File tree

cfg/gtk.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,7 @@
15061506
</function>
15071507
<!-- guint g_list_length (GList *list); -->
15081508
<function name="g_list_length">
1509+
<pure/>
15091510
<leak-ignore/>
15101511
<noreturn>false</noreturn>
15111512
<returnValue type="guint"/>
@@ -1679,6 +1680,7 @@
16791680
</function>
16801681
<!-- guint g_slist_length (GSList *list); -->
16811682
<function name="g_slist_length">
1683+
<pure/>
16821684
<leak-ignore/>
16831685
<noreturn>false</noreturn>
16841686
<returnValue type="guint"/>
@@ -4039,6 +4041,7 @@
40394041
</function>
40404042
<!-- gboolean g_str_equal (gconstpointer v1, gconstpointer v2); -->
40414043
<function name="g_str_equal">
4044+
<pure/>
40424045
<leak-ignore/>
40434046
<noreturn>false</noreturn>
40444047
<returnValue type="gboolean"/>

cfg/opengl.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@
211211
<!-- https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIsEnabled.xml -->
212212
<!-- GLboolean glIsEnabled( GLenum cap ); -->
213213
<function name="glIsEnabled">
214+
<pure/>
214215
<noreturn>false</noreturn>
215216
<returnValue type="GLboolean"/>
216217
<use-retval/>

cfg/qt.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
</function>
7373
<!-- const T &qBound(const T &min, const T &val, const T &max) -->
7474
<function name="qBound">
75+
<pure/>
7576
<noreturn>false</noreturn>
7677
<use-retval/>
7778
<arg nr="1" direction="in">

cfg/sqlite3.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@
966966
<!-- https://www.sqlite.org/capi3ref.html#sqlite3_mutex_held -->
967967
<!-- int sqlite3_mutex_held(sqlite3_mutex*); -->
968968
<function name="sqlite3_mutex_held">
969+
<pure/>
969970
<noreturn>false</noreturn>
970971
<returnValue type="int"/>
971972
<use-retval/>
@@ -988,6 +989,7 @@
988989
<!-- https://www.sqlite.org/capi3ref.html#sqlite3_mutex_held -->
989990
<!-- int sqlite3_mutex_notheld(sqlite3_mutex*); -->
990991
<function name="sqlite3_mutex_notheld">
992+
<pure/>
991993
<noreturn>false</noreturn>
992994
<returnValue type="int"/>
993995
<use-retval/>

cfg/std.cfg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4806,6 +4806,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
48064806
</function>
48074807
<!-- char * strchr(const char *cs, int c); -->
48084808
<function name="strchr,std::strchr">
4809+
<pure/>
48094810
<use-retval/>
48104811
<returnValue type="char *"/>
48114812
<noreturn>false</noreturn>
@@ -5119,6 +5120,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
51195120
</function>
51205121
<!-- char* strstr(const char *s1, const char *s2); -->
51215122
<function name="strstr,std::strstr">
5123+
<pure/>
51225124
<use-retval/>
51235125
<returnValue type="char *"/>
51245126
<noreturn>false</noreturn>
@@ -5377,6 +5379,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
53775379
<!-- const char * strrchr(const char * str, int character);-->
53785380
<!-- char * strrchr(char * str, int character); -->
53795381
<function name="strrchr,std::strrchr">
5382+
<pure/>
53805383
<use-retval/>
53815384
<returnValue type="char *"/>
53825385
<noreturn>false</noreturn>
@@ -5620,6 +5623,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
56205623
</function>
56215624
<!-- int tolower(int c); -->
56225625
<function name="tolower,std::tolower">
5626+
<pure/>
56235627
<use-retval/>
56245628
<returnValue type="int">arg1 &lt; 'A' || arg1 &gt; 'Z' ? arg1 : arg1 + 32</returnValue>
56255629
<noreturn>false</noreturn>
@@ -8129,6 +8133,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
81298133
<!-- template< class T1, class T2 > std::pair<V1,V2> make_pair( T1&& t, T2&& u ); // since C++11 until C++14 -->
81308134
<!-- template< class T1, class T2 > constexpr std::pair<V1,V2> make_pair( T1&& t, T2&& u ); // since C++14 -->
81318135
<function name="std::make_pair">
8136+
<pure/>
81328137
<noreturn>false</noreturn>
81338138
<use-retval/>
81348139
<arg nr="1"/>
@@ -8171,6 +8176,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
81718176
</function>
81728177
<!--#define offsetof(type, member) /*implementation-defined*/-->
81738178
<function name="offsetof">
8179+
<pure/>
81748180
<noreturn>false</noreturn>
81758181
<returnValue type="std::size_t"/>
81768182
<use-retval/>
@@ -8217,6 +8223,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
82178223
</arg>
82188224
</function>
82198225
<function name="std::size">
8226+
<pure/>
82208227
<noreturn>false</noreturn>
82218228
<use-retval/>
82228229
<leak-ignore/>
@@ -8667,6 +8674,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
86678674
</arg>
86688675
</function>
86698676
<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">
8677+
<const/>
86708678
<noreturn>false</noreturn>
86718679
<use-retval/>
86728680
<returnValue type="const char *"/>
@@ -8815,6 +8823,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
88158823
<function name="emplace" action="push"/>
88168824
<function name="try_emplace" action="push"/>
88178825
<function name="insert_or_assign" action="push"/>
8826+
<function name="at" yields="at_index"/>
88188827
</access>
88198828
</container>
88208829
<container id="stdList" startPattern="std :: list|forward_list &lt;" inherits="stdContainer">

lib/checkassert.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ void CheckAssert::assertWithSideEffects()
6868
return ac.second.iteratorInfo.container > 0; // bailout, takes iterators -> assume read access
6969
}))
7070
continue;
71+
if (tmp->str() == "get" && Token::simpleMatch(tmp->astParent(), ".") && astIsSmartPointer(tmp->astParent()->astOperand1()))
72+
continue;
73+
if (f->containerYield == Library::Container::Yield::START_ITERATOR || // bailout for std::begin/end
74+
f->containerYield == Library::Container::Yield::END_ITERATOR)
75+
continue;
7176
sideEffectInAssertError(tmp, mSettings->library.getFunctionName(tmp));
7277
}
7378
continue;

test/cfg/std.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5022,3 +5022,22 @@ void assertWithSideEffect_system()
50225022
// cppcheck-suppress [assertWithSideEffect,checkLibraryNoReturn] // TODO: #8329
50235023
assert(std::system("abc"));
50245024
}
5025+
5026+
void assertWithSideEffect_std_map_at(const std::map<int, int>& m) // #12695
5027+
{
5028+
// cppcheck-suppress checkLibraryNoReturn
5029+
assert(m.at(0));
5030+
}
5031+
5032+
void assertWithSideEffect_std_unique_ptr_get(std::unique_ptr<int>& p)
5033+
{
5034+
// cppcheck-suppress checkLibraryNoReturn
5035+
assert(p.get());
5036+
}
5037+
5038+
void assertWithSideEffect_std_begin(const std::vector<std::string>& v) {
5039+
// cppcheck-suppress checkLibraryFunction // TODO
5040+
assert(std::is_sorted(std::begin(v), std::end(v), [](const std::string& a, const std::string& b) {
5041+
return a.size() < b.size();
5042+
})); // cppcheck-suppress checkLibraryNoReturn
5043+
}

0 commit comments

Comments
 (0)