OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ | 5 #ifndef BASE_NUMERICS_SAFE_MATH_H_ |
6 #define BASE_NUMERICS_SAFE_MATH_H_ | 6 #define BASE_NUMERICS_SAFE_MATH_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
(...skipping 19 matching lines...) Expand all Loading... |
30 // CheckAdd() - Addition. | 30 // CheckAdd() - Addition. |
31 // CheckSub() - Subtraction. | 31 // CheckSub() - Subtraction. |
32 // CheckMul() - Multiplication. | 32 // CheckMul() - Multiplication. |
33 // CheckDiv() - Division. | 33 // CheckDiv() - Division. |
34 // CheckMod() - Modulous (integer only). | 34 // CheckMod() - Modulous (integer only). |
35 // CheckLsh() - Left integer shift (integer only). | 35 // CheckLsh() - Left integer shift (integer only). |
36 // CheckRsh() - Right integer shift (integer only). | 36 // CheckRsh() - Right integer shift (integer only). |
37 // CheckAnd() - Bitwise AND (integer only with unsigned result). | 37 // CheckAnd() - Bitwise AND (integer only with unsigned result). |
38 // CheckOr() - Bitwise OR (integer only with unsigned result). | 38 // CheckOr() - Bitwise OR (integer only with unsigned result). |
39 // CheckXor() - Bitwise XOR (integer only with unsigned result). | 39 // CheckXor() - Bitwise XOR (integer only with unsigned result). |
| 40 // CheckMax() - Maximum of supplied arguments. |
| 41 // CheckMin() - Minimum of supplied arguments. |
40 // | 42 // |
41 // The unary negation, increment, and decrement operators are supported, along | 43 // The unary negation, increment, and decrement operators are supported, along |
42 // with the following unary arithmetic methods, which return a new | 44 // with the following unary arithmetic methods, which return a new |
43 // CheckedNumeric as a result of the operation: | 45 // CheckedNumeric as a result of the operation: |
44 // Abs() - Absolute value. | 46 // Abs() - Absolute value. |
45 // UnsignedAbs() - Absolute value as an equival-width unsigned underlying type | 47 // UnsignedAbs() - Absolute value as an equal-width unsigned underlying type |
46 // (valid for only integral types). | 48 // (valid for only integral types). |
| 49 // Max() - Returns whichever is greater of the current instance or argument. |
| 50 // The underlying return type is whichever has the greatest magnitude. |
| 51 // Min() - Returns whichever is lowest of the current instance or argument. |
| 52 // The underlying return type is whichever has can represent the lowest |
| 53 // number in the smallest width (e.g. int8_t over unsigned, int over |
| 54 // int8_t, and float over int). |
47 // | 55 // |
48 // The following methods convert from CheckedNumeric to standard numeric values: | 56 // The following methods convert from CheckedNumeric to standard numeric values: |
49 // AssignIfValid() - Assigns the underlying value to the supplied destination | 57 // AssignIfValid() - Assigns the underlying value to the supplied destination |
50 // pointer if the value is currently valid and within the range | 58 // pointer if the value is currently valid and within the range |
51 // supported by the destination type. Returns true on success. | 59 // supported by the destination type. Returns true on success. |
52 // **************************************************************************** | 60 // **************************************************************************** |
53 // * WARNING: All of the following functions return a StrictNumeric, which * | 61 // * WARNING: All of the following functions return a StrictNumeric, which * |
54 // * is valid for comparison and assignment operations, but will trigger a * | 62 // * is valid for comparison and assignment operations, but will trigger a * |
55 // * compile failure on attempts to assign to a type of insufficient range. * | 63 // * compile failure on attempts to assign to a type of insufficient range. * |
56 // **************************************************************************** | 64 // **************************************************************************** |
57 // IsValid() - Returns true if the underlying numeric value is valid (i.e. has | 65 // IsValid() - Returns true if the underlying numeric value is valid (i.e. has |
58 // has not wrapped and is not the result of an invalid conversion). | 66 // has not wrapped and is not the result of an invalid conversion). |
59 // ValueOrDie() - Returns the underlying value. If the state is not valid this | 67 // ValueOrDie() - Returns the underlying value. If the state is not valid this |
60 // call will crash on a CHECK. | 68 // call will crash on a CHECK. |
61 // ValueOrDefault() - Returns the current value, or the supplied default if the | 69 // ValueOrDefault() - Returns the current value, or the supplied default if the |
62 // state is not valid (will not trigger a CHECK). | 70 // state is not valid (will not trigger a CHECK). |
63 // | 71 // |
64 // The following wrapper functions can be used to avoid the template | 72 // The following wrapper functions can be used to avoid the template |
65 // disambiguator syntax when converting a destination type. | 73 // disambiguator syntax when converting a destination type. |
66 // IsValidForType<>() in place of: a.template IsValid<Dst>() | 74 // IsValidForType<>() in place of: a.template IsValid<Dst>() |
67 // ValueOrDieForType<>() in place of: a.template ValueOrDie() | 75 // ValueOrDieForType<>() in place of: a.template ValueOrDie() |
68 // ValueOrDefaultForType<>() in place of: a.template ValueOrDefault(default) | 76 // ValueOrDefaultForType<>() in place of: a.template ValueOrDefault(default) |
69 // | 77 // |
70 // The following are general utility methods that are useful for converting | 78 // The following are general utility methods that are useful for converting |
71 // between arithmetic types and CheckedNumeric types: | 79 // between arithmetic types and CheckedNumeric types: |
72 // CheckedNumeric::Cast<Dst>() - Instance method returning a CheckedNumeric | 80 // CheckedNumeric::Cast<Dst>() - Instance method returning a CheckedNumeric |
73 // derived from casting the current instance to a CheckedNumeric of | 81 // derived from casting the current instance to a CheckedNumeric of |
74 // the supplied destination type. | 82 // the supplied destination type. |
75 // CheckNum() - Creates a new CheckedNumeric from the underlying type of the | 83 // CheckNum() - Creates a new CheckedNumeric from the underlying type of the |
76 // supplied arithmetic or CheckedNumeric type. | 84 // supplied arithmetic, CheckedNumeric, or StrictNumeric type. |
77 // | 85 // |
78 // Comparison operations are explicitly not supported because they could result | 86 // Comparison operations are explicitly not supported because they could result |
79 // in a crash on an unexpected CHECK condition. You should use patterns like the | 87 // in a crash on an unexpected CHECK condition. You should use patterns like the |
80 // following for comparisons: | 88 // following for comparisons: |
81 // CheckedNumeric<size_t> checked_size = untrusted_input_value; | 89 // CheckedNumeric<size_t> checked_size = untrusted_input_value; |
82 // checked_size += HEADER LENGTH; | 90 // checked_size += HEADER LENGTH; |
83 // if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) | 91 // if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) |
84 // Do stuff... | 92 // Do stuff... |
85 | 93 |
86 template <typename T> | 94 template <typename T> |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 } | 221 } |
214 | 222 |
215 CheckedNumeric Abs() const { | 223 CheckedNumeric Abs() const { |
216 // Absolute value is always valid for floating point. | 224 // Absolute value is always valid for floating point. |
217 T value = 0; | 225 T value = 0; |
218 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) && | 226 bool is_valid = (std::numeric_limits<T>::is_iec559 || IsValid()) && |
219 CheckedAbs(state_.value(), &value); | 227 CheckedAbs(state_.value(), &value); |
220 return CheckedNumeric<T>(value, is_valid); | 228 return CheckedNumeric<T>(value, is_valid); |
221 } | 229 } |
222 | 230 |
| 231 template <typename U> |
| 232 constexpr CheckedNumeric<typename MathWrapper<CheckedMaxOp, T, U>::type> Max( |
| 233 const U rhs) const { |
| 234 using R = typename UnderlyingType<U>::type; |
| 235 using result_type = typename MathWrapper<CheckedMaxOp, T, U>::type; |
| 236 // TODO(jschuh): This can be converted to the MathOp version and remain |
| 237 // constexpr once we have C++14 support. |
| 238 return CheckedNumeric<result_type>( |
| 239 static_cast<result_type>( |
| 240 IsGreater<T, R>::Test(state_.value(), Wrapper<U>::value(rhs)) |
| 241 ? state_.value() |
| 242 : Wrapper<U>::value(rhs)), |
| 243 state_.is_valid() && Wrapper<U>::is_valid(rhs)); |
| 244 } |
| 245 |
| 246 template <typename U> |
| 247 constexpr CheckedNumeric<typename MathWrapper<CheckedMinOp, T, U>::type> Min( |
| 248 const U rhs) const { |
| 249 using R = typename UnderlyingType<U>::type; |
| 250 using result_type = typename MathWrapper<CheckedMinOp, T, U>::type; |
| 251 // TODO(jschuh): This can be converted to the MathOp version and remain |
| 252 // constexpr once we have C++14 support. |
| 253 return CheckedNumeric<result_type>( |
| 254 static_cast<result_type>( |
| 255 IsLess<T, R>::Test(state_.value(), Wrapper<U>::value(rhs)) |
| 256 ? state_.value() |
| 257 : Wrapper<U>::value(rhs)), |
| 258 state_.is_valid() && Wrapper<U>::is_valid(rhs)); |
| 259 } |
| 260 |
223 // This function is available only for integral types. It returns an unsigned | 261 // This function is available only for integral types. It returns an unsigned |
224 // integer of the same width as the source type, containing the absolute value | 262 // integer of the same width as the source type, containing the absolute value |
225 // of the source, and properly handling signed min. | 263 // of the source, and properly handling signed min. |
226 constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> | 264 constexpr CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> |
227 UnsignedAbs() const { | 265 UnsignedAbs() const { |
228 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( | 266 return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( |
229 SafeUnsignedAbs(state_.value()), state_.is_valid()); | 267 SafeUnsignedAbs(state_.value()), state_.is_valid()); |
230 } | 268 } |
231 | 269 |
232 CheckedNumeric& operator++() { | 270 CheckedNumeric& operator++() { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 | 331 |
294 template <typename Src> | 332 template <typename Src> |
295 struct Wrapper<CheckedNumeric<Src>> { | 333 struct Wrapper<CheckedNumeric<Src>> { |
296 static constexpr bool is_valid(const CheckedNumeric<Src> v) { | 334 static constexpr bool is_valid(const CheckedNumeric<Src> v) { |
297 return v.IsValid(); | 335 return v.IsValid(); |
298 } | 336 } |
299 static constexpr Src value(const CheckedNumeric<Src> v) { | 337 static constexpr Src value(const CheckedNumeric<Src> v) { |
300 return v.state_.value(); | 338 return v.state_.value(); |
301 } | 339 } |
302 }; | 340 }; |
| 341 |
| 342 template <typename Src> |
| 343 struct Wrapper<StrictNumeric<Src>> { |
| 344 static constexpr bool is_valid(const StrictNumeric<Src>) { return true; } |
| 345 static constexpr Src value(const StrictNumeric<Src> v) { |
| 346 return static_cast<Src>(v); |
| 347 } |
| 348 }; |
303 }; | 349 }; |
304 | 350 |
305 // Convenience functions to avoid the ugly template disambiguator syntax. | 351 // Convenience functions to avoid the ugly template disambiguator syntax. |
306 template <typename Dst, typename Src> | 352 template <typename Dst, typename Src> |
307 constexpr bool IsValidForType(const CheckedNumeric<Src> value) { | 353 constexpr bool IsValidForType(const CheckedNumeric<Src> value) { |
308 return value.template IsValid<Dst>(); | 354 return value.template IsValid<Dst>(); |
309 } | 355 } |
310 | 356 |
311 template <typename Dst, typename Src> | 357 template <typename Dst, typename Src> |
312 constexpr StrictNumeric<Dst> ValueOrDieForType( | 358 constexpr StrictNumeric<Dst> ValueOrDieForType( |
(...skipping 30 matching lines...) Expand all Loading... |
343 struct ResultType { | 389 struct ResultType { |
344 // The typedef was required here because MSVC fails to compile with "using". | 390 // The typedef was required here because MSVC fails to compile with "using". |
345 typedef | 391 typedef |
346 typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type | 392 typename ResultType<M, typename ResultType<M, L, R>::type, Args...>::type |
347 type; | 393 type; |
348 }; | 394 }; |
349 | 395 |
350 // Convience wrapper to return a new CheckedNumeric from the provided arithmetic | 396 // Convience wrapper to return a new CheckedNumeric from the provided arithmetic |
351 // or CheckedNumericType. | 397 // or CheckedNumericType. |
352 template <typename T> | 398 template <typename T> |
353 CheckedNumeric<typename UnderlyingType<T>::type> CheckNum(T value) { | 399 constexpr CheckedNumeric<typename UnderlyingType<T>::type> CheckNum( |
| 400 const T value) { |
354 return value; | 401 return value; |
355 } | 402 } |
356 | 403 |
357 // These implement the variadic wrapper for the math operations. | 404 // These implement the variadic wrapper for the math operations. |
358 template <template <typename, typename, typename> class M, | 405 template <template <typename, typename, typename> class M, |
359 typename L, | 406 typename L, |
360 typename R> | 407 typename R> |
361 CheckedNumeric<typename MathWrapper<M, L, R>::type> ChkMathOp(const L lhs, | 408 CheckedNumeric<typename MathWrapper<M, L, R>::type> ChkMathOp(const L lhs, |
362 const R rhs) { | 409 const R rhs) { |
363 using Math = typename MathWrapper<M, L, R>::math; | 410 using Math = typename MathWrapper<M, L, R>::math; |
364 return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs, | 411 return CheckedNumeric<typename Math::result_type>::template MathOp<M>(lhs, |
365 rhs); | 412 rhs); |
366 }; | 413 } |
367 | 414 |
| 415 // General purpose wrapper template for arithmetic operations. |
368 template <template <typename, typename, typename> class M, | 416 template <template <typename, typename, typename> class M, |
369 typename L, | 417 typename L, |
370 typename R, | 418 typename R, |
371 typename... Args> | 419 typename... Args> |
372 CheckedNumeric<typename ResultType<M, L, R, Args...>::type> | 420 CheckedNumeric<typename ResultType<M, L, R, Args...>::type> |
373 ChkMathOp(const L lhs, const R rhs, const Args... args) { | 421 ChkMathOp(const L lhs, const R rhs, const Args... args) { |
374 auto tmp = ChkMathOp<M>(lhs, rhs); | 422 auto tmp = ChkMathOp<M>(lhs, rhs); |
375 return tmp.IsValid() ? ChkMathOp<M>(tmp, args...) | 423 return tmp.IsValid() ? ChkMathOp<M>(tmp, args...) |
376 : decltype(ChkMathOp<M>(tmp, args...))(tmp); | 424 : decltype(ChkMathOp<M>(tmp, args...))(tmp); |
377 }; | 425 }; |
378 | 426 |
379 // This is just boilerplate for the standard arithmetic operator overloads. | 427 // The following macros are just boilerplate for the standard arithmetic |
380 // A macro isn't the nicest solution, but it beats rewriting these repeatedly. | 428 // operator overloads and variadic function templates. A macro isn't the nicest |
| 429 // solution, but it beats rewriting these over and over again. |
| 430 #define BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME) \ |
| 431 template <typename L, typename R, typename... Args> \ |
| 432 CheckedNumeric<typename ResultType<Checked##NAME##Op, L, R, Args...>::type> \ |
| 433 Check##NAME(const L lhs, const R rhs, const Args... args) { \ |
| 434 return ChkMathOp<Checked##NAME##Op, L, R, Args...>(lhs, rhs, args...); \ |
| 435 } |
| 436 |
381 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ | 437 #define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ |
382 /* Binary arithmetic operator for all CheckedNumeric operations. */ \ | 438 /* Binary arithmetic operator for all CheckedNumeric operations. */ \ |
383 template <typename L, typename R, \ | 439 template <typename L, typename R, \ |
384 typename std::enable_if<IsCheckedOp<L, R>::value>::type* = \ | 440 typename std::enable_if<IsCheckedOp<L, R>::value>::type* = \ |
385 nullptr> \ | 441 nullptr> \ |
386 CheckedNumeric<typename MathWrapper<Checked##NAME##Op, L, R>::type> \ | 442 CheckedNumeric<typename MathWrapper<Checked##NAME##Op, L, R>::type> \ |
387 operator OP(const L lhs, const R rhs) { \ | 443 operator OP(const L lhs, const R rhs) { \ |
388 return decltype(lhs OP rhs)::template MathOp<Checked##NAME##Op>(lhs, rhs); \ | 444 return decltype(lhs OP rhs)::template MathOp<Checked##NAME##Op>(lhs, rhs); \ |
389 } \ | 445 } \ |
390 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ | 446 /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ |
391 template <typename L> \ | 447 template <typename L> \ |
392 template <typename R> \ | 448 template <typename R> \ |
393 CheckedNumeric<L>& CheckedNumeric<L>::operator COMPOUND_OP(const R rhs) { \ | 449 CheckedNumeric<L>& CheckedNumeric<L>::operator COMPOUND_OP(const R rhs) { \ |
394 return MathOp<Checked##NAME##Op>(rhs); \ | 450 return MathOp<Checked##NAME##Op>(rhs); \ |
395 } \ | 451 } \ |
396 /* Variadic arithmetic functions that return CheckedNumeric. */ \ | 452 /* Variadic arithmetic functions that return CheckedNumeric. */ \ |
397 template <typename L, typename R, typename... Args> \ | 453 BASE_NUMERIC_ARITHMETIC_VARIADIC(NAME) |
398 CheckedNumeric<typename ResultType<Checked##NAME##Op, L, R, Args...>::type> \ | |
399 Check##NAME(const L lhs, const R rhs, const Args... args) { \ | |
400 return ChkMathOp<Checked##NAME##Op, L, R, Args...>(lhs, rhs, args...); \ | |
401 } | |
402 | 454 |
403 BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=) | 455 BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=) |
404 BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=) | 456 BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=) |
405 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=) | 457 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=) |
406 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=) | 458 BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=) |
407 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=) | 459 BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=) |
408 BASE_NUMERIC_ARITHMETIC_OPERATORS(Lsh, <<, <<=) | 460 BASE_NUMERIC_ARITHMETIC_OPERATORS(Lsh, <<, <<=) |
409 BASE_NUMERIC_ARITHMETIC_OPERATORS(Rsh, >>, >>=) | 461 BASE_NUMERIC_ARITHMETIC_OPERATORS(Rsh, >>, >>=) |
410 BASE_NUMERIC_ARITHMETIC_OPERATORS(And, &, &=) | 462 BASE_NUMERIC_ARITHMETIC_OPERATORS(And, &, &=) |
411 BASE_NUMERIC_ARITHMETIC_OPERATORS(Or, |, |=) | 463 BASE_NUMERIC_ARITHMETIC_OPERATORS(Or, |, |=) |
412 BASE_NUMERIC_ARITHMETIC_OPERATORS(Xor, ^, ^=) | 464 BASE_NUMERIC_ARITHMETIC_OPERATORS(Xor, ^, ^=) |
| 465 BASE_NUMERIC_ARITHMETIC_VARIADIC(Max) |
| 466 BASE_NUMERIC_ARITHMETIC_VARIADIC(Min) |
413 | 467 |
| 468 #undef BASE_NUMERIC_ARITHMETIC_VARIADIC |
414 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS | 469 #undef BASE_NUMERIC_ARITHMETIC_OPERATORS |
415 | 470 |
416 // These are some extra StrictNumeric operators to support simple pointer | 471 // These are some extra StrictNumeric operators to support simple pointer |
417 // arithmetic with our result types. Since wrapping on a pointer is always | 472 // arithmetic with our result types. Since wrapping on a pointer is always |
418 // bad, we trigger the CHECK condition here. | 473 // bad, we trigger the CHECK condition here. |
419 template <typename L, typename R> | 474 template <typename L, typename R> |
420 L* operator+(L* lhs, const StrictNumeric<R> rhs) { | 475 L* operator+(L* lhs, const StrictNumeric<R> rhs) { |
421 uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs), | 476 uintptr_t result = CheckAdd(reinterpret_cast<uintptr_t>(lhs), |
422 CheckMul(sizeof(L), static_cast<R>(rhs))) | 477 CheckMul(sizeof(L), static_cast<R>(rhs))) |
423 .template ValueOrDie<uintptr_t>(); | 478 .template ValueOrDie<uintptr_t>(); |
424 return reinterpret_cast<L*>(result); | 479 return reinterpret_cast<L*>(result); |
425 } | 480 } |
426 | 481 |
427 template <typename L, typename R> | 482 template <typename L, typename R> |
428 L* operator-(L* lhs, const StrictNumeric<R> rhs) { | 483 L* operator-(L* lhs, const StrictNumeric<R> rhs) { |
429 uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs), | 484 uintptr_t result = CheckSub(reinterpret_cast<uintptr_t>(lhs), |
430 CheckMul(sizeof(L), static_cast<R>(rhs))) | 485 CheckMul(sizeof(L), static_cast<R>(rhs))) |
431 .template ValueOrDie<uintptr_t>(); | 486 .template ValueOrDie<uintptr_t>(); |
432 return reinterpret_cast<L*>(result); | 487 return reinterpret_cast<L*>(result); |
433 } | 488 } |
434 | 489 |
435 } // namespace internal | 490 } // namespace internal |
436 | 491 |
437 using internal::CheckedNumeric; | 492 using internal::CheckedNumeric; |
438 using internal::IsValidForType; | 493 using internal::IsValidForType; |
439 using internal::ValueOrDieForType; | 494 using internal::ValueOrDieForType; |
440 using internal::ValueOrDefaultForType; | 495 using internal::ValueOrDefaultForType; |
441 using internal::CheckNum; | 496 using internal::CheckNum; |
| 497 using internal::CheckMax; |
| 498 using internal::CheckMin; |
442 using internal::CheckAdd; | 499 using internal::CheckAdd; |
443 using internal::CheckSub; | 500 using internal::CheckSub; |
444 using internal::CheckMul; | 501 using internal::CheckMul; |
445 using internal::CheckDiv; | 502 using internal::CheckDiv; |
446 using internal::CheckMod; | 503 using internal::CheckMod; |
447 using internal::CheckLsh; | 504 using internal::CheckLsh; |
448 using internal::CheckRsh; | 505 using internal::CheckRsh; |
449 using internal::CheckAnd; | 506 using internal::CheckAnd; |
450 using internal::CheckOr; | 507 using internal::CheckOr; |
451 using internal::CheckXor; | 508 using internal::CheckXor; |
452 | 509 |
453 } // namespace base | 510 } // namespace base |
454 | 511 |
455 #endif // BASE_NUMERICS_SAFE_MATH_H_ | 512 #endif // BASE_NUMERICS_SAFE_MATH_H_ |
OLD | NEW |