Skip to content

Commit

Permalink
Merge branch 'chr_Fix12327' of https://github.com/chrchr-github/cppcheck
Browse files Browse the repository at this point in the history
 into chr_Fix12327
  • Loading branch information
chrchr-github committed Jan 15, 2024
2 parents eb617fa + 2a8a69c commit 54ae2bb
Show file tree
Hide file tree
Showing 19 changed files with 597 additions and 135 deletions.
23 changes: 17 additions & 6 deletions cfg/std.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6642,7 +6642,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<!-- void std::stack::push( value_type&& value ); // since C++11 -->
<!-- void std::vector::push_back( const T& value ); -->
<!-- void std::vector::push_back( T&& value ); // since C++11 -->
<function name="std::deque::push_back,std::deque::push_front,std::list::push_back,std::list::push_front,std::forward_list::push_front,std::queue::push,std::stack::push,std::vector::push_back">
<function name="std::deque::push_back,std::deque::push_front,std::list::push_back,std::list::push_front,std::forward_list::push_front,std::queue::push,std::priority_queue::push,std::stack::push,std::vector::push_back">
<noreturn>false</noreturn>
<returnValue type="void"/>
<arg nr="1">
Expand Down Expand Up @@ -6678,7 +6678,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<not-uninit/>
</arg>
</function>
<function name="std::deque::emplace_back,std::deque::emplace_front,std::list::emplace_back,std::list::emplace_front,std::forward_list::emplace_front,std::queue::emplace,std::stack::emplace,std::vector::emplace_back,std::vector::emplace_front,std::unordered_set::emplace">
<function name="std::deque::emplace_back,std::deque::emplace_front,std::list::emplace_back,std::list::emplace_front,std::forward_list::emplace_front,std::queue::emplace,std::priority_queue::emplace,std::stack::emplace,std::vector::emplace_back,std::vector::emplace_front,std::unordered_set::emplace">
<noreturn>false</noreturn>
<arg nr="variadic">
<not-uninit/>
Expand Down Expand Up @@ -6811,10 +6811,10 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<arg nr="1">
</arg>
</function>
<function name="std::stack::pop,std::queue::pop">
<function name="std::stack::pop,std::queue::pop,std::priority_queue::pop">
<noreturn>false</noreturn>
</function>
<function name="std::stack::top">
<function name="std::stack::top,std::priority_queue::top">
<use-retval/>
<noreturn>false</noreturn>
</function>
Expand Down Expand Up @@ -8587,6 +8587,17 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<noreturn>false</noreturn>
<returnValue type="void *"/>
</function>
<function name="std::tie">
<noreturn>false</noreturn>
<use-retval/>
<arg nr="variadic">
</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::ios_base::failure::what,std::bad_variant_access::what">
<noreturn>false</noreturn>
<use-retval/>
<returnValue type="const char *"/>
</function>
<memory>
<alloc init="false" buffer-size="malloc">malloc,std::malloc</alloc>
<alloc init="true" buffer-size="calloc">calloc,std::calloc</alloc>
Expand Down Expand Up @@ -8675,7 +8686,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<size templateParameter="0"/>
<access indexOperator="array-like"/>
</container>
<container id="stdQueue" startPattern="std :: queue|priority_queue &lt;" inherits="stdContainer">
<container id="stdQueue" startPattern="std :: queue &lt;" inherits="stdContainer">
<access>
<function name="emplace" action="push" yields="item"/>
<function name="push" action="push"/>
Expand All @@ -8684,7 +8695,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
<function name="back" yields="item"/>
</access>
</container>
<container id="stdStack" startPattern="std :: stack &lt;" inherits="stdContainer">
<container id="stdStack" startPattern="std :: stack|priority_queue &lt;" inherits="stdContainer">
<access>
<function name="emplace" action="push" yields="item"/>
<function name="push" action="push"/>
Expand Down
2 changes: 2 additions & 0 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a

// Special Cppcheck Premium options
else if (std::strncmp(argv[i], "--premium=", 10) == 0 && isCppcheckPremium()) {
if (std::strcmp(argv[i], "--premium=safety") == 0)
mSettings.safety = true;
if (!mSettings.premiumArgs.empty())
mSettings.premiumArgs += " ";
const std::string p(argv[i] + 10);
Expand Down
57 changes: 40 additions & 17 deletions lib/checkclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2633,6 +2633,7 @@ namespace { // avoid one-definition-rule violation

const Variable *var;
const Token *tok;
std::vector<const Variable*> initArgs;
};
}

Expand Down Expand Up @@ -2663,25 +2664,44 @@ void CheckClass::initializerListOrder()
tok = tok->next();

// find all variable initializations in list
while (tok && tok != func->functionScope->bodyStart) {
for (; tok && tok != func->functionScope->bodyStart; tok = tok->next()) {
if (Token::Match(tok, "%name% (|{")) {
const Token* const end = tok->linkAt(1);
const Variable *var = scope->getVariable(tok->str());
if (var)
vars.emplace_back(var, tok);

if (Token::Match(tok->tokAt(2), "%name% =")) {
var = scope->getVariable(tok->strAt(2));

if (var)
vars.emplace_back(var, tok->tokAt(2));
else
tok = end;

for (; tok != end; tok = tok->next()) {
if (const Variable* argVar = scope->getVariable(tok->str())) {
if (scope != argVar->scope())
continue;
if (argVar->isStatic())
continue;
if (tok->variable() && tok->variable()->isArgument())
continue;
if (var->isPointer() && (argVar->isArray() || Token::simpleMatch(tok->astParent(), "&")))
continue;
if (var->isReference())
continue;
if (Token::simpleMatch(tok->astParent(), "="))
continue;
vars.back().initArgs.emplace_back(argVar);
}
}
tok = tok->next()->link()->next();
} else
tok = tok->next();
}
}

// need at least 2 members to have out of order initialization
for (int j = 1; j < vars.size(); j++) {
for (int j = 0; j < vars.size(); j++) {
// check for use of uninitialized arguments
for (const auto& arg : vars[j].initArgs)
if (vars[j].var->index() < arg->index())
initializerListError(vars[j].tok, vars[j].var->nameToken(), scope->className, vars[j].var->name(), arg->name());

// need at least 2 members to have out of order initialization
if (j == 0)
continue;
// check for out of order initialization
if (vars[j].var->index() < vars[j - 1].var->index())
initializerListError(vars[j].tok,vars[j].var->nameToken(), scope->className, vars[j].var->name());
Expand All @@ -2692,15 +2712,18 @@ void CheckClass::initializerListOrder()
}
}

void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname)
void CheckClass::initializerListError(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &varname, const std::string& argname)
{
std::list<const Token *> toks = { tok1, tok2 };
const std::string msg = argname.empty() ?
"Member variable '$symbol' is in the wrong place in the initializer list." :
"Member variable '$symbol' uses an uninitialized argument '" + argname + "' due to the order of declarations.";
reportError(toks, Severity::style, "initializerList",
"$symbol:" + classname + "::" + varname +"\n"
"Member variable '$symbol' is in the wrong place in the initializer list.\n"
"Member variable '$symbol' is in the wrong place in the initializer list. "
"$symbol:" + classname + "::" + varname + '\n' +
msg + '\n' +
msg + ' ' +
"Members are initialized in the order they are declared, not in the "
"order they are in the initializer list. Keeping the initializer list "
"order they are in the initializer list. Keeping the initializer list "
"in the same order that the members were declared prevents order dependent "
"initialization errors.", CWE398, Certainty::inconclusive);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/checkclass.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class CPPCHECKLIB CheckClass : public Check {
void operatorEqToSelfError(const Token *tok);
void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic);
void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic);
void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname);
void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname, const std::string& argname = {});
void suggestInitializationList(const Token *tok, const std::string& varname);
void selfInitializationError(const Token* tok, const std::string& varname);
void pureVirtualFunctionCallInConstructorError(const Function * scopeFunction, const std::list<const Token *> & tokStack, const std::string &purefuncname);
Expand Down
Loading

0 comments on commit 54ae2bb

Please sign in to comment.