[clang] [clang] Suppress a dangling false positive when owner is moved in member initializer. (PR #114213)

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 30 04:47:29 PDT 2024


https://github.com/hokein created https://github.com/llvm/llvm-project/pull/114213

This patch extends the filtering heuristic to apply for the Lifetimebound code path.

This will suppress a common false positive:

```
namespace std {
template<typename T>
struct unique_ptr {
  T &operator*();
  T *get() const [[clang::lifetimebound]];
};
} // namespace std

struct X {
  X(std::unique_ptr<int> up) :
    pointer(up.get()), owner(std::move(up)) {}

  int *pointer;
  std::unique_ptr<int> owner;
};
```

See #112751.

>From ebd9182e4ae3486fd2e2edd55c7c683605f33294 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Wed, 30 Oct 2024 12:42:15 +0100
Subject: [PATCH] [clang] Suppress a dangling false positive when owner is
 moved in the member initializer.

This patch extends the filtering heuristic to apply for the
Lifetimebound code path.

This will suppress a common false positive:

```
namespace std {
template<typename T>
struct unique_ptr {
  T &operator*();
  T *get() const [[clang::lifetimebound]];
};
} // namespace std

struct X {
  X(std::unique_ptr<int> up) :
    pointer(up.get()), owner(std::move(up)) {}

  int *pointer;
  std::unique_ptr<int> owner;
};
```
---
 clang/lib/Sema/CheckExprLifetime.cpp             |  6 +++---
 clang/test/Sema/warn-lifetime-analysis-nocfg.cpp | 13 +++++++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index aa0a2e223e708f..33d308fe7bdb60 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -1261,12 +1261,12 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
         if (pathContainsInit(Path))
           return false;
 
+        auto *DRE = dyn_cast<DeclRefExpr>(L);
         // Suppress false positives for code like the one below:
-        //   Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}
-        if (IsLocalGslOwner && pathOnlyHandlesGslPointer(Path))
+        //   Ctor(unique_ptr<T> up) : pointer(up.get()), owner(move(up)) {}
+        if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType()))
           return false;
 
-        auto *DRE = dyn_cast<DeclRefExpr>(L);
         auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
         if (!VD) {
           // A member was initialized to a local block.
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index 688f55edfe84df..6a2af01ea5116c 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -384,6 +384,19 @@ struct X {
   std::unique_ptr<int> pointer;
 };
 
+struct [[gsl::Owner]] XOwner {
+  int* get() const [[clang::lifetimebound]];
+};
+struct X2 {
+  // A common usage that moves the passing owner to the class.
+  // verify no warning on this case.
+  X2(XOwner owner) :
+    pointee(owner.get()),
+    owner(std::move(owner)) {}
+  int* pointee;
+  XOwner owner;
+};
+
 std::vector<int>::iterator getIt();
 std::vector<int> getVec();
 



More information about the cfe-commits mailing list