[cogl/wip/cogl-2.0: 1/3] Add _COGL_STATIC_ASSERT macro



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]