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
