// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.NoDeleteChecker -verify %s #include "mock-types.h" void crash(); template [[clang::suppress]] inline void [[clang::annotate_type("webkit.nodelete")]] lazyInitialize(const RefPtr& ptr, Ref&& obj) { if (ptr) crash(); const_cast&>(ptr) = WTF::move(obj); } struct RefObj { static Ref [[clang::annotate_type("webkit.nodelete")]] create(int = 0); void ref() const; void deref() const; int value() const; }; struct Container { void [[clang::annotate_type("webkit.nodelete")]] foo() { if (!m_bar) lazyInitialize(m_bar, RefObj::create()); // expected-warning@-1{{A function 'foo' has [[clang::annotate_type("webkit.nodelete")]] but it contains code that could destruct an object}} // The 'RefObj::create()' temporary is passed as an argument, so its // lifetime ends at this full-expression in 'foo' (the caller destroys // arguments) and its destructor may run delete. Only returned prvalues // are elided, so this is correctly flagged. } void [[clang::annotate_type("webkit.nodelete")]] bar() { if (!m_bar) lazyInitialize(m_bar, RefObj::create(RefObj::create()->value())); // expected-warning@-1{{A function 'bar' has [[clang::annotate_type("webkit.nodelete")]] but it contains code that could destruct an object}} } const RefPtr m_bar; };