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