| 1 | // RUN: %check_clang_tidy %s readability-magic-numbers %t \ |
| 2 | // RUN: -config='{CheckOptions: \ |
| 3 | // RUN: {readability-magic-numbers.IgnoredIntegerValues: "0;1;2;10;100;", \ |
| 4 | // RUN: readability-magic-numbers.IgnoredFloatingPointValues: "3.14;2.71828;9.81;10000.0;101.0;0x1.2p3", \ |
| 5 | // RUN: readability-magic-numbers.IgnoreBitFieldsWidths: false, \ |
| 6 | // RUN: readability-magic-numbers.IgnorePowersOf2IntegerValues: true, \ |
| 7 | // RUN: readability-magic-numbers.IgnoreTypeAliases: false}}' \ |
| 8 | // RUN: -- |
| 9 | |
| 10 | template <typename T, int V> |
| 11 | struct ValueBucket { |
| 12 | T value[V]; |
| 13 | }; |
| 14 | |
| 15 | int BadGlobalInt = 5; |
| 16 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 5 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 17 | |
| 18 | int IntSquarer(int param) { |
| 19 | return param * param; |
| 20 | } |
| 21 | |
| 22 | void BuggyFunction() { |
| 23 | int BadLocalInt = 6; |
| 24 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 6 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 25 | |
| 26 | (void)IntSquarer(param: 7); |
| 27 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 7 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 28 | |
| 29 | int LocalArray[15]; |
| 30 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 15 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 31 | |
| 32 | for (int ii = 0; ii < 22; ++ii) |
| 33 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 22 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 34 | { |
| 35 | LocalArray[ii] = 3 * ii; |
| 36 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 37 | } |
| 38 | |
| 39 | ValueBucket<int, 66> Bucket; |
| 40 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 66 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 41 | } |
| 42 | |
| 43 | class TwoIntContainer { |
| 44 | public: |
| 45 | TwoIntContainer(int val) : anotherMember(val * val), yetAnotherMember(6), anotherConstant(val + val) {} |
| 46 | // CHECK-MESSAGES: :[[@LINE-1]]:73: warning: 6 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 47 | |
| 48 | int getValue() const; |
| 49 | |
| 50 | private: |
| 51 | int oneMember = 9; |
| 52 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 9 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 53 | |
| 54 | int anotherMember; |
| 55 | |
| 56 | int yetAnotherMember; |
| 57 | |
| 58 | const int oneConstant = 2; |
| 59 | |
| 60 | const int anotherConstant; |
| 61 | }; |
| 62 | |
| 63 | int ValueArray[] = {3, 5, 0, 0, 0}; |
| 64 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 65 | // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: 5 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 66 | |
| 67 | float FloatPiVariable = 3.1415926535f; |
| 68 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 3.1415926535f is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 69 | double DoublePiVariable = 6.283185307; |
| 70 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 6.283185307 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 71 | |
| 72 | float SomeFloats[] = {0.5, 0x1.2p4}; |
| 73 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 0.5 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 74 | // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: 0x1.2p4 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 75 | |
| 76 | int getAnswer() { |
| 77 | if (ValueArray[0] < ValueArray[1]) |
| 78 | return ValueArray[1]; |
| 79 | |
| 80 | return -3; // FILENOTFOUND |
| 81 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 82 | } |
| 83 | |
| 84 | struct HardwareGateway { |
| 85 | unsigned int Some: 5; |
| 86 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 5 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 87 | unsigned int Bits: 7; |
| 88 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 7 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 89 | unsigned int: 6; |
| 90 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 6 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 91 | unsigned int Flag: 1; // no warning since this is suppressed by IgnoredIntegerValues rule |
| 92 | unsigned int: 0; // no warning since this is suppressed by IgnoredIntegerValues rule |
| 93 | unsigned int Rest: 13; |
| 94 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: 13 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 95 | // |
| 96 | unsigned int Another[3]; |
| 97 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 3 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 98 | }; |
| 99 | |
| 100 | using NumberInTypeAlias = ValueBucket<int, 25>; |
| 101 | // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: 25 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 102 | typedef ValueBucket<char, 243> NumberInTypedef; |
| 103 | // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 243 is a magic number; consider replacing it with a named constant [readability-magic-numbers] |
| 104 | |
| 105 | /* |
| 106 | * Clean code |
| 107 | */ |
| 108 | |
| 109 | #define INT_MACRO 5 |
| 110 | |
| 111 | const int GoodGlobalIntConstant = 42; |
| 112 | |
| 113 | constexpr int AlsoGoodGlobalIntConstant = 42; |
| 114 | |
| 115 | int InitializedByMacro = INT_MACRO; |
| 116 | |
| 117 | void SolidFunction() { |
| 118 | const int GoodLocalIntConstant = 43; |
| 119 | |
| 120 | (void)IntSquarer(param: GoodLocalIntConstant); |
| 121 | |
| 122 | int LocalArray[INT_MACRO]; |
| 123 | |
| 124 | ValueBucket<int, INT_MACRO> Bucket; |
| 125 | } |
| 126 | |
| 127 | const int ConstValueArray[] = {7, 9}; |
| 128 | |
| 129 | const int ConstValueArray2D[2][2] = {{7, 9}, {13, 15}}; |
| 130 | |
| 131 | /* |
| 132 | * no warnings for ignored values (specified in the configuration above) |
| 133 | */ |
| 134 | int GrandfatheredIntegerValues[] = {0, 1, 2, 10, 100, -1, -10, -100, 65536}; |
| 135 | |
| 136 | float GrandfatheredFloatValues[] = {3.14f, 3.14, 2.71828, 2.71828f, -1.01E2, 1E4, 0x1.2p3}; |
| 137 | |
| 138 | /* |
| 139 | * no warnings for enums |
| 140 | */ |
| 141 | enum Smorgasbord { |
| 142 | STARTER, |
| 143 | ALPHA = 3, |
| 144 | BETA = 1 << 5, |
| 145 | }; |
| 146 | |
| 147 | const float FloatPiConstant = 3.1415926535f; |
| 148 | const double DoublePiConstant = 6.283185307; |
| 149 | |
| 150 | const float Angles[] = {45.0f, 90.0f, 135.0f}; |
| 151 | |
| 152 | double DoubleZeroIsAccepted = 0.0; |
| 153 | float FloatZeroIsAccepted = 0.0f; |
| 154 | |
| 155 | namespace geometry { |
| 156 | |
| 157 | template <typename T> |
| 158 | struct Point { |
| 159 | T x; |
| 160 | T y; |
| 161 | |
| 162 | explicit Point(T xval, T yval) noexcept : x{xval}, y{yval} { |
| 163 | } |
| 164 | }; |
| 165 | |
| 166 | template <typename T> |
| 167 | struct Dimension { |
| 168 | T x; |
| 169 | T y; |
| 170 | |
| 171 | explicit Dimension(T xval, T yval) noexcept : x{xval}, y{yval} { |
| 172 | } |
| 173 | }; |
| 174 | |
| 175 | template <typename T> |
| 176 | struct Rectangle { |
| 177 | Point<T> origin; |
| 178 | Dimension<T> size; |
| 179 | T rotation; // angle of rotation around origin |
| 180 | |
| 181 | Rectangle(Point<T> origin_, Dimension<T> size_, T rotation_ = 0) noexcept : origin{origin_}, size{size_}, rotation{rotation_} { |
| 182 | } |
| 183 | |
| 184 | bool contains(Point<T> point) const; |
| 185 | }; |
| 186 | |
| 187 | } // namespace geometry |
| 188 | |
| 189 | const geometry::Rectangle<double> mandelbrotCanvas{geometry::Point<double>{-2.5, -1}, geometry::Dimension<double>{3.5, 2}}; |
| 190 | |
| 191 | // Simulate the macro magic in Google Test internal headers. |
| 192 | class AssertionHelper { |
| 193 | public: |
| 194 | AssertionHelper(const char *Message, int LineNumber) : Message(Message), LineNumber(LineNumber) {} |
| 195 | |
| 196 | private: |
| 197 | const char *Message; |
| 198 | int LineNumber; |
| 199 | }; |
| 200 | |
| 201 | #define ASSERTION_HELPER_AT(M, L) AssertionHelper(M, L) |
| 202 | |
| 203 | #define ASSERTION_HELPER(M) ASSERTION_HELPER_AT(M, __LINE__) |
| 204 | |
| 205 | void FunctionWithCompilerDefinedSymbol(void) { |
| 206 | ASSERTION_HELPER("here and now" ); |
| 207 | } |
| 208 | |
| 209 | // Prove that integer literals introduced by the compiler are accepted silently. |
| 210 | extern int ConsumeString(const char *Input); |
| 211 | |
| 212 | const char *SomeStrings[] = {"alpha" , "beta" , "gamma" }; |
| 213 | |
| 214 | int TestCheckerOverreach() { |
| 215 | int Total = 0; |
| 216 | |
| 217 | for (const auto *Str : SomeStrings) { |
| 218 | Total += ConsumeString(Input: Str); |
| 219 | } |
| 220 | |
| 221 | return Total; |
| 222 | } |
| 223 | |
| 224 | // Prove that using enumerations values don't produce warnings. |
| 225 | enum class Letter : unsigned { |
| 226 | A, B, C, D, E, F, G, H, I, J |
| 227 | }; |
| 228 | |
| 229 | template<Letter x> struct holder { Letter letter = x; }; |
| 230 | template<Letter x> struct wrapper { using h_type = holder<x>; }; |
| 231 | |
| 232 | template struct wrapper<Letter::A>; |
| 233 | template struct wrapper<Letter::J>; |
| 234 | |