4 #define MOZ_MUST_RETURN_FROM_CALLER_IF_THIS_IS_ARG __attribute__((annotate("moz_must_return_from_caller_if_this_is_arg")))
5 #define MOZ_MAY_CALL_AFTER_MUST_RETURN __attribute__((annotate("moz_may_call_after_must_return")))
8 void MOZ_MUST_RETURN_FROM_CALLER_IF_THIS_IS_ARG
Throw() {}
11 void DoAnythingElse();
13 int MOZ_MAY_CALL_AFTER_MUST_RETURN
SafeMakeInt();
16 // It might be nicer to #include "mozilla/ScopeExit.h" and use that here -- but
17 // doing so also will #define the two attribute-macros defined above, running a
18 // risk of redefinition errors. Just stick to the normal clang-plugin test
19 // style and use as little external code as possible.
21 template<typename Func
>
24 bool callOnDestruction
;
26 explicit ScopeExit(Func
&& func
)
27 : exitFunction(std::move(func
))
28 , callOnDestruction(true)
32 if (callOnDestruction
) {
37 void release() { callOnDestruction
= false; }
40 template<typename ExitFunction
>
41 ScopeExit
<ExitFunction
>
42 MakeScopeExit(ExitFunction
&& func
)
44 return ScopeExit
<ExitFunction
>(std::move(func
));
49 __attribute__((annotate("moz_implicit"))) Foo(std::nullptr_t
);
53 void a1(Thrower
& thrower
) {
57 int a2(Thrower
& thrower
) {
58 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
62 int a3(Thrower
& thrower
) {
63 // RAII operations happening after a must-immediately-return are fine.
64 auto atExit
= MakeScopeExit([] { DoAnythingElse(); });
69 int a4(Thrower
& thrower
) {
70 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
71 return Condition() ? MakeAnInt() : MakeAnInt();
74 void a5(Thrower
& thrower
) {
75 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
79 int a6(Thrower
& thrower
) {
80 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
85 int a7(Thrower
& thrower
) {
86 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
88 return Condition() ? MakeAnInt() : MakeAnInt();
91 int a8(Thrower
& thrower
) {
96 int a9(Thrower
& thrower
) {
100 return SafeMakeInt();
103 int a10(Thrower
& thrower
) {
104 auto atExit
= MakeScopeExit([] { DoAnythingElse(); });
108 return SafeMakeInt();
116 void b1(Thrower
& thrower
) {
122 int b2(Thrower
& thrower
) {
124 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
129 int b3(Thrower
& thrower
) {
136 // Explicit test in orer to also verify the `UnaryOperator` node in the `CFG`
137 int b3a(Thrower
& thrower
) {
144 float b3b(Thrower
& thrower
) {
151 bool b3c(Thrower
& thrower
) {
158 int b4(Thrower
& thrower
) {
160 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
162 return Condition() ? MakeAnInt() : MakeAnInt();
165 void b5(Thrower
& thrower
) {
167 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
172 void b6(Thrower
& thrower
) {
174 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
179 void b7(Thrower
& thrower
) {
187 void b8(Thrower
& thrower
) {
189 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
196 void b9(Thrower
& thrower
) {
197 while (Condition()) {
198 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
202 void b10(Thrower
& thrower
) {
203 while (Condition()) {
209 void b11(Thrower
& thrower
) {
210 thrower
.Throw(); // expected-error {{You must immediately return after calling this function}}
218 void b12(Thrower
& thrower
) {
219 switch (MakeAnInt()) {
228 void b13(Thrower
& thrower
) {
235 Foo
b14(Thrower
& thrower
) {
243 Foo
b15(Thrower
& thrower
) {
250 Foo
b16(Thrower
& thrower
) {
260 DoAnythingElse(); // Should be allowed, since our thrower is not an arg
264 TestRet
*b13(Thrower
&thrower
) {