Skip to content
Draft
2 changes: 1 addition & 1 deletion cfg/gtk.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8761,7 +8761,7 @@
<function name="g_variant_builder_init">
<noreturn>false</noreturn>
<returnValue type="void"/>
<arg nr="1" direction="in">
<arg nr="1" direction="out">
<not-null/>
</arg>
<arg nr="2" direction="in">
Expand Down
4 changes: 2 additions & 2 deletions cfg/std.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8751,15 +8751,15 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<use-retval/>
<leak-ignore/>
<noreturn>false</noreturn>
<arg nr="1" direction="in"/>
<arg nr="1" direction="in" indirect="0"/>
<container yields="start-iterator"/>
<returnValue type="iterator" container="1"/>
</function>
<function name="std::end,std::cend,std::rend,std::crend">
<use-retval/>
<leak-ignore/>
<noreturn>false</noreturn>
<arg nr="1" direction="in"/>
<arg nr="1" direction="in" indirect="0"/>
<container yields="end-iterator"/>
<returnValue type="iterator" container="1"/>
</function>
Expand Down
3 changes: 3 additions & 0 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3471,6 +3471,9 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
const bool isuninitbad = settings.library.isuninitargbad(ftok, argnr + 1, indirect, &hasIndirect);
if (isuninitbad && (!addressOf || isnullbad))
return ExprUsage::Used;
const Library::ArgumentChecks::Direction argDirection = settings.library.getArgDirection(ftok, argnr + 1, indirect);
if (argDirection == Library::ArgumentChecks::Direction::DIR_IN)
return ExprUsage::Used;
}
return ExprUsage::Inconclusive;
}
Expand Down
11 changes: 7 additions & 4 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8035,10 +8035,13 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
}
}
//Is iterator fetching function called?
} else if (Token::simpleMatch(tok->astOperand1(), "::") &&
tok->astOperand2() &&
tok->astOperand2()->isVariable()) {
const auto* const paramVariable = tok->astOperand2()->variable();
} else if (Token::simpleMatch(tok->astOperand1(), "::") && Token::Match(tok->astOperand2(), "%var%|.|[")) {
const Token* varTok = tok->astOperand2();
while (Token::simpleMatch(varTok, "["))
varTok = varTok->astOperand1();
if (Token::simpleMatch(varTok, "."))
varTok = varTok->astOperand2();
const auto* const paramVariable = varTok->variable();
if (!paramVariable ||
!paramVariable->valueType() ||
!paramVariable->valueType()->container) {
Expand Down
4 changes: 2 additions & 2 deletions test/cfg/posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1312,7 +1312,7 @@ void uninitvar(int fd)
pthread_mutex_t mutex, mutex1, mutex2, mutex3;
// cppcheck-suppress uninitvar
write(x1,"ab",2);
// TODO cppcheck-suppress uninitvar
// cppcheck-suppress uninitvar
write(fd,buf,2); // #6325
// cppcheck-suppress uninitvar
write(fd,"ab",x2);
Expand Down Expand Up @@ -1408,7 +1408,7 @@ void timet_h(const struct timespec* ptp1)
clock_settime(clk_id2, ptp1);

struct timespec tp;
// FIXME cppcheck-suppress uninitvar
// cppcheck-suppress uninitvar
clock_settime(CLOCK_REALTIME, &tp); // #6577 - false negative
// cppcheck-suppress uninitvar
clock_settime(clk_id3, &tp);
Expand Down
35 changes: 34 additions & 1 deletion test/cfg/std.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5003,7 +5003,7 @@ void beginEnd()
//cppcheck-suppress ignoredReturnValue
std::crend(v);

// cppcheck-suppress constVariable
// TODO cppcheck-suppress constVariable
int arr[4];

//cppcheck-suppress ignoredReturnValue
Expand All @@ -5025,6 +5025,39 @@ void beginEnd()
std::crend(arr);
}

struct S_constParameter_std_begin { // #11617
int a[2];
};

struct T_constParameter_std_begin {
std::vector<int> v;
};

struct U_constParameter_std_begin {
std::vector<int> v[1][1];
};

void f(S_constParameter_std_begin& s) {
std::for_each(std::begin(s.a), std::end(s.a), [](int& i) { ++i; });
}

void f(T_constParameter_std_begin& t) {
std::for_each(std::begin(t.v), std::end(t.v), [](int& i) { ++i; });
}

void f(U_constParameter_std_begin& u) {
std::for_each(std::begin(u.v[0][0]), std::end(u.v[0][0]), [](int& i) { ++i; });
}

void g_constVariable_std_begin(int* p) { *p = 0; }

int f_constVariable_std_begin() {
int arr[1];
g_constVariable_std_begin(std::begin(arr));
*std::begin(arr) = 1;
return arr[0];
}

void smartPtr_get()
{
std::unique_ptr<int> p;
Expand Down
12 changes: 12 additions & 0 deletions test/testsymboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9969,6 +9969,18 @@ class TestSymbolDatabase : public TestFixture {
ASSERT(tok && tok->valueType());
ASSERT_EQUALS("iterator(std :: vector <)", tok->valueType()->str());
}
{
GET_SYMBOL_DB("struct S { std::vector<int> v[1][1]; };\n"
"void f(S& s) {\n"
" auto it = std::begin(s.v[0][0]);\n"
"}\n");
ASSERT_EQUALS("", errout_str());

const Token* tok = tokenizer.tokens();
tok = Token::findsimplematch(tok, "auto");
ASSERT(tok && tok->valueType());
ASSERT_EQUALS("iterator(std :: vector <)", tok->valueType()->str());
}
{
GET_SYMBOL_DB("void f(std::vector<int>::iterator beg, std::vector<int>::iterator end) {\n"
" auto it = std::find(beg, end, 0);\n"
Expand Down
Loading