From 4d9dacff79c4eb209a2174e308946a5eeb7f5a26 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Apr 2025 12:27:42 -0500 Subject: [PATCH 1/2] Fix 13760: false negative: danglingTemporaryLifetime with temporary lambda --- lib/astutils.cpp | 2 ++ test/testautovariables.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index fe761b9c42e..e2beb81681c 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -440,6 +440,8 @@ bool isTemporary(const Token* tok, const Library* library, bool unknown) return isTemporary(tok->astOperand2(), library); if (tok->isCast() || (tok->isCpp() && isCPPCast(tok))) return isTemporary(tok->astOperand2(), library); + if(findLambdaEndToken(tok) != nullptr) + return true; if (Token::Match(tok, ".|[|++|--|%name%|%assign%")) return false; if (tok->isUnaryOp("*")) diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 217f6c1a606..421613197ad 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -4209,6 +4209,19 @@ class TestAutoVariables : public TestFixture { " if (!p) {}\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + // #13760 + check("template\n" + "auto f(T&& x) {\n" + " return [&] {\n" + " return x();\n" + " };\n" + "}\n" + "auto g() {\n" + " auto y = f([](auto x) { return 1; });\n" + " return y();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:12] -> [test.cpp:2:13] -> [test.cpp:4:16] -> [test.cpp:8:16] -> [test.cpp:8:16] -> [test.cpp:9:12]: (error) Using object that is a temporary. [danglingTemporaryLifetime]\n", errout_str()); } void danglingLifetimeBorrowedMembers() From 5f4ab8bd16e5ceabcd901cc8a720a13402417e52 Mon Sep 17 00:00:00 2001 From: Paul Date: Sat, 12 Apr 2025 12:29:47 -0500 Subject: [PATCH 2/2] Format --- lib/astutils.cpp | 2 +- test/testautovariables.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index e2beb81681c..9c869bbcffd 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -440,7 +440,7 @@ bool isTemporary(const Token* tok, const Library* library, bool unknown) return isTemporary(tok->astOperand2(), library); if (tok->isCast() || (tok->isCpp() && isCPPCast(tok))) return isTemporary(tok->astOperand2(), library); - if(findLambdaEndToken(tok) != nullptr) + if (findLambdaEndToken(tok) != nullptr) return true; if (Token::Match(tok, ".|[|++|--|%name%|%assign%")) return false; diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 421613197ad..0c37b7505e1 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -4221,7 +4221,9 @@ class TestAutoVariables : public TestFixture { " auto y = f([](auto x) { return 1; });\n" " return y();\n" "}\n"); - ASSERT_EQUALS("[test.cpp:3:12] -> [test.cpp:2:13] -> [test.cpp:4:16] -> [test.cpp:8:16] -> [test.cpp:8:16] -> [test.cpp:9:12]: (error) Using object that is a temporary. [danglingTemporaryLifetime]\n", errout_str()); + ASSERT_EQUALS( + "[test.cpp:3:12] -> [test.cpp:2:13] -> [test.cpp:4:16] -> [test.cpp:8:16] -> [test.cpp:8:16] -> [test.cpp:9:12]: (error) Using object that is a temporary. [danglingTemporaryLifetime]\n", + errout_str()); } void danglingLifetimeBorrowedMembers()