Chromium Code Reviews| Index: src/base/macros.h |
| diff --git a/src/base/macros.h b/src/base/macros.h |
| index 50828db57ff95420fe2ab386c8ed69dec197f56b..c8a140849dcf3e370c7e845929c25ebf3409ca0c 100644 |
| --- a/src/base/macros.h |
| +++ b/src/base/macros.h |
| @@ -20,13 +20,74 @@ |
| (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(4)->field)) - 4) |
| -// The expression ARRAY_SIZE(a) is a compile-time constant of type |
| -// size_t which represents the number of elements of the given |
| -// array. You should only use ARRAY_SIZE on statically allocated |
| -// arrays. |
| -#define ARRAY_SIZE(a) \ |
| - ((sizeof(a) / sizeof(*(a))) / \ |
| - static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) |
| +// The arraysize(arr) macro returns the # of elements in an array arr. |
| +// The expression is a compile-time constant, and therefore can be |
| +// used in defining new arrays, for example. If you use arraysize on |
| +// a pointer by mistake, you will get a compile-time error. |
| +// |
| +// One caveat is that arraysize() doesn't accept any array of an |
| +// anonymous type or a type defined inside a function. In these rare |
| +// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is |
| +// due to a limitation in C++'s template system. The limitation might |
| +// eventually be removed, but it hasn't happened yet. |
| +#define arraysize(array) (sizeof(ArraySizeHelper(array))) |
| + |
| + |
| +// This template function declaration is used in defining arraysize. |
| +// Note that the function doesn't need an implementation, as we only |
| +// use its type. |
| +template <typename T, size_t N> |
| +char (&ArraySizeHelper(T (&array)[N]))[N]; |
| + |
| + |
| +#if V8_CC_GNU |
| +// That gcc wants both of these prototypes seems mysterious. VC, for |
| +// its part, can't decide which to use (another mystery). Matching of |
| +// template overloads: the final frontier. |
| +template <typename T, size_t N> |
| +char (&ArraySizeHelper(const T (&array)[N]))[N]; |
| +#endif |
| + |
| + |
| +// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, |
| +// but can be used on anonymous types or types defined inside |
| +// functions. It's less safe than arraysize as it accepts some |
| +// (although not all) pointers. Therefore, you should use arraysize |
| +// whenever possible. |
| +// |
| +// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type |
| +// size_t. |
| +// |
| +// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error |
| +// |
| +// "warning: division by zero in ..." |
| +// |
| +// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. |
| +// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. |
| +// |
| +// The following comments are on the implementation details, and can |
| +// be ignored by the users. |
| +// |
| +// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in |
| +// the array) and sizeof(*(arr)) (the # of bytes in one array |
| +// element). If the former is divisible by the latter, perhaps arr is |
| +// indeed an array, in which case the division result is the # of |
| +// elements in the array. Otherwise, arr cannot possibly be an array, |
| +// and we generate a compiler error to prevent the code from |
| +// compiling. |
| +// |
| +// Since the size of bool is implementation-defined, we need to cast |
| +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final |
| +// result has type size_t. |
| +// |
| +// This macro is not perfect as it wrongfully accepts certain |
| +// pointers, namely where the pointer size is divisible by the pointee |
| +// size. Since all our code has to go through a 32-bit compiler, |
| +// where a pointer is 4 bytes, this means all pointers to a type whose |
| +// size is 3 or greater than 4 will be (righteously) rejected. |
| +#define ARRAYSIZE_UNSAFE(a) \ |
|
Yang
2014/08/26 09:17:22
Do we actually need this?
|
| + ((sizeof(a) / sizeof(*(a))) / \ |
| + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) // NOLINT |
| // A macro to disallow the evil copy constructor and operator= functions |