tor-browser

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

DebugOnly.h (3220B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /*
      8 * Provides DebugOnly, a type for variables used only in debug builds (i.e. by
      9 * assertions).
     10 */
     11 
     12 #ifndef mozilla_DebugOnly_h
     13 #define mozilla_DebugOnly_h
     14 
     15 #include "mozilla/Attributes.h"
     16 
     17 #include <utility>
     18 
     19 namespace mozilla {
     20 
     21 /**
     22 * DebugOnly contains a value of type T, but only in debug builds.  In release
     23 * builds, it does not contain a value.  This helper is intended to be used with
     24 * MOZ_ASSERT()-style macros, allowing one to write:
     25 *
     26 *   DebugOnly<bool> check = func();
     27 *   MOZ_ASSERT(check);
     28 *
     29 * more concisely than declaring |check| conditional on #ifdef DEBUG.
     30 *
     31 * DebugOnly instances can only be coerced to T in debug builds.  In release
     32 * builds they don't have a value, so type coercion is not well defined.
     33 *
     34 * NOTE: DebugOnly instances still take up one byte of space, plus padding, even
     35 * in optimized, non-DEBUG builds (see bug 1253094 comment 37 for more info).
     36 * For this reason the class is MOZ_STACK_CLASS to prevent consumers using
     37 * DebugOnly for struct/class members and unwittingly inflating the size of
     38 * their objects in release builds.
     39 */
     40 template <typename T>
     41 class MOZ_STACK_CLASS DebugOnly {
     42 public:
     43 #ifdef DEBUG
     44  T value;
     45 
     46  DebugOnly() = default;
     47  MOZ_IMPLICIT DebugOnly(T&& aOther) : value(std::move(aOther)) {}
     48  MOZ_IMPLICIT DebugOnly(const T& aOther) : value(aOther) {}
     49  DebugOnly(const DebugOnly& aOther) : value(aOther.value) {}
     50  DebugOnly& operator=(const T& aRhs) {
     51    value = aRhs;
     52    return *this;
     53  }
     54  DebugOnly& operator=(T&& aRhs) {
     55    value = std::move(aRhs);
     56    return *this;
     57  }
     58 
     59  void operator++(int) { value++; }
     60  void operator--(int) { value--; }
     61 
     62  // Do not define operator+=(), etc. here.  These will coerce via the
     63  // implicit cast and built-in operators.  Defining explicit methods here
     64  // will create ambiguity the compiler can't deal with.
     65 
     66  T* operator&() { return &value; }
     67 
     68  operator T&() { return value; }
     69  operator const T&() const { return value; }
     70 
     71  T& operator->() { return value; }
     72  const T& operator->() const { return value; }
     73 
     74  const T& inspect() const { return value; }
     75 
     76 #else
     77  DebugOnly() = default;
     78  MOZ_IMPLICIT DebugOnly(const T&) {}
     79  DebugOnly(const DebugOnly&) {}
     80  DebugOnly& operator=(const T&) { return *this; }
     81  MOZ_IMPLICIT DebugOnly(T&&) {}
     82  DebugOnly& operator=(T&&) { return *this; }
     83  void operator++(int) {}
     84  void operator--(int) {}
     85  DebugOnly& operator+=(const T&) { return *this; }
     86  DebugOnly& operator-=(const T&) { return *this; }
     87  DebugOnly& operator&=(const T&) { return *this; }
     88  DebugOnly& operator|=(const T&) { return *this; }
     89  DebugOnly& operator^=(const T&) { return *this; }
     90 #endif
     91 
     92  /*
     93   * DebugOnly must always have a user-defined destructor or else it will
     94   * generate "unused variable" warnings, exactly what it's intended
     95   * to avoid!
     96   */
     97  ~DebugOnly() {}
     98 };
     99 
    100 }  // namespace mozilla
    101 
    102 #endif /* mozilla_DebugOnly_h */