Author: Benedek Kaibas
Date: 2026-08-16T00:11:02+02:00
New Revision: 8f88dfdbe8ea21a312b805d4550ed1fa99a6205b

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

LOG: [analyzer] Correctly highlight the variables' range in UseAfterLifetimeEnd 
reports (#215905)

Currently in the emitted reports from the `UseAfterLifetimeEnd` checker
the highlight range of the variables is incorrect which can lead to
confusion for the user.

```
temp.cpp:5:31: note: Value's lifetime bound to the lifetime of 'y' here
    4 |   int x = 1, y = 2;
      |   ~~~~~~~~~~~~~~~~
```

In this emitted note the highlight of the variable `y` incorrectly spans
to the variable `x` as well and vice versa. This does not meet the
quality requirements of a core Clang Static Analyzer Checker.

In this PR I get the `VarDecl` of the `VarRegion` and then return the
`SourceRange` based on the `VarDecl`'s location through `getLocation`.
This leads to the following emitted notes:

```text
temp.cpp:5:37: note: Value's lifetime bound to the lifetime of 'y' here
    4 |   int x = 1, y = 2;
      |              ~
```

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp 
b/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp
index de89836ee5dc2..f10da977172c0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UseAfterLifetimeEnd.cpp
@@ -98,8 +98,10 @@ void UseAfterLifetimeEnd::checkEndFunction(const ReturnStmt 
*RS,
 }
 
 static SourceRange getRegionDeclRange(const MemRegion *Source) {
-  if (const auto *VR = dyn_cast_or_null<VarRegion>(Source))
-    return VR->getDecl()->getSourceRange();
+  if (const auto *VR = dyn_cast_or_null<VarRegion>(Source)) {
+    const VarDecl *VD = VR->getDecl();
+    return SourceRange(VD->getLocation());
+  }
   return SourceRange();
 }
 

diff  --git a/clang/test/Analysis/lifetime-bound.cpp 
b/clang/test/Analysis/lifetime-bound.cpp
index cd31c37aef16c..ff8b4e45c0dee 100644
--- a/clang/test/Analysis/lifetime-bound.cpp
+++ b/clang/test/Analysis/lifetime-bound.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling
 \
 // RUN:   -analyzer-config cfg-lifetime=true -analyzer-output=text -verify %s
 // RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.cplusplus.UseAfterLifetimeEnd,debug.DebugLifetimeModeling
 \
-// RUN:   -analyzer-output=text %s 2>&1 | FileCheck %s
+// RUN:   -analyzer-output=text %s 2>&1 | FileCheck --strict-whitespace %s
 struct A {};
 
 struct Pair {
@@ -450,3 +450,31 @@ int test_correct_param_highlight() {
   // CHECK: return multi_params_annotated(&global_var, &local_n);
   // CHECK-NEXT:{{\|                                              \^~~~~~~~$}}
 }
+
+int test_multi_local_bound_to_param_highlight() {
+  int j = 4, k = 5;
+  // expected-note@-1 {{'j' initialized here}}
+  // expected-note@-2 {{'k' initialized here}}
+  return multi_params_annotated(&j, &k);
+  // expected-warning@-1 {{address of stack memory associated with local 
variable 'j' returned}}
+  // expected-warning@-2 {{address of stack memory associated with local 
variable 'k' returned}}
+  // expected-warning@-3 {{Returning value bound to 'j' that will go out of 
scope}}
+  // expected-note@-4    {{Value's lifetime bound to the lifetime of 'j' here}}
+  // expected-note@-5    {{Lifetime of 'j' ended here}}
+  // expected-warning@-6 {{Returning value bound to 'k' that will go out of 
scope}}
+  // expected-note@-7    {{Value's lifetime bound to the lifetime of 'k' here}}
+  // expected-note@-8    {{Lifetime of 'k' ended here}}
+
+  // CHECK: note: Value's lifetime bound to the lifetime of 'j' here
+  // CHECK-NEXT: int j = 4, k = 5;
+  // CHECK-NEXT:{{\|       ~$}}
+  // CHECK: note: Lifetime of 'j' ended here
+  // CHECK-NEXT: int j = 4, k = 5;
+  // CHECK-NEXT:{{\|       ~$}}
+  // CHECK: note: Value's lifetime bound to the lifetime of 'k' here
+  // CHECK-NEXT: int j = 4, k = 5;
+  // CHECK-NEXT:{{\|              ~$}}
+  // CHECK: note: Lifetime of 'k' ended here
+  // CHECK-NEXT: int j = 4, k = 5;
+  // CHECK-NEXT:{{\|              ~$}}
+}


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

Reply via email to