Author: Ryosuke Niwa Date: 2024-12-19T11:09:36-08:00 New Revision: 98c97d4a19412a76f7279003af6cb219dea1f0c3
URL: https://github.com/llvm/llvm-project/commit/98c97d4a19412a76f7279003af6cb219dea1f0c3 DIFF: https://github.com/llvm/llvm-project/commit/98c97d4a19412a76f7279003af6cb219dea1f0c3.diff LOG: [WebKit checkers] Recognize adoptRef as a safe function (#119846) 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. Added: Modified: clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp clang/test/Analysis/Checkers/WebKit/call-args.cpp clang/test/Analysis/Checkers/WebKit/mock-types.h clang/test/Analysis/Checkers/WebKit/ref-cntbl-crtp-base-no-virtual-dtor.cpp Removed: ################################################################################ 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 2146eae9975b93..b4613d5090f299 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args.cpp @@ -376,3 +376,21 @@ namespace call_with_explicit_temporary_obj { namespace call_with_explicit_construct { } + +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 f3bd20f8bcf603..0908e7fdb34dc2 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -74,7 +74,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()) { } @@ -101,10 +104,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) @@ -113,6 +125,17 @@ 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() { if (t) t->deref(); @@ -138,8 +161,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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits