summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/alpha/tests
diff options
context:
space:
mode:
Diffstat (limited to 'build/clang-plugin/alpha/tests')
-rw-r--r--build/clang-plugin/alpha/tests/TestNonStdMove.cpp125
-rw-r--r--build/clang-plugin/alpha/tests/TestTempRefPtr.cpp52
-rw-r--r--build/clang-plugin/alpha/tests/sources.mozbuild11
3 files changed, 188 insertions, 0 deletions
diff --git a/build/clang-plugin/alpha/tests/TestNonStdMove.cpp b/build/clang-plugin/alpha/tests/TestNonStdMove.cpp
new file mode 100644
index 0000000000..379f9655dd
--- /dev/null
+++ b/build/clang-plugin/alpha/tests/TestNonStdMove.cpp
@@ -0,0 +1,125 @@
+#include <mozilla/RefPtr.h>
+
+// we can't include nsCOMPtr.h here, so let's redefine a basic version
+template<typename T>
+struct nsCOMPtr {
+ nsCOMPtr() = default;
+
+ template<typename U>
+ MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>&& aSrc);
+
+ template<typename U>
+ nsCOMPtr& operator=(already_AddRefed<U>&& aSrc);
+};
+
+
+using namespace mozilla;
+
+struct RefCountedBase {
+ void AddRef();
+ void Release();
+
+ void method_test();
+};
+
+struct RefCountedDerived : RefCountedBase {};
+
+struct RefCountedBaseHolder {
+ RefPtr<RefCountedBase> GetRefCountedBase() const {
+ return mRefCountedBase;
+ }
+
+private:
+ RefPtr<RefCountedBase> mRefCountedBase = MakeRefPtr<RefCountedBase>();
+};
+
+
+void test_assign_same_type() {
+ RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>();
+ RefPtr<RefCountedBase> b;
+
+ b = a.forget(); // expected-warning {{non-standard move assignment}}
+}
+
+void test_assign_implicit_cast() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ RefPtr<RefCountedBase> b;
+
+ b = a.forget(); // expected-warning {{non-standard move assignment}}
+}
+
+void test_assign_different_template() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ nsCOMPtr<RefCountedBase> b;
+
+ b = a.forget(); // expected-warning {{non-standard move assignment}}
+}
+
+void test_construct_different_template() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ nsCOMPtr<RefCountedBase> b = a.forget(); // expected-warning {{non-standard move construction}}
+}
+
+void test_assign_already_addrefed() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ already_AddRefed<RefCountedDerived> b;
+
+ b = a.forget();
+}
+
+void test_construct_already_addrefed() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ already_AddRefed<RefCountedDerived> b = a.forget();
+}
+
+void test_construct_same_type() {
+ RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>();
+ RefPtr<RefCountedBase> b = a.forget(); // expected-warning {{non-standard move construction}}
+}
+
+void test_construct_implicit_cast() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ RefPtr<RefCountedBase> b = a.forget(); // expected-warning {{non-standard move construction}}
+}
+
+void test_construct_brace_same_type() {
+ RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>();
+ auto b = RefPtr<RefCountedBase>{a.forget()}; // expected-warning {{non-standard move construction}}
+}
+
+void test_construct_brace_implicit_cast() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ auto b = RefPtr<RefCountedBase>{a.forget()}; // expected-warning {{non-standard move construction}}
+}
+
+void test_construct_function_style_same_type() {
+ RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>();
+ auto b = RefPtr<RefCountedBase>(a.forget()); // expected-warning {{non-standard move construction}}
+}
+
+void test_construct_function_style_implicit_cast() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ auto b = RefPtr<RefCountedBase>(a.forget()); // expected-warning {{non-standard move construction}}
+}
+
+void test_construct_result_type() {
+ RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>();
+ already_AddRefed<RefCountedBase> b = a.forget();
+}
+
+void test_construct_implicitly_cast_result_type() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ already_AddRefed<RefCountedBase> b = a.forget();
+}
+
+void foo(already_AddRefed<RefCountedBase>&& aArg);
+
+void test_call_with_result_type() {
+ RefPtr<RefCountedBase> a = MakeRefPtr<RefCountedBase>();
+ foo(a.forget());
+}
+
+void test_call_with_implicitly_cast_result_type() {
+ RefPtr<RefCountedDerived> a = MakeRefPtr<RefCountedDerived>();
+ foo(a.forget());
+}
diff --git a/build/clang-plugin/alpha/tests/TestTempRefPtr.cpp b/build/clang-plugin/alpha/tests/TestTempRefPtr.cpp
new file mode 100644
index 0000000000..51f756b8e6
--- /dev/null
+++ b/build/clang-plugin/alpha/tests/TestTempRefPtr.cpp
@@ -0,0 +1,52 @@
+#include <mozilla/RefPtr.h>
+
+using namespace mozilla;
+
+struct RefCountedBase {
+ void AddRef();
+ void Release();
+
+ void method_test();
+};
+
+struct RefCountedBaseHolder {
+ RefPtr<RefCountedBase> GetRefCountedBase() const {
+ return mRefCountedBase;
+ }
+
+private:
+ RefPtr<RefCountedBase> mRefCountedBase = MakeRefPtr<RefCountedBase>();
+};
+
+
+void test_arrow_temporary_new_refptr_function_style_cast() {
+ RefPtr<RefCountedBase>(new RefCountedBase())->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}}
+}
+
+void test_arrow_temporary_new_refptr_brace() {
+ RefPtr<RefCountedBase>{new RefCountedBase()}->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}}
+}
+
+void test_arrow_temporary_new_c_style_cast() {
+ ((RefPtr<RefCountedBase>)(new RefCountedBase()))->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}}
+}
+
+void test_arrow_temporary_new_static_cast() {
+ static_cast<RefPtr<RefCountedBase>>(new RefCountedBase())->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}}
+}
+
+void test_arrow_temporary_new_refptr_makerefptr() {
+ MakeRefPtr<RefCountedBase>()->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}}
+}
+
+void test_arrow_temporary_get_refptr_from_member_function() {
+ const RefCountedBaseHolder holder;
+ holder.GetRefCountedBase()->method_test(); // expected-warning {{performance issue: temporary 'RefPtr<RefCountedBase>' is only dereferenced here once which involves short-lived AddRef/Release calls}} expected-note {{consider changing function RefCountedBaseHolder::GetRefCountedBase to return a raw reference instead}}
+}
+
+void test_ref(RefCountedBase &aRefCountedBase);
+
+void test_star_temporary_new_refptr_function_style_cast() {
+ // TODO: Should we warn about operator* as well?
+ test_ref(*RefPtr<RefCountedBase>(new RefCountedBase()));
+}
diff --git a/build/clang-plugin/alpha/tests/sources.mozbuild b/build/clang-plugin/alpha/tests/sources.mozbuild
new file mode 100644
index 0000000000..b72cacd253
--- /dev/null
+++ b/build/clang-plugin/alpha/tests/sources.mozbuild
@@ -0,0 +1,11 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+ # 'AlphaTest.cpp',
+ "TestNonStdMove.cpp",
+ 'TestTempRefPtr.cpp',
+]