tor-browser

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

TestNoRefcountedInsideLambdas.cpp (17292B)


      1 #include <mozilla/StaticAnalysisFunctions.h>
      2 
      3 #include <functional>
      4 #define MOZ_STRONG_REF
      5 #define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
      6 
      7 // Ensure that warnings about returning stack addresses of local variables are
      8 // errors, so our `expected-error` annotations below work correctly.
      9 #pragma GCC diagnostic error "-Wreturn-stack-address"
     10 
     11 struct RefCountedBase {
     12  void AddRef();
     13  void Release();
     14 };
     15 
     16 template <class T>
     17 struct SmartPtr {
     18  SmartPtr();
     19  MOZ_IMPLICIT SmartPtr(T*);
     20  T* MOZ_STRONG_REF t;
     21  T* operator->() const;
     22 };
     23 
     24 struct R : RefCountedBase {
     25  void method();
     26 private:
     27  void privateMethod();
     28 };
     29 
     30 void take(...);
     31 void foo() {
     32  R* ptr;
     33  SmartPtr<R> sp;
     34  take([&](R* argptr) {
     35    R* localptr;
     36    ptr->method();
     37    argptr->method();
     38    localptr->method();
     39  });
     40  take([&](SmartPtr<R> argsp) {
     41    SmartPtr<R> localsp;
     42    sp->method();
     43    argsp->method();
     44    localsp->method();
     45  });
     46  take([&](R* argptr) {
     47    R* localptr;
     48    take(ptr);
     49    take(argptr);
     50    take(localptr);
     51  });
     52  take([&](SmartPtr<R> argsp) {
     53    SmartPtr<R> localsp;
     54    take(sp);
     55    take(argsp);
     56    take(localsp);
     57  });
     58  take([=](R* argptr) {
     59    R* localptr;
     60    ptr->method();
     61    argptr->method();
     62    localptr->method();
     63  });
     64  take([=](SmartPtr<R> argsp) {
     65    SmartPtr<R> localsp;
     66    sp->method();
     67    argsp->method();
     68    localsp->method();
     69  });
     70  take([=](R* argptr) {
     71    R* localptr;
     72    take(ptr);
     73    take(argptr);
     74    take(localptr);
     75  });
     76  take([=](SmartPtr<R> argsp) {
     77    SmartPtr<R> localsp;
     78    take(sp);
     79    take(argsp);
     80    take(localsp);
     81  });
     82  take([ptr](R* argptr) {
     83    R* localptr;
     84    ptr->method();
     85    argptr->method();
     86    localptr->method();
     87  });
     88  take([sp](SmartPtr<R> argsp) {
     89    SmartPtr<R> localsp;
     90    sp->method();
     91    argsp->method();
     92    localsp->method();
     93  });
     94  take([ptr](R* argptr) {
     95    R* localptr;
     96    take(ptr);
     97    take(argptr);
     98    take(localptr);
     99  });
    100  take([sp](SmartPtr<R> argsp) {
    101    SmartPtr<R> localsp;
    102    take(sp);
    103    take(argsp);
    104    take(localsp);
    105  });
    106  take([&ptr](R* argptr) {
    107    R* localptr;
    108    ptr->method();
    109    argptr->method();
    110    localptr->method();
    111  });
    112  take([&sp](SmartPtr<R> argsp) {
    113    SmartPtr<R> localsp;
    114    sp->method();
    115    argsp->method();
    116    localsp->method();
    117  });
    118  take([&ptr](R* argptr) {
    119    R* localptr;
    120    take(ptr);
    121    take(argptr);
    122    take(localptr);
    123  });
    124  take([&sp](SmartPtr<R> argsp) {
    125    SmartPtr<R> localsp;
    126    take(sp);
    127    take(argsp);
    128    take(localsp);
    129  });
    130 }
    131 
    132 void b() {
    133  R* ptr;
    134  SmartPtr<R> sp;
    135  std::function<void(R*)>([&](R* argptr) {
    136    R* localptr;
    137    ptr->method();
    138    argptr->method();
    139    localptr->method();
    140  });
    141  std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
    142    SmartPtr<R> localsp;
    143    sp->method();
    144    argsp->method();
    145    localsp->method();
    146  });
    147  std::function<void(R*)>([&](R* argptr) {
    148    R* localptr;
    149    take(ptr);
    150    take(argptr);
    151    take(localptr);
    152  });
    153  std::function<void(SmartPtr<R>)>([&](SmartPtr<R> argsp) {
    154    SmartPtr<R> localsp;
    155    take(sp);
    156    take(argsp);
    157    take(localsp);
    158  });
    159  std::function<void(R*)>([=](R* argptr) {
    160    R* localptr;
    161    ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    162    argptr->method();
    163    localptr->method();
    164  });
    165  std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
    166    SmartPtr<R> localsp;
    167    sp->method();
    168    argsp->method();
    169    localsp->method();
    170  });
    171  std::function<void(R*)>([=](R* argptr) {
    172    R* localptr;
    173    take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    174    take(argptr);
    175    take(localptr);
    176  });
    177  std::function<void(SmartPtr<R>)>([=](SmartPtr<R> argsp) {
    178    SmartPtr<R> localsp;
    179    take(sp);
    180    take(argsp);
    181    take(localsp);
    182  });
    183  std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    184    R* localptr;
    185    ptr->method();
    186    argptr->method();
    187    localptr->method();
    188  });
    189  std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
    190    SmartPtr<R> localsp;
    191    sp->method();
    192    argsp->method();
    193    localsp->method();
    194  });
    195  std::function<void(R*)>([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    196    R* localptr;
    197    take(ptr);
    198    take(argptr);
    199    take(localptr);
    200  });
    201  std::function<void(SmartPtr<R>)>([sp](SmartPtr<R> argsp) {
    202    SmartPtr<R> localsp;
    203    take(sp);
    204    take(argsp);
    205    take(localsp);
    206  });
    207  std::function<void(R*)>([&ptr](R* argptr) {
    208    R* localptr;
    209    ptr->method();
    210    argptr->method();
    211    localptr->method();
    212  });
    213  std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
    214    SmartPtr<R> localsp;
    215    sp->method();
    216    argsp->method();
    217    localsp->method();
    218  });
    219  std::function<void(R*)>([&ptr](R* argptr) {
    220    R* localptr;
    221    take(ptr);
    222    take(argptr);
    223    take(localptr);
    224  });
    225  std::function<void(SmartPtr<R>)>([&sp](SmartPtr<R> argsp) {
    226    SmartPtr<R> localsp;
    227    take(sp);
    228    take(argsp);
    229    take(localsp);
    230  });
    231 }
    232 
    233 // These tests would check c++14 deduced return types, if they were supported in
    234 // our codebase. They are being kept here for convenience in the future if we do
    235 // add support for c++14 deduced return types
    236 #if 0
    237 auto d1() {
    238  R* ptr;
    239  SmartPtr<R> sp;
    240  return ([&](R* argptr) {
    241    R* localptr;
    242    ptr->method();
    243    argptr->method();
    244    localptr->method();
    245  });
    246 }
    247 auto d2() {
    248  R* ptr;
    249  SmartPtr<R> sp;
    250  return ([&](SmartPtr<R> argsp) {
    251    SmartPtr<R> localsp;
    252    sp->method();
    253    argsp->method();
    254    localsp->method();
    255  });
    256 }
    257 auto d3() {
    258  R* ptr;
    259  SmartPtr<R> sp;
    260  return ([&](R* argptr) {
    261    R* localptr;
    262    take(ptr);
    263    take(argptr);
    264    take(localptr);
    265  });
    266 }
    267 auto d4() {
    268  R* ptr;
    269  SmartPtr<R> sp;
    270  return ([&](SmartPtr<R> argsp) {
    271    SmartPtr<R> localsp;
    272    take(sp);
    273    take(argsp);
    274    take(localsp);
    275  });
    276 }
    277 auto d5() {
    278  R* ptr;
    279  SmartPtr<R> sp;
    280  return ([=](R* argptr) {
    281    R* localptr;
    282    ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    283    argptr->method();
    284    localptr->method();
    285  });
    286 }
    287 auto d6() {
    288  R* ptr;
    289  SmartPtr<R> sp;
    290  return ([=](SmartPtr<R> argsp) {
    291    SmartPtr<R> localsp;
    292    sp->method();
    293    argsp->method();
    294    localsp->method();
    295  });
    296 }
    297 auto d8() {
    298  R* ptr;
    299  SmartPtr<R> sp;
    300  return ([=](R* argptr) {
    301    R* localptr;
    302    take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    303    take(argptr);
    304    take(localptr);
    305  });
    306 }
    307 auto d9() {
    308  R* ptr;
    309  SmartPtr<R> sp;
    310  return ([=](SmartPtr<R> argsp) {
    311    SmartPtr<R> localsp;
    312    take(sp);
    313    take(argsp);
    314    take(localsp);
    315  });
    316 }
    317 auto d10() {
    318  R* ptr;
    319  SmartPtr<R> sp;
    320  return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    321    R* localptr;
    322    ptr->method();
    323    argptr->method();
    324    localptr->method();
    325  });
    326 }
    327 auto d11() {
    328  R* ptr;
    329  SmartPtr<R> sp;
    330  return ([sp](SmartPtr<R> argsp) {
    331    SmartPtr<R> localsp;
    332    sp->method();
    333    argsp->method();
    334    localsp->method();
    335  });
    336 }
    337 auto d12() {
    338  R* ptr;
    339  SmartPtr<R> sp;
    340  return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    341    R* localptr;
    342    take(ptr);
    343    take(argptr);
    344    take(localptr);
    345  });
    346 }
    347 auto d13() {
    348  R* ptr;
    349  SmartPtr<R> sp;
    350  return ([sp](SmartPtr<R> argsp) {
    351    SmartPtr<R> localsp;
    352    take(sp);
    353    take(argsp);
    354    take(localsp);
    355  });
    356 }
    357 auto d14() {
    358  R* ptr;
    359  SmartPtr<R> sp;
    360  return ([&ptr](R* argptr) {
    361    R* localptr;
    362    ptr->method();
    363    argptr->method();
    364    localptr->method();
    365  });
    366 }
    367 auto d15() {
    368  R* ptr;
    369  SmartPtr<R> sp;
    370  return ([&sp](SmartPtr<R> argsp) {
    371    SmartPtr<R> localsp;
    372    sp->method();
    373    argsp->method();
    374    localsp->method();
    375  });
    376 }
    377 auto d16() {
    378  R* ptr;
    379  SmartPtr<R> sp;
    380  return ([&ptr](R* argptr) {
    381    R* localptr;
    382    take(ptr);
    383    take(argptr);
    384    take(localptr);
    385  });
    386 }
    387 auto d17() {
    388  R* ptr;
    389  SmartPtr<R> sp;
    390  return ([&sp](SmartPtr<R> argsp) {
    391    SmartPtr<R> localsp;
    392    take(sp);
    393    take(argsp);
    394    take(localsp);
    395  });
    396 }
    397 #endif
    398 
    399 void e() {
    400  auto e1 = []() {
    401    R* ptr;
    402    SmartPtr<R> sp;
    403    return ([&](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
    404      R* localptr;
    405 #if __clang_major__ >= 12
    406      ptr->method(); // expected-note{{implicitly captured by reference due to use here}}
    407 #else
    408      ptr->method();
    409 #endif
    410      argptr->method();
    411      localptr->method();
    412    });
    413  };
    414  auto e2 = []() {
    415    R* ptr;
    416    SmartPtr<R> sp;
    417    return ([&](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
    418      SmartPtr<R> localsp;
    419 #if __clang_major__ >= 12
    420      sp->method(); // expected-note{{implicitly captured by reference due to use here}}
    421 #else
    422      sp->method();
    423 #endif
    424      argsp->method();
    425      localsp->method();
    426    });
    427  };
    428  auto e3 = []() {
    429    R* ptr;
    430    SmartPtr<R> sp;
    431    return ([&](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
    432      R* localptr;
    433 #if __clang_major__ >= 12
    434      take(ptr); // expected-note{{implicitly captured by reference due to use here}}
    435 #else
    436      take(ptr);
    437 #endif
    438      take(argptr);
    439      take(localptr);
    440    });
    441  };
    442  auto e4 = []() {
    443    R* ptr;
    444    SmartPtr<R> sp;
    445    return ([&](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
    446      SmartPtr<R> localsp;
    447 #if __clang_major__ >= 12
    448      take(sp); // expected-note{{implicitly captured by reference due to use here}}
    449 #else
    450      take(sp);
    451 #endif
    452      take(argsp);
    453      take(localsp);
    454    });
    455  };
    456  auto e5 = []() {
    457    R* ptr;
    458    SmartPtr<R> sp;
    459    return ([=](R* argptr) {
    460      R* localptr;
    461      ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    462      argptr->method();
    463      localptr->method();
    464    });
    465  };
    466  auto e6 = []() {
    467    R* ptr;
    468    SmartPtr<R> sp;
    469    return ([=](SmartPtr<R> argsp) {
    470      SmartPtr<R> localsp;
    471      sp->method();
    472      argsp->method();
    473      localsp->method();
    474    });
    475  };
    476  auto e8 = []() {
    477    R* ptr;
    478    SmartPtr<R> sp;
    479    return ([=](R* argptr) {
    480      R* localptr;
    481      take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    482      take(argptr);
    483      take(localptr);
    484    });
    485  };
    486  auto e9 = []() {
    487    R* ptr;
    488    SmartPtr<R> sp;
    489    return ([=](SmartPtr<R> argsp) {
    490      SmartPtr<R> localsp;
    491      take(sp);
    492      take(argsp);
    493      take(localsp);
    494    });
    495  };
    496  auto e10 = []() {
    497    R* ptr;
    498    SmartPtr<R> sp;
    499    return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    500      R* localptr;
    501      ptr->method();
    502      argptr->method();
    503      localptr->method();
    504    });
    505  };
    506  auto e11 = []() {
    507    R* ptr;
    508    SmartPtr<R> sp;
    509    return ([sp](SmartPtr<R> argsp) {
    510      SmartPtr<R> localsp;
    511      sp->method();
    512      argsp->method();
    513      localsp->method();
    514    });
    515  };
    516  auto e12 = []() {
    517    R* ptr;
    518    SmartPtr<R> sp;
    519    return ([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    520      R* localptr;
    521      take(ptr);
    522      take(argptr);
    523      take(localptr);
    524    });
    525  };
    526  auto e13 = []() {
    527    R* ptr;
    528    SmartPtr<R> sp;
    529    return ([sp](SmartPtr<R> argsp) {
    530      SmartPtr<R> localsp;
    531      take(sp);
    532      take(argsp);
    533      take(localsp);
    534    });
    535  };
    536  auto e14 = []() {
    537    R* ptr;
    538    SmartPtr<R> sp;
    539 #if __clang_major__ >= 12
    540    return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} expected-note{{captured by reference here}}
    541      R* localptr;
    542      ptr->method();
    543      argptr->method();
    544      localptr->method();
    545    });
    546 #else
    547    return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
    548      R* localptr;
    549      ptr->method();
    550      argptr->method();
    551      localptr->method();
    552    });
    553 #endif
    554  };
    555  auto e15 = []() {
    556    R* ptr;
    557    SmartPtr<R> sp;
    558 #if __clang_major__ >= 12
    559    return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} expected-note{{captured by reference here}}
    560      SmartPtr<R> localsp;
    561      sp->method();
    562      argsp->method();
    563      localsp->method();
    564    });
    565 #else
    566    return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
    567      SmartPtr<R> localsp;
    568      sp->method();
    569      argsp->method();
    570      localsp->method();
    571    });
    572 #endif
    573  };
    574  auto e16 = []() {
    575    R* ptr;
    576    SmartPtr<R> sp;
    577 #if __clang_major__ >= 12
    578    return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}} expected-note{{captured by reference here}}
    579      R* localptr;
    580      take(ptr);
    581      take(argptr);
    582      take(localptr);
    583    });
    584 #else
    585    return ([&ptr](R* argptr) { // expected-error{{address of stack memory associated with local variable 'ptr' returned}}
    586      R* localptr;
    587      take(ptr);
    588      take(argptr);
    589      take(localptr);
    590    });
    591 #endif
    592  };
    593  auto e17 = []() {
    594    R* ptr;
    595    SmartPtr<R> sp;
    596 #if __clang_major__ >= 12
    597    return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}} expected-note{{captured by reference here}}
    598      SmartPtr<R> localsp;
    599      take(sp);
    600      take(argsp);
    601      take(localsp);
    602    });
    603 #else
    604    return ([&sp](SmartPtr<R> argsp) { // expected-error{{address of stack memory associated with local variable 'sp' returned}}
    605      SmartPtr<R> localsp;
    606      take(sp);
    607      take(argsp);
    608      take(localsp);
    609    });
    610 #endif
    611  };
    612 }
    613 
    614 void
    615 R::privateMethod() {
    616  SmartPtr<R> self = this;
    617  std::function<void()>([&]() {
    618    self->method();
    619  });
    620  std::function<void()>([&]() {
    621    self->privateMethod();
    622  });
    623  std::function<void()>([&]() {
    624    this->method();
    625  });
    626  std::function<void()>([&]() {
    627    this->privateMethod();
    628  });
    629  std::function<void()>([=]() {
    630    self->method();
    631  });
    632  std::function<void()>([=]() {
    633    self->privateMethod();
    634  });
    635  std::function<void()>([=]() {
    636    this->method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    637  });
    638  std::function<void()>([=]() {
    639    this->privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    640  });
    641  std::function<void()>([self]() {
    642    self->method();
    643  });
    644  std::function<void()>([self]() {
    645    self->privateMethod();
    646  });
    647  std::function<void()>([this]() {
    648    this->method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    649  });
    650  std::function<void()>([this]() {
    651    this->privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    652  });
    653  std::function<void()>([this]() {
    654    method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    655  });
    656  std::function<void()>([this]() {
    657    privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    658  });
    659  std::function<void()>([=]() {
    660    method(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    661  });
    662  std::function<void()>([=]() {
    663    privateMethod(); // expected-error{{Refcounted variable 'this' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
    664  });
    665  std::function<void()>([&]() {
    666    method();
    667  });
    668  std::function<void()>([&]() {
    669    privateMethod();
    670  });
    671 
    672  std::function<void()>(
    673      [instance = MOZ_KnownLive(this)]() { instance->privateMethod(); });
    674 
    675  // It should be OK to go through `this` if we have captured a reference to it.
    676  std::function<void()>([this, self]() {
    677    this->method();
    678    this->privateMethod();
    679    method();
    680    privateMethod();
    681  });
    682 }