[clang] [WebKit checkers] Recognize adoptRef as a safe function (PR #120629)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 19 11:53:47 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Ryosuke Niwa (rniwa)
<details>
<summary>Changes</summary>
adoptRef in WebKit constructs Ref/RefPtr so treat it as such in isCtorOfRefCounted.
Also removed the support for makeRef and makeRefPtr as they don't exist any more.
---
Full diff: https://github.com/llvm/llvm-project/pull/120629.diff
4 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp (+2-3)
- (modified) clang/test/Analysis/Checkers/WebKit/call-args.cpp (+18)
- (modified) clang/test/Analysis/Checkers/WebKit/mock-types.h (+44-1)
- (modified) clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp (-8)
``````````diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 797f3e1f3fba5a..5487fea1b956c8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -125,9 +125,8 @@ bool isCtorOfRefCounted(const clang::FunctionDecl *F) {
assert(F);
const std::string &FunctionName = safeGetName(F);
- return isRefType(FunctionName) || FunctionName == "makeRef" ||
- FunctionName == "makeRefPtr" || FunctionName == "UniqueRef" ||
- FunctionName == "makeUniqueRef" ||
+ return isRefType(FunctionName) || FunctionName == "adoptRef" ||
+ FunctionName == "UniqueRef" || FunctionName == "makeUniqueRef" ||
FunctionName == "makeUniqueRefWithoutFastMallocCheck"
|| FunctionName == "String" || FunctionName == "AtomString" ||
diff --git a/clang/test/Analysis/Checkers/WebKit/call-args.cpp b/clang/test/Analysis/Checkers/WebKit/call-args.cpp
index 94efddeaf66cd8..f1eee216cdffa1 100644
--- a/clang/test/Analysis/Checkers/WebKit/call-args.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/call-args.cpp
@@ -365,3 +365,21 @@ namespace call_with_explicit_temporary_obj {
RefPtr { provide() }->method();
}
}
+
+namespace call_with_adopt_ref {
+ class Obj {
+ public:
+ void ref() const;
+ void deref() const;
+ void method();
+ };
+
+ // This is needed due to rdar://141692212.
+ struct dummy {
+ RefPtr<Obj> any;
+ };
+
+ void foo() {
+ adoptRef(new Obj)->method();
+ }
+}
diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h
index fb1ee51c7ec1de..0dc4259a14e291 100644
--- a/clang/test/Analysis/Checkers/WebKit/mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h
@@ -46,7 +46,10 @@ template<typename T> struct DefaultRefDerefTraits {
template <typename T, typename PtrTraits = RawPtrTraits<T>, typename RefDerefTraits = DefaultRefDerefTraits<T>> struct Ref {
typename PtrTraits::StorageType t;
+ enum AdoptTag { Adopt };
+
Ref() : t{} {};
+ Ref(T &t, AdoptTag) : t(&t) { }
Ref(T &t) : t(&RefDerefTraits::ref(t)) { }
Ref(const Ref& o) : t(RefDerefTraits::refIfNotNull(PtrTraits::unwrap(o.t))) { }
Ref(Ref&& o) : t(o.leakRef()) { }
@@ -73,10 +76,19 @@ template <typename T, typename PtrTraits = RawPtrTraits<T>, typename RefDerefTra
T* leakRef() { return PtrTraits::exchange(t, nullptr); }
};
+template <typename T> Ref<T> adoptRef(T& t) {
+ using Ref = Ref<T>;
+ return Ref(t, Ref::Adopt);
+}
+
+template<typename T> class RefPtr;
+template<typename T> RefPtr<T> adoptRef(T*);
+
template <typename T> struct RefPtr {
T *t;
- RefPtr() : t(new T) {}
+ RefPtr() : t(nullptr) { }
+
RefPtr(T *t)
: t(t) {
if (t)
@@ -85,6 +97,26 @@ template <typename T> struct RefPtr {
RefPtr(Ref<T>&& o)
: t(o.leakRef())
{ }
+ RefPtr(RefPtr&& o)
+ : t(o.t)
+ {
+ o.t = nullptr;
+ }
+ RefPtr(const RefPtr& o)
+ : t(o.t)
+ {
+ if (t)
+ t->ref();
+ }
+ RefPtr operator=(const RefPtr& o)
+ {
+ if (t)
+ t->deref();
+ t = o.t;
+ if (t)
+ t->ref();
+ return *this;
+ }
~RefPtr() {
if (t)
t->deref();
@@ -110,8 +142,19 @@ template <typename T> struct RefPtr {
return *this;
}
operator bool() const { return t; }
+
+private:
+ friend RefPtr adoptRef<T>(T*);
+
+ // call_with_adopt_ref in call-args.cpp requires this method to be private.
+ enum AdoptTag { Adopt };
+ RefPtr(T *t, AdoptTag) : t(t) { }
};
+template <typename T> RefPtr<T> adoptRef(T* t) {
+ return RefPtr<T>(t, RefPtr<T>::Adopt);
+}
+
template <typename T> bool operator==(const RefPtr<T> &, const RefPtr<T> &) {
return false;
}
diff --git a/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp b/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp
index 33c60ea8ca64d1..4209db14eaa52b 100644
--- a/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp
@@ -61,14 +61,6 @@ template<typename Out, typename... In> Function<Out(In...)> adopt(Detail::Callab
return Function<Out(In...)>(impl, Function<Out(In...)>::Adopt);
}
-template<typename T, typename PtrTraits = RawPtrTraits<T>, typename RefDerefTraits = DefaultRefDerefTraits<T>> Ref<T, PtrTraits, RefDerefTraits> adoptRef(T&);
-
-template<typename T, typename _PtrTraits, typename RefDerefTraits>
-inline Ref<T, _PtrTraits, RefDerefTraits> adoptRef(T& reference)
-{
- return Ref<T, _PtrTraits, RefDerefTraits>(reference);
-}
-
enum class DestructionThread : unsigned char { Any, Main, MainRunLoop };
void ensureOnMainThread(Function<void()>&&); // Sync if called on main thread, async otherwise.
void ensureOnMainRunLoop(Function<void()>&&); // Sync if called on main run loop, async otherwise.
``````````
</details>
https://github.com/llvm/llvm-project/pull/120629
More information about the cfe-commits
mailing list