Fix issue 9783: wrong lifetime analysis temporary assigned to object (#2711)
This commit is contained in:
parent
dea5a23c34
commit
32df807b22
|
@ -169,17 +169,15 @@ std::string astCanonicalType(const Token *expr)
|
||||||
{
|
{
|
||||||
if (!expr)
|
if (!expr)
|
||||||
return "";
|
return "";
|
||||||
if (expr->variable()) {
|
std::pair<const Token*, const Token*> decl = Token::typeDecl(expr);
|
||||||
const Variable *var = expr->variable();
|
if (decl.first && decl.second) {
|
||||||
std::string ret;
|
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"))
|
if (!Token::Match(type, "const|static"))
|
||||||
ret += type->str();
|
ret += type->str();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
// TODO: handle expressions
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -682,6 +682,9 @@ std::string ErrorLogger::toxml(const std::string &str)
|
||||||
case '\"':
|
case '\"':
|
||||||
xml << """;
|
xml << """;
|
||||||
break;
|
break;
|
||||||
|
case '\'':
|
||||||
|
xml << "'";
|
||||||
|
break;
|
||||||
case '\0':
|
case '\0':
|
||||||
xml << "\\0";
|
xml << "\\0";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5707,7 +5707,7 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V
|
||||||
} else
|
} else
|
||||||
valuetype->type = ValueType::Type::RECORD;
|
valuetype->type = ValueType::Type::RECORD;
|
||||||
bool par = false;
|
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()) {
|
!type->variable() && !type->function()) {
|
||||||
if (type->str() == "(") {
|
if (type->str() == "(") {
|
||||||
if (Token::Match(type->link(), ") const| {"))
|
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()));
|
const std::string& typestr(mSettings->library.returnValueType(tok->previous()));
|
||||||
if (!typestr.empty()) {
|
if (!typestr.empty()) {
|
||||||
ValueType valuetype;
|
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);
|
setValueType(tok, valuetype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6091,6 +6095,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
|
||||||
tokenList.simplifyPlatformTypes();
|
tokenList.simplifyPlatformTypes();
|
||||||
tokenList.simplifyStdType();
|
tokenList.simplifyStdType();
|
||||||
if (parsedecl(tokenList.front(), &vt, mDefaultSignedness, mSettings)) {
|
if (parsedecl(tokenList.front(), &vt, mDefaultSignedness, mSettings)) {
|
||||||
|
vt.originalTypeName = typestr;
|
||||||
setValueType(tok, vt);
|
setValueType(tok, vt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6352,7 +6357,7 @@ std::string ValueType::dump() const
|
||||||
ret << " valueType-typeScope=\"" << typeScope << '\"';
|
ret << " valueType-typeScope=\"" << typeScope << '\"';
|
||||||
|
|
||||||
if (!originalTypeName.empty())
|
if (!originalTypeName.empty())
|
||||||
ret << " valueType-originalTypeName=\"" << originalTypeName << '\"';
|
ret << " valueType-originalTypeName=\"" << ErrorLogger::toxml(originalTypeName) << '\"';
|
||||||
|
|
||||||
return ret.str();
|
return ret.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3211,6 +3211,21 @@ static bool isNotEqual(std::pair<const Token*, const Token*> x, std::pair<const
|
||||||
start2 = skipCVRefs(start2, y.second);
|
start2 = skipCVRefs(start2, y.second);
|
||||||
return !(start1 == x.second && 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)
|
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());
|
std::pair<const Token*, const Token*> parentdecl = Token::typeDecl(tok->astParent());
|
||||||
if (isNotEqual(decl, parentdecl))
|
if (isNotEqual(decl, parentdecl))
|
||||||
return false;
|
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 (") &&
|
} else if (Token::Match(tok->astParent()->tokAt(-3), "%var% . push_back|push_front|insert|push (") &&
|
||||||
|
|
|
@ -24,7 +24,6 @@ void validCode()
|
||||||
|
|
||||||
{
|
{
|
||||||
char * buf = sqlite3_malloc(10);
|
char * buf = sqlite3_malloc(10);
|
||||||
// cppcheck-suppress invalidPrintfArgType_uint
|
|
||||||
printf("size: %ull\n", sqlite3_msize(buf));
|
printf("size: %ull\n", sqlite3_msize(buf));
|
||||||
sqlite3_free(buf);
|
sqlite3_free(buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -975,7 +975,7 @@ private:
|
||||||
"std::string &f() {\n"
|
"std::string &f() {\n"
|
||||||
" return hello().substr(1);\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"
|
check("class Foo;\n"
|
||||||
"Foo hello() {\n"
|
"Foo hello() {\n"
|
||||||
|
|
|
@ -4340,6 +4340,14 @@ private:
|
||||||
"}\n",true);
|
"}\n",true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
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
|
// #9796
|
||||||
check("struct A {};\n"
|
check("struct A {};\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
|
|
Loading…
Reference in New Issue