llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-analysis

@llvm/pr-subscribers-clang-temporal-safety

Author: Utkarsh Saxena (usx95)

<details>
<summary>Changes</summary>

Enhanced the `shouldTrackFirstArgument` function in `LifetimeAnnotations.cpp` 
to recognize standard library algorithm functions like `find`, `find_if`, 
`search`, etc. that return iterators whose lifetimes are bound to their 
container arguments. This allows the lifetime checker to detect when these 
iterators outlive their containers.

The implementation now:
- Checks for standard library algorithm functions that take at least two 
parameters
- Identifies specific functions by name (find, find_if, find_if_not, etc.)
- Verifies the return type is a GSL pointer type


---
Full diff: https://github.com/llvm/llvm-project/pull/179227.diff


3 Files Affected:

- (modified) clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp (+30-3) 
- (modified) clang/test/Sema/Inputs/lifetime-analysis.h (+3) 
- (modified) clang/test/Sema/warn-lifetime-analysis-nocfg.cpp (+23) 


``````````diff
diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp 
b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
index be33caf327802..ac1eb9db8a153 100644
--- a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp
@@ -174,13 +174,41 @@ bool shouldTrackImplicitObjectArg(const CXXMethodDecl 
*Callee,
 }
 
 bool shouldTrackFirstArgument(const FunctionDecl *FD) {
-  if (!FD->getIdentifier() || FD->getNumParams() != 1)
+  if (!FD->getIdentifier() || FD->getNumParams() < 1)
     return false;
+  if (!FD->isInStdNamespace())
+    return false;
+  // Track std:: algorithm functions that return an iterator whose lifetime is
+  // bound to the first argument.
+  if (FD->getNumParams() >= 2 && FD->isInStdNamespace() &&
+      isGslPointerType(FD->getReturnType())) {
+    if (llvm::StringSwitch<bool>(FD->getName())
+            .Cases(
+                {
+                    "find",
+                    "find_if",
+                    "find_if_not",
+                    "find_first_of",
+                    "adjacent_find",
+                    "search",
+                    "find_end",
+                    "lower_bound",
+                    "upper_bound",
+                    "partition_point",
+                },
+                true)
+            .Default(false))
+      return true;
+  }
   const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
-  if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
+  if (!RD || !RD->isInStdNamespace())
     return false;
   if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
     return false;
+
+  if (FD->getNumParams() != 1)
+    return false;
+
   if (FD->getReturnType()->isPointerType() ||
       isGslPointerType(FD->getReturnType())) {
     return llvm::StringSwitch<bool>(FD->getName())
@@ -226,5 +254,4 @@ template <typename T> static bool isRecordWithAttr(QualType 
Type) {
 
 bool isGslPointerType(QualType QT) { return isRecordWithAttr<PointerAttr>(QT); 
}
 bool isGslOwnerType(QualType QT) { return isRecordWithAttr<OwnerAttr>(QT); }
-
 } // namespace clang::lifetimes
diff --git a/clang/test/Sema/Inputs/lifetime-analysis.h 
b/clang/test/Sema/Inputs/lifetime-analysis.h
index 4f881d463ebcc..27882e68c1524 100644
--- a/clang/test/Sema/Inputs/lifetime-analysis.h
+++ b/clang/test/Sema/Inputs/lifetime-analysis.h
@@ -16,6 +16,9 @@ template<typename T> struct remove_reference       { typedef 
T type; };
 template<typename T> struct remove_reference<T &>  { typedef T type; };
 template<typename T> struct remove_reference<T &&> { typedef T type; };
 
+template< class InputIt, class T >
+InputIt find( InputIt first, InputIt last, const T& value );
+
 template<typename T>
 typename remove_reference<T>::type &&move(T &&t) noexcept;
 
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp 
b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index c82cf41b07361..a58b446fe4c07 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -429,6 +429,29 @@ int *returnPtrToLocalArray() {
   return std::begin(a); // TODO
 }
 
+namespace lifetimebound_stl_algorithms {
+
+std::vector<std::string> GetTemporaryString();
+std::vector<std::string_view> GetTemporaryView();
+
+std::string_view test_str_local() {
+  std::vector<std::string> v;
+  return *std::find(v.begin(), // cfg-warning {{address of stack memory is 
returned later}} cfg-note {{returned here}}
+                    v.end(), "42");
+}
+std::string_view test_str_temporary() {
+  return *std::find(GetTemporaryString().begin(), // cfg-warning {{address of 
stack memory is returned later}} cfg-note {{returned here}}
+                    GetTemporaryString().end(), "42");
+}
+std::string_view test_view() {
+  std::vector<std::string_view> v;
+  return *std::find(v.begin(), v.end(), "42");
+}
+std::string_view test_view_local() {
+  return *std::find(GetTemporaryView().begin(), GetTemporaryView().end(), 
"42");
+}
+} // namespace lifetimebound_stl_algorithms
+
 struct ptr_wrapper {
   std::vector<int>::iterator member;
 };

``````````

</details>


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

Reply via email to