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
4950static const CWE CWE562 (562U ); // Return of Stack Variable Address
5051static 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+
5294static 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