https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/90180
>From e00d9f1a928f3bec0780a43b64ea9cab5252126e Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa <rn...@webkit.org> Date: Fri, 26 Apr 2024 01:50:35 -0700 Subject: [PATCH 1/2] [alpha.webkit.UncountedCallArgsChecker] Ignore methods of WTF String classes. --- .../WebKit/UncountedCallArgsChecker.cpp | 11 +- .../WebKit/call-args-wtf-containers.cpp | 118 ++++++++++++++++++ .../Analysis/Checkers/WebKit/mock-types.h | 2 +- 3 files changed, 128 insertions(+), 3 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index 8b41a949fd6734..bdd020585a9af1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -220,10 +220,17 @@ class UncountedCallArgsChecker return NamespaceName == "WTF" && (MethodName == "find" || MethodName == "findIf" || MethodName == "reverseFind" || MethodName == "reverseFindIf" || + MethodName == "findIgnoringASCIICase" || MethodName == "get" || MethodName == "inlineGet" || - MethodName == "contains" || MethodName == "containsIf") && + MethodName == "contains" || MethodName == "containsIf" || + MethodName == "containsIgnoringASCIICase" || + MethodName == "startsWith" || MethodName == "endsWith" || + MethodName == "startsWithIgnoringASCIICase" || + MethodName == "endsWithIgnoringASCIICase" || + MethodName == "substring") && (ClsName.ends_with("Vector") || ClsName.ends_with("Set") || - ClsName.ends_with("Map")); + ClsName.ends_with("Map") || ClsName == "StringImpl" || + ClsName.ends_with("String")); } void reportBug(const Expr *CallArg, const ParmVarDecl *Param) const { diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-wtf-containers.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-wtf-containers.cpp index 0a63a789856127..17e25d9a627039 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args-wtf-containers.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args-wtf-containers.cpp @@ -4,6 +4,92 @@ namespace WTF { + constexpr unsigned long notFound = static_cast<unsigned long>(-1); + + class String; + class StringImpl; + + class StringView { + public: + StringView(const String&); + private: + RefPtr<StringImpl> m_impl; + }; + + class StringImpl { + public: + void ref() const { ++m_refCount; } + void deref() const { + if (!--m_refCount) + delete this; + } + + static constexpr unsigned s_flagIs8Bit = 1u << 0; + bool is8Bit() const { return m_hashAndFlags & s_flagIs8Bit; } + const char* characters8() const { return m_char8; } + const short* characters16() const { return m_char16; } + unsigned length() const { return m_length; } + Ref<StringImpl> substring(unsigned position, unsigned length) const; + + unsigned long find(char) const; + unsigned long find(StringView) const; + unsigned long contains(StringView) const; + unsigned long findIgnoringASCIICase(StringView) const; + + bool startsWith(StringView) const; + bool startsWithIgnoringASCIICase(StringView) const; + bool endsWith(StringView) const; + bool endsWithIgnoringASCIICase(StringView) const; + + private: + mutable unsigned m_refCount { 0 }; + unsigned m_length { 0 }; + union { + const char* m_char8; + const short* m_char16; + }; + unsigned m_hashAndFlags { 0 }; + }; + + class String { + public: + String() = default; + String(StringImpl& impl) : m_impl(&impl) { } + String(StringImpl* impl) : m_impl(impl) { } + String(Ref<StringImpl>&& impl) : m_impl(impl.get()) { } + StringImpl* impl() { return m_impl.get(); } + unsigned length() const { return m_impl ? m_impl->length() : 0; } + const char* characters8() const { return m_impl ? m_impl->characters8() : nullptr; } + const short* characters16() const { return m_impl ? m_impl->characters16() : nullptr; } + + bool is8Bit() const { return !m_impl || m_impl->is8Bit(); } + + unsigned long find(char character) const { return m_impl ? m_impl->find(character) : notFound; } + unsigned long find(StringView str) const { return m_impl ? m_impl->find(str) : notFound; } + unsigned long findIgnoringASCIICase(StringView) const; + + bool contains(char character) const { return find(character) != notFound; } + bool contains(StringView) const; + bool containsIgnoringASCIICase(StringView) const; + + bool startsWith(StringView) const; + bool startsWithIgnoringASCIICase(StringView) const; + bool endsWith(StringView) const; + bool endsWithIgnoringASCIICase(StringView) const; + + String substring(unsigned position, unsigned length) const + { + if (!m_impl) + return { }; + if (!position && length >= m_impl->length()) + return *this; + return m_impl->substring(position, length); + } + + private: + RefPtr<StringImpl> m_impl; + }; + template <typename T> class HashSet { public: @@ -89,6 +175,9 @@ namespace WTF { } +using WTF::StringView; +using WTF::StringImpl; +using WTF::String; using WTF::HashSet; using WTF::HashMap; using WTF::WeakHashSet; @@ -101,8 +190,37 @@ class RefCounted { }; RefCounted* object(); +StringImpl* strImpl(); +String* str(); +StringView strView(); void test() { + strImpl()->is8Bit(); + strImpl()->characters8(); + strImpl()->characters16(); + strImpl()->length(); + strImpl()->substring(2, 4); + strImpl()->find(strView()); + strImpl()->contains(strView()); + strImpl()->findIgnoringASCIICase(strView()); + strImpl()->startsWith(strView()); + strImpl()->startsWithIgnoringASCIICase(strView()); + strImpl()->endsWith(strView()); + strImpl()->endsWithIgnoringASCIICase(strView()); + + str()->is8Bit(); + str()->characters8(); + str()->characters16(); + str()->length(); + str()->substring(2, 4); + str()->find(strView()); + str()->contains(strView()); + str()->findIgnoringASCIICase(strView()); + str()->startsWith(strView()); + str()->startsWithIgnoringASCIICase(strView()); + str()->endsWith(strView()); + str()->endsWithIgnoringASCIICase(strView()); + HashSet<RefPtr<RefCounted>> set; set.find(*object()); set.contains(*object()); diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h index aab99197dfa49e..48e4913811c1c5 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -39,7 +39,7 @@ template <typename T> struct RefPtr { const T *operator->() const { return t; } T &operator*() { return *t; } RefPtr &operator=(T *) { return *this; } - operator bool() { return t; } + operator bool() const { return t; } }; template <typename T> bool operator==(const RefPtr<T> &, const RefPtr<T> &) { >From 3233f49195e5a746d0b7ea1f9ea559396978faa7 Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa <rn...@webkit.org> Date: Fri, 26 Apr 2024 02:10:47 -0700 Subject: [PATCH 2/2] Fix formatting. --- .../Checkers/WebKit/UncountedCallArgsChecker.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp index bdd020585a9af1..14b3ba4c0cb074 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp @@ -220,9 +220,9 @@ class UncountedCallArgsChecker return NamespaceName == "WTF" && (MethodName == "find" || MethodName == "findIf" || MethodName == "reverseFind" || MethodName == "reverseFindIf" || - MethodName == "findIgnoringASCIICase" || - MethodName == "get" || MethodName == "inlineGet" || - MethodName == "contains" || MethodName == "containsIf" || + MethodName == "findIgnoringASCIICase" || MethodName == "get" || + MethodName == "inlineGet" || MethodName == "contains" || + MethodName == "containsIf" || MethodName == "containsIgnoringASCIICase" || MethodName == "startsWith" || MethodName == "endsWith" || MethodName == "startsWithIgnoringASCIICase" || _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits