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
