Skip to content

Commit f97b07a

Browse files
committed
checkimpl
1 parent e09e94d commit f97b07a

4 files changed

Lines changed: 126 additions & 124 deletions

File tree

lib/checkassert.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "checkassert.h"
2424

25+
#include "checkimpl.h"
2526
#include "errortypes.h"
2627
#include "settings.h"
2728
#include "symboldatabase.h"
@@ -39,7 +40,21 @@ namespace {
3940
CheckAssert instance;
4041
}
4142

42-
void CheckAssert::assertWithSideEffects()
43+
class CheckAssertImpl: public CheckImpl {
44+
public:
45+
CheckAssertImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
46+
: CheckImpl(tokenizer, settings, errorLogger) {}
47+
48+
void assertWithSideEffects();
49+
50+
void checkVariableAssignment(const Token* assignTok, const Scope *assertionScope);
51+
static bool inSameScope(const Token* returnTok, const Token* assignTok);
52+
53+
void sideEffectInAssertError(const Token *tok, const std::string& functionName);
54+
void assignmentInAssertError(const Token *tok, const std::string &varname);
55+
};
56+
57+
void CheckAssertImpl::assertWithSideEffects()
4358
{
4459
if (!mSettings->severity.isEnabled(Severity::warning))
4560
return;
@@ -97,7 +112,7 @@ void CheckAssert::assertWithSideEffects()
97112
//---------------------------------------------------------------------------
98113

99114

100-
void CheckAssert::sideEffectInAssertError(const Token *tok, const std::string& functionName)
115+
void CheckAssertImpl::sideEffectInAssertError(const Token *tok, const std::string& functionName)
101116
{
102117
reportError(tok, Severity::warning,
103118
"assertWithSideEffect",
@@ -109,7 +124,7 @@ void CheckAssert::sideEffectInAssertError(const Token *tok, const std::string& f
109124
"builds, this is a bug.", CWE398, Certainty::normal);
110125
}
111126

112-
void CheckAssert::assignmentInAssertError(const Token *tok, const std::string& varname)
127+
void CheckAssertImpl::assignmentInAssertError(const Token *tok, const std::string& varname)
113128
{
114129
reportError(tok, Severity::warning,
115130
"assignmentInAssert",
@@ -122,7 +137,7 @@ void CheckAssert::assignmentInAssertError(const Token *tok, const std::string& v
122137
}
123138

124139
// checks if side effects happen on the variable prior to tmp
125-
void CheckAssert::checkVariableAssignment(const Token* assignTok, const Scope *assertionScope)
140+
void CheckAssertImpl::checkVariableAssignment(const Token* assignTok, const Scope *assertionScope)
126141
{
127142
if (!assignTok->isAssignmentOp() && assignTok->tokType() != Token::eIncDecOp)
128143
return;
@@ -150,8 +165,21 @@ void CheckAssert::checkVariableAssignment(const Token* assignTok, const Scope *a
150165
// TODO: function calls on var
151166
}
152167

153-
bool CheckAssert::inSameScope(const Token* returnTok, const Token* assignTok)
168+
bool CheckAssertImpl::inSameScope(const Token* returnTok, const Token* assignTok)
154169
{
155170
// TODO: even if a return is in the same scope, the assignment might not affect it.
156171
return returnTok->scope() == assignTok->scope();
157172
}
173+
174+
void CheckAssert::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger)
175+
{
176+
CheckAssertImpl checkAssert(&tokenizer, tokenizer.getSettings(), errorLogger);
177+
checkAssert.assertWithSideEffects();
178+
}
179+
180+
void CheckAssert::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const
181+
{
182+
CheckAssertImpl c(nullptr, settings, errorLogger);
183+
c.sideEffectInAssertError(nullptr, "function");
184+
c.assignmentInAssertError(nullptr, "var");
185+
}

lib/checkassert.h

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,12 @@
2424

2525
#include "check.h"
2626
#include "config.h"
27-
#include "tokenize.h"
2827

2928
#include <string>
3029

3130
class ErrorLogger;
32-
class Scope;
3331
class Settings;
34-
class Token;
32+
class Tokenizer;
3533

3634
/// @addtogroup Checks
3735
/// @{
@@ -42,36 +40,13 @@ class Token;
4240

4341
class CPPCHECKLIB CheckAssert : public Check {
4442
public:
45-
CheckAssert() : Check(myName()) {}
46-
47-
CheckAssert(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
48-
: Check(myName(), tokenizer, settings, errorLogger) {}
43+
CheckAssert() : Check("Assert") {}
4944

5045
/** run checks, the token list is not simplified */
51-
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override {
52-
CheckAssert checkAssert(&tokenizer, tokenizer.getSettings(), errorLogger);
53-
checkAssert.assertWithSideEffects();
54-
}
55-
56-
void assertWithSideEffects();
57-
58-
protected:
59-
void checkVariableAssignment(const Token* assignTok, const Scope *assertionScope);
60-
static bool inSameScope(const Token* returnTok, const Token* assignTok);
46+
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override;
6147

6248
private:
63-
void sideEffectInAssertError(const Token *tok, const std::string& functionName);
64-
void assignmentInAssertError(const Token *tok, const std::string &varname);
65-
66-
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
67-
CheckAssert c(nullptr, settings, errorLogger);
68-
c.sideEffectInAssertError(nullptr, "function");
69-
c.assignmentInAssertError(nullptr, "var");
70-
}
71-
72-
static std::string myName() {
73-
return "Assert";
74-
}
49+
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override;
7550

7651
std::string classInfo() const override {
7752
return "Warn if there are side effects in assert statements (since this cause different behaviour in debug/release builds).\n";

lib/checkautovariables.cpp

Lines changed: 86 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "checkautovariables.h"
2424

2525
#include "astutils.h"
26+
#include "checkimpl.h"
2627
#include "library.h"
2728
#include "settings.h"
2829
#include "symboldatabase.h"
@@ -49,6 +50,47 @@ static const CWE CWE398(398U); // Indicator of Poor Code Quality
4950
static const CWE CWE562(562U); // Return of Stack Variable Address
5051
static const CWE CWE590(590U); // Free of Memory not on the Heap
5152

53+
class CheckAutoVariablesImpl : public CheckImpl
54+
{
55+
public:
56+
/** This constructor is used when running checks. */
57+
CheckAutoVariablesImpl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
58+
: CheckImpl(tokenizer, settings, errorLogger) {}
59+
60+
/** assign function argument */
61+
void assignFunctionArg();
62+
63+
/** Check auto variables */
64+
void autoVariables();
65+
66+
/**
67+
* Check variable assignment.. value must be changed later or there will be a error reported
68+
* @return true if error is reported */
69+
bool checkAutoVariableAssignment(const Token *expr, bool inconclusive, const Token *startToken = nullptr);
70+
71+
void checkVarLifetime();
72+
void checkVarLifetimeScope(const Token * start, const Token * end);
73+
74+
void errorAutoVariableAssignment(const Token *tok, bool inconclusive);
75+
void errorReturnDanglingLifetime(const Token *tok, const ValueFlow::Value* val);
76+
void errorInvalidLifetime(const Token *tok, const ValueFlow::Value* val);
77+
void errorDanglngLifetime(const Token *tok, const ValueFlow::Value *val);
78+
void errorDanglingTemporaryLifetime(const Token* tok, const ValueFlow::Value* val, const Token* tempTok);
79+
void errorReturnReference(const Token* tok, ErrorPath errorPath, bool inconclusive);
80+
void errorDanglingReference(const Token *tok, const Variable *var, ErrorPath errorPath);
81+
void errorDanglingTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive);
82+
void errorReturnTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive);
83+
void errorInvalidDeallocation(const Token *tok, const ValueFlow::Value *val);
84+
void errorUselessAssignmentArg(const Token *tok);
85+
void errorUselessAssignmentPtrArg(const Token *tok);
86+
87+
private:
88+
/** returns true if tokvalue has already been diagnosed */
89+
bool diag(const Token* tokvalue);
90+
91+
std::set<const Token*> mDiagDanglingTemp;
92+
};
93+
5294
static bool isPtrArg(const Token *tok)
5395
{
5496
const Variable *var = tok->variable();
@@ -206,7 +248,7 @@ static bool variableIsUsedInScope(const Token* start, nonneg int varId, const Sc
206248
return false;
207249
}
208250

209-
void CheckAutoVariables::assignFunctionArg()
251+
void CheckAutoVariablesImpl::assignFunctionArg()
210252
{
211253
const bool printStyle = mSettings->severity.isEnabled(Severity::style);
212254
const bool printWarning = mSettings->severity.isEnabled(Severity::warning);
@@ -259,7 +301,7 @@ static bool hasOverloadedAssignment(const Token* tok, bool c, bool& inconclusive
259301
return true;
260302
}
261303

262-
void CheckAutoVariables::autoVariables()
304+
void CheckAutoVariablesImpl::autoVariables()
263305
{
264306
const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive);
265307
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
@@ -319,7 +361,7 @@ void CheckAutoVariables::autoVariables()
319361
}
320362
}
321363

322-
bool CheckAutoVariables::checkAutoVariableAssignment(const Token *expr, bool inconclusive, const Token *startToken)
364+
bool CheckAutoVariablesImpl::checkAutoVariableAssignment(const Token *expr, bool inconclusive, const Token *startToken)
323365
{
324366
if (!startToken)
325367
startToken = Token::findsimplematch(expr, "=")->next();
@@ -360,7 +402,7 @@ bool CheckAutoVariables::checkAutoVariableAssignment(const Token *expr, bool inc
360402

361403
//---------------------------------------------------------------------------
362404

363-
void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inconclusive)
405+
void CheckAutoVariablesImpl::errorAutoVariableAssignment(const Token *tok, bool inconclusive)
364406
{
365407
if (!inconclusive) {
366408
reportError(tok, Severity::error, "autoVariables",
@@ -381,23 +423,23 @@ void CheckAutoVariables::errorAutoVariableAssignment(const Token *tok, bool inco
381423
}
382424
}
383425

384-
void CheckAutoVariables::errorUselessAssignmentArg(const Token *tok)
426+
void CheckAutoVariablesImpl::errorUselessAssignmentArg(const Token *tok)
385427
{
386428
reportError(tok,
387429
Severity::style,
388430
"uselessAssignmentArg",
389431
"Assignment of function parameter has no effect outside the function.", CWE398, Certainty::normal);
390432
}
391433

392-
void CheckAutoVariables::errorUselessAssignmentPtrArg(const Token *tok)
434+
void CheckAutoVariablesImpl::errorUselessAssignmentPtrArg(const Token *tok)
393435
{
394436
reportError(tok,
395437
Severity::warning,
396438
"uselessAssignmentPtrArg",
397439
"Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?", CWE398, Certainty::normal);
398440
}
399441

400-
bool CheckAutoVariables::diag(const Token* tokvalue)
442+
bool CheckAutoVariablesImpl::diag(const Token* tokvalue)
401443
{
402444
if (!tokvalue)
403445
return true;
@@ -532,7 +574,7 @@ static bool isAssignedToNonLocal(const Token* tok)
532574
return !var->isLocal() || var->isStatic();
533575
}
534576

535-
void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token * end)
577+
void CheckAutoVariablesImpl::checkVarLifetimeScope(const Token * start, const Token * end)
536578
{
537579
const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive);
538580
if (!start)
@@ -672,7 +714,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
672714
}
673715
}
674716

675-
void CheckAutoVariables::checkVarLifetime()
717+
void CheckAutoVariablesImpl::checkVarLifetime()
676718
{
677719
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
678720
for (const Scope * scope : symbolDatabase->functionScopes) {
@@ -682,7 +724,7 @@ void CheckAutoVariables::checkVarLifetime()
682724
}
683725
}
684726

685-
void CheckAutoVariables::errorReturnDanglingLifetime(const Token *tok, const ValueFlow::Value *val)
727+
void CheckAutoVariablesImpl::errorReturnDanglingLifetime(const Token *tok, const ValueFlow::Value *val)
686728
{
687729
const bool inconclusive = val ? val->isInconclusive() : false;
688730
ErrorPath errorPath = val ? val->errorPath : ErrorPath();
@@ -691,7 +733,7 @@ void CheckAutoVariables::errorReturnDanglingLifetime(const Token *tok, const Val
691733
reportError(errorPath, Severity::error, "returnDanglingLifetime", msg + " that will be invalid when returning.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal);
692734
}
693735

694-
void CheckAutoVariables::errorInvalidLifetime(const Token *tok, const ValueFlow::Value* val)
736+
void CheckAutoVariablesImpl::errorInvalidLifetime(const Token *tok, const ValueFlow::Value* val)
695737
{
696738
const bool inconclusive = val ? val->isInconclusive() : false;
697739
ErrorPath errorPath = val ? val->errorPath : ErrorPath();
@@ -700,7 +742,7 @@ void CheckAutoVariables::errorInvalidLifetime(const Token *tok, const ValueFlow:
700742
reportError(errorPath, Severity::error, "invalidLifetime", msg + " that is out of scope.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal);
701743
}
702744

703-
void CheckAutoVariables::errorDanglingTemporaryLifetime(const Token* tok, const ValueFlow::Value* val, const Token* tempTok)
745+
void CheckAutoVariablesImpl::errorDanglingTemporaryLifetime(const Token* tok, const ValueFlow::Value* val, const Token* tempTok)
704746
{
705747
const bool inconclusive = val ? val->isInconclusive() : false;
706748
ErrorPath errorPath = val ? val->errorPath : ErrorPath();
@@ -715,7 +757,7 @@ void CheckAutoVariables::errorDanglingTemporaryLifetime(const Token* tok, const
715757
inconclusive ? Certainty::inconclusive : Certainty::normal);
716758
}
717759

718-
void CheckAutoVariables::errorDanglngLifetime(const Token *tok, const ValueFlow::Value *val)
760+
void CheckAutoVariablesImpl::errorDanglngLifetime(const Token *tok, const ValueFlow::Value *val)
719761
{
720762
const bool inconclusive = val ? val->isInconclusive() : false;
721763
ErrorPath errorPath = val ? val->errorPath : ErrorPath();
@@ -725,21 +767,21 @@ void CheckAutoVariables::errorDanglngLifetime(const Token *tok, const ValueFlow:
725767
reportError(errorPath, Severity::error, "danglingLifetime", msg + ".", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal);
726768
}
727769

728-
void CheckAutoVariables::errorDanglingTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive)
770+
void CheckAutoVariablesImpl::errorDanglingTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive)
729771
{
730772
errorPath.emplace_back(tok, "");
731773
reportError(
732774
errorPath, Severity::error, "danglingTempReference", "Using reference to dangling temporary.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal);
733775
}
734776

735-
void CheckAutoVariables::errorReturnReference(const Token* tok, ErrorPath errorPath, bool inconclusive)
777+
void CheckAutoVariablesImpl::errorReturnReference(const Token* tok, ErrorPath errorPath, bool inconclusive)
736778
{
737779
errorPath.emplace_back(tok, "");
738780
reportError(
739781
errorPath, Severity::error, "returnReference", "Reference to local variable returned.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal);
740782
}
741783

742-
void CheckAutoVariables::errorDanglingReference(const Token *tok, const Variable *var, ErrorPath errorPath)
784+
void CheckAutoVariablesImpl::errorDanglingReference(const Token *tok, const Variable *var, ErrorPath errorPath)
743785
{
744786
std::string tokName = tok ? tok->str() : "x";
745787
std::string varName = var ? var->name() : "y";
@@ -748,14 +790,14 @@ void CheckAutoVariables::errorDanglingReference(const Token *tok, const Variable
748790
reportError(errorPath, Severity::error, "danglingReference", msg, CWE562, Certainty::normal);
749791
}
750792

751-
void CheckAutoVariables::errorReturnTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive)
793+
void CheckAutoVariablesImpl::errorReturnTempReference(const Token* tok, ErrorPath errorPath, bool inconclusive)
752794
{
753795
errorPath.emplace_back(tok, "");
754796
reportError(
755797
errorPath, Severity::error, "returnTempReference", "Reference to temporary returned.", CWE562, inconclusive ? Certainty::inconclusive : Certainty::normal);
756798
}
757799

758-
void CheckAutoVariables::errorInvalidDeallocation(const Token *tok, const ValueFlow::Value *val)
800+
void CheckAutoVariablesImpl::errorInvalidDeallocation(const Token *tok, const ValueFlow::Value *val)
759801
{
760802
const Variable *var = val ? val->tokvalue->variable() : (tok ? tok->variable() : nullptr);
761803

@@ -781,3 +823,29 @@ void CheckAutoVariables::errorInvalidDeallocation(const Token *tok, const ValueF
781823
"The deallocation of " + type + " results in undefined behaviour. You should only free memory "
782824
"that has been allocated dynamically.", CWE590, Certainty::normal);
783825
}
826+
827+
void CheckAutoVariables::runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger)
828+
{
829+
CheckAutoVariablesImpl checkAutoVariables(&tokenizer, tokenizer.getSettings(), errorLogger);
830+
checkAutoVariables.assignFunctionArg();
831+
checkAutoVariables.checkVarLifetime();
832+
checkAutoVariables.autoVariables();
833+
}
834+
835+
void CheckAutoVariables::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const
836+
{
837+
ErrorPath errorPath;
838+
CheckAutoVariablesImpl c(nullptr,settings,errorLogger);
839+
c.errorAutoVariableAssignment(nullptr, false);
840+
c.errorReturnReference(nullptr, errorPath, false);
841+
c.errorDanglingReference(nullptr, nullptr, errorPath);
842+
c.errorReturnTempReference(nullptr, errorPath, false);
843+
c.errorDanglingTempReference(nullptr, errorPath, false);
844+
c.errorInvalidDeallocation(nullptr, nullptr);
845+
c.errorUselessAssignmentArg(nullptr);
846+
c.errorUselessAssignmentPtrArg(nullptr);
847+
c.errorReturnDanglingLifetime(nullptr, nullptr);
848+
c.errorInvalidLifetime(nullptr, nullptr);
849+
c.errorDanglngLifetime(nullptr, nullptr);
850+
c.errorDanglingTemporaryLifetime(nullptr, nullptr, nullptr);
851+
}

0 commit comments

Comments
 (0)