diff options
Diffstat (limited to 'clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp')
| -rw-r--r-- | clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp index a4ad741..fd1eecd 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp @@ -107,6 +107,79 @@ private: ValueType* m_table { nullptr }; }; +class ScopeExit final { +public: + template<typename ExitFunctionParameter> + explicit ScopeExit(ExitFunctionParameter&& exitFunction) + : m_exitFunction(std::move(exitFunction)) { + } + + ScopeExit(ScopeExit&& other) + : m_exitFunction(std::move(other.m_exitFunction)) + , m_execute(std::move(other.m_execute)) { + } + + ~ScopeExit() { + if (m_execute) + m_exitFunction(); + } + + WTF::Function<void()> take() { + m_execute = false; + return std::move(m_exitFunction); + } + + void release() { m_execute = false; } + + ScopeExit(const ScopeExit&) = delete; + ScopeExit& operator=(const ScopeExit&) = delete; + ScopeExit& operator=(ScopeExit&&) = delete; + +private: + WTF::Function<void()> m_exitFunction; + bool m_execute { true }; +}; + +template<typename ExitFunction> ScopeExit makeScopeExit(ExitFunction&&); +template<typename ExitFunction> +ScopeExit makeScopeExit(ExitFunction&& exitFunction) +{ + return ScopeExit(std::move(exitFunction)); +} + +// Visitor adapted from http://stackoverflow.com/questions/25338795/is-there-a-name-for-this-tuple-creation-idiom + +template<class A, class... B> struct Visitor : Visitor<A>, Visitor<B...> { + Visitor(A a, B... b) + : Visitor<A>(a) + , Visitor<B...>(b...) + { + } + + using Visitor<A>::operator (); + using Visitor<B...>::operator (); +}; + +template<class A> struct Visitor<A> : A { + Visitor(A a) + : A(a) + { + } + + using A::operator(); +}; + +template<class... F> Visitor<F...> makeVisitor(F... f) +{ + return Visitor<F...>(f...); +} + +void opaqueFunction(); +template <typename Visitor, typename... Variants> void visit(Visitor&& v, Variants&&... values) +{ + opaqueFunction(); +} + } // namespace WTF struct A { @@ -501,3 +574,81 @@ void RefCountedObj::call() const }; callLambda(lambda); } + +void scope_exit(RefCountable* obj) { + auto scope = WTF::makeScopeExit([&] { + obj->method(); + }); + someFunction(); + WTF::ScopeExit scope2([&] { + obj->method(); + }); + someFunction(); +} + +void doWhateverWith(WTF::ScopeExit& obj); + +void scope_exit_with_side_effect(RefCountable* obj) { + auto scope = WTF::makeScopeExit([&] { + obj->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }); + doWhateverWith(scope); +} + +void scope_exit_static(RefCountable* obj) { + static auto scope = WTF::makeScopeExit([&] { + obj->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }); +} + +WTF::Function<void()> scope_exit_take_lambda(RefCountable* obj) { + auto scope = WTF::makeScopeExit([&] { + obj->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }); + return scope.take(); +} + +// FIXME: Ideally, we treat release() as a trivial function. +void scope_exit_release(RefCountable* obj) { + auto scope = WTF::makeScopeExit([&] { + obj->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }); + scope.release(); +} + +void make_visitor(RefCountable* obj) { + auto visitor = WTF::makeVisitor([&] { + obj->method(); + }); +} + +void use_visitor(RefCountable* obj) { + auto visitor = WTF::makeVisitor([&] { + obj->method(); + }); + WTF::visit(visitor, obj); +} + +template <typename Visitor, typename ObjectType> +void bad_visit(Visitor&, ObjectType*) { + someFunction(); +} + +void static_visitor(RefCountable* obj) { + static auto visitor = WTF::makeVisitor([&] { + obj->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }); +} + +void bad_use_visitor(RefCountable* obj) { + auto visitor = WTF::makeVisitor([&] { + obj->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'obj' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }); + bad_visit(visitor, obj); +} |
