Fix issue 9783: wrong lifetime analysis temporary assigned to object (#2711)

This commit is contained in:
Paul Fultz II 2020-09-02 00:13:15 -05:00 committed by GitHub
parent dea5a23c34
commit 32df807b22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 42 additions and 10 deletions

View File

@ -169,17 +169,15 @@ std::string astCanonicalType(const Token *expr)
{
if (!expr)
return "";
if (expr->variable()) {
const Variable *var = expr->variable();
std::pair<const Token*, const Token*> decl = Token::typeDecl(expr);
if (decl.first && decl.second) {
std::string ret;
for (const Token *type = var->typeStartToken(); Token::Match(type,"%name%|::") && type != var->nameToken(); type = type->next()) {
for (const Token *type = decl.first; Token::Match(type,"%name%|::") && type != decl.second; type = type->next()) {
if (!Token::Match(type, "const|static"))
ret += type->str();
}
return ret;
}
// TODO: handle expressions
return "";
}

View File

@ -682,6 +682,9 @@ std::string ErrorLogger::toxml(const std::string &str)
case '\"':
xml << "&quot;";
break;
case '\'':
xml << "&apos;";
break;
case '\0':
xml << "\\0";
break;

View File

@ -5707,7 +5707,7 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V
} else
valuetype->type = ValueType::Type::RECORD;
bool par = false;
while (Token::Match(type, "%name%|*|&|::|(") && !Token::Match(type, "typename|template") &&
while (Token::Match(type, "%name%|*|&|::|(") && !Token::Match(type, "typename|template") && type->varId() == 0 &&
!type->variable() && !type->function()) {
if (type->str() == "(") {
if (Token::Match(type->link(), ") const| {"))
@ -6058,7 +6058,11 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
const std::string& typestr(mSettings->library.returnValueType(tok->previous()));
if (!typestr.empty()) {
ValueType valuetype;
if (valuetype.fromLibraryType(typestr, mSettings)) {
TokenList tokenList(mSettings);
std::istringstream istr(typestr+";");
tokenList.createTokens(istr);
if (parsedecl(tokenList.front(), &valuetype, mDefaultSignedness, mSettings)) {
valuetype.originalTypeName = typestr;
setValueType(tok, valuetype);
}
}
@ -6091,6 +6095,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
tokenList.simplifyPlatformTypes();
tokenList.simplifyStdType();
if (parsedecl(tokenList.front(), &vt, mDefaultSignedness, mSettings)) {
vt.originalTypeName = typestr;
setValueType(tok, vt);
}
}
@ -6352,7 +6357,7 @@ std::string ValueType::dump() const
ret << " valueType-typeScope=\"" << typeScope << '\"';
if (!originalTypeName.empty())
ret << " valueType-originalTypeName=\"" << originalTypeName << '\"';
ret << " valueType-originalTypeName=\"" << ErrorLogger::toxml(originalTypeName) << '\"';
return ret.str();
}

View File

@ -3211,6 +3211,21 @@ static bool isNotEqual(std::pair<const Token*, const Token*> x, std::pair<const
start2 = skipCVRefs(start2, y.second);
return !(start1 == x.second && start2 == y.second);
}
static bool isNotEqual(std::pair<const Token*, const Token*> x, const std::string& y)
{
TokenList tokenList(nullptr);
std::istringstream istr(y);
tokenList.createTokens(istr);
return isNotEqual(x, std::make_pair(tokenList.front(), tokenList.back()));
}
static bool isNotEqual(std::pair<const Token*, const Token*> x, const ValueType* y)
{
if (y == nullptr)
return false;
if (y->originalTypeName.empty())
return false;
return isNotEqual(x, y->originalTypeName);
}
bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
{
@ -3240,6 +3255,10 @@ bool isLifetimeBorrowed(const Token *tok, const Settings *settings)
std::pair<const Token*, const Token*> parentdecl = Token::typeDecl(tok->astParent());
if (isNotEqual(decl, parentdecl))
return false;
if (isNotEqual(decl, tok->astParent()->valueType()))
return false;
if (isNotEqual(parentdecl, tok->valueType()))
return false;
}
}
} else if (Token::Match(tok->astParent()->tokAt(-3), "%var% . push_back|push_front|insert|push (") &&

View File

@ -24,7 +24,6 @@ void validCode()
{
char * buf = sqlite3_malloc(10);
// cppcheck-suppress invalidPrintfArgType_uint
printf("size: %ull\n", sqlite3_msize(buf));
sqlite3_free(buf);
}

View File

@ -975,7 +975,7 @@ private:
"std::string &f() {\n"
" return hello().substr(1);\n"
"}");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str());
check("class Foo;\n"
"Foo hello() {\n"

View File

@ -4340,6 +4340,14 @@ private:
"}\n",true);
ASSERT_EQUALS("", errout.str());
// #9783
check("std::string GetTaskIDPerUUID(int);\n"
"void InitializeJumpList(CString s);\n"
"void foo() {\n"
" CString sAppID = GetTaskIDPerUUID(123).c_str();\n"
" InitializeJumpList(sAppID);\n"
"}\n",true);
ASSERT_EQUALS("", errout.str());
// #9796
check("struct A {};\n"
"void f() {\n"