https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/176643
>From d75dddae42e1c5fe8df949282e0d73fb24276d23 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 | 8 +++ .../Sema/warn-lifetime-analysis-nocfg.cpp | 57 +++++++++++++++++-- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp index 2772fe20de19b..2ddd4c72c30f4 100644 --- a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp @@ -99,6 +99,14 @@ 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 (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) + if (MD->getOverloadedOperator() == OverloadedOperatorKind::OO_Star || + MD->getOverloadedOperator() == OverloadedOperatorKind::OO_Arrow) + 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 7fdc493dbd17a..7830017245b46 100644 --- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp @@ -911,10 +911,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}; @@ -926,15 +929,59 @@ 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> views) { + return views.begin()->data(); // expected-warning {{address of stack memory associated with parameter 'views' returned}} \ + // cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}} +} +} // 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
