[cogl/wip/cogl-2.0: 1/3] Add _COGL_STATIC_ASSERT macro
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/cogl-2.0: 1/3] Add _COGL_STATIC_ASSERT macro
- Date: Tue, 17 Apr 2012 10:45:45 +0000 (UTC)
commit 88f0ac9e21fc04b16df1eb745ba206597bd4f199
Author: Robert Bragg <robert linux intel com>
Date: Mon Apr 16 17:23:15 2012 +0100
Add _COGL_STATIC_ASSERT macro
This adds a _COGL_STATIC_ASSERT macro that can be used for compile time
assertions in C code. If supported by the compiler this macro uses
_Static_assert so that a message can be printed out if the assertion
fails.
cogl/cogl-bitmask.c | 5 ++++-
cogl/cogl-pipeline.c | 14 ++++++++++++--
cogl/cogl-util.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 13 +++++++++++++
4 files changed, 77 insertions(+), 3 deletions(-)
---
diff --git a/cogl/cogl-bitmask.c b/cogl/cogl-bitmask.c
index 1d2f2f8..50f3f0f 100644
--- a/cogl/cogl-bitmask.c
+++ b/cogl/cogl-bitmask.c
@@ -37,7 +37,10 @@
/* This code assumes that we can cast an unsigned long to a pointer
and back without losing any data */
-G_STATIC_ASSERT (sizeof (unsigned long) <= sizeof (void *));
+_COGL_STATIC_ASSERT (sizeof (unsigned long) <= sizeof (void *),
+ "This toolchain breaks Cogl's assumption that it can "
+ "safely cast and unsigned long to a pointer without "
+ "loosing data");
#define ARRAY_INDEX(bit_num) \
((bit_num) / (sizeof (unsigned long) * 8))
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index a5f938c..0b37695 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -2590,8 +2590,13 @@ _cogl_pipeline_init_layer_state_hash_functions (void)
layer_state_hash_functions[_index] =
_cogl_pipeline_layer_hash_fragment_snippets_state;
+ {
/* So we get a big error if we forget to update this code! */
- g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 10);
+ _COGL_STATIC_ASSERT (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 10,
+ "Don't forget to install a hash function for new "
+ "pipeline state and update assert at end of "
+ "_cogl_pipeline_init_state_hash_functions");
+ }
}
static gboolean
@@ -2697,8 +2702,13 @@ _cogl_pipeline_init_state_hash_functions (void)
state_hash_functions[COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS_INDEX] =
_cogl_pipeline_hash_fragment_snippets_state;
+ {
/* So we get a big error if we forget to update this code! */
- g_assert (COGL_PIPELINE_STATE_SPARSE_COUNT == 16);
+ _COGL_STATIC_ASSERT (COGL_PIPELINE_STATE_SPARSE_COUNT == 16,
+ "Make sure to install a hash function for "
+ "newly added pipeline state and update assert "
+ "in _cogl_pipeline_init_state_hash_functions");
+ }
}
unsigned int
diff --git a/cogl/cogl-util.h b/cogl/cogl-util.h
index 199a11b..de0fdb3 100644
--- a/cogl/cogl-util.h
+++ b/cogl/cogl-util.h
@@ -34,6 +34,8 @@
#include <stdio.h>
#endif
+#include "config.h"
+
/* When compiling with Visual Studio, symbols that represent data that
are exported out of the DLL need to be marked with the dllexport
attribute. */
@@ -227,4 +229,50 @@ _cogl_util_pixel_format_from_masks (unsigned long r_mask,
int depth, int bpp,
int byte_order);
+/* Since we can't rely on _Static_assert always being available for
+ * all compilers we have limited static assert that can be used in
+ * C code but not in headers.
+ */
+#define _COGL_TYPEDEF_ASSERT(EXPRESSION) \
+ typedef struct { char Compile_Time_Assertion[(EXPRESSION) ? 1 : -1]; } \
+ G_PASTE (_GStaticAssert_, __LINE__)
+
+/* _COGL_STATIC_ASSERT:
+ * @expression: An expression to assert evaluates to true at compile
+ * time.
+ * @message: A message to print to the console if the assertion fails
+ * at compile time.
+ *
+ * Allows you to assert that an expression evaluates to true at
+ * compile time and aborts compilation if not. If possible message
+ * will also be printed if the assertion fails.
+ *
+ * Note: Only Gcc >= 4.6 supports the c11 _Static_assert which lets us
+ * print a nice message if the compile time assertion fails.
+ *
+ * Note: this assertion macro can only be used in C code where it is
+ * valid to use a typedef. This macro should not be used in headers
+ * because we can't guarantee a unique name for the typedef due to
+ * the name being based on the line number of the file it's used in.
+ *
+ * Although we can remove this limitation if the compiler supports
+ * _Static_assert we currently choose to maintain the limitation in
+ * any case to help ensure we don't accidentally create code that
+ * doesn't compile on some toolchains because we forgot about this
+ * limitation.
+ */
+#ifdef HAVE_STATIC_ASSERT
+#define _COGL_STATIC_ASSERT(EXPRESSION, MESSAGE) \
+ _Static_assert (EXPRESSION, MESSAGE); \
+ _COGL_TYPEDEF_ASSERT(EXPRESSION)
+#else
+#define _COGL_STATIC_ASSERT(EXPRESSION, MESSAGE) \
+ _COGL_TYPEDEF_ASSERT(EXPRESSION)
+
+/* So that we can safely use _Static_assert() if we want to add
+ * assertions to internal headers we define it to a NOP here
+ * if it's not supported by the compiler. */
+#define _Static_assert(EXPRESSION, MESSAGE)
+#endif
+
#endif /* __COGL_UTIL_H */
diff --git a/configure.ac b/configure.ac
index 9d3c991..668bf87 100644
--- a/configure.ac
+++ b/configure.ac
@@ -925,6 +925,19 @@ AM_PROG_CC_C_O
AC_ISC_POSIX
AC_C_CONST
+dnl ============================================================
+dnl Compiler features
+dnl ============================================================
+AC_TRY_COMPILE([],
+[
+_Static_assert (1, "");
+int
+main (int argc, char **argv)
+{
+ return 0;
+}
+],
+[AC_DEFINE([HAVE_STATIC_ASSERT], [1], [Whether _Static_assert can be used or not])])
dnl ================================================================
dnl Libtool stuff.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]