[cogl/wip/rib/cogl-1.12: 7/101] Add _COGL_STATIC_ASSERT macro



commit 92a7c910432882acd8ed43414b517350bc3dcf14
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.
    
    Reviewed-by: Neil Roberts <neil linux intel com>
    
    (cherry picked from commit 465b39a764f2720e77678cafa56acb0e69007ffd)

 cogl/cogl-bitmask.c          |    5 +++-
 cogl/cogl-pipeline.c         |   14 ++++++++++-
 cogl/cogl-util.h             |   51 ++++++++++++++++++++++++++++++++++++++++++
 configure.ac                 |   13 ++++++++++
 tests/conform/test-bitmask.c |    2 +-
 5 files changed, 81 insertions(+), 4 deletions(-)
---
diff --git a/cogl/cogl-bitmask.c b/cogl/cogl-bitmask.c
index 1d2f2f8..73c9d7c 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 an 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..5cd6897 100644
--- a/cogl/cogl-util.h
+++ b/cogl/cogl-util.h
@@ -34,6 +34,11 @@
 #include <stdio.h>
 #endif
 
+/* Double check that config.h has been included */
+#if !defined (GETTEXT_PACKAGE) && !defined (_COGL_IN_TEST_BITMASK)
+#error "config.h must be included before including cogl-util.h"
+#endif
+
 /* 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 +232,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 55fa37c..c890ac3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -935,6 +935,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.
diff --git a/tests/conform/test-bitmask.c b/tests/conform/test-bitmask.c
index 3e5e173..fdf7566 100644
--- a/tests/conform/test-bitmask.c
+++ b/tests/conform/test-bitmask.c
@@ -9,9 +9,9 @@
    within Cogl. Cogl doesn't export the symbols for this data type so
    we just directly include the source instead */
 
+#define _COGL_IN_TEST_BITMASK
 #include <cogl/cogl-bitmask.h>
 #include <cogl/cogl-bitmask.c>
-#define _COGL_IN_TEST_BITMASK
 #include <cogl/cogl-util.c>
 
 typedef struct



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]