diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index ca76a13cf..ca2d28fc3 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -505,39 +505,41 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token for (const ValueFlow::Value& val:tok->values()) { if (!val.isLocalLifetimeValue()) continue; - const Token * tokvalue = getParentLifetime(val.tokvalue); - if (Token::Match(tok->astParent(), "return|throw")) { - if (getPointerDepth(tok) < getPointerDepth(tokvalue)) - continue; - if (!isLifetimeBorrowed(tok, mSettings)) - continue; - if ((tokvalue->variable() && isInScope(tokvalue->variable()->nameToken(), scope)) || - isDeadTemporary(mTokenizer->isCPP(), tokvalue, tok, &mSettings->library)) { - errorReturnDanglingLifetime(tok, &val); - break; - } - } else if (tokvalue->variable() && isDeadScope(tokvalue->variable()->nameToken(), tok->scope())) { - errorInvalidLifetime(tok, &val); - break; - } else if (!tokvalue->variable() && isDeadTemporary(mTokenizer->isCPP(), tokvalue, tok, &mSettings->library)) { - errorDanglingTemporaryLifetime(tok, &val); - break; - } else if (tokvalue->variable() && isInScope(tokvalue->variable()->nameToken(), tok->scope())) { - const Variable * var = nullptr; - const Token * tok2 = tok; - if (Token::simpleMatch(tok->astParent(), "=")) { - if (tok->astParent()->astOperand2() == tok) { - var = getLHSVariable(tok->astParent()); - tok2 = tok->astParent()->astOperand1(); + for(const LifetimeToken& lt :getLifetimeTokens(getParentLifetime(val.tokvalue))) { + const Token * tokvalue = lt.token; + if (Token::Match(tok->astParent(), "return|throw")) { + if (getPointerDepth(tok) < getPointerDepth(tokvalue)) + continue; + if (!isLifetimeBorrowed(tok, mSettings)) + continue; + if ((tokvalue->variable() && isInScope(tokvalue->variable()->nameToken(), scope)) || + isDeadTemporary(mTokenizer->isCPP(), tokvalue, tok, &mSettings->library)) { + errorReturnDanglingLifetime(tok, &val); + break; } - } else if (tok->variable() && tok->variable()->declarationId() == tok->varId()) { - var = tok->variable(); - } - if (!isLifetimeBorrowed(tok, mSettings)) - continue; - if (var && !var->isLocal() && !var->isArgument() && !isVariableChanged(tok->next(), tok->scope()->bodyEnd, var->declarationId(), var->isGlobal(), mSettings, mTokenizer->isCPP())) { - errorDanglngLifetime(tok2, &val); + } else if (tokvalue->variable() && isDeadScope(tokvalue->variable()->nameToken(), tok->scope())) { + errorInvalidLifetime(tok, &val); break; + } else if (!tokvalue->variable() && isDeadTemporary(mTokenizer->isCPP(), tokvalue, tok, &mSettings->library)) { + errorDanglingTemporaryLifetime(tok, &val); + break; + } else if (tokvalue->variable() && isInScope(tokvalue->variable()->nameToken(), tok->scope())) { + const Variable * var = nullptr; + const Token * tok2 = tok; + if (Token::simpleMatch(tok->astParent(), "=")) { + if (tok->astParent()->astOperand2() == tok) { + var = getLHSVariable(tok->astParent()); + tok2 = tok->astParent()->astOperand1(); + } + } else if (tok->variable() && tok->variable()->declarationId() == tok->varId()) { + var = tok->variable(); + } + if (!isLifetimeBorrowed(tok, mSettings)) + continue; + if (var && !var->isLocal() && !var->isArgument() && !isVariableChanged(tok->next(), tok->scope()->bodyEnd, var->declarationId(), var->isGlobal(), mSettings, mTokenizer->isCPP())) { + errorDanglngLifetime(tok2, &val); + break; + } } } } diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 897afc702..49bd45770 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -2261,6 +2261,17 @@ private: " ptr = &arr[2];\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // #9639 + check("struct Fred {\n" + " std::string s;\n" + "};\n" + "const Fred &getFred();\n" + "const char * f() {\n" + " const Fred &fred = getFred();\n" + " return fred.s.c_str();\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void danglingLifetimeFunction() {