Author: Benedek Kaibas
Date: 2026-07-21T11:15:57+02:00
New Revision: feabbb0f4611a9c26d6ae694232bfca7964e6233

URL: 
https://github.com/llvm/llvm-project/commit/feabbb0f4611a9c26d6ae694232bfca7964e6233
DIFF: 
https://github.com/llvm/llvm-project/commit/feabbb0f4611a9c26d6ae694232bfca7964e6233.diff

LOG: [analyzer] Fix false positive when a lifetimebound method is called during 
destruction (#210801)

When a `lifetimebound` method is called during destruction the checker
emits warnings which leads to false positives. To avoid this a dangling
stack source is not reported if any frame on the current stack belongs
to a destructor.

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
    clang/test/Analysis/lifetime-bound.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp 
b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
index 42219edc5cceb..2b6f5dae4243f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/LifetimeModeling.cpp
@@ -43,6 +43,16 @@ static bool isDanglingStackSource(const MemRegion *Source,
           Source->getMemorySpaceAs<StackSpaceRegion>(State)) {
     const StackFrame *SF = StackSpace->getStackFrame();
     const StackFrame *CurrentSF = C.getStackFrame();
+    // If any frame on the current stack belongs to a destructor
+    // the warning should be suppressed. When a lifetimebound method
+    // is called from a destructor then its return value is not expected
+    // to outlive the object being destroyed.
+    for (const StackFrame *DtorSF = CurrentSF; DtorSF;
+         DtorSF = DtorSF->getParent()) {
+      if (isa<CXXDestructorDecl>(DtorSF->getDecl()))
+        return false;
+    }
+
     if (SF == CurrentSF || !SF->isParentOf(CurrentSF))
       return true;
   }

diff  --git a/clang/test/Analysis/lifetime-bound.cpp 
b/clang/test/Analysis/lifetime-bound.cpp
index f8519b76798fd..4920a3c928fb8 100644
--- a/clang/test/Analysis/lifetime-bound.cpp
+++ b/clang/test/Analysis/lifetime-bound.cpp
@@ -217,3 +217,35 @@ int *one_dangling_source_ptr(int *a 
[[clang::lifetimebound]]) {
   return multi_param_test_ptr(a, x_ptr); // expected-warning {{Returning value 
bound to 'x' that will go out of scope}}
 }
 
+struct S {
+    int x;
+    int* get() [[clang::lifetimebound]] { return &x; }
+    S() = default;
+    S(S&& other) { (void)other.get(); }
+    ~S() { get(); }
+};
+
+S make() { return S(); }
+
+S passThrough(S param) { return param; }
+
+void outer() {
+    auto f = passThrough(make());
+    (void)f; // no-warning
+}
+
+int *danglingLocal() {
+  S s;
+  return s.get();
+  // expected-warning@-1 {{Returning value bound to 's' that will go out of 
scope}}
+  // expected-warning@-2 {{Address of stack memory associated with local 
variable 's' returned}}
+  // expected-warning@-3 {{address of stack memory associated with local 
variable 's' returned}}
+}
+
+int *danglingParam(S param) {
+  return param.get();
+  // expected-warning@-1 {{Returning value bound to 'param' that will go out 
of scope}}
+  // expected-warning@-2 {{Address of stack memory associated with local 
variable 'param' returned}}
+  // expected-warning@-3 {{address of stack memory associated with parameter 
'param' returned}}
+}
+


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to