tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestMustReturnFromCaller.cpp (5573B)


      1 #include <cstddef>
      2 #include <utility>
      3 
      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")))
      6 
      7 struct Thrower {
      8  void MOZ_MUST_RETURN_FROM_CALLER_IF_THIS_IS_ARG Throw() {}
      9 };
     10 
     11 void DoAnythingElse();
     12 int MakeAnInt();
     13 int MOZ_MAY_CALL_AFTER_MUST_RETURN SafeMakeInt();
     14 bool Condition();
     15 
     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.
     20 
     21 template<typename Func>
     22 class ScopeExit {
     23  Func exitFunction;
     24  bool callOnDestruction;
     25 public:
     26  explicit ScopeExit(Func&& func)
     27    : exitFunction(std::move(func))
     28    , callOnDestruction(true)
     29  {}
     30 
     31  ~ScopeExit() {
     32    if (callOnDestruction) {
     33      exitFunction();
     34    }
     35  }
     36 
     37  void release() { callOnDestruction = false; }
     38 };
     39 
     40 template<typename ExitFunction>
     41 ScopeExit<ExitFunction>
     42 MakeScopeExit(ExitFunction&& func)
     43 {
     44  return ScopeExit<ExitFunction>(std::move(func));
     45 }
     46 
     47 class Foo {
     48 public:
     49  __attribute__((annotate("moz_implicit"))) Foo(std::nullptr_t);
     50  Foo();
     51 };
     52 
     53 void a1(Thrower& thrower) {
     54  thrower.Throw();
     55 }
     56 
     57 int a2(Thrower& thrower) {
     58  thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
     59  return MakeAnInt();
     60 }
     61 
     62 int a3(Thrower& thrower) {
     63  // RAII operations happening after a must-immediately-return are fine.
     64  auto atExit = MakeScopeExit([] { DoAnythingElse(); });
     65  thrower.Throw();
     66  return 5;
     67 }
     68 
     69 int a4(Thrower& thrower) {
     70  thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
     71  return Condition() ? MakeAnInt() : MakeAnInt();
     72 }
     73 
     74 void a5(Thrower& thrower) {
     75  thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
     76  DoAnythingElse();
     77 }
     78 
     79 int a6(Thrower& thrower) {
     80  thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
     81  DoAnythingElse();
     82  return MakeAnInt();
     83 }
     84 
     85 int a7(Thrower& thrower) {
     86  thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
     87  DoAnythingElse();
     88  return Condition() ? MakeAnInt() : MakeAnInt();
     89 }
     90 
     91 int a8(Thrower& thrower) {
     92  thrower.Throw();
     93  return SafeMakeInt();
     94 }
     95 
     96 int a9(Thrower& thrower) {
     97  if (Condition()) {
     98    thrower.Throw();
     99  }
    100  return SafeMakeInt();
    101 }
    102 
    103 int a10(Thrower& thrower) {
    104  auto atExit = MakeScopeExit([] { DoAnythingElse(); });
    105 
    106  if (Condition()) {
    107    thrower.Throw();
    108    return SafeMakeInt();
    109  }
    110 
    111  atExit.release();
    112  DoAnythingElse();
    113  return 5;
    114 }
    115 
    116 void b1(Thrower& thrower) {
    117  if (Condition()) {
    118    thrower.Throw();
    119  }
    120 }
    121 
    122 int b2(Thrower& thrower) {
    123  if (Condition()) {
    124    thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
    125  }
    126  return MakeAnInt();
    127 }
    128 
    129 int b3(Thrower& thrower) {
    130  if (Condition()) {
    131    thrower.Throw();
    132  }
    133  return 5;
    134 }
    135 
    136 // Explicit test in orer to also verify the `UnaryOperator` node in the `CFG`
    137 int b3a(Thrower& thrower) {
    138  if (Condition()) {
    139    thrower.Throw();
    140  }
    141  return -1;
    142 }
    143 
    144 float b3b(Thrower& thrower) {
    145  if (Condition()) {
    146    thrower.Throw();
    147  }
    148  return 1.0f;
    149 }
    150 
    151 bool b3c(Thrower& thrower) {
    152  if (Condition()) {
    153    thrower.Throw();
    154  }
    155  return false;
    156 }
    157 
    158 int b4(Thrower& thrower) {
    159  if (Condition()) {
    160    thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
    161  }
    162  return Condition() ? MakeAnInt() : MakeAnInt();
    163 }
    164 
    165 void b5(Thrower& thrower) {
    166  if (Condition()) {
    167    thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
    168  }
    169  DoAnythingElse();
    170 }
    171 
    172 void b6(Thrower& thrower) {
    173  if (Condition()) {
    174    thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
    175    DoAnythingElse();
    176  }
    177 }
    178 
    179 void b7(Thrower& thrower) {
    180  if (Condition()) {
    181    thrower.Throw();
    182    return;
    183  }
    184  DoAnythingElse();
    185 }
    186 
    187 void b8(Thrower& thrower) {
    188  if (Condition()) {
    189    thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
    190    DoAnythingElse();
    191    return;
    192  }
    193  DoAnythingElse();
    194 }
    195 
    196 void b9(Thrower& thrower) {
    197  while (Condition()) {
    198    thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
    199  }
    200 }
    201 
    202 void b10(Thrower& thrower) {
    203  while (Condition()) {
    204    thrower.Throw();
    205    return;
    206  }
    207 }
    208 
    209 void b11(Thrower& thrower) {
    210  thrower.Throw(); // expected-error {{You must immediately return after calling this function}}
    211  if (Condition()) {
    212    return;
    213  } else {
    214    return;
    215  }
    216 }
    217 
    218 void b12(Thrower& thrower) {
    219  switch (MakeAnInt()) {
    220  case 1:
    221    break;
    222  default:
    223    thrower.Throw();
    224    return;
    225  }
    226 }
    227 
    228 void b13(Thrower& thrower) {
    229  if (Condition()) {
    230    thrower.Throw();
    231  }
    232  return;
    233 }
    234 
    235 Foo b14(Thrower& thrower) {
    236  if (Condition()) {
    237    thrower.Throw();
    238    return nullptr;
    239  }
    240  return nullptr;
    241 }
    242 
    243 Foo b15(Thrower& thrower) {
    244  if (Condition()) {
    245    thrower.Throw();
    246  }
    247  return nullptr;
    248 }
    249 
    250 Foo b16(Thrower& thrower) {
    251  if (Condition()) {
    252    thrower.Throw();
    253  }
    254  return Foo();
    255 }
    256 
    257 void c1() {
    258  Thrower thrower;
    259  thrower.Throw();
    260  DoAnythingElse(); // Should be allowed, since our thrower is not an arg
    261 }
    262 
    263 class TestRet {
    264  TestRet *b13(Thrower &thrower) {
    265    if (Condition()) {
    266      thrower.Throw();
    267    }
    268    return this;
    269  }
    270 };