https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/176794

>From 1729d1ad8e823ccd30ea44d2437697fed8b4b25e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Mon, 19 Jan 2026 18:10:47 +0000
Subject: [PATCH] do this only for lifetime analysis

---
 .../LifetimeSafety/LifetimeAnnotations.h      |  3 +-
 .../LifetimeSafety/FactsGenerator.cpp         |  6 ++--
 .../LifetimeSafety/LifetimeAnnotations.cpp    | 15 +++++---
 clang/lib/Sema/CheckExprLifetime.cpp          |  3 +-
 clang/test/Sema/Inputs/lifetime-analysis.h    |  6 ++++
 .../Sema/warn-lifetime-analysis-nocfg.cpp     | 34 +++++++++++++++++--
 6 files changed, 56 insertions(+), 11 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h
index 760d34d33b15b..3ca7a79d32ee1 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h
@@ -51,7 +51,8 @@ bool implicitObjectParamIsLifetimeBound(const FunctionDecl 
*FD);
 // pointers or references that depend on the lifetime of the object, such as
 // container iterators (begin, end), data accessors (c_str, data, get), or
 // element accessors (operator[], operator*, front, back, at).
-bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee);
+bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee,
+                                  bool RunningUnderLifetimeSafety);
 
 // Returns true if the first argument of a free function should be tracked for
 // GSL lifetime analysis. This applies to STL free functions that take a 
pointer
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp 
b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 5d1afd15c795d..bbab0627bdead 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -501,7 +501,8 @@ void FactsGenerator::handleFunctionCall(const Expr *Call,
       if (I == 0)
         // For the 'this' argument, the attribute is on the method itself.
         return implicitObjectParamIsLifetimeBound(Method) ||
-               shouldTrackImplicitObjectArg(Method);
+               shouldTrackImplicitObjectArg(
+                   Method, /*RunningUnderLifetimeSafety=*/true);
       if ((I - 1) < Method->getNumParams())
         // For explicit arguments, find the corresponding parameter
         // declaration.
@@ -520,7 +521,8 @@ void FactsGenerator::handleFunctionCall(const Expr *Call,
       return false;
     return I == 0 &&
            isGslPointerType(Method->getFunctionObjectParameterType()) &&
-           shouldTrackImplicitObjectArg(Method);
+           shouldTrackImplicitObjectArg(Method,
+                                        /*RunningUnderLifetimeSafety=*/true);
   };
   if (Args.empty())
     return;
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
index c380543e52a98..93c7a86d0a57c 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
@@ -100,7 +100,8 @@ bool isPointerLikeType(QualType QT) {
   return isGslPointerType(QT) || QT->isPointerType() || QT->isNullPtrType();
 }
 
-bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
+bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee,
+                                  bool RunningUnderLifetimeSafety) {
   if (!Callee)
     return false;
   if (auto *Conv = dyn_cast<CXXConversionDecl>(Callee))
@@ -113,10 +114,14 @@ bool shouldTrackImplicitObjectArg(const CXXMethodDecl 
*Callee) {
       !isGslOwnerType(Callee->getFunctionObjectParameterType()))
     return false;
 
-  // Track dereference operator for GSL pointers in STL.
-  if (isGslPointerType(Callee->getFunctionObjectParameterType()))
-    if (Callee->getOverloadedOperator() == OverloadedOperatorKind::OO_Star)
-      return true;
+  // Track dereference operator for GSL pointers in STL. Only do so for 
lifetime
+  // safety analysis and not for Sema's statement-local analysis as it starts
+  // to have false-positives.
+  if (RunningUnderLifetimeSafety &&
+      isGslPointerType(Callee->getFunctionObjectParameterType()) &&
+      (Callee->getOverloadedOperator() == OverloadedOperatorKind::OO_Star ||
+       Callee->getOverloadedOperator() == OverloadedOperatorKind::OO_Arrow))
+    return true;
 
   if (isPointerLikeType(Callee->getReturnType())) {
     if (!Callee->getIdentifier())
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 0b2f00f417337..5d4b4508541b7 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -482,7 +482,8 @@ static void visitFunctionCallArguments(IndirectLocalPath 
&Path, Expr *Call,
       VisitLifetimeBoundArg(Callee, ObjectArg);
     else if (EnableGSLAnalysis) {
       if (auto *CME = dyn_cast<CXXMethodDecl>(Callee);
-          CME && lifetimes::shouldTrackImplicitObjectArg(CME))
+          CME && lifetimes::shouldTrackImplicitObjectArg(
+                     CME, /*RunningUnderLifetimeSafety=*/false))
         VisitGSLPointerArg(Callee, ObjectArg);
     }
   }
diff --git a/clang/test/Sema/Inputs/lifetime-analysis.h 
b/clang/test/Sema/Inputs/lifetime-analysis.h
index b47fe78bdf0fb..4f881d463ebcc 100644
--- a/clang/test/Sema/Inputs/lifetime-analysis.h
+++ b/clang/test/Sema/Inputs/lifetime-analysis.h
@@ -58,6 +58,12 @@ struct vector {
   void insert(iterator, T&&);
 };
 
+template<typename A, typename B>
+struct pair {
+  A first;
+  B second;
+};
+
 template<typename T>
 struct basic_string_view {
   basic_string_view();
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp 
b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index f4d175981619f..5b6a548389bd5 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -986,8 +986,38 @@ std::string_view 
test_opt_strings(std::optional<std::vector<std::string>> string
 namespace iterator_arrow {
 std::string_view test() {
   std::vector<std::string> strings;
-  // FIXME: Track operator-> of iterators.
-  return strings.begin()->data();
+  return strings.begin()->data(); // cfg-warning {{address of stack memory is 
returned later}} cfg-note {{returned here}}
+}
+
+void operator_star_arrow_reference() {
+  std::vector<std::string> v;
+  const char* p = v.begin()->data();
+  const char* q = (*v.begin()).data();
+  const std::string& r = *v.begin();
+
+  auto temporary = []() { return std::vector<std::string>{{"1"}}; };
+  const char* x = temporary().begin()->data();    // cfg-warning {{object 
whose reference is captured does not live long enough}} cfg-note {{destroyed 
here}}
+  const char* y = (*temporary().begin()).data();  // cfg-warning {{object 
whose reference is captured does not live long enough}} cfg-note {{destroyed 
here}}
+  const std::string& z = (*temporary().begin());  // cfg-warning {{object 
whose reference is captured does not live long enough}} cfg-note {{destroyed 
here}}
+
+  use(p, q, r, x, y, z); // cfg-note 3 {{later used here}}
+}
+
+void operator_star_arrow_of_iterators_false_positive_no_cfg_analysis() {
+  std::vector<std::pair<int, std::string>> v;
+  const char* p = v.begin()->second.data();
+  const char* q = (*v.begin()).second.data();
+  const std::string& r = (*v.begin()).second;
+
+  // FIXME: Detect this using the CFG-based lifetime analysis.
+  //        Detect dangling references to struct field.
+  //        https://github.com/llvm/llvm-project/issues/176144
+  auto temporary = []() { return std::vector<std::pair<int, std::string>>{{1, 
"1"}}; };
+  const char* x = temporary().begin()->second.data();
+  const char* y = (*temporary().begin()).second.data();
+  const std::string& z = (*temporary().begin()).second;
+
+  use(p, q, r, x, y, z);
 }
 } // namespace iterator_arrow
 

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

Reply via email to