summaryrefslogtreecommitdiffstats
path: root/src/macros.h
diff options
context:
space:
mode:
authorCarl Shapiro <cshapiro@google.com>2011-06-22 11:45:37 -0700
committerCarl Shapiro <cshapiro@google.com>2011-06-22 11:45:37 -0700
commitd2bdb57c9a3ceb5ac86060186cfe735a11f1e76e (patch)
tree48635d154094ee3443bfc94557e2b62291a669d5 /src/macros.h
parenta2e18e1e77fc25c8260aad5daa267ababfcb65f6 (diff)
downloadart-d2bdb57c9a3ceb5ac86060186cfe735a11f1e76e.zip
art-d2bdb57c9a3ceb5ac86060186cfe735a11f1e76e.tar.gz
art-d2bdb57c9a3ceb5ac86060186cfe735a11f1e76e.tar.bz2
Add a macro for sizing anonymous or locally defined arrays.
Change-Id: If7f7c7fb7b45d9f07a729aad978b26ffd88222d6
Diffstat (limited to 'src/macros.h')
-rw-r--r--src/macros.h42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/macros.h b/src/macros.h
index be31e03..078628f 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -59,7 +59,7 @@ struct CompileAssert {
//
// 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() macro below. This is
+// 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.
@@ -71,6 +71,46 @@ char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+// 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) \
+ ((sizeof(a) / sizeof(*(a))) / \
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+
#define SIZEOF_MEMBER(t, f) sizeof(((t*) 4096)->f)
#define OFFSETOF_MEMBER(t, f) \