Test for return address of reference (#2991)

This commit is contained in:
shaneasd 2020-12-28 17:50:42 +08:00 committed by GitHub
parent 28b4d1a6b3
commit 53734a3da1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 1 deletions

View File

@ -2742,7 +2742,8 @@ std::vector<LifetimeToken> getLifetimeTokens(const Token* tok, bool escape, Valu
} else if (Token::simpleMatch(var->declEndToken(), "=")) { } else if (Token::simpleMatch(var->declEndToken(), "=")) {
errorPath.emplace_back(var->declEndToken(), "Assigned to reference."); errorPath.emplace_back(var->declEndToken(), "Assigned to reference.");
const Token *vartok = var->declEndToken()->astOperand2(); const Token *vartok = var->declEndToken()->astOperand2();
const bool temporary = isTemporary(true, vartok, nullptr, true); const bool temporaryDefault = false; //If we can't tell then assume the value is not temporary as this will result in fewer false positives.
const bool temporary = isTemporary(true, vartok, nullptr, temporaryDefault);
const bool nonlocal = var->isStatic() || var->isGlobal(); const bool nonlocal = var->isStatic() || var->isGlobal();
if (vartok == tok || (nonlocal && temporary) || (!escape && (var->isConst() || var->isRValueReference()) && temporary)) if (vartok == tok || (nonlocal && temporary) || (!escape && (var->isConst() || var->isRValueReference()) && temporary))
return {{tok, true, std::move(errorPath)}}; return {{tok, true, std::move(errorPath)}};

View File

@ -2564,6 +2564,21 @@ private:
" }\n" " }\n"
"};\n"); "};\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
//Make sure we can still take the address of a reference without warning
check("int* foo() {\n"
" int& x = getX();\n"
" return &x;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("struct C {\n"
" int* m_x;\n"
" void foo() {\n"
" const int& x = getX();\n"
" m_x = &x;\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
void danglingLifetimeFunction() { void danglingLifetimeFunction() {