Fix #11681 FN constParameterPointer with std::vector (#5000)

This commit is contained in:
chrchr-github 2023-05-04 11:10:58 +02:00 committed by GitHub
parent e6ae312a0b
commit 100d17df4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 119 additions and 45 deletions

View File

@ -9385,7 +9385,7 @@
<!-- virtual void wxPGSpinCtrlEditor::OnFocus (wxPGProperty *property, wxWindow *wnd) const--> <!-- virtual void wxPGSpinCtrlEditor::OnFocus (wxPGProperty *property, wxWindow *wnd) const-->
<!-- virtual void wxPGTextCtrlEditor::OnFocus (wxPGProperty *property, wxWindow *wnd) const--> <!-- virtual void wxPGTextCtrlEditor::OnFocus (wxPGProperty *property, wxWindow *wnd) const-->
<!-- virtual void wxPGTextCtrlAndButtonEditor::OnFocus (wxPGProperty *property, wxWindow *wnd) const--> <!-- virtual void wxPGTextCtrlAndButtonEditor::OnFocus (wxPGProperty *property, wxWindow *wnd) const-->
<function name="wxPGSpinCtrlEditor::OnFocus,wxPGProperty::Hide,wxPGTextCtrlAndButtonEditor::OnFocus"> <function name="wxPGSpinCtrlEditor::OnFocus,wxPGTextCtrlAndButtonEditor::OnFocus">
<noreturn>false</noreturn> <noreturn>false</noreturn>
<leak-ignore/> <leak-ignore/>
<const/> <const/>

View File

@ -1565,17 +1565,29 @@ void CheckOther::checkConstPointer()
continue; continue;
pointers.emplace_back(var); pointers.emplace_back(var);
const Token* const parent = tok->astParent(); const Token* const parent = tok->astParent();
bool deref = false; enum Deref { NONE, DEREF, MEMBER } deref = NONE;
if (parent && parent->isUnaryOp("*")) if (parent && parent->isUnaryOp("*"))
deref = true; deref = DEREF;
else if (Token::simpleMatch(parent, "[") && parent->astOperand1() == tok && tok != nameTok) else if (Token::simpleMatch(parent, "[") && parent->astOperand1() == tok && tok != nameTok)
deref = true; deref = DEREF;
else if (Token::Match(parent, "%op%") && Token::simpleMatch(parent->astParent(), ".")) else if (Token::Match(parent, "%op%") && Token::simpleMatch(parent->astParent(), "."))
deref = true; deref = DEREF;
else if (Token::simpleMatch(parent, "."))
deref = MEMBER;
else if (astIsRangeBasedForDecl(tok)) else if (astIsRangeBasedForDecl(tok))
continue; continue;
if (deref) { if (deref != NONE) {
const Token* const gparent = parent->astParent(); const Token* const gparent = parent->astParent();
if (deref == MEMBER) {
if (!gparent)
continue;
if (parent->astOperand2()) {
if (parent->astOperand2()->function() && parent->astOperand2()->function()->isConst())
continue;
if (mSettings->library.isFunctionConst(parent->astOperand2()))
continue;
}
}
if (Token::Match(gparent, "%cop%") && !gparent->isUnaryOp("&") && !gparent->isUnaryOp("*")) if (Token::Match(gparent, "%cop%") && !gparent->isUnaryOp("&") && !gparent->isUnaryOp("*"))
continue; continue;
int argn = -1; int argn = -1;

View File

@ -1523,7 +1523,7 @@ static void setTypes(TokenList *tokenList)
} }
} }
static void setValues(Tokenizer *tokenizer, SymbolDatabase *symbolDatabase) static void setValues(const Tokenizer *tokenizer, const SymbolDatabase *symbolDatabase)
{ {
const Settings * const settings = tokenizer->getSettings(); const Settings * const settings = tokenizer->getSettings();

View File

@ -1805,7 +1805,7 @@ void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map<s
ctuFileInfo.loadFromXml(e); ctuFileInfo.loadFromXml(e);
continue; continue;
} }
for (Check *check : Check::instances()) { for (const Check *check : Check::instances()) {
if (checkClassAttr == check->name()) if (checkClassAttr == check->name())
fileInfoList.push_back(check->loadFileInfoFromXml(e)); fileInfoList.push_back(check->loadFileInfoFromXml(e));
} }

View File

@ -1390,7 +1390,7 @@ static void createAstAtTokenInner(Token * const tok1, const Token *endToken, boo
} }
} }
static Token * findAstTop(Token *tok1, Token *tok2) static Token * findAstTop(Token *tok1, const Token *tok2)
{ {
for (Token *tok = tok1; tok && (tok != tok2); tok = tok->next()) { for (Token *tok = tok1; tok && (tok != tok2); tok = tok->next()) {
if (tok->astParent() || tok->astOperand1() || tok->astOperand2()) { if (tok->astParent() || tok->astOperand1() || tok->astOperand2()) {

View File

@ -3966,7 +3966,7 @@ struct LifetimeStore {
} }
} }
static LifetimeStore fromFunctionArg(const Function * f, Token *tok, const Variable *var, TokenList *tokenlist, const Settings* settings, ErrorLogger *errorLogger) { static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, TokenList *tokenlist, const Settings* settings, ErrorLogger *errorLogger) {
if (!var) if (!var)
return LifetimeStore{}; return LifetimeStore{};
if (!var->isArgument()) if (!var->isArgument())
@ -5039,7 +5039,7 @@ static const Token * findEndOfFunctionCallForParameter(const Token * parameterTo
return nextAfterAstRightmostLeaf(parent); return nextAfterAstRightmostLeaf(parent);
} }
static void valueFlowAfterMove(TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings) static void valueFlowAfterMove(TokenList* tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings)
{ {
if (!tokenlist->isCPP() || settings->standards.cpp < Standards::CPP11) if (!tokenlist->isCPP() || settings->standards.cpp < Standards::CPP11)
return; return;
@ -5178,7 +5178,7 @@ static const Scope* getLoopScope(const Token* tok)
} }
// //
static void valueFlowConditionExpressions(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings &settings) static void valueFlowConditionExpressions(TokenList *tokenlist, const SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings &settings)
{ {
for (const Scope * scope : symboldatabase->functionScopes) { for (const Scope * scope : symboldatabase->functionScopes) {
if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) { if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) {
@ -5308,7 +5308,7 @@ static std::set<nonneg int> getVarIds(const Token* tok)
return result; return result;
} }
static void valueFlowSymbolic(TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings) static void valueFlowSymbolic(const TokenList* tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings)
{ {
for (const Scope* scope : symboldatabase->functionScopes) { for (const Scope* scope : symboldatabase->functionScopes) {
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
@ -5401,7 +5401,7 @@ static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth =
static ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val); static ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val);
static void valueFlowSymbolicOperators(SymbolDatabase* symboldatabase, const Settings* settings) static void valueFlowSymbolicOperators(const SymbolDatabase* symboldatabase, const Settings* settings)
{ {
for (const Scope* scope : symboldatabase->functionScopes) { for (const Scope* scope : symboldatabase->functionScopes) {
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
@ -5512,7 +5512,7 @@ struct SymbolicInferModel : InferModel {
} }
}; };
static void valueFlowSymbolicInfer(SymbolDatabase* symboldatabase, const Settings* settings) static void valueFlowSymbolicInfer(const SymbolDatabase* symboldatabase, const Settings* settings)
{ {
for (const Scope* scope : symboldatabase->functionScopes) { for (const Scope* scope : symboldatabase->functionScopes) {
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
@ -5792,7 +5792,7 @@ static bool intersects(const C1& c1, const C2& c2)
} }
static void valueFlowAfterAssign(TokenList *tokenlist, static void valueFlowAfterAssign(TokenList *tokenlist,
SymbolDatabase* symboldatabase, const SymbolDatabase* symboldatabase,
ErrorLogger *errorLogger, ErrorLogger *errorLogger,
const Settings *settings, const Settings *settings,
const std::set<const Scope*>& skippedFunctions) const std::set<const Scope*>& skippedFunctions)
@ -5925,7 +5925,7 @@ static std::vector<const Variable*> getVariables(const Token* tok)
} }
static void valueFlowAfterSwap(TokenList* tokenlist, static void valueFlowAfterSwap(TokenList* tokenlist,
SymbolDatabase* symboldatabase, const SymbolDatabase* symboldatabase,
ErrorLogger* errorLogger, ErrorLogger* errorLogger,
const Settings* settings) const Settings* settings)
{ {
@ -6098,8 +6098,8 @@ struct ConditionHandler {
return valueFlowReverse(start, endToken, exprTok, values, tokenlist, settings, loc); return valueFlowReverse(start, endToken, exprTok, values, tokenlist, settings, loc);
} }
void traverseCondition(TokenList* tokenlist, void traverseCondition(const TokenList* tokenlist,
SymbolDatabase* symboldatabase, const SymbolDatabase* symboldatabase,
const Settings* settings, const Settings* settings,
const std::set<const Scope*>& skippedFunctions, const std::set<const Scope*>& skippedFunctions,
const std::function<void(const Condition& cond, Token* tok, const Scope* scope)>& f) const const std::function<void(const Condition& cond, Token* tok, const Scope* scope)>& f) const
@ -6137,7 +6137,7 @@ struct ConditionHandler {
} }
void beforeCondition(TokenList* tokenlist, void beforeCondition(TokenList* tokenlist,
SymbolDatabase* symboldatabase, const SymbolDatabase* symboldatabase,
ErrorLogger* errorLogger, ErrorLogger* errorLogger,
const Settings* settings, const Settings* settings,
const std::set<const Scope*>& skippedFunctions) const { const std::set<const Scope*>& skippedFunctions) const {
@ -6285,7 +6285,7 @@ struct ConditionHandler {
} }
void afterCondition(TokenList* tokenlist, void afterCondition(TokenList* tokenlist,
SymbolDatabase* symboldatabase, const SymbolDatabase* symboldatabase,
ErrorLogger* errorLogger, ErrorLogger* errorLogger,
const Settings* settings, const Settings* settings,
const std::set<const Scope*>& skippedFunctions) const { const std::set<const Scope*>& skippedFunctions) const {
@ -7040,7 +7040,7 @@ static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const
} }
} }
static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings) static void valueFlowForLoop(TokenList *tokenlist, const SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
{ {
for (const Scope &scope : symboldatabase->scopeList) { for (const Scope &scope : symboldatabase->scopeList) {
if (scope.type != Scope::eFor) if (scope.type != Scope::eFor)
@ -7363,7 +7363,7 @@ static void valueFlowInjectParameter(const TokenList* tokenlist,
settings); settings);
} }
static void valueFlowSwitchVariable(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings) static void valueFlowSwitchVariable(TokenList *tokenlist, const SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
{ {
for (const Scope &scope : symboldatabase->scopeList) { for (const Scope &scope : symboldatabase->scopeList) {
if (scope.type != Scope::ScopeType::eSwitch) if (scope.type != Scope::ScopeType::eSwitch)
@ -7581,7 +7581,7 @@ static void valueFlowSubFunction(TokenList* tokenlist, SymbolDatabase* symboldat
} }
} }
static void valueFlowFunctionDefaultParameter(TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings) static void valueFlowFunctionDefaultParameter(const TokenList* tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings)
{ {
if (!tokenlist->isCPP()) if (!tokenlist->isCPP())
return; return;
@ -8624,7 +8624,7 @@ static const Scope* getFunctionScope(const Scope* scope) {
} }
static void valueFlowContainerSize(TokenList* tokenlist, static void valueFlowContainerSize(TokenList* tokenlist,
SymbolDatabase* symboldatabase, const SymbolDatabase* symboldatabase,
ErrorLogger* /*errorLogger*/, ErrorLogger* /*errorLogger*/,
const Settings* settings, const Settings* settings,
const std::set<const Scope*>& skippedFunctions) const std::set<const Scope*>& skippedFunctions)
@ -8838,7 +8838,7 @@ struct ContainerConditionHandler : ConditionHandler {
} }
}; };
static void valueFlowDynamicBufferSize(const TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings) static void valueFlowDynamicBufferSize(const TokenList* tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings)
{ {
auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint { auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint {
MathLib::bigint sizeValue = -1; MathLib::bigint sizeValue = -1;
@ -9010,7 +9010,7 @@ static bool getMinMaxValues(const std::string &typestr, const Settings *settings
return getMinMaxValues(&vt, settings->platform, minvalue, maxvalue); return getMinMaxValues(&vt, settings->platform, minvalue, maxvalue);
} }
static void valueFlowSafeFunctions(TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings) static void valueFlowSafeFunctions(TokenList* tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings)
{ {
for (const Scope *functionScope : symboldatabase->functionScopes) { for (const Scope *functionScope : symboldatabase->functionScopes) {
if (!functionScope->bodyStart) if (!functionScope->bodyStart)

View File

@ -3585,6 +3585,38 @@ private:
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:2]: (style) Parameter 'p' can be declared as pointer to const. " ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:2]: (style) Parameter 'p' can be declared as pointer to const. "
"However it seems that 'cb' is a callback function, if 'p' is declared with const you might also need to cast function pointer(s).\n", "However it seems that 'cb' is a callback function, if 'p' is declared with const you might also need to cast function pointer(s).\n",
errout.str()); errout.str());
check("void f1(std::vector<int>* p) {\n" // #11681
" if (p->empty()) {}\n" // warn
"}\n"
"void f2(std::vector<int>* p) {\n"
" p->resize(0);\n"
"}\n"
"struct S {\n"
" void h1() const;\n"
" void h2();\n"
" int i;\n"
"};\n"
"void k(int&);\n"
"void g1(S* s) {\n"
" s->h1();\n" // warn
"}\n"
"void g1(S* s) {\n"
" s->h2();\n"
"}\n"
"void g1(S* s) {\n"
" if (s->i) {}\n" // warn
"}\n"
"void g2(S* s) {\n"
" s->i = 0;\n"
"}\n"
"void g3(S* s) {\n"
" k(s->i);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n"
"[test.cpp:13]: (style) Parameter 's' can be declared as pointer to const\n"
"[test.cpp:19]: (style) Parameter 's' can be declared as pointer to const\n",
errout.str());
} }
void switchRedundantAssignmentTest() { void switchRedundantAssignmentTest() {
@ -7180,13 +7212,19 @@ private:
" int start = x->first;\n" " int start = x->first;\n"
" int end = x->first;\n" " int end = x->first;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'start' and 'end'.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'start' and 'end'.\n"
"[test.cpp:2]: (style) Parameter 'x' can be declared as pointer to const\n",
errout.str());
check("struct SW { int first; };\n" check("struct SW { int first; };\n"
"void foo(SW* x, int i, int j) {\n" "void foo(SW* x, int i, int j) {\n"
" int start = x->first;\n" " int start = x->first;\n"
" int end = x->first;\n" " int end = x->first;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'start' and 'end'.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (style, inconclusive) Same expression used in consecutive assignments of 'start' and 'end'.\n"
"[test.cpp:2]: (style) Parameter 'x' can be declared as pointer to const\n",
errout.str());
check("struct Foo { int f() const; };\n" check("struct Foo { int f() const; };\n"
"void test() {\n" "void test() {\n"
" Foo f = Foo{};\n" " Foo f = Foo{};\n"
@ -7738,7 +7776,9 @@ private:
"void foo(S* first) {\n" "void foo(S* first) {\n"
" if (first.ptr >= 0) {}\n" " if (first.ptr >= 0) {}\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n"
"[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7746,7 +7786,9 @@ private:
"void foo(S* first, S* second) {\n" "void foo(S* first, S* second) {\n"
" if((first.ptr - second.ptr) >= 0) {}\n" " if((first.ptr - second.ptr) >= 0) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
"[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7754,7 +7796,9 @@ private:
"void foo(S* first) {\n" "void foo(S* first) {\n"
" if((first.ptr) >= 0) {}\n" " if((first.ptr) >= 0) {}\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n"
"[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7762,7 +7806,9 @@ private:
"void foo(S* first, S* second) {\n" "void foo(S* first, S* second) {\n"
" if(0 <= first.ptr - second.ptr) {}\n" " if(0 <= first.ptr - second.ptr) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
"[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7770,7 +7816,9 @@ private:
"void foo(S* first, S* second) {\n" "void foo(S* first, S* second) {\n"
" if(0 <= (first.ptr - second.ptr)) {}\n" " if(0 <= (first.ptr - second.ptr)) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
"[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7778,7 +7826,9 @@ private:
"void foo(S* first, S* second) {\n" "void foo(S* first, S* second) {\n"
" if(first.ptr - second.ptr < 0) {}\n" " if(first.ptr - second.ptr < 0) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
"[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7786,7 +7836,9 @@ private:
"void foo(S* first, S* second) {\n" "void foo(S* first, S* second) {\n"
" if((first.ptr - second.ptr) < 0) {}\n" " if((first.ptr - second.ptr) < 0) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
"[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7794,7 +7846,9 @@ private:
"void foo(S* first, S* second) {\n" "void foo(S* first, S* second) {\n"
" if(0 > first.ptr - second.ptr) {}\n" " if(0 > first.ptr - second.ptr) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
"[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
errout.str());
check("struct S {\n" check("struct S {\n"
" int* ptr;\n" " int* ptr;\n"
@ -7802,7 +7856,9 @@ private:
"void foo(S* first, S* second) {\n" "void foo(S* first, S* second) {\n"
" if(0 > (first.ptr - second.ptr)) {}\n" " if(0 > (first.ptr - second.ptr)) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Parameter 'first' can be declared as pointer to const\n"
"[test.cpp:4]: (style) Parameter 'second' can be declared as pointer to const\n",
errout.str());
check("void foo(const int* x) {\n" check("void foo(const int* x) {\n"
" if (0 <= x[0]) {}\n" " if (0 <= x[0]) {}\n"
@ -7812,17 +7868,19 @@ private:
check("void foo(Bar* x) {\n" check("void foo(Bar* x) {\n"
" if (0 <= x.y) {}\n" " if (0 <= x.y) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout.str());
check("void foo(Bar* x) {\n" check("void foo(Bar* x) {\n"
" if (0 <= x->y) {}\n" " if (0 <= x->y) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout.str());
check("void foo(Bar* x, Bar* y) {\n" check("void foo(Bar* x, Bar* y) {\n"
" if (0 <= x->y - y->y ) {}\n" " if (0 <= x->y - y->y ) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n"
"[test.cpp:1]: (style) Parameter 'y' can be declared as pointer to const\n",
errout.str());
check("void foo(const Bar* x) {\n" check("void foo(const Bar* x) {\n"
" if (0 > x) {}\n" " if (0 > x) {}\n"
@ -7837,12 +7895,12 @@ private:
check("void foo(Bar* x) {\n" check("void foo(Bar* x) {\n"
" if (0 > x.y) {}\n" " if (0 > x.y) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout.str());
check("void foo(Bar* x) {\n" check("void foo(Bar* x) {\n"
" if (0 > x->y) {}\n" " if (0 > x->y) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'x' can be declared as pointer to const\n", errout.str());
check("void foo() {\n" check("void foo() {\n"
" int (*t)(void *a, void *b);\n" " int (*t)(void *a, void *b);\n"
@ -7860,13 +7918,17 @@ private:
"void packed_object_info(struct object_info *oi) {\n" "void packed_object_info(struct object_info *oi) {\n"
" if (oi->typep < 0);\n" " if (oi->typep < 0);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n"
"[test.cpp:2]: (style) Parameter 'oi' can be declared as pointer to const\n",
errout.str());
check("struct object_info { int typep[10]; };\n" check("struct object_info { int typep[10]; };\n"
"void packed_object_info(struct object_info *oi) {\n" "void packed_object_info(struct object_info *oi) {\n"
" if (oi->typep < 0);\n" " if (oi->typep < 0);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n"
"[test.cpp:2]: (style) Parameter 'oi' can be declared as pointer to const\n",
errout.str());
check("struct object_info { int *typep; };\n" check("struct object_info { int *typep; };\n"
"void packed_object_info(struct object_info *oi) {\n" "void packed_object_info(struct object_info *oi) {\n"