RNA: check for valid ranges with int properties (C11 only)
authorCampbell Barton <ideasman42@gmail.com>
Mon, 28 Jul 2014 10:00:33 +0000 (20:00 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 28 Jul 2014 10:08:25 +0000 (20:08 +1000)
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_internal.h

index 7f1f04cdb6a13f91e01adc6389c193edaeee2870..9023f25e3d544cac1a858ffb85a33a639a3d27da 100644 (file)
@@ -745,6 +745,24 @@ static void rna_clamp_value_range(FILE *f, PropertyRNA *prop)
        }
 }
 
+#ifdef USE_RNA_RANGE_CHECK
+static void rna_clamp_value_range_check(
+        FILE *f, PropertyRNA *prop,
+        const char *dnaname_prefix, const char *dnaname)
+{
+       if (prop->type == PROP_INT) {
+               IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
+               fprintf(f,
+                       "       { BLI_STATIC_ASSERT("
+                       "(TYPEOF_MAX(%s%s) >= %d) && "
+                       "(TYPEOF_MIN(%s%s) <= %d), "
+                       "\"invalid limits\"); }\n",
+                       dnaname_prefix, dnaname, iprop->hardmax,
+                       dnaname_prefix, dnaname, iprop->hardmin);
+       }
+}
+#endif  /* USE_RNA_RANGE_CHECK */
+
 static void rna_clamp_value(FILE *f, PropertyRNA *prop, int array)
 {
        if (prop->type == PROP_INT) {
@@ -944,6 +962,18 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
                                        }
                                        fprintf(f, "    }\n");
                                }
+
+#ifdef USE_RNA_RANGE_CHECK
+                               if (dp->dnaname && manualfunc == NULL) {
+                                       if (dp->dnaarraylength == 1) {
+                                               rna_clamp_value_range_check(f, prop, "data->", dp->dnaname);
+                                       }
+                                       else {
+                                               rna_clamp_value_range_check(f, prop, "*data->", dp->dnaname);
+                                       }
+                               }
+#endif
+
                                fprintf(f, "}\n\n");
                        }
                        else {
@@ -975,6 +1005,13 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
                                                rna_clamp_value(f, prop, 0);
                                        }
                                }
+
+#ifdef USE_RNA_RANGE_CHECK
+                               if (dp->dnaname && manualfunc == NULL) {
+                                       rna_clamp_value_range_check(f, prop, "data->", dp->dnaname);
+                               }
+#endif
+
                                fprintf(f, "}\n\n");
                        }
                        break;
index e3179077cf4411e57c3c2e25b7b7bdae37c4e761..bec6afff1317a2398ef0d1f701e14fb4ea98a6e3 100644 (file)
@@ -413,4 +413,24 @@ void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
 #  endif
 #endif
 
+/* C11 for compile time range checks */
+#if __STDC_VERSION__ >= 201112L
+#  define USE_RNA_RANGE_CHECK
+#  define TYPEOF_MAX(x) \
+       _Generic(x, \
+               bool: 1, \
+               char: CHAR_MAX, signed char: SCHAR_MAX, unsigned char: UCHAR_MAX, \
+               signed short: SHRT_MAX, unsigned short: USHRT_MAX, \
+               signed int: INT_MAX, unsigned int: UINT_MAX, \
+               float: FLT_MAX, double: DBL_MAX)
+
+#  define TYPEOF_MIN(x) \
+       _Generic(x, \
+               bool: 0, \
+               char: CHAR_MIN, signed char: SCHAR_MIN, unsigned char: 0, \
+               signed short: SHRT_MIN, unsigned short: 0, \
+               signed int: INT_MIN, unsigned int: 0, \
+               float: -FLT_MAX, double: -DBL_MAX)
+#endif
+
 #endif  /* __RNA_INTERNAL_H__ */