diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 5f4c5b900..d9706da16 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -21,6 +21,7 @@ #include "astutils.h" #include "errorlogger.h" +#include "library.h" #include "mathlib.h" #include "platform.h" #include "settings.h" @@ -5968,7 +5969,8 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to valuetype.sign = ValueType::Sign::SIGNED; } setValueType(tok, valuetype); - } else if (tok->link() && tok->str() == "(") { + } else if (tok->link() && Token::Match(tok, "(|{")) { + const Token* start = tok->astOperand1() ? tok->astOperand1()->findExpressionStartEndTokens().first : nullptr; // cast if (tok->isCast() && !tok->astOperand2() && Token::Match(tok, "( %name%")) { ValueType valuetype; @@ -5983,6 +5985,16 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to setValueType(tok, valuetype); } + // Construct smart pointer + else if (mSettings->library.isSmartPointer(start)) { + ValueType valuetype; + if (parsedecl(start, &valuetype, mDefaultSignedness, mSettings)) { + setValueType(tok, valuetype); + setValueType(tok->astOperand1(), valuetype); + } + + } + // function else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) { ValueType valuetype; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index c91dc02ac..c0931b222 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5952,47 +5952,53 @@ static void valueFlowSmartPointer(TokenList *tokenlist, ErrorLogger * errorLogge continue; if (!tok->scope()->isExecutable()) continue; - if (!tok->variable()) - continue; - const Variable * var = tok->variable(); - if (!var->isSmartPointer()) - continue; - if (var->nameToken() == tok) { - if (Token::Match(tok, "%var% (|{") && tok->next()->astOperand2() && tok->next()->astOperand2()->str() != ",") { - Token * inTok = tok->next()->astOperand2(); - std::list values = inTok->values(); - const bool constValue = inTok->isNumber(); - valueFlowForwardAssign(inTok, var, values, constValue, true, tokenlist, errorLogger, settings); + if (tok->variable()) { + const Variable * var = tok->variable(); + if (!var->isSmartPointer()) + continue; + if (var->nameToken() == tok) { + if (Token::Match(tok, "%var% (|{") && tok->next()->astOperand2() && tok->next()->astOperand2()->str() != ",") { + Token * inTok = tok->next()->astOperand2(); + std::list values = inTok->values(); + const bool constValue = inTok->isNumber(); + valueFlowForwardAssign(inTok, var, values, constValue, true, tokenlist, errorLogger, settings); - } else if (Token::Match(tok, "%var% ;")) { - std::list values; - ValueFlow::Value v(0); - v.setKnown(); - values.push_back(v); - valueFlowForwardAssign(tok, var, values, false, true, tokenlist, errorLogger, settings); - } - } else if (Token::Match(tok, "%var% . reset (") && tok->next()->originalName() != "->") { - if (Token::simpleMatch(tok->tokAt(3), "( )")) { + } else if (Token::Match(tok, "%var% ;")) { + std::list values; + ValueFlow::Value v(0); + v.setKnown(); + values.push_back(v); + valueFlowForwardAssign(tok, var, values, false, true, tokenlist, errorLogger, settings); + } + } else if (Token::Match(tok, "%var% . reset (") && tok->next()->originalName() != "->") { + if (Token::simpleMatch(tok->tokAt(3), "( )")) { + std::list values; + ValueFlow::Value v(0); + v.setKnown(); + values.push_back(v); + valueFlowForwardAssign(tok->tokAt(4), var, values, false, false, tokenlist, errorLogger, settings); + } else { + tok->removeValues(std::mem_fn(&ValueFlow::Value::isIntValue)); + Token * inTok = tok->tokAt(3)->astOperand2(); + if (!inTok) + continue; + std::list values = inTok->values(); + const bool constValue = inTok->isNumber(); + valueFlowForwardAssign(inTok, var, values, constValue, false, tokenlist, errorLogger, settings); + } + } else if (Token::Match(tok, "%var% . release ( )") && tok->next()->originalName() != "->") { std::list values; ValueFlow::Value v(0); v.setKnown(); values.push_back(v); valueFlowForwardAssign(tok->tokAt(4), var, values, false, false, tokenlist, errorLogger, settings); - } else { - tok->removeValues(std::mem_fn(&ValueFlow::Value::isIntValue)); - Token * inTok = tok->tokAt(3)->astOperand2(); - if (!inTok) - continue; - std::list values = inTok->values(); - const bool constValue = inTok->isNumber(); - valueFlowForwardAssign(inTok, var, values, constValue, false, tokenlist, errorLogger, settings); } - } else if (Token::Match(tok, "%var% . release ( )") && tok->next()->originalName() != "->") { - std::list values; - ValueFlow::Value v(0); - v.setKnown(); - values.push_back(v); - valueFlowForwardAssign(tok->tokAt(4), var, values, false, false, tokenlist, errorLogger, settings); + } else if (Token::Match(tok->previous(), "%name%|> (|{") && astIsSmartPointer(tok) && astIsSmartPointer(tok->astOperand1())) { + std::vector args = getArguments(tok); + if (args.empty()) + continue; + for(const ValueFlow::Value& v:args.front()->values()) + setTokenValue(tok, v, settings); } } } @@ -6681,7 +6687,6 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, valueFlowGlobalStaticVar(tokenlist, settings); valueFlowPointerAlias(tokenlist); valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings); - valueFlowFunctionReturn(tokenlist, errorLogger); valueFlowBitAnd(tokenlist); valueFlowSameExpressions(tokenlist); valueFlowFwdAnalysis(tokenlist, settings); @@ -6703,6 +6708,7 @@ void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings); valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings); valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings); + valueFlowFunctionReturn(tokenlist, errorLogger); valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings); valueFlowUninit(tokenlist, symboldatabase, errorLogger, settings); if (tokenlist->isCPP()) { diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 9bca1691a..a8d14172d 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -1442,7 +1442,7 @@ private: check("auto& f() {\n" " return std::vector{1}.front();\n" "}\n"); - TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (error) Reference to temporary returned.\n", "", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (error) Reference to temporary returned.\n", errout.str()); check("struct A { int foo; };\n" "int& f(std::vector v) {\n" diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 3c7c1421e..b7414c57f 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -2859,6 +2859,15 @@ private: " return x.release();\n" "}\n", true); ASSERT_EQUALS("", errout.str()); + + // #9496 + check("std::shared_ptr f() {\n" + " return std::shared_ptr(nullptr);\n" + "}\n" + "void g() {\n" + " int a = *f();\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference: f()\n", errout.str()); } void functioncall() { // #3443 - function calls diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 2e4984f56..0b0478970 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -1152,6 +1152,7 @@ private: ASSERT_EQUALS(expected, tok(code, false)); ASSERT_EQUALS_WITHOUT_LINENUMBERS( + "[test.cpp:31]: (debug) valueflow.cpp:3109:valueFlowFunctionReturn bailout: function return; nontrivial function body\n" "[test.cpp:28]: (debug) valueflow.cpp:3109:valueFlowFunctionReturn bailout: function return; nontrivial function body\n" , errout.str()); }