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

>From c873b51ec8f9bc49bcb249d47cddc2cd7f5fa228 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sun, 18 Jan 2026 11:49:39 +0000
Subject: [PATCH] range based for loops

---
 .../LifetimeSafety/LifetimeAnnotations.cpp    | 10 +++-
 .../Sema/warn-lifetime-analysis-nocfg.cpp     | 58 +++++++++++++++++--
 2 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
index ced0ad537604a..c380543e52a98 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
@@ -101,7 +101,9 @@ bool isPointerLikeType(QualType QT) {
 }
 
 bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
-  if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
+  if (!Callee)
+    return false;
+  if (auto *Conv = dyn_cast<CXXConversionDecl>(Callee))
     if (isGslPointerType(Conv->getConversionType()) &&
         Callee->getParent()->hasAttr<OwnerAttr>())
       return true;
@@ -110,6 +112,12 @@ bool shouldTrackImplicitObjectArg(const CXXMethodDecl 
*Callee) {
   if (!isGslPointerType(Callee->getFunctionObjectParameterType()) &&
       !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;
+
   if (isPointerLikeType(Callee->getReturnType())) {
     if (!Callee->getIdentifier())
       return false;
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp 
b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index 77fb39ebb10f3..f4d175981619f 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -919,10 +919,13 @@ struct MySpan {
   MySpan(const std::vector<T>& v);
   ~MySpan();
   using iterator = std::iterator<T>;
-  iterator begin() const [[clang::lifetimebound]];
+  // FIXME: It is not possible to annotate accessor methods of non-owning view 
types.
+  // Clang should provide another annotation to mark such functions as 
'transparent'.
+  iterator begin() const;
 };
+// FIXME: Same as above.
 template <typename T>
-typename MySpan<T>::iterator ReturnFirstIt(const MySpan<T>& v 
[[clang::lifetimebound]]);
+typename MySpan<T>::iterator ReturnFirstIt(const MySpan<T>& v);
 
 void test4() {
   std::vector<int> v{1};
@@ -934,15 +937,60 @@ void test4() {
   // Ideally, we would diagnose the following case, but due to implementation
   // constraints, we do not.
   const int& t4 = *MySpan<int>(std::vector<int>{}).begin();
+  use(t1, t2, t4);
 
-  // FIXME: Detect this using the CFG-based lifetime analysis (constructor of 
a pointer).
-  auto it1 = MySpan<int>(v).begin(); // expected-warning {{temporary whose 
address is use}}
-  auto it2 = ReturnFirstIt(MySpan<int>(v)); // expected-warning {{temporary 
whose address is used}}
+  auto it1 = MySpan<int>(v).begin();
+  auto it2 = ReturnFirstIt(MySpan<int>(v));
   use(it1, it2);
 }
 
 } // namespace LifetimeboundInterleave
 
+namespace range_based_for_loop_variables {
+std::string_view test_view_loop_var(std::vector<std::string> strings) {
+  for (std::string_view s : strings) {  // cfg-warning {{address of stack 
memory is returned later}} 
+    return s; //cfg-note {{returned here}}
+  }
+  return "";
+}
+
+const char* test_view_loop_var_with_data(std::vector<std::string> strings) {
+  for (std::string_view s : strings) {  // cfg-warning {{address of stack 
memory is returned later}} 
+    return s.data(); //cfg-note {{returned here}}
+  }
+  return "";
+}
+
+std::string_view test_no_error_for_views(std::vector<std::string_view> views) {
+  for (std::string_view s : views) {
+    return s;
+  }
+  return "";
+}
+
+std::string_view test_string_ref_var(std::vector<std::string> strings) {
+  for (const std::string& s : strings) {  // cfg-warning {{address of stack 
memory is returned later}} 
+    return s; //cfg-note {{returned here}}
+  }
+  return "";
+}
+
+std::string_view test_opt_strings(std::optional<std::vector<std::string>> 
strings_or) {
+  for (const std::string& s : *strings_or) {  // cfg-warning {{address of 
stack memory is returned later}} 
+    return s; //cfg-note {{returned here}}
+  }
+  return "";
+}
+} // namespace range_based_for_loop_variables
+
+namespace iterator_arrow {
+std::string_view test() {
+  std::vector<std::string> strings;
+  // FIXME: Track operator-> of iterators.
+  return strings.begin()->data();
+}
+} // namespace iterator_arrow
+
 namespace GH120206 {
 struct S {
   std::string_view s;

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

Reply via email to