Line data Source code
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 : namespace mozilla {
18 :
19 : /**
20 : * DebugOnly contains a value of type T, but only in debug builds. In release
21 : * builds, it does not contain a value. This helper is intended to be used with
22 : * MOZ_ASSERT()-style macros, allowing one to write:
23 : *
24 : * DebugOnly<bool> check = func();
25 : * MOZ_ASSERT(check);
26 : *
27 : * more concisely than declaring |check| conditional on #ifdef DEBUG.
28 : *
29 : * DebugOnly instances can only be coerced to T in debug builds. In release
30 : * builds they don't have a value, so type coercion is not well defined.
31 : *
32 : * NOTE: DebugOnly instances still take up one byte of space, plus padding, even
33 : * in optimized, non-DEBUG builds (see bug 1253094 comment 37 for more info).
34 : * For this reason the class is MOZ_STACK_CLASS to prevent consumers using
35 : * DebugOnly for struct/class members and unwittingly inflating the size of
36 : * their objects in release builds.
37 : */
38 : template<typename T>
39 : class MOZ_STACK_CLASS DebugOnly
40 : {
41 : public:
42 : #ifdef DEBUG
43 : T value;
44 :
45 43867 : DebugOnly() { }
46 1749648 : MOZ_IMPLICIT DebugOnly(const T& aOther) : value(aOther) { }
47 0 : DebugOnly(const DebugOnly& aOther) : value(aOther.value) { }
48 97084 : DebugOnly& operator=(const T& aRhs) {
49 97084 : value = aRhs;
50 97084 : return *this;
51 : }
52 :
53 16698 : void operator++(int) { value++; }
54 : void operator--(int) { value--; }
55 :
56 : // Do not define operator+=(), etc. here. These will coerce via the
57 : // implicit cast and built-in operators. Defining explicit methods here
58 : // will create ambiguity the compiler can't deal with.
59 :
60 8038 : T* operator&() { return &value; }
61 :
62 4918169 : operator T&() { return value; }
63 790071 : operator const T&() const { return value; }
64 :
65 38481 : T& operator->() { return value; }
66 : const T& operator->() const { return value; }
67 :
68 : #else
69 : DebugOnly() { }
70 : MOZ_IMPLICIT DebugOnly(const T&) { }
71 : DebugOnly(const DebugOnly&) { }
72 : DebugOnly& operator=(const T&) { return *this; }
73 : void operator++(int) { }
74 : void operator--(int) { }
75 : DebugOnly& operator+=(const T&) { return *this; }
76 : DebugOnly& operator-=(const T&) { return *this; }
77 : DebugOnly& operator&=(const T&) { return *this; }
78 : DebugOnly& operator|=(const T&) { return *this; }
79 : DebugOnly& operator^=(const T&) { return *this; }
80 : #endif
81 :
82 : /*
83 : * DebugOnly must always have a destructor or else it will
84 : * generate "unused variable" warnings, exactly what it's intended
85 : * to avoid!
86 : */
87 1797507 : ~DebugOnly() {}
88 : };
89 :
90 : } // namespace mozilla
91 :
92 : #endif /* mozilla_DebugOnly_h */
|