[clang-tools-extra] [clang-tidy] Add bugprone-smart-ptr-initialization check (PR #181570)
Denis Mikhailov via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 15 02:14:23 PDT 2026
================
@@ -0,0 +1,106 @@
+# clang-tidy - bugprone-smart-ptr-initialization
+
+## bugprone-smart-ptr-initialization
+
+Detects dangerous initialization of smart pointers with raw pointers that are
+already owned elsewhere, which can lead to double deletion.
+
+This check implements CERT C++ rule [MEM56-CPP. Do not store an already-owned
+pointer value in an unrelated smart pointer](https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM56-CPP.+Do+not+store+an+already-owned+pointer+value+in+an+unrelated+smart+pointer).
+
+## Examples
+
+The check flags cases where raw pointers that are already owned or managed
+elsewhere are passed to smart pointer constructors or `reset()` methods:
+
+```cpp
+A& getA();
+void foo() {
+ // Warning: '&getA()' is already managed elsewhere
+ std::shared_ptr<A> a(&getA());
+}
+
+void bar() {
+ int x = 10;
+ // Warning: '&x' points to a local variable
+ std::unique_ptr<int> ptr(&x);
+}
+
+void baz() {
+ std::vector<int> vec{1, 2, 3};
+ std::shared_ptr<int> sp;
+ // Warning: '&vec[0]' is managed by the vector
+ sp.reset(&vec[0]);
+}
+```
+
+## Allowed cases
+
+The check ignores legitimate cases:
+
+1. **New expressions**: Pointers from `new` operators are safe:
+
+ ```cpp
+ std::unique_ptr<int> p(new int(5)); // OK
+ ```
+
+2. **Release calls**: Pointers from `release()` method are transferred:
+
+ ```cpp
+ auto p1 = std::make_unique<int>(5);
+ std::unique_ptr<int> p2(p1.release()); // OK
+ ```
+
+3. **Custom deleters**: Smart pointers with custom deleters are ignored:
+
+ ```cpp
+ void customDeleter(int* p) { delete p; }
+ std::unique_ptr<int, decltype(&customDeleter)> p(&getA(), customDeleter);
+ ```
+
+4. **Null pointers**: `nullptr` is always safe:
+
+ ```cpp
+ std::shared_ptr<int> p(nullptr); // OK
+ p.reset(nullptr); // OK
+ ```
+
+## Options
+
+- **SharedPointers**
+
+ A semicolon-separated list of (fully qualified) shared pointer type names
+ that should be checked. Default value is
+ `::std::shared_ptr;::boost::shared_ptr`.
+
+- **UniquePointers**
+
+ A semicolon-separated list of (fully qualified) unique pointer type names
+ that should be checked. Default value is `::std::unique_ptr`.
+
+- **DefaultDeleters**
+
+ A semicolon-separated list of (fully qualified) default deleter type names.
+ Smart pointers with deleters matching these types are considered to use the
+ default deleter and are checked. Smart pointers with custom deleters are
+ ignored. Default value is `::std::default_delete`.
+
+## Limitations
+
+This check only supports smart pointers with shared and unique ownership
+semantics. Smart pointers with different semantics, such as
+`boost::scoped_ptr`, cannot be used with the current version of this check.
+
+This check unable to catch relevant cases inside a ternary operator:
+
+ ```cpp
+ std::shared_ptr<A> a(flag ? nullptr : &getA());
+ ```
----------------
denzor200 wrote:
The checker should provide warning in this sampled case, but it don't. This is a limitation.
https://github.com/llvm/llvm-project/pull/181570
More information about the cfe-commits
mailing list