parent
796ad6c008
commit
e54ad24d2c
2
Makefile
2
Makefile
|
@ -407,7 +407,7 @@ validateRules:
|
||||||
$(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/path.h lib/platform.h lib/suppressions.h lib/utils.h
|
$(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/path.h lib/platform.h lib/suppressions.h lib/utils.h
|
||||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/analyzerinfo.o $(libcppdir)/analyzerinfo.cpp
|
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/analyzerinfo.o $(libcppdir)/analyzerinfo.cpp
|
||||||
|
|
||||||
$(libcppdir)/astutils.o: lib/astutils.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h
|
$(libcppdir)/astutils.o: lib/astutils.cpp lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errortypes.h lib/importproject.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h
|
||||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/astutils.o $(libcppdir)/astutils.cpp
|
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/astutils.o $(libcppdir)/astutils.cpp
|
||||||
|
|
||||||
$(libcppdir)/bughuntingchecks.o: lib/bughuntingchecks.cpp lib/astutils.h lib/bughuntingchecks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h
|
$(libcppdir)/bughuntingchecks.o: lib/bughuntingchecks.cpp lib/astutils.h lib/bughuntingchecks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "valueflow.h"
|
#include "valueflow.h"
|
||||||
#include "valueptr.h"
|
#include "valueptr.h"
|
||||||
|
#include "checkclass.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -1747,7 +1748,7 @@ bool isConstExpression(const Token *tok, const Library& library, bool pure, bool
|
||||||
return isConstExpression(tok->astOperand1(), library, pure, cpp) && isConstExpression(tok->astOperand2(), library, pure, cpp);
|
return isConstExpression(tok->astOperand1(), library, pure, cpp) && isConstExpression(tok->astOperand2(), library, pure, cpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWithoutSideEffects(bool cpp, const Token* tok)
|
bool isWithoutSideEffects(bool cpp, const Token* tok, bool checkArrayAccess)
|
||||||
{
|
{
|
||||||
if (!cpp)
|
if (!cpp)
|
||||||
return true;
|
return true;
|
||||||
|
@ -1756,7 +1757,7 @@ bool isWithoutSideEffects(bool cpp, const Token* tok)
|
||||||
tok = tok->astOperand2();
|
tok = tok->astOperand2();
|
||||||
if (tok && tok->varId()) {
|
if (tok && tok->varId()) {
|
||||||
const Variable* var = tok->variable();
|
const Variable* var = tok->variable();
|
||||||
return var && (!var->isClass() || var->isPointer() || var->isStlType());
|
return var && (!var->isClass() || var->isPointer() || (checkArrayAccess ? var->isStlType() && !var->isStlType(CheckClass::stl_containers_not_const) : var->isStlType()));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ bool isConstFunctionCall(const Token* ftok, const Library& library);
|
||||||
|
|
||||||
bool isConstExpression(const Token *tok, const Library& library, bool pure, bool cpp);
|
bool isConstExpression(const Token *tok, const Library& library, bool pure, bool cpp);
|
||||||
|
|
||||||
bool isWithoutSideEffects(bool cpp, const Token* tok);
|
bool isWithoutSideEffects(bool cpp, const Token* tok, bool checkArrayAccess = false);
|
||||||
|
|
||||||
bool isUniqueExpression(const Token* tok);
|
bool isUniqueExpression(const Token* tok);
|
||||||
|
|
||||||
|
|
|
@ -1769,6 +1769,11 @@ static bool isConstStatement(const Token *tok, bool cpp)
|
||||||
return tok->astParent() ? isConstStatement(tok->astOperand1(), cpp) && isConstStatement(tok->astOperand2(), cpp) : isConstStatement(tok->astOperand2(), cpp);
|
return tok->astParent() ? isConstStatement(tok->astOperand1(), cpp) && isConstStatement(tok->astOperand2(), cpp) : isConstStatement(tok->astOperand2(), cpp);
|
||||||
if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) // ternary operator
|
if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) // ternary operator
|
||||||
return isConstStatement(tok->astOperand1(), cpp) && isConstStatement(tok->astOperand2()->astOperand1(), cpp) && isConstStatement(tok->astOperand2()->astOperand2(), cpp);
|
return isConstStatement(tok->astOperand1(), cpp) && isConstStatement(tok->astOperand2()->astOperand1(), cpp) && isConstStatement(tok->astOperand2()->astOperand2(), cpp);
|
||||||
|
if (Token::simpleMatch(tok, "[") && !Token::Match(tok->tokAt(-2), "%type% %name%") && isWithoutSideEffects(cpp, tok->astOperand1(), /*checkArrayAccess*/ true)) {
|
||||||
|
if (Token::simpleMatch(tok->astParent(), "["))
|
||||||
|
return isConstStatement(tok->astOperand2(), cpp) && isConstStatement(tok->astParent(), cpp);
|
||||||
|
return isConstStatement(tok->astOperand2(), cpp);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1801,6 +1806,13 @@ static bool isConstTop(const Token *tok)
|
||||||
else
|
else
|
||||||
return tok->astParent()->astOperand1() == tok;
|
return tok->astParent()->astOperand1() == tok;
|
||||||
}
|
}
|
||||||
|
if (Token::simpleMatch(tok, "[")) {
|
||||||
|
const Token* bracTok = tok;
|
||||||
|
while (Token::simpleMatch(bracTok->astParent(), "["))
|
||||||
|
bracTok = bracTok->astParent();
|
||||||
|
if (!bracTok->astParent())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1894,6 +1906,8 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type,
|
||||||
msg = "Redundant code: Found unused result of ternary operator.";
|
msg = "Redundant code: Found unused result of ternary operator.";
|
||||||
else if (tok->str() == "." && tok->tokType() == Token::Type::eOther)
|
else if (tok->str() == "." && tok->tokType() == Token::Type::eOther)
|
||||||
msg = "Redundant code: Found unused member access.";
|
msg = "Redundant code: Found unused member access.";
|
||||||
|
else if (tok->str() == "[" && tok->tokType() == Token::Type::eExtendedOp)
|
||||||
|
msg = "Redundant code: Found unused array access.";
|
||||||
else {
|
else {
|
||||||
reportError(tok, Severity::debug, "debug", "constStatementError not handled.");
|
reportError(tok, Severity::debug, "debug", "constStatementError not handled.");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -498,6 +498,42 @@ private:
|
||||||
"[test.cpp:15]: (warning) Redundant code: Found unused member access.\n",
|
"[test.cpp:15]: (warning) Redundant code: Found unused member access.\n",
|
||||||
errout.str());
|
errout.str());
|
||||||
|
|
||||||
|
check("struct S { int a[2]{}; };\n"
|
||||||
|
"struct T { S s; };\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" int i[2];\n"
|
||||||
|
" i[0] = 0;\n"
|
||||||
|
" i[0];\n" // <--
|
||||||
|
" S s[1];\n"
|
||||||
|
" s[0].a[1];\n" // <--
|
||||||
|
" T t;\n"
|
||||||
|
" t.s.a[1];\n" // <--
|
||||||
|
" int j[2][2][1] = {};\n"
|
||||||
|
" j[0][0][0];\n" // <--
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:6]: (warning) Redundant code: Found unused array access.\n"
|
||||||
|
"[test.cpp:8]: (warning) Redundant code: Found unused array access.\n"
|
||||||
|
"[test.cpp:10]: (warning) Redundant code: Found unused array access.\n"
|
||||||
|
"[test.cpp:12]: (warning) Redundant code: Found unused array access.\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("void g() {\n"
|
||||||
|
" int j[2]{};\n"
|
||||||
|
" int k[2] = {};\n"
|
||||||
|
" int l[]{ 1, 2 };\n"
|
||||||
|
" int m[] = { 1, 2 };\n"
|
||||||
|
" h(0, j[0], 1);\n"
|
||||||
|
" C c{ 0, j[0], 1 };\n"
|
||||||
|
" c[0];\n"
|
||||||
|
" int j[2][2][2] = {};\n"
|
||||||
|
" j[h()][0][0];\n"
|
||||||
|
" j[0][h()][0];\n"
|
||||||
|
" j[0][0][h()];\n"
|
||||||
|
" std::map<std::string, int> M;\n"
|
||||||
|
" M[\"abc\"];\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("struct S { void* p; };\n" // #10875
|
check("struct S { void* p; };\n" // #10875
|
||||||
"void f(S s) {\n"
|
"void f(S s) {\n"
|
||||||
" delete (int*)s.p;\n"
|
" delete (int*)s.p;\n"
|
||||||
|
|
Loading…
Reference in New Issue