#include #include #define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script"))) #define MOZ_CAN_RUN_SCRIPT_BOUNDARY __attribute__((annotate("moz_can_run_script_boundary"))) MOZ_CAN_RUN_SCRIPT void test() { } void test_parent() { // expected-note {{caller function declared here}} test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} } MOZ_CAN_RUN_SCRIPT void test_parent2() { test(); } struct RefCountedBase; MOZ_CAN_RUN_SCRIPT void test2(RefCountedBase* param) { } struct RefCountedBase { void AddRef(); void Release(); MOZ_CAN_RUN_SCRIPT void method_test() { test(); } MOZ_CAN_RUN_SCRIPT void method_test2() { test2(this); } virtual void method_test3() { // expected-note {{caller function declared here}} test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} } MOZ_CAN_RUN_SCRIPT void method_test4() { method_test(); } MOZ_CAN_RUN_SCRIPT void method_test5() { this->method_test(); } }; MOZ_CAN_RUN_SCRIPT void testLambda() { auto doIt = []() MOZ_CAN_RUN_SCRIPT { test(); }; auto doItWrong = []() { // expected-note {{caller function declared here}} test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} }; doIt(); doItWrong(); } void test2_parent() { // expected-note {{caller function declared here}} test2(new RefCountedBase); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'new RefCountedBase' is neither.}} \ // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} } MOZ_CAN_RUN_SCRIPT void test2_parent2() { test2(new RefCountedBase); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'new RefCountedBase' is neither.}} } MOZ_CAN_RUN_SCRIPT void test2_parent3(RefCountedBase* param) { test2(param); RefCountedBase*& paramRef = param; test2(paramRef); } MOZ_CAN_RUN_SCRIPT void test2_parent4() { RefPtr refptr = new RefCountedBase; test2(refptr); RefPtr& refptrRef = refptr; test2(refptrRef); const RefPtr& refptrConstRef = refptr; test2(refptrConstRef); RefPtr refptrOther = refptr; RefPtr& refptrRef2 = refptr ? refptr : refptrOther; test2(refptrRef2); RefPtr* refPtrInHeap = new RefPtr; RefPtr& refptrRefUnsafe1 = *refPtrInHeap; test2(refptrRefUnsafe1); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe1' is neither.}} RefPtr& refptrRefUnsafe2 = refPtrInHeap ? *refPtrInHeap : refptr; test2(refptrRefUnsafe2); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe2' is neither.}} RefPtr& refptrRefUnsafe3 = refPtrInHeap ? refptr : *refPtrInHeap; test2(refptrRefUnsafe3); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe3' is neither.}} } MOZ_CAN_RUN_SCRIPT void test2_parent5() { test2(MOZ_KnownLive(new RefCountedBase)); } MOZ_CAN_RUN_SCRIPT void test2_parent6() { RefPtr refptr = new RefCountedBase; refptr->method_test(); refptr->method_test2(); RefPtr& refptrRef = refptr; refptrRef->method_test(); refptrRef->method_test2(); RefPtr refptrOther = refptr; RefPtr& refptrRef2 = refptr ? refptr : refptrOther; refptrRef2->method_test(); refptrRef2->method_test2(); RefPtr* refPtrInHeap = new RefPtr; RefPtr& refptrRefUnsafe1 = *refPtrInHeap; refptrRefUnsafe1->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe1->' is neither.}} refptrRefUnsafe1->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe1->' is neither.}} RefPtr& refptrRefUnsafe2 = refPtrInHeap ? *refPtrInHeap : refptr; refptrRefUnsafe2->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe2->' is neither.}} refptrRefUnsafe2->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe2->' is neither.}} RefPtr& refptrRefUnsafe3 = refPtrInHeap ? refptr : *refPtrInHeap; refptrRefUnsafe3->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe3->' is neither.}} refptrRefUnsafe3->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refptrRefUnsafe3->' is neither.}} } MOZ_CAN_RUN_SCRIPT void test2_parent7() { RefCountedBase* t = new RefCountedBase; t->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} t->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} RefCountedBase*& tRef = t; tRef->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'tRef' is neither.}} tRef->method_test2(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'tRef' is neither.}} } MOZ_CAN_RUN_SCRIPT void test2_parent8() { test2(nullptr); } MOZ_CAN_RUN_SCRIPT void test3(int* param) {} MOZ_CAN_RUN_SCRIPT void test3_parent() { test3(new int); } struct RefCountedChild : public RefCountedBase { virtual void method_test3() override; // expected-note {{overridden function declared here}} expected-note {{overridden function declared here}} expected-note {{caller function declared here}} }; void RefCountedChild::method_test3() { test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}} } struct RefCountedSubChild : public RefCountedChild { MOZ_CAN_RUN_SCRIPT void method_test3() override; // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT cannot override functions that are not marked MOZ_CAN_RUN_SCRIPT}} }; void RefCountedSubChild::method_test3() { // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT cannot override functions that are not marked MOZ_CAN_RUN_SCRIPT}} test(); } MOZ_CAN_RUN_SCRIPT void test4() { RefPtr refptr1 = new RefCountedChild; refptr1->method_test3(); RefPtr refptr2 = new RefCountedSubChild; refptr2->method_test3(); RefPtr refptr3 = new RefCountedSubChild; refptr3->method_test3(); RefPtr refptr4 = new RefCountedSubChild; refptr4->method_test3(); } MOZ_CAN_RUN_SCRIPT_BOUNDARY void test5() { RefPtr refptr1 = new RefCountedChild; refptr1->method_test3(); RefPtr refptr2 = new RefCountedSubChild; refptr2->method_test3(); RefPtr refptr3 = new RefCountedSubChild; refptr3->method_test3(); RefPtr refptr4 = new RefCountedSubChild; refptr4->method_test3(); } // We should be able to call test5 from a non-can_run_script function. void test5_b() { test5(); } MOZ_CAN_RUN_SCRIPT void test6() { void* x = new RefCountedBase(); test2((RefCountedBase*)x); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'x' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_ref(const RefCountedBase&) { } MOZ_CAN_RUN_SCRIPT void test_ref_1() { RefCountedBase* t = new RefCountedBase; test_ref(*t); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*t' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_ref_2() { RefCountedBase* t = new RefCountedBase; (*t).method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*t' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_ref_3() { RefCountedBase* t = new RefCountedBase; auto& ref = *t; test_ref(ref); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'ref' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_ref_4() { RefCountedBase* t = new RefCountedBase; auto& ref = *t; ref.method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'ref' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_ref_5() { RefPtr t = new RefCountedBase; test_ref(*t); } MOZ_CAN_RUN_SCRIPT void test_ref_6() { RefPtr t = new RefCountedBase; (*t).method_test(); } MOZ_CAN_RUN_SCRIPT void test_ref_7() { RefPtr t = new RefCountedBase; auto& ref = *t; MOZ_KnownLive(ref).method_test(); } MOZ_CAN_RUN_SCRIPT void test_ref_8() { RefPtr t = new RefCountedBase; auto& ref = *t; test_ref(MOZ_KnownLive(ref)); } MOZ_CAN_RUN_SCRIPT void test_ref_9() { void* x = new RefCountedBase(); test_ref(*(RefCountedBase*)x); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*(RefCountedBase*)x' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_maybe() { mozilla::Maybe unsafe; unsafe.emplace(new RefCountedBase); (*unsafe)->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*unsafe' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_maybe_2() { // FIXME(bz): This should not generate an error! mozilla::Maybe> safe; safe.emplace(new RefCountedBase); (*safe)->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '(*safe){{(->)?}}' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_defaults_helper_1(RefCountedBase* arg = nullptr) { } MOZ_CAN_RUN_SCRIPT void test_defaults_1() { test_defaults_helper_1(); } MOZ_CAN_RUN_SCRIPT void test_defaults_2() { RefCountedBase* t = new RefCountedBase; test_defaults_helper_1(t); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_defaults_3() { RefPtr t = new RefCountedBase; test_defaults_helper_1(t); } MOZ_CAN_RUN_SCRIPT void test_defaults_helper_2(RefCountedBase* arg = new RefCountedBase()) { // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'new RefCountedBase()' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_defaults_4() { test_defaults_helper_2(); } MOZ_CAN_RUN_SCRIPT void test_defaults_5() { RefCountedBase* t = new RefCountedBase; test_defaults_helper_2(t); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 't' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_defaults_6() { RefPtr t = new RefCountedBase; test_defaults_helper_2(t); } MOZ_CAN_RUN_SCRIPT void test_arg_deref_helper(RefCountedBase&) { } MOZ_CAN_RUN_SCRIPT void test_arg_deref(RefCountedBase* arg) { test_arg_deref_helper(*arg); } struct RefCountedDerefTester : public RefCountedBase { MOZ_CAN_RUN_SCRIPT void foo() { test_arg_deref_helper(*this); } }; struct DisallowMemberArgs { RefPtr mRefCounted; MOZ_CAN_RUN_SCRIPT void foo() { mRefCounted->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted{{(->)?}}' is neither.}} RefPtr& unsafeMemberRef = mRefCounted; unsafeMemberRef->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef{{(->)?}}' is neither.}} RefPtr safeRefCounted = mRefCounted; RefPtr& maybeUnsafeMemberRef1 = mRefCounted ? mRefCounted : safeRefCounted; maybeUnsafeMemberRef1->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1{{(->)?}}' is neither.}} RefPtr& maybeUnsafeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; maybeUnsafeMemberRef2->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2{{(->)?}}' is neither.}} } MOZ_CAN_RUN_SCRIPT void bar() { test2(mRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted' is neither.}} RefPtr& unsafeMemberRef = mRefCounted; test2(unsafeMemberRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef' is neither.}} RefPtr safeRefCounted = mRefCounted; RefPtr& maybeUnsafeMemberRef1 = mRefCounted ? mRefCounted : safeRefCounted; test2(maybeUnsafeMemberRef1); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1' is neither.}} RefPtr& maybeUnsafeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; test2(maybeUnsafeMemberRef2); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2' is neither.}} } }; struct DisallowMemberArgsWithGet { RefPtr mRefCounted; MOZ_CAN_RUN_SCRIPT void foo() { mRefCounted.get()->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted.get()' is neither.}} } MOZ_CAN_RUN_SCRIPT void bar() { test2(mRefCounted.get()); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted.get()' is neither.}} } }; struct AllowKnownLiveMemberArgs { RefPtr mRefCounted; MOZ_CAN_RUN_SCRIPT void foo() { MOZ_KnownLive(mRefCounted)->method_test(); RefPtr& unsafeMemberRef = mRefCounted; MOZ_KnownLive(unsafeMemberRef)->method_test(); } MOZ_CAN_RUN_SCRIPT void bar() { test2(MOZ_KnownLive(mRefCounted)); RefPtr& unsafeMemberRef = mRefCounted; test2(MOZ_KnownLive(unsafeMemberRef)); } }; struct WeakPtrReturner : public RefCountedBase { RefCountedBase* getWeakPtr() { return new RefCountedBase(); } }; struct DisallowMemberCallsOnRandomKnownLive { RefPtr mWeakPtrReturner1; WeakPtrReturner* mWeakPtrReturner2; MOZ_CAN_RUN_SCRIPT void test_refptr_method() { MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_refptr_function() { test2(MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner1)->getWeakPtr()' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_raw_method() { MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_raw_function() { test2(MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'MOZ_KnownLive(mWeakPtrReturner2)->getWeakPtr()' is neither.}} } }; struct AllowConstMemberArgs { const RefPtr mRefCounted; MOZ_CAN_RUN_SCRIPT void foo() { mRefCounted->method_test(); const RefPtr& safeMemberRef1 = mRefCounted; safeMemberRef1->method_test(); const RefPtr safeRefCounted = new RefCountedBase; const RefPtr& safeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; safeMemberRef2->method_test(); const RefPtr& safeMemberRef3 = mRefCounted ? mRefCounted : safeRefCounted; safeMemberRef3->method_test(); } MOZ_CAN_RUN_SCRIPT void bar() { test2(mRefCounted); const RefPtr& safeMemberRef1 = mRefCounted; test2(safeMemberRef1); const RefPtr safeRefCounted = new RefCountedBase; const RefPtr& safeMemberRef2 = safeRefCounted ? safeRefCounted : mRefCounted; test2(safeMemberRef2); const RefPtr& safeMemberRef3 = mRefCounted ? mRefCounted : safeRefCounted; test2(safeMemberRef3); } }; struct AllowConstMemberArgsWithExplicitThis { const RefPtr mRefCounted; MOZ_CAN_RUN_SCRIPT void foo() { this->mRefCounted->method_test(); const RefPtr& safeMemberRef1 = this->mRefCounted; safeMemberRef1->method_test(); const RefPtr safeRefCounted = new RefCountedBase; const RefPtr& safeMemberRef2 = safeRefCounted ? safeRefCounted : this->mRefCounted; safeMemberRef2->method_test(); const RefPtr& safeMemberRef3 = this->mRefCounted ? this->mRefCounted : safeRefCounted; safeMemberRef3->method_test(); } MOZ_CAN_RUN_SCRIPT void bar() { test2(this->mRefCounted); const RefPtr& safeMemberRef1 = this->mRefCounted; test2(safeMemberRef1); const RefPtr safeRefCounted = new RefCountedBase; const RefPtr& safeMemberRef2 = safeRefCounted ? safeRefCounted : this->mRefCounted; test2(safeMemberRef2); const RefPtr& safeMemberRef3 = this->mRefCounted ? this->mRefCounted : safeRefCounted; test2(safeMemberRef3); } }; struct DisallowConstMemberArgsOfMembers { RefPtr mMember; MOZ_CAN_RUN_SCRIPT void foo() { mMember->mRefCounted->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mRefCounted{{(->)?}}' is neither.}} const RefPtr& unsafeMemberRef = mMember->mRefCounted; unsafeMemberRef->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef{{(->)?}}' is neither.}} const RefPtr safeRefCounted = new RefCountedBase; const RefPtr& maybeUnsafeMemberRef1 = safeRefCounted ? safeRefCounted : mMember->mRefCounted; maybeUnsafeMemberRef1->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1{{(->)?}}' is neither.}} const RefPtr& maybeUnsafeMemberRef2 = mMember->mRefCounted ? mMember->mRefCounted : safeRefCounted; maybeUnsafeMemberRef2->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2{{(->)?}}' is neither.}} } MOZ_CAN_RUN_SCRIPT void bar() { test2(mMember->mRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mRefCounted' is neither.}} const RefPtr& unsafeMemberRef = mMember->mRefCounted; test2(unsafeMemberRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRef' is neither.}} const RefPtr safeRefCounted = new RefCountedBase; const RefPtr& maybeUnsafeMemberRef1 = safeRefCounted ? safeRefCounted : mMember->mRefCounted; test2(maybeUnsafeMemberRef1); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef1' is neither.}} const RefPtr& maybeUnsafeMemberRef2 = mMember->mRefCounted ? mMember->mRefCounted : safeRefCounted; test2(maybeUnsafeMemberRef2); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'maybeUnsafeMemberRef2' is neither.}} } }; struct DisallowConstNonRefPtrMemberArgs { RefCountedBase* const mRefCounted; MOZ_CAN_RUN_SCRIPT void foo() { mRefCounted->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted' is neither.}} RefCountedBase* const& unsafeMemberRefCounted = mRefCounted; unsafeMemberRefCounted->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRefCounted' is neither.}} } MOZ_CAN_RUN_SCRIPT void bar() { test2(mRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mRefCounted' is neither.}} RefCountedBase* const& unsafeMemberRefCounted = mRefCounted; test2(unsafeMemberRefCounted); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'unsafeMemberRefCounted' is neither.}} } }; MOZ_CAN_RUN_SCRIPT void test_temporary_1() { #ifdef MOZ_CLANG_PLUGIN_ALPHA RefPtr(new RefCountedBase())->method_test(); // expected-warning {{performance issue: temporary 'RefPtr' is only dereferenced here once which involves short-lived AddRef/Release calls}} #else RefPtr(new RefCountedBase())->method_test(); #endif } MOZ_CAN_RUN_SCRIPT void test_temporary_2() { test_ref(*RefPtr(new RefCountedBase())); } struct WeakSmartPtr { RefCountedBase* member; explicit WeakSmartPtr(RefCountedBase* arg) : member(arg) {} RefCountedBase* operator->() const { return member; } RefCountedBase& operator*() const { return *member; } operator RefCountedBase*() const { return member; } }; MOZ_CAN_RUN_SCRIPT void test_temporary_3() { WeakSmartPtr(new RefCountedBase())->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'WeakSmartPtr(new RefCountedBase()){{(->)?}}' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_temporary_4() { test_ref(*WeakSmartPtr(new RefCountedBase())); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*WeakSmartPtr(new RefCountedBase())' is neither.}} } MOZ_CAN_RUN_SCRIPT void test_temporary_5() { test2(WeakSmartPtr(new RefCountedBase())); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'WeakSmartPtr(new RefCountedBase())' is neither.}} } template struct TArray { TArray() { mArray[0] = new RefCountedBase(); } T& operator[](unsigned int index) { return mArray[index]; } T mArray[1]; }; struct DisallowRawTArrayElement { TArray mArray; MOZ_CAN_RUN_SCRIPT void foo() { mArray[0]->method_test(); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]' is neither.}} } MOZ_CAN_RUN_SCRIPT void bar() { test2(mArray[0]); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]' is neither.}} } }; struct DisallowRefPtrTArrayElement { TArray> mArray; MOZ_CAN_RUN_SCRIPT void foo() { mArray[0]->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]{{(->)?}}' is neither.}} } MOZ_CAN_RUN_SCRIPT void bar() { test2(mArray[0]); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mArray[0]' is neither.}} } }; struct AllowConstexprMembers { static constexpr RefCountedBase* mRefCounted = nullptr; static constexpr RefCountedBase* mRefCounted2 = nullptr; MOZ_CAN_RUN_SCRIPT void foo() { mRefCounted->method_test(); } MOZ_CAN_RUN_SCRIPT void bar() { test2(mRefCounted); } MOZ_CAN_RUN_SCRIPT void baz() { test_ref(*mRefCounted); } }; MOZ_CAN_RUN_SCRIPT void test_constexpr_1() { AllowConstexprMembers::mRefCounted->method_test(); } MOZ_CAN_RUN_SCRIPT void test_constexpr_2() { test2(AllowConstexprMembers::mRefCounted); } MOZ_CAN_RUN_SCRIPT void test_constexpr_3() { test_ref(*AllowConstexprMembers::mRefCounted); } MOZ_CAN_RUN_SCRIPT void test_ternary_1(RefCountedBase* arg1, RefCountedBase* arg2) { (arg1 ? arg1 : arg2)->method_test(); RefCountedBase*& safeArg = arg1 ? arg1 : arg2; safeArg->method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_2(RefCountedBase* arg1, RefCountedBase* arg2) { test2(arg1 ? arg1 : arg2); RefCountedBase*& safeArg = arg1 ? arg1 : arg2; test2(safeArg); } MOZ_CAN_RUN_SCRIPT void test_ternary_3(RefCountedBase* arg1, RefCountedBase& arg2) { (arg1 ? *arg1 : arg2).method_test(); RefCountedBase& safeArg = arg1 ? *arg1 : arg2; safeArg.method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_4(RefCountedBase* arg1, RefCountedBase& arg2) { test_ref(arg1 ? *arg1 : arg2); RefCountedBase& safeArg = arg1 ? *arg1 : arg2; test_ref(safeArg); } MOZ_CAN_RUN_SCRIPT void test_ternary_5(RefCountedBase* arg) { RefPtr local = new RefCountedBase(); (arg ? arg : local.get())->method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_6(RefCountedBase* arg) { RefPtr local = new RefCountedBase(); test2(arg ? arg : local.get()); } MOZ_CAN_RUN_SCRIPT void test_ternary_7(RefCountedBase* arg) { RefPtr local = new RefCountedBase(); (arg ? *arg : *local).method_test(); RefCountedBase& safeArgOrLocal = arg ? *arg : *local; safeArgOrLocal.method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_8(RefCountedBase* arg) { RefPtr local = new RefCountedBase(); test_ref(arg ? *arg : *local); RefCountedBase& safeArgOrLocal = arg ? *arg : *local; test_ref(safeArgOrLocal); } MOZ_CAN_RUN_SCRIPT void test_ternary_9(RefCountedBase* arg) { (arg ? arg : AllowConstexprMembers::mRefCounted)->method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_10(RefCountedBase* arg) { test2(arg ? arg : AllowConstexprMembers::mRefCounted); } MOZ_CAN_RUN_SCRIPT void test_ternary_11(RefCountedBase* arg) { (arg ? *arg : *AllowConstexprMembers::mRefCounted).method_test(); RefCountedBase& safeArgOrMember = arg ? *arg : *AllowConstexprMembers::mRefCounted; safeArgOrMember.method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_12(RefCountedBase* arg) { test_ref(arg ? *arg : *AllowConstexprMembers::mRefCounted); RefCountedBase& safeArgOrMember = arg ? *arg : *AllowConstexprMembers::mRefCounted; test_ref(safeArgOrMember); } MOZ_CAN_RUN_SCRIPT void test_ternary_13(RefCountedBase* arg1, RefCountedBase& arg2) { (arg1 ? arg1 : &arg2)->method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_44(RefCountedBase* arg1, RefCountedBase& arg2) { test2(arg1 ? arg1 : &arg2); } MOZ_CAN_RUN_SCRIPT void test_ternary_13(bool arg) { (arg ? AllowConstexprMembers::mRefCounted : AllowConstexprMembers::mRefCounted2)->method_test(); RefCountedBase* const& safeConstexprMember = arg ? AllowConstexprMembers::mRefCounted : AllowConstexprMembers::mRefCounted2; safeConstexprMember->method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_14(bool arg) { test2(arg ? AllowConstexprMembers::mRefCounted : AllowConstexprMembers::mRefCounted2); RefCountedBase* const& safeConstexprMember = arg ? AllowConstexprMembers::mRefCounted : AllowConstexprMembers::mRefCounted2; test2(safeConstexprMember); } MOZ_CAN_RUN_SCRIPT void test_ternary_15(bool arg) { (arg ? *AllowConstexprMembers::mRefCounted : *AllowConstexprMembers::mRefCounted2).method_test(); RefCountedBase& safeConstexprMember = arg ? *AllowConstexprMembers::mRefCounted : *AllowConstexprMembers::mRefCounted2; safeConstexprMember.method_test(); } MOZ_CAN_RUN_SCRIPT void test_ternary_16(bool arg) { test_ref(arg ? *AllowConstexprMembers::mRefCounted : *AllowConstexprMembers::mRefCounted2); RefCountedBase& safeConstexprMember = arg ? *AllowConstexprMembers::mRefCounted : *AllowConstexprMembers::mRefCounted2; test_ref(safeConstexprMember); } MOZ_CAN_RUN_SCRIPT void test_pointer_to_ref_1(RefCountedBase& arg) { (&arg)->method_test(); } MOZ_CAN_RUN_SCRIPT void test_pointer_to_ref_2(RefCountedBase& arg) { test2(&arg); } struct DisallowMemberArgsViaReferenceAlias { RefPtr mRefCounted; MOZ_CAN_RUN_SCRIPT void foo() { RefPtr& bogus = mRefCounted; bogus->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'bogus{{(->)?}}' is neither.}} } MOZ_CAN_RUN_SCRIPT void bar() { RefPtr& bogus = mRefCounted; test2(bogus); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'bogus' is neither.}} } }; struct DisallowMemberArgsViaReferenceAlias2 { RefPtr mRefCountedArr[2]; MOZ_CAN_RUN_SCRIPT void foo1() { for (RefPtr& item : mRefCountedArr) { item->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item{{(->)?}}' is neither.}} } } MOZ_CAN_RUN_SCRIPT void foo2() { for (auto& item : mRefCountedArr) { item->method_test(); // expected-error-re {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item{{(->)?}}' is neither.}} } } MOZ_CAN_RUN_SCRIPT void foo3() { for (RefPtr item : mRefCountedArr) { item->method_test(); } } MOZ_CAN_RUN_SCRIPT void foo4() { for (auto item : mRefCountedArr) { item->method_test(); } } MOZ_CAN_RUN_SCRIPT void bar1() { for (RefPtr& item : mRefCountedArr) { test2(item); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item' is neither.}} } } MOZ_CAN_RUN_SCRIPT void bar2() { for (auto& item : mRefCountedArr) { test2(item); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'item' is neither.}} } } MOZ_CAN_RUN_SCRIPT void bar3() { for (RefPtr item : mRefCountedArr) { test2(item); } } MOZ_CAN_RUN_SCRIPT void bar4() { for (auto item : mRefCountedArr) { test2(item); } } }; struct AllowMozKnownLiveMember { public: MOZ_KNOWN_LIVE RefCountedBase* mWhatever; MOZ_KNOWN_LIVE RefPtr mRefCountedWhatever; MOZ_CAN_RUN_SCRIPT void fooPtr(RefCountedBase* aWhatever) {} MOZ_CAN_RUN_SCRIPT void fooRef(RefCountedBase& aWhatever) {} MOZ_CAN_RUN_SCRIPT void bar() { fooPtr(mWhatever); fooRef(*mWhatever); fooPtr(mRefCountedWhatever); fooRef(*mRefCountedWhatever); RefCountedBase*& whateverRef = mWhatever; fooPtr(whateverRef); fooRef(*whateverRef); RefPtr& refCountedWhateverRef = mRefCountedWhatever; fooPtr(refCountedWhateverRef); fooRef(*refCountedWhateverRef); } }; struct AllowMozKnownLiveMemberParent : AllowMozKnownLiveMember { MOZ_CAN_RUN_SCRIPT void baz() { fooPtr(mWhatever); fooRef(*mWhatever); fooPtr(mRefCountedWhatever); fooRef(*mRefCountedWhatever); RefCountedBase*& whateverRef = mWhatever; fooPtr(whateverRef); fooRef(*whateverRef); RefPtr& refCountedWhateverRef = mRefCountedWhatever; fooPtr(refCountedWhateverRef); fooRef(*refCountedWhateverRef); } }; struct AllowMozKnownLiveParamMember { public: MOZ_CAN_RUN_SCRIPT void foo(AllowMozKnownLiveMember& aAllow) { aAllow.fooPtr(aAllow.mWhatever); aAllow.fooRef(*aAllow.mWhatever); aAllow.fooPtr(aAllow.mRefCountedWhatever); aAllow.fooRef(*aAllow.mRefCountedWhatever); RefCountedBase*& whateverRef = aAllow.mWhatever; aAllow.fooPtr(whateverRef); aAllow.fooRef(*whateverRef); RefPtr& refCountedWhateverRef = aAllow.mRefCountedWhatever; aAllow.fooPtr(refCountedWhateverRef); aAllow.fooRef(*refCountedWhateverRef); } MOZ_CAN_RUN_SCRIPT void bar(AllowMozKnownLiveMemberParent& aAllowParent) { aAllowParent.fooPtr(aAllowParent.mWhatever); aAllowParent.fooRef(*aAllowParent.mWhatever); aAllowParent.fooPtr(aAllowParent.mRefCountedWhatever); aAllowParent.fooRef(*aAllowParent.mRefCountedWhatever); RefCountedBase*& whateverRef = aAllowParent.mWhatever; aAllowParent.fooPtr(whateverRef); aAllowParent.fooRef(*whateverRef); RefPtr& refCountedWhateverRef = aAllowParent.mRefCountedWhatever; aAllowParent.fooPtr(refCountedWhateverRef); aAllowParent.fooRef(*refCountedWhateverRef); } }; MOZ_CAN_RUN_SCRIPT void AllowMozKnownLiveMemberInAutoStorage() { AllowMozKnownLiveMember inStack; AllowMozKnownLiveMember* inHeap = new AllowMozKnownLiveMember(); inStack.fooPtr(inStack.mWhatever); inStack.fooRef(*inStack.mWhatever); inStack.fooPtr(inStack.mRefCountedWhatever); inStack.fooRef(*inStack.mRefCountedWhatever); RefCountedBase*& whateverRefInStack = inStack.mWhatever; inStack.fooPtr(whateverRefInStack); inStack.fooRef(*whateverRefInStack); RefPtr& refCountedWhateverRefInStack = inStack.mRefCountedWhatever; inStack.fooPtr(refCountedWhateverRefInStack); inStack.fooRef(*refCountedWhateverRefInStack); inStack.fooPtr(inHeap->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'inHeap->mWhatever' is neither.}} inStack.fooRef(*inHeap->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*inHeap->mWhatever' is neither.}} inStack.fooPtr(inHeap->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'inHeap->mRefCountedWhatever' is neither.}} inStack.fooRef(*inHeap->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*inHeap->mRefCountedWhatever' is neither.}} RefCountedBase*& whateverRefInHeap = inHeap->mWhatever; inStack.fooPtr(whateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'whateverRefInHeap' is neither.}} inStack.fooRef(*whateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*whateverRefInHeap' is neither.}} RefPtr& refCountedWhateverRefInHeap = inHeap->mRefCountedWhatever; inStack.fooPtr(refCountedWhateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refCountedWhateverRefInHeap' is neither.}} inStack.fooRef(*refCountedWhateverRefInHeap); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*refCountedWhateverRefInHeap' is neither.}} } struct DisallowMozKnownLiveMemberNotFromKnownLive { AllowMozKnownLiveMember* mMember; MOZ_CAN_RUN_SCRIPT void fooPtr(RefCountedBase* aWhatever) {} MOZ_CAN_RUN_SCRIPT void fooRef(RefCountedBase& aWhatever) {} MOZ_CAN_RUN_SCRIPT void bar() { fooPtr(mMember->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mWhatever' is neither.}} fooRef(*mMember->mWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*mMember->mWhatever' is neither.}} fooPtr(mMember->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'mMember->mRefCountedWhatever' is neither.}} fooRef(*mMember->mRefCountedWhatever); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*mMember->mRefCountedWhatever' is neither.}} RefCountedBase*& whateverRef = mMember->mWhatever; fooPtr(whateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'whateverRef' is neither.}} fooRef(*whateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*whateverRef' is neither.}} RefPtr& refCountedWhateverRef = mMember->mRefCountedWhatever; fooPtr(refCountedWhateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). 'refCountedWhateverRef' is neither.}} fooRef(*refCountedWhateverRef); // expected-error {{arguments must all be strong refs or caller's parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument). '*refCountedWhateverRef' is neither.}} } }; void IncorrectlyUnmarkedEarlyDeclaration(); // expected-note {{The first declaration exists here}} MOZ_CAN_RUN_SCRIPT void IncorrectlyUnmarkedEarlyDeclaration() {}; // expected-error {{MOZ_CAN_RUN_SCRIPT must be put in front of the declaration, not the definition}}