[gnumeric] Standards: be C99 compliant when accessing GnmValue's type.



commit d660a287364ffa9ea1e8617645882e63c41c65ba
Author: Morten Welinder <terra gnome org>
Date:   Sun Oct 26 17:09:48 2014 -0400

    Standards: be C99 compliant when accessing GnmValue's type.
    
    There are three standards compliant ways of getting the tag field
    for a union like GnmValue.
    
    1. Via the subtype struct that the value has.  That only works (and
       is utterly pointless) when we already know the value type.
    
    2. Via another union member that is a structure having one or more
       initial members matching the actual struct type.  The silly thing
       is that this rule only applies to structs; I guess that is an
       oversight, but a fat lot of good that does us now.  In practice
       this means we should use ->v_any.type for that.
    
    3. Using the pointer-to-first-struct-member rule.
    
    To simplify matters, define VALUE_IS_ARRAY and VALUE_IS_CELLRANGE
    macros.

 ChangeLog                                    |    7 ++++
 NEWS                                         |    1 +
 plugins/excel/ms-chart.c                     |    4 +-
 plugins/excel/ms-excel-read.c                |    2 +-
 plugins/excel/ms-excel-write.c               |   10 +++---
 plugins/excel/ms-formula-write.c             |   10 ++---
 plugins/excel/xls-write-pivot.c              |    2 +-
 plugins/excel/xlsx-write-pivot.c             |    2 +-
 plugins/excel/xlsx-write.c                   |    2 +-
 plugins/excelplugins/excelplugins.c          |    6 ++--
 plugins/fn-database/functions.c              |    4 +-
 plugins/fn-eng/functions.c                   |    2 +-
 plugins/fn-info/functions.c                  |   12 +++---
 plugins/fn-lookup/functions.c                |   32 +++++++++---------
 plugins/fn-math/functions.c                  |   12 +++---
 plugins/fn-stat/functions.c                  |    9 ++---
 plugins/html/html.c                          |    2 +-
 plugins/openoffice/openoffice-write.c        |   10 +++---
 plugins/perl-loader/perl-gnumeric.c          |    2 +-
 plugins/python-loader/py-gnumeric.c          |    2 +-
 plugins/sc/sc.c                              |    2 +-
 src/auto-format.c                            |    2 +-
 src/collect.c                                |    8 ++--
 src/dependent.c                              |    2 +-
 src/dialogs/dialog-analysis-tool-sign-test.c |    4 +-
 src/dialogs/dialog-simulation.c              |    4 +-
 src/expr-name.c                              |    2 +-
 src/expr.c                                   |   46 +++++++++++++-------------
 src/func.c                                   |    8 ++--
 src/gnm-format.c                             |    4 +-
 src/graph.c                                  |   26 +++++++-------
 src/mstyle.c                                 |    2 +-
 src/ranges.c                                 |    8 ++--
 src/sheet-object-widget.c                    |    2 +-
 src/sheet.c                                  |    2 +-
 src/sort.c                                   |    4 +-
 src/ssdiff.c                                 |    2 +-
 src/stf-export.c                             |    2 +-
 src/style.c                                  |    2 +-
 src/tools/analysis-frequency.c               |    2 +-
 src/tools/analysis-histogram.c               |    2 +-
 src/tools/analysis-tools.c                   |    8 ++--
 src/tools/analysis-wilcoxon-mann-whitney.c   |    2 +-
 src/tools/dao.c                              |    3 +-
 src/tools/filter.c                           |    2 +-
 src/tools/gnm-solver.c                       |    4 +-
 src/tools/scenarios.c                        |    2 +-
 src/validation.c                             |    2 +-
 src/value-sheet.c                            |   18 +++++-----
 src/value.c                                  |   42 ++++++++++++------------
 src/value.h                                  |   19 ++++++-----
 src/widgets/gnumeric-expr-entry.c            |    4 +-
 src/workbook.c                               |    2 +-
 src/xml-sax-write.c                          |    6 ++--
 54 files changed, 194 insertions(+), 189 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 59b85da..509013e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-10-26  Morten Welinder  <terra gnome org>
+
+       * src/value.h (VALUE_IS_CELLRANGE, VALUE_IS_ARRAY): New macros.
+       Use throughout.
+       (GnmValue): Drop type union member.  C99 requires that this be
+       accessed in a structure.  We have v_any for that.
+
 2014-10-25  Morten Welinder  <terra gnome org>
 
        * src/expr-impl.h (GNM_EXPR_GET_OPER): Redefine in a way that
diff --git a/NEWS b/NEWS
index 850d925..aa36429 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Gnumeric 1.12.19
 
 Morten:
        * Plug leaks.
+       * Pay more attention to union access rules.
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.18
diff --git a/plugins/excel/ms-chart.c b/plugins/excel/ms-chart.c
index 91fddee..bf67598 100644
--- a/plugins/excel/ms-chart.c
+++ b/plugins/excel/ms-chart.c
@@ -5491,7 +5491,7 @@ chart_write_siindex (XLChartWriteState *s, guint msdim)
        msdim--;
        for (i = 0; i < s->values[msdim]->len; i++) {
                XLValue *xlval = s->values[msdim]->pdata[i];
-               if (xlval->value->type != VALUE_ARRAY)
+               if (!VALUE_IS_ARRAY (xlval->value))
                        continue;
                as_col = xlval->value->v_array.y > xlval->value->v_array.x;
                jmax = as_col
@@ -5501,7 +5501,7 @@ chart_write_siindex (XLChartWriteState *s, guint msdim)
                        GnmValue const* value = as_col
                                ? xlval->value->v_array.vals[0][j]
                                : xlval->value->v_array.vals[j][0];
-                       switch (value->type) {
+                       switch (value->v_any.type) {
                        case VALUE_FLOAT:
                                data = ms_biff_put_len_next (s->bp, BIFF_NUMBER_v2, 14);
                                GSF_LE_SET_DOUBLE (data + 6, value_get_as_float (value));
diff --git a/plugins/excel/ms-excel-read.c b/plugins/excel/ms-excel-read.c
index 0dad815..998a274 100644
--- a/plugins/excel/ms-excel-read.c
+++ b/plugins/excel/ms-excel-read.c
@@ -3698,7 +3698,7 @@ excel_parse_name (GnmXLImporter *importer, Sheet *sheet, char *name,
 
        if (0 == strcmp (name, "Print_Area")) {
                GnmValue *val = gnm_expr_get_range (texpr->expr);
-               if (val != NULL && val->type == VALUE_CELLRANGE) {
+               if (val != NULL && VALUE_IS_CELLRANGE (val)) {
                        GnmEvalPos ep;
                        int height, width;
 
diff --git a/plugins/excel/ms-excel-write.c b/plugins/excel/ms-excel-write.c
index 9bbd6a5..f4e109c 100644
--- a/plugins/excel/ms-excel-write.c
+++ b/plugins/excel/ms-excel-write.c
@@ -3386,7 +3386,7 @@ excel_write_map_errcode (GnmValue const *v)
 static void
 excel_write_value (ExcelWriteState *ewb, GnmValue *v, guint32 col, guint32 row, guint16 xf)
 {
-       switch (v->type) {
+       switch (v->v_any.type) {
 
        case VALUE_EMPTY: {
                guint8 *data = ms_biff_put_len_next (ewb->bp, BIFF_BLANK_v2, 6);
@@ -3486,7 +3486,7 @@ excel_write_value (ExcelWriteState *ewb, GnmValue *v, guint32 col, guint32 row,
                break;
 
        default:
-               g_printerr ("Unhandled value type %d\n", v->type);
+               g_printerr ("Unhandled value type %d\n", v->v_any.type);
                break;
        }
 }
@@ -3518,7 +3518,7 @@ excel_write_FORMULA (ExcelWriteState *ewb, ExcelWriteSheet *esheet, GnmCell cons
        EX_SETROW (data, row);
        EX_SETCOL (data, col);
        EX_SETXF  (data, xf);
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_FLOAT:
                gsf_le_set_double (data + 6, value_get_as_float (v));
                break;
@@ -3547,7 +3547,7 @@ excel_write_FORMULA (ExcelWriteState *ewb, ExcelWriteSheet *esheet, GnmCell cons
                break;
 
        default:
-               g_warning ("Unhandled value->type (%d) in excel_write_FORMULA.", v->type);
+               g_warning ("Unhandled value->type (%d) in excel_write_FORMULA.", v->v_any.type);
        }
 
        GSF_LE_SET_GUINT16 (data + 14, /* alwaysCalc & calcOnLoad */
@@ -3994,7 +3994,7 @@ excel_write_DOPER (GnmFilterCondition const *cond, int i, guint8 *buf)
 
        if (cond->op[i] == GNM_FILTER_UNUSED)
                return NULL;
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_BOOLEAN:
                buf[0] = 8;
                buf[2] = 0;
diff --git a/plugins/excel/ms-formula-write.c b/plugins/excel/ms-formula-write.c
index b3615db..b88c41a 100644
--- a/plugins/excel/ms-formula-write.c
+++ b/plugins/excel/ms-formula-write.c
@@ -118,7 +118,7 @@ cb_excel_write_prep_expr (GnmExpr const *expr, GnmExprWalk *data)
 
        case GNM_EXPR_OP_CONSTANT: {
                GnmValue const *v = expr->constant.value;
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        ExcelSheetPair pair;
                        pair.a = v->v_range.cell.a.sheet;
                        pair.b = v->v_range.cell.b.sheet;
@@ -753,7 +753,7 @@ write_node (PolishData *pd, GnmExpr const *expr, int paren_level,
 
         case GNM_EXPR_OP_CONSTANT : {
                GnmValue const *v = expr->constant.value;
-               switch (v->type) {
+               switch (v->v_any.type) {
 
                case VALUE_FLOAT: {
                        guint8 data[10];
@@ -826,10 +826,8 @@ write_node (PolishData *pd, GnmExpr const *expr, int paren_level,
                }
 
                default : {
-                       gchar *err = g_strdup_printf ("Unknown value %d\n", v->type);
-                       write_string (pd, err);
-                       g_free (err);
-                       g_warning ("Unhandled value type %d", v->type);
+                       write_string (pd, "(Unknown value)");
+                       g_warning ("Unhandled value type %d", v->v_any.type);
                        break;
                }
                }
diff --git a/plugins/excel/xls-write-pivot.c b/plugins/excel/xls-write-pivot.c
index 3501c09..96add48 100644
--- a/plugins/excel/xls-write-pivot.c
+++ b/plugins/excel/xls-write-pivot.c
@@ -106,7 +106,7 @@ static void
 xls_write_pivot_cache_value (ExcelWriteState *ewb, GOVal const *v)
 {
        if (NULL != v) {
-               switch (v->type) {
+               switch (v->v_any.type) {
                case VALUE_CELLRANGE:
                case VALUE_ARRAY:
                        g_warning ("REMOVE THIS CODE WHEN WE MOVE TO GOFFICE");
diff --git a/plugins/excel/xlsx-write-pivot.c b/plugins/excel/xlsx-write-pivot.c
index a0daf21..e1d56cd 100644
--- a/plugins/excel/xlsx-write-pivot.c
+++ b/plugins/excel/xlsx-write-pivot.c
@@ -37,7 +37,7 @@ xlsx_write_pivot_val (XLSXWriteState *state, GsfXMLOut *xml,
                      GOVal const *v)
 {
        g_return_if_fail (v != NULL);
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_CELLRANGE:
        case VALUE_ARRAY:
                g_warning ("REMOVE THIS CODE WHEN WE MOVE TO GOFFICE");
diff --git a/plugins/excel/xlsx-write.c b/plugins/excel/xlsx-write.c
index bbfc221..1995b95 100644
--- a/plugins/excel/xlsx-write.c
+++ b/plugins/excel/xlsx-write.c
@@ -1588,7 +1588,7 @@ xlsx_write_cells (XLSXWriteState *state, GsfXMLOut *xml,
                                if (style_id > -1)
                                        gsf_xml_out_add_int (xml, "s", style_id);
 
-                               switch (val->type) {
+                               switch (val->v_any.type) {
                                default :
                                case VALUE_EMPTY:
                                        type = NULL; /* FIXME : what to do ? */
diff --git a/plugins/excelplugins/excelplugins.c b/plugins/excelplugins/excelplugins.c
index cde4c22..1665a91 100644
--- a/plugins/excelplugins/excelplugins.c
+++ b/plugins/excelplugins/excelplugins.c
@@ -148,7 +148,7 @@ static const char *
 gnm_value_type_name (const GnmValue*g)
 {
        if (NULL != g) {
-               switch (g->type) {
+               switch (g->v_any.type) {
                CASE(VALUE_EMPTY);
                CASE(VALUE_BOOLEAN);
                CASE(VALUE_FLOAT);
@@ -277,7 +277,7 @@ copy_construct_xloper_from_gnm_value (XLOPER*out, const GnmValue*in,
        out->val.num = 0;
 
        if (NULL != in) {
-               switch (in->type) {
+               switch (in->v_any.type) {
                case VALUE_EMPTY:
                        out->xltype = xltypeNil;
                        break;
@@ -347,7 +347,7 @@ copy_construct_xloper_from_gnm_value (XLOPER*out, const GnmValue*in,
                        break;
                }
                default:;
-                       g_warning (_("Unsupported GnmValue type (%d)"),in->type);
+                       g_warning (_("Unsupported GnmValue type (%d)"),in->v_any.type);
                }
        }
 }
diff --git a/plugins/fn-database/functions.c b/plugins/fn-database/functions.c
index c33a6cf..9841cb1 100644
--- a/plugins/fn-database/functions.c
+++ b/plugins/fn-database/functions.c
@@ -222,7 +222,7 @@ database_float_range_function (GnmFuncEvalInfo *ei,
                return value_new_error_NUM (ei->pos);
 
        /* I don't like this -- minimal fix for now.  509427.  */
-       if (criteria->type != VALUE_CELLRANGE)
+       if (!VALUE_IS_CELLRANGE (criteria))
                return value_new_error_NUM (ei->pos);
 
        criterias = parse_database_criteria (ei->pos, database, criteria);
@@ -284,7 +284,7 @@ database_value_range_function (GnmFuncEvalInfo *ei,
                return value_new_error_NUM (ei->pos);
 
        /* I don't like this -- minimal fix for now.  509427.  */
-       if (criteria->type != VALUE_CELLRANGE)
+       if (!VALUE_IS_CELLRANGE (criteria))
                return value_new_error_NUM (ei->pos);
 
        criterias = parse_database_criteria (ei->pos, database, criteria);
diff --git a/plugins/fn-eng/functions.c b/plugins/fn-eng/functions.c
index acc514f..c71a27e 100644
--- a/plugins/fn-eng/functions.c
+++ b/plugins/fn-eng/functions.c
@@ -86,7 +86,7 @@ val_to_base (GnmFuncEvalInfo *ei,
        if (aplaces && VALUE_IS_BOOLEAN (aplaces))
                return value_new_error_VALUE (ei->pos);
 
-       switch (value->type) {
+       switch (value->v_any.type) {
        default:
                return value_new_error_NUM (ei->pos);
 
diff --git a/plugins/fn-info/functions.c b/plugins/fn-info/functions.c
index cf06ef1..c8d6993 100644
--- a/plugins/fn-info/functions.c
+++ b/plugins/fn-info/functions.c
@@ -1181,7 +1181,7 @@ static GnmValue *
 gnumeric_expression (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
        GnmValue const * const v = argv[0];
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmCell *cell;
                GnmCellRef const * a = &v->v_range.cell.a;
                GnmCellRef const * b = &v->v_range.cell.b;
@@ -1221,7 +1221,7 @@ static GnmValue *
 gnumeric_get_formula (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
        GnmValue const * const v = argv[0];
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmCell *cell;
                GnmCellRef const * a = &v->v_range.cell.a;
                GnmCellRef const * b = &v->v_range.cell.b;
@@ -1260,7 +1260,7 @@ static GnmValue *
 gnumeric_isformula (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
        GnmValue const * const v = argv[0];
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmCell *cell;
                GnmCellRef const * a = &v->v_range.cell.a;
                GnmCellRef const * b = &v->v_range.cell.b;
@@ -1312,7 +1312,7 @@ gnumeric_countblank (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
                value_area_get_height (v, ei->pos);
        int nsheets = 1;
 
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmRange r;
                Sheet *start_sheet, *end_sheet;
 
@@ -1766,7 +1766,7 @@ static GnmValue *
 gnumeric_type (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
        GnmValue const *v = argv[0];
-       switch (v ? v->type : VALUE_EMPTY) {
+       switch (v ? v->v_any.type : VALUE_EMPTY) {
        case VALUE_BOOLEAN:
                return value_new_int (4);
        case VALUE_EMPTY:
@@ -1826,7 +1826,7 @@ gnumeric_get_link (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
 {
        GnmValue const * const v = argv[0];
 
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmCellRef const * a = &v->v_range.cell.a;
                GnmCellRef const * b = &v->v_range.cell.b;
                Sheet *sheet;
diff --git a/plugins/fn-lookup/functions.c b/plugins/fn-lookup/functions.c
index e130ca5..9b2fafc 100644
--- a/plugins/fn-lookup/functions.c
+++ b/plugins/fn-lookup/functions.c
@@ -325,7 +325,7 @@ get_linear_lookup_cache (GnmFuncEvalInfo *ei,
                return NULL;
        }
 
-       switch (data->type) {
+       switch (data->v_any.type) {
        case VALUE_CELLRANGE: {
                GnmSheetRange sr;
                GnmRangeRef const *rr = value_get_rangeref (data);
@@ -425,7 +425,7 @@ get_bisection_lookup_cache (GnmFuncEvalInfo *ei,
                return NULL;
        }
 
-       switch (data->type) {
+       switch (data->v_any.type) {
        case VALUE_CELLRANGE: {
                GnmSheetRange sr;
                GnmRangeRef const *rr = value_get_rangeref (data);
@@ -491,7 +491,7 @@ find_compare_type_valid (GnmValue const *find, GnmValue const *val)
        if (!val)
                return FALSE;
 
-       if (find->type == val->type)
+       if (find->v_any.type == val->v_any.type)
                return TRUE;
 
        /* Note: floats do not match bools.  */
@@ -595,7 +595,7 @@ find_index_linear_equal_float (GnmFuncEvalInfo *ei,
        LinearLookupInfo info;
 
        /* This handles floats and bools, but with separate caches.  */
-       h = get_linear_lookup_cache (ei, data, find->type, vertical,
+       h = get_linear_lookup_cache (ei, data, find->v_any.type, vertical,
                                     &info);
        if (!h)
                return LOOKUP_DATA_ERROR;
@@ -688,12 +688,12 @@ find_index_bisection (GnmFuncEvalInfo *ei,
        LookupBisectionCacheItemElem key;
        BisectionLookupInfo info;
 
-       bc = get_bisection_lookup_cache (ei, data, find->type, vertical,
+       bc = get_bisection_lookup_cache (ei, data, find->v_any.type, vertical,
                                         &info);
        if (!bc)
                return LOOKUP_DATA_ERROR;
 
-       stringp = (find->type == VALUE_STRING);
+       stringp = VALUE_IS_STRING (find);
        comparer = stringp ? bisection_compare_string : bisection_compare_float;
 
        if (info.is_new) {
@@ -926,7 +926,7 @@ gnumeric_areas (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
        case GNM_EXPR_OP_CONSTANT:
                if (VALUE_IS_ERROR (expr->constant.value))
                        return value_dup (expr->constant.value);
-               if (expr->constant.value->type != VALUE_CELLRANGE)
+               if (!VALUE_IS_CELLRANGE (expr->constant.value))
                        break;
 
        case GNM_EXPR_OP_CELLREF:
@@ -938,7 +938,7 @@ gnumeric_areas (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
        case GNM_EXPR_OP_FUNCALL: {
                GnmValue *v = gnm_expr_eval (expr, ei->pos,
                        GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
-               if (v->type == VALUE_CELLRANGE)
+               if (VALUE_IS_CELLRANGE (v))
                        res = 1;
                value_release (v);
                break;
@@ -1198,7 +1198,7 @@ gnumeric_lookup (GnmFuncEvalInfo *ei, GnmValue const * const *args)
                }
 
                vertical_lookup = (width < height);
-               is_cellrange = (lookup->type == VALUE_CELLRANGE);
+               is_cellrange = VALUE_IS_CELLRANGE (lookup);
 #if 0
                if (is_cellrange) {
                        GnmRange r;
@@ -1422,7 +1422,7 @@ gnumeric_index (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
        }
 
 #warning Work out a way to fall back to returning value when a reference is unneeded
-       if (VALUE_CELLRANGE == v->type) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmRangeRef const *src = &v->v_range.cell;
                GnmCellRef a = src->a, b = src->b;
                Sheet *start_sheet, *end_sheet;
@@ -1436,7 +1436,7 @@ gnumeric_index (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
                a.col = r.start.col; if (a.col_relative) a.col -= ei->pos->eval.col;
                b.col = r.start.col; if (b.col_relative) b.col -= ei->pos->eval.col;
                res = value_new_cellrange_unsafe (&a, &b);
-       } else if (VALUE_ARRAY == v->type)
+       } else if (VALUE_IS_ARRAY (v))
                res = value_dup (value_area_fetch_x_y (v, elem[1], elem[0], ei->pos));
        else
                res = value_new_error_REF (ei->pos);
@@ -1474,7 +1474,7 @@ gnumeric_column (GnmFuncEvalInfo *ei, GnmValue const * const *args)
                        width = ei->pos->array->cols;
                else
                        return value_new_int (col);
-       } else if (ref->type == VALUE_CELLRANGE) {
+       } else if (VALUE_IS_CELLRANGE (ref)) {
                Sheet    *tmp;
                GnmRange  r;
 
@@ -1625,7 +1625,7 @@ gnumeric_row (GnmFuncEvalInfo *ei, GnmValue const * const *args)
                        n = ei->pos->array->rows;
                else
                        return value_new_int (row);
-       } else if (ref->type == VALUE_CELLRANGE) {
+       } else if (VALUE_IS_CELLRANGE (ref)) {
                Sheet    *tmp;
                GnmRange  r;
 
@@ -1681,7 +1681,7 @@ gnumeric_sheets (GnmFuncEvalInfo *ei, GnmValue const * const *args)
        GnmValue const *v = args[0];
 
        if(v) {
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        GnmRangeRef const *r = &v->v_range.cell;
                        int ans_min, ans_max, a, b;
 
@@ -1722,7 +1722,7 @@ gnumeric_sheet (GnmFuncEvalInfo *ei, GnmValue const * const *args)
        int n;
 
        if(v) {
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        GnmRangeRef const *r = &v->v_range.cell;
                        int a, b;
 
@@ -1735,7 +1735,7 @@ gnumeric_sheet (GnmFuncEvalInfo *ei, GnmValue const * const *args)
                                n = MAX (a,b);
                        else
                                return value_new_error_NUM (ei->pos);
-               } else if (v->type == VALUE_STRING) {
+               } else if (VALUE_IS_STRING (v)) {
                        Sheet *sheet = workbook_sheet_by_name
                                (wb, value_peek_string (v));
                        if (!sheet)
diff --git a/plugins/fn-math/functions.c b/plugins/fn-math/functions.c
index 5dceb59..3472fc1 100644
--- a/plugins/fn-math/functions.c
+++ b/plugins/fn-math/functions.c
@@ -524,7 +524,7 @@ gnumeric_countif (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
         * not need to.
         * 1) @range must be a range, arrays are not supported
         * 2) @range can not be 3d */
-       if (r->type != VALUE_CELLRANGE ||
+       if (!VALUE_IS_CELLRANGE (argv[0]) ||
            ((sheet = eval_sheet (r->cell.a.sheet, ei->pos->sheet)) != r->cell.b.sheet &&
             r->cell.b.sheet != NULL) ||
            (!VALUE_IS_NUMBER (argv[1]) && !VALUE_IS_STRING (argv[1])))
@@ -622,9 +622,9 @@ gnumeric_sumif (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
         * not need to.
         * 1) @range must be a range, arrays are not supported
         * 2) @range can not be 3d */
-       if (argv[0]->type != VALUE_CELLRANGE ||
+       if (!VALUE_IS_CELLRANGE (argv[0]) ||
            (!VALUE_IS_NUMBER (argv[1]) && !VALUE_IS_STRING (argv[1])) ||
-           (argv[2] != NULL && argv[2]->type != VALUE_CELLRANGE))
+           (argv[2] != NULL && !VALUE_IS_CELLRANGE (argv[2])))
                return value_new_error_VALUE (ei->pos);
 
        gnm_rangeref_normalize (&argv[0]->v_range.cell, ei->pos,
@@ -687,9 +687,9 @@ gnumeric_averageif (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
         * not need to.
         * 1) @range must be a range, arrays are not supported
         * 2) @range can not be 3d */
-       if (argv[0]->type != VALUE_CELLRANGE ||
+       if (!VALUE_IS_CELLRANGE (argv[0]) ||
            (!VALUE_IS_NUMBER (argv[1]) && !VALUE_IS_STRING (argv[1])) ||
-           (argv[2] != NULL && argv[2]->type != VALUE_CELLRANGE))
+           (argv[2] != NULL && !VALUE_IS_CELLRANGE (argv[2])))
                return value_new_error_VALUE (ei->pos);
 
        gnm_rangeref_normalize (&argv[0]->v_range.cell, ei->pos,
@@ -3064,7 +3064,7 @@ gnumeric_sumproduct_common (gboolean ignore_bools, GnmFuncEvalInfo *ei,
                        for (x = 0; x < thissizex; x++) {
                                /* FIXME: efficiency worries?  */
                                GnmValue const *v = value_area_fetch_x_y (val, x, y, ei->pos);
-                               switch (v->type) {
+                               switch (v->v_any.type) {
                                case VALUE_ERROR:
                                        /*
                                         * We carefully tranverse the argument
diff --git a/plugins/fn-stat/functions.c b/plugins/fn-stat/functions.c
index d54309b..e27bb7f 100644
--- a/plugins/fn-stat/functions.c
+++ b/plugins/fn-stat/functions.c
@@ -3685,7 +3685,7 @@ gnumeric_logfit (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
        int                nx, ny, i;
        gnm_float         *logfit_res = NULL;
 
-       if (argv[0] == NULL || argv[0]->type != VALUE_CELLRANGE)
+       if (argv[0] == NULL || !VALUE_IS_CELLRANGE (argv[0]))
                goto out;
        ys = collect_floats_value (argv[0], ei->pos,
                                   COLLECT_IGNORE_BLANKS | /* zeroing blanks
@@ -3697,7 +3697,7 @@ numbers */
                                   &ny, &result);
        if (result)
                goto out;
-       if (argv[1] == NULL || argv[1]->type != VALUE_CELLRANGE)
+       if (argv[1] == NULL || !VALUE_IS_CELLRANGE (argv[1]))
                goto out;
        xs = collect_floats_value (argv[1], ei->pos,
                                   COLLECT_IGNORE_BLANKS |
@@ -4355,12 +4355,11 @@ function_marshal_arg (GnmFuncEvalInfo *ei,
        else
                v = gnm_expr_eval (t, ei->pos, GNM_EXPR_EVAL_PERMIT_NON_SCALAR);
 
-       if (v->type != VALUE_ARRAY &&
-           v->type != VALUE_CELLRANGE) {
+       if (!VALUE_IS_ARRAY (v) && !VALUE_IS_CELLRANGE (v)) {
                *type_mismatch = value_new_error_VALUE (ei->pos);
        }
 
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                gnm_cellref_make_abs (&v->v_range.cell.a, &v->v_range.cell.a,
                        ei->pos);
                gnm_cellref_make_abs (&v->v_range.cell.b, &v->v_range.cell.b,
diff --git a/plugins/html/html.c b/plugins/html/html.c
index 2e2f553..5a07597 100644
--- a/plugins/html/html.c
+++ b/plugins/html/html.c
@@ -332,7 +332,7 @@ html_write_cell_content (GsfOutput *output, GnmCell *cell, GnmStyle const *style
                                        gsf_output_printf (output, "<font color=\"#%02X%02X%02X\">", r, g, b);
                        }
 
-                       if ((cell->value->type == VALUE_STRING)
+                       if (VALUE_IS_STRING (cell->value)
                            && (VALUE_FMT (cell->value) != NULL)
                            && go_format_is_markup (VALUE_FMT (cell->value)))
                                markup = go_format_get_markup (VALUE_FMT (cell->value));
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index 9c0df83..3378b0e 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -3343,7 +3343,7 @@ odf_write_cell (GnmOOExport *state, GnmCell *cell, GnmRange const *merge_range,
                        g_free (eq_formula);
                }
 
-               switch (cell->value->type) {
+               switch (cell->value->v_any.type) {
                case VALUE_EMPTY:
                        break;
                case VALUE_BOOLEAN:
@@ -4035,7 +4035,7 @@ odf_write_sheet_control_radio_button (GnmOOExport *state, SheetObject *so)
        gsf_xml_out_add_cstr (state->xml, FORM "label", label);
 
        if (val != NULL) {
-               switch (val->type) {
+               switch (val->v_any.type) {
                case VALUE_EMPTY:
                        break;
                case VALUE_BOOLEAN:
@@ -6199,7 +6199,7 @@ odf_write_data_element_range (GnmOOExport *state,  GnmParsePos *pp, GnmExprTop c
 
        switch (GNM_EXPR_GET_OPER (texpr->expr)) {
        case GNM_EXPR_OP_CONSTANT: 
-               if (texpr->expr->constant.value->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (texpr->expr->constant.value)) {
                        str = gnm_expr_top_as_string (texpr, pp, state->conv);
                        gsf_xml_out_add_cstr (state->xml, attribute,
                                              odf_strip_brackets (str));
@@ -6215,7 +6215,7 @@ odf_write_data_element_range (GnmOOExport *state,  GnmParsePos *pp, GnmExprTop c
                for (i = 0; i < expr->set.argc; i++) {
                        GnmExpr const *expr_arg = expr->set.argv[i];
                        if (GNM_EXPR_GET_OPER (expr_arg) == GNM_EXPR_OP_CONSTANT && 
-                           expr_arg->constant.value->type == VALUE_CELLRANGE) {
+                           VALUE_IS_CELLRANGE (expr_arg->constant.value)) {
                                char *str = gnm_expr_as_string (expr_arg, pp, state->conv);
                                if (gstr->len > 0)
                                        g_string_append_c (gstr, ' ');
@@ -7891,7 +7891,7 @@ odf_write_plot (GnmOOExport *state, SheetObject *so, GogObject const *graph,
                                                = gnm_go_data_get_expr (dat);
                                        if (texpr != NULL &&
                                            GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_CONSTANT
-                                           && texpr->expr->constant.value->type == VALUE_STRING) {
+                                           && VALUE_IS_STRING (texpr->expr->constant.value)) {
                                                gboolean white_written = TRUE;
                                                char const *str;
                                                gboolean pp = TRUE;
diff --git a/plugins/perl-loader/perl-gnumeric.c b/plugins/perl-loader/perl-gnumeric.c
index de8b694..e14968b 100644
--- a/plugins/perl-loader/perl-gnumeric.c
+++ b/plugins/perl-loader/perl-gnumeric.c
@@ -6,7 +6,7 @@ value2perl(const GnmValue *v)
 {
        SV *sv;
 
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_BOOLEAN:
                sv = newSViv(value_get_as_int (v));
                break;
diff --git a/plugins/python-loader/py-gnumeric.c b/plugins/python-loader/py-gnumeric.c
index add1e21..6a3e04e 100644
--- a/plugins/python-loader/py-gnumeric.c
+++ b/plugins/python-loader/py-gnumeric.c
@@ -325,7 +325,7 @@ gnm_value_to_py_obj (const GnmEvalPos *eval_pos, const GnmValue *val)
        g_return_val_if_fail (eval_pos != NULL, NULL);
        g_return_val_if_fail (val != NULL, NULL);
 
-    switch (val->type) {
+    switch (val->v_any.type) {
        case VALUE_BOOLEAN:
                py_val = py_new_Boolean_object (value_get_as_checked_bool (val));
                break;
diff --git a/plugins/sc/sc.c b/plugins/sc/sc.c
index 362e734..21243fb 100644
--- a/plugins/sc/sc.c
+++ b/plugins/sc/sc.c
@@ -261,7 +261,7 @@ sc_parse_coord_real (ScParseState *state, char const *strdata, GnmCellPos *pos,
        parse_pos_init (&pp, NULL, state->sheet, 0, 0);
        nexpr = expr_name_lookup (&pp, tmpstr);
        if (nexpr && (v = gnm_expr_top_get_range (nexpr->texpr))) {
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        GnmEvalPos ep;
                        const GnmCellRef *cr = &v->v_range.cell.a;
 
diff --git a/src/auto-format.c b/src/auto-format.c
index e759e34..04f5a40 100644
--- a/src/auto-format.c
+++ b/src/auto-format.c
@@ -157,7 +157,7 @@ do_af_suggest (GnmExpr const *expr, GnmEvalPos const *epos, GOFormat const **exp
        case GNM_EXPR_OP_CONSTANT: {
                GnmValue const *v = expr->constant.value;
 
-               switch (v->type) {
+               switch (v->v_any.type) {
                case VALUE_STRING:
                case VALUE_ERROR:
                        return GNM_FUNC_AUTO_UNKNOWN;
diff --git a/src/collect.c b/src/collect.c
index 2cfbf48..636d57d 100644
--- a/src/collect.c
+++ b/src/collect.c
@@ -321,7 +321,7 @@ callback_function_collect (GnmEvalPos const *ep, GnmValue const *value,
        collect_floats_t *cl = closure;
        gboolean ignore = FALSE;
 
-       switch (value ? value->type : VALUE_EMPTY) {
+       switch (value ? value->v_any.type : VALUE_EMPTY) {
        case VALUE_EMPTY:
                if (cl->flags & COLLECT_IGNORE_BLANKS)
                        ignore = TRUE;
@@ -381,7 +381,7 @@ callback_function_collect (GnmEvalPos const *ep, GnmValue const *value,
 
        default:
                g_warning ("Trouble in callback_function_collect. (%d)",
-                          value->type);
+                          value->v_any.type);
                ignore = TRUE;
        }
 
@@ -783,9 +783,9 @@ collect_float_pairs (GnmValue const *vx, GnmValue const *vy,
        PairsFloatsCacheEntry *ce = NULL;
        gboolean use_cache, free_keys = TRUE;
 
-       if (vx->type == VALUE_CELLRANGE)
+       if (VALUE_IS_CELLRANGE (vx))
                key_x = get_single_cache_key_from_value (vx, ep);
-       if (vy->type == VALUE_CELLRANGE)
+       if (VALUE_IS_CELLRANGE (vy))
                key_y = get_single_cache_key_from_value (vy, ep);
 
        if ((use_cache = (key_x && key_y)))
diff --git a/src/dependent.c b/src/dependent.c
index e89971f..6f582f2 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -1076,7 +1076,7 @@ link_unlink_expr_dep (GnmEvalPos *ep, GnmExpr const *tree, gboolean qlink)
                /* TODO: pass in eval flags so that we can use implicit
                 * intersection
                 */
-               if (VALUE_CELLRANGE == tree->constant.value->type)
+               if (VALUE_IS_CELLRANGE (tree->constant.value))
                        return link_unlink_cellrange_dep
                                (ep->dep, dependent_pos (ep->dep),
                                 &tree->constant.value->v_range.cell.a,
diff --git a/src/dialogs/dialog-analysis-tool-sign-test.c b/src/dialogs/dialog-analysis-tool-sign-test.c
index f91294c..83be3f5 100644
--- a/src/dialogs/dialog-analysis-tool-sign-test.c
+++ b/src/dialogs/dialog-analysis-tool-sign-test.c
@@ -136,7 +136,7 @@ sign_test_two_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
         input_range = gnm_expr_entry_parse_as_value
                (GNM_EXPR_ENTRY (state->base.input_entry),
                 state->base.sheet);
-       if (input_range == NULL || input_range->type != VALUE_CELLRANGE) {
+       if (input_range == NULL || !VALUE_IS_CELLRANGE (input_range)) {
                gtk_label_set_text (GTK_LABEL (state->base.warning),
                                    (state->base.input_entry_2 == NULL)
                                    ? _("The input range is invalid.")
@@ -157,7 +157,7 @@ sign_test_two_tool_update_sensitivity_cb (G_GNUC_UNUSED GtkWidget *dummy,
                input_range = gnm_expr_entry_parse_as_value
                        (GNM_EXPR_ENTRY (state->base.input_entry_2),
                         state->base.sheet);
-               if (input_range == NULL || input_range->type != VALUE_CELLRANGE) {
+               if (input_range == NULL || !VALUE_IS_CELLRANGE (input_range)) {
                        gtk_label_set_text (GTK_LABEL (state->base.warning),
                                            _("The second input range is invalid."));
                        gtk_widget_set_sensitive (state->base.ok_button, FALSE);
diff --git a/src/dialogs/dialog-simulation.c b/src/dialogs/dialog-simulation.c
index 1e445a0..6cc7ca9 100644
--- a/src/dialogs/dialog-simulation.c
+++ b/src/dialogs/dialog-simulation.c
@@ -100,8 +100,8 @@ prepare_ranges (simulation_t *sim)
 {
        int i, n, base_col, base_row;
 
-       if (sim->inputs->type != VALUE_CELLRANGE ||
-           sim->outputs->type != VALUE_CELLRANGE)
+       if (!VALUE_IS_CELLRANGE (sim->inputs) ||
+           !VALUE_IS_CELLRANGE (sim->outputs))
                return TRUE;
 
        sim->ref_inputs  = gnm_rangeref_dup (value_get_rangeref (sim->inputs));
diff --git a/src/expr-name.c b/src/expr-name.c
index 6de077d..ae9614b 100644
--- a/src/expr-name.c
+++ b/src/expr-name.c
@@ -459,7 +459,7 @@ cb_check_name (G_GNUC_UNUSED gpointer key, GnmNamedExpr *nexpr,
 
        v = gnm_expr_top_get_range (nexpr->texpr);
        if (v != NULL) {
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        GnmRangeRef const *ref = &v->v_range.cell;
                        if (!ref->a.col_relative &&
                            !ref->b.col_relative &&
diff --git a/src/expr.c b/src/expr.c
index 3aa981c..5130eab 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -674,7 +674,7 @@ gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
                v = function_call_with_exprs (&ei);
 
                if (v != NULL) {
-                       if (v->type == VALUE_CELLRANGE) {
+                       if (VALUE_IS_CELLRANGE (v)) {
                                *res = v->v_range.cell;
                                failed = FALSE;
                        }
@@ -690,7 +690,7 @@ gnm_expr_extract_ref (GnmRangeRef *res, GnmExpr const *expr,
 
        case GNM_EXPR_OP_CONSTANT: {
                GnmValue const *v = expr->constant.value;
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        *res = v->v_range.cell;
                        return FALSE;
                }
@@ -750,7 +750,7 @@ value_intersection (GnmValue *v, GnmEvalPos const *pos)
        Sheet *start_sheet, *end_sheet;
        gboolean found = FALSE;
 
-       if (v->type == VALUE_ARRAY) {
+       if (VALUE_IS_ARRAY (v)) {
                res = (v->v_array.x == 0 || v->v_array.y == 0)
                        ? value_new_error_VALUE (NULL)
                        : value_dup (v->v_array.vals[0][0]);
@@ -1025,7 +1025,7 @@ bin_array_iter_a (GnmEvalPos const *ep,
         * If both items have non-singular sizes for
         * the same dimension use the min size (see samples/array.xls) */
        if (b != NULL &&
-           (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)) {
+           (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))) {
                int sa, sb, w = 1, h = 1;
 
                sa = value_area_get_width  (a, ep);
@@ -1248,7 +1248,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                if (a != NULL) {
                        if (VALUE_IS_ERROR (a))
                                return a;
-                       if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)
+                       if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))
                                return bin_array_iter_a (pos, a,
                                        gnm_expr_eval (expr->binary.value_b, pos, flags),
                                        (BinOpImplicitIteratorFunc) cb_bin_cmp,
@@ -1261,7 +1261,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                                value_release (a);
                                return b;
                        }
-                       if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
+                       if (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))
                                return bin_array_iter_b (pos, a, b,
                                        (BinOpImplicitIteratorFunc) cb_bin_cmp,
                                        expr);
@@ -1304,7 +1304,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                        if (tmp == NULL)
                                return value_new_error_VALUE (pos);
                        a = tmp;
-               } else if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY) {
+               } else if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a)) {
                        b = gnm_expr_eval (expr->binary.value_b, pos, flags);
                        if (VALUE_IS_STRING (b)) {
                                res = format_match_number (value_peek_string (b), NULL,
@@ -1338,7 +1338,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                                return value_new_error_VALUE (pos);
                        }
                        b = tmp;
-               } else if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
+               } else if (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))
                        return bin_array_iter_b (pos, a, b,
                                (BinOpImplicitIteratorFunc) cb_bin_arith,
                                expr);
@@ -1380,7 +1380,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                        if (tmp == NULL)
                                return value_new_error_VALUE (pos);
                        a = tmp;
-               } else if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY) {
+               } else if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a)) {
                        res = value_new_array_empty (
                                value_area_get_width  (a, pos),
                                value_area_get_height (a, pos));
@@ -1409,7 +1409,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                if (a != NULL) {
                        if (VALUE_IS_ERROR (a))
                                return a;
-                       if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)
+                       if (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))
                                return bin_array_iter_a (pos, a,
                                        gnm_expr_eval (expr->binary.value_b, pos, flags),
                                        (BinOpImplicitIteratorFunc) cb_bin_cat,
@@ -1421,7 +1421,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                                value_release (a);
                                return b;
                        }
-                       if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
+                       if (VALUE_IS_CELLRANGE (b) || VALUE_IS_ARRAY (b))
                                return bin_array_iter_b (pos, a, b,
                                        (BinOpImplicitIteratorFunc) cb_bin_cat,
                                        expr);
@@ -1454,7 +1454,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                if (res == NULL)
                        return (flags & GNM_EXPR_EVAL_PERMIT_EMPTY)
                            ? NULL : value_new_int (0);
-               if (res->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (res)) {
                        /*
                         * pos->dep really shouldn't be NULL here, but it
                         * will be if someone puts "indirect" into an
@@ -1471,7 +1471,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                        }
                        return res;
                }
-               if (res->type == VALUE_ARRAY &&
+               if (VALUE_IS_ARRAY (res) &&
                    !(flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)) {
                        a = value_dup (res->v_array.vals[0][0]);
                        value_release (res);
@@ -1506,7 +1506,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
 
        case GNM_EXPR_OP_CONSTANT:
                res = value_dup (expr->constant.value);
-               if (res->type == VALUE_CELLRANGE || res->type == VALUE_ARRAY) {
+               if (VALUE_IS_CELLRANGE (res) || VALUE_IS_ARRAY (res)) {
                        if (flags & GNM_EXPR_EVAL_PERMIT_NON_SCALAR)
                                return res;
                        res = value_intersection (res, pos);
@@ -1529,7 +1529,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                ((GnmExpr*)expr)->array_corner.value = a;
 
                if (a != NULL &&
-                   (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)) {
+                   (VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
                        if (value_area_get_width (a, pos) <= 0 ||
                            value_area_get_height (a, pos) <= 0)
                                return value_new_error_NA (pos);
@@ -1553,7 +1553,7 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
                if (a == NULL)
                        return handle_empty (NULL, flags);
 
-               if ((a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)) {
+               if ((VALUE_IS_CELLRANGE (a) || VALUE_IS_ARRAY (a))) {
                        int const num_x = value_area_get_width (a, pos);
                        int const num_y = value_area_get_height (a, pos);
                        int x = expr->array_elem.x;
@@ -1764,12 +1764,12 @@ do_expr_as_string (GnmExpr const *expr, int paren_level,
                        return;
                }
 
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        out->convs->output.range_ref (out, &v->v_range.cell);
                        return;
                }
 
-               if (v->type == VALUE_BOOLEAN &&
+               if (VALUE_IS_BOOLEAN (v) &&
                    out->convs->output.boolean != NULL) {
                        out->convs->output.boolean (out, v->v_bool.val);
                        return;
@@ -2232,7 +2232,7 @@ cb_relocate (GnmExpr const *expr, GnmExprWalk *data)
        }
 
        case GNM_EXPR_OP_CONSTANT:
-               if (expr->constant.value->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (expr->constant.value)) {
                        GnmValueRange const *vr = &expr->constant.value->v_range;
                        switch (rinfo->details->reloc_type) {
                        case GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
@@ -2347,7 +2347,7 @@ gnm_expr_get_range (GnmExpr const *expr)
                        &expr->cellref.ref, &expr->cellref.ref);
 
        case GNM_EXPR_OP_CONSTANT:
-               if (expr->constant.value->type == VALUE_CELLRANGE)
+               if (VALUE_IS_CELLRANGE (expr->constant.value))
                        return value_dup (expr->constant.value);
                return NULL;
 
@@ -2409,7 +2409,7 @@ gnm_expr_is_rangeref (GnmExpr const *expr)
                return TRUE;
 
        case GNM_EXPR_OP_CONSTANT:
-               if (expr->constant.value->type == VALUE_CELLRANGE)
+               if (VALUE_IS_CELLRANGE (expr->constant.value))
                        return TRUE;
                return FALSE;
 
@@ -3144,7 +3144,7 @@ cb_referenced_sheets (GnmExpr const *expr, GnmExprWalk *data)
 
        case GNM_EXPR_OP_CONSTANT: {
                GnmValue const *v = expr->constant.value;
-               if (v->type != VALUE_CELLRANGE)
+               if (!VALUE_IS_CELLRANGE (v))
                        break;
                *psheets = gnm_insert_unique (*psheets, v->v_range.cell.a.sheet);
                /* A NULL b sheet means a's sheet.  Do not insert that.  */
@@ -3255,7 +3255,7 @@ cb_get_boundingbox (GnmExpr const *expr, GnmExprWalk *data)
        case GNM_EXPR_OP_CONSTANT: {
                GnmValue const *v = expr->constant.value;
 
-               if (v->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (v)) {
                        cellref_boundingbox (&v->v_range.cell.a, args->sheet, args->bound);
                        cellref_boundingbox (&v->v_range.cell.b, args->sheet, args->bound);
                }
diff --git a/src/func.c b/src/func.c
index febb34f..1228a3d 100644
--- a/src/func.c
+++ b/src/func.c
@@ -1838,7 +1838,7 @@ function_call_with_exprs (GnmFuncEvalInfo *ei)
                                return tmp;
                        }
 
-                       if (tmp->type == VALUE_CELLRANGE) {
+                       if (VALUE_IS_CELLRANGE (tmp)) {
                                gnm_cellref_make_abs (&tmp->v_range.cell.a,
                                                      &tmp->v_range.cell.a,
                                                      ei->pos);
@@ -1846,7 +1846,7 @@ function_call_with_exprs (GnmFuncEvalInfo *ei)
                                                      &tmp->v_range.cell.b,
                                                      ei->pos);
                                /* Array args accept scalars */
-                       } else if (arg_type != 'A' && tmp->type != VALUE_ARRAY) {
+                       } else if (arg_type != 'A' && !VALUE_IS_ARRAY (tmp)) {
                                free_values (args, i + 1);
                                return value_new_error_VALUE (ei->pos);
                        }
@@ -1880,7 +1880,7 @@ function_call_with_exprs (GnmFuncEvalInfo *ei)
                        tmp = args[i] = value_new_empty ();
 
                /* Handle implicit intersection or iteration depending on flags */
-               if (tmp->type == VALUE_CELLRANGE || tmp->type == VALUE_ARRAY) {
+               if (VALUE_IS_CELLRANGE (tmp) || VALUE_IS_ARRAY (tmp)) {
                        if (iter_count > 0) {
                                if (iter_width != value_area_get_width (tmp, ei->pos) ||
                                    iter_height != value_area_get_height (tmp, ei->pos)) {
@@ -2148,7 +2148,7 @@ function_iterate_do_value (GnmEvalPos const  *ep,
 {
        GnmValue *res = NULL;
 
-       switch (value->type){
+       switch (value->v_any.type){
        case VALUE_ERROR:
                if (strict) {
                        res = value_dup (value);
diff --git a/src/gnm-format.c b/src/gnm-format.c
index bf77536..0458edb 100644
--- a/src/gnm-format.c
+++ b/src/gnm-format.c
@@ -39,7 +39,7 @@
 static char const *
 format_nonnumber (GnmValue const *value)
 {
-       switch (value->type) {
+       switch (value->v_any.type) {
        case VALUE_EMPTY:
                return "";
 
@@ -112,7 +112,7 @@ format_value_common (PangoLayout *layout, GString *str,
 
        /* Use top left corner of an array result.  This will not work for
         * ranges because we dont't have a location */
-       if (value->type == VALUE_ARRAY)
+       if (value->v_any.type == VALUE_ARRAY)
                value = value_area_fetch_x_y (value, 0, 0, NULL);
 
        if (VALUE_IS_FLOAT (value)) {
diff --git a/src/graph.c b/src/graph.c
index a9305e6..775c194 100644
--- a/src/graph.c
+++ b/src/graph.c
@@ -91,7 +91,7 @@ render_val (GnmValue const *v, int i, int j,
                    fmt ? go_format_as_XL (fmt) : "-");
 #endif
 
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                Sheet *start_sheet, *end_sheet;
                GnmCell *cell;
                GnmRange r;
@@ -108,7 +108,7 @@ render_val (GnmValue const *v, int i, int j,
 
                if (fmt == NULL)
                        fmt = gnm_cell_get_format (cell);
-       } else if (v->type == VALUE_ARRAY)
+       } else if (VALUE_IS_ARRAY (v))
                v = value_area_get_x_y (v, i, j, ep);
 
        return format_value (fmt, v, -1, date_conv);
@@ -558,7 +558,7 @@ gnm_go_data_vector_load_len (GODataVector *dat)
        }
 
        if (vec->val != NULL) {
-               switch (vec->val->type) {
+               switch (vec->val->v_any.type) {
                case VALUE_CELLRANGE:
                        gnm_rangeref_normalize (&vec->val->v_range.cell, &ep,
                                &start_sheet, &end_sheet, &r);
@@ -585,7 +585,7 @@ gnm_go_data_vector_load_len (GODataVector *dat)
                        for (j = 0; j < vec->val->v_array.y; j++)
                                for (i = 0; i < vec->val->v_array.x; i++) {
                                        v = vec->val->v_array.vals[i][j];
-                                       if (v->type == VALUE_CELLRANGE) {
+                                       if (VALUE_IS_CELLRANGE (v)) {
                                                gnm_rangeref_normalize (&v->v_range.cell, &ep,
                                                        &start_sheet, &end_sheet, &r);
                                                new_len += (guint64)range_width (&r) * range_height (&r)
@@ -690,7 +690,7 @@ gnm_go_data_vector_load_values (GODataVector *dat)
        if (dat->values == NULL)
                dat->values = g_new (double, dat->len);
        vals = dat->values;
-       switch (vec->val->type) {
+       switch (vec->val->v_any.type) {
        case VALUE_CELLRANGE:
                gnm_rangeref_normalize (&vec->val->v_range.cell,
                        eval_pos_init_dep (&ep, &vec->dep),
@@ -744,7 +744,7 @@ gnm_go_data_vector_load_values (GODataVector *dat)
                        x--;
                        v = vec->val->v_array.vals [x][y];
 
-                       if (v->type == VALUE_CELLRANGE) {
+                       if (VALUE_IS_CELLRANGE (v)) {
                                gnm_rangeref_normalize (&v->v_range.cell,
                                        eval_pos_init_dep (&ep, &vec->dep),
                                        &start_sheet, &end_sheet, &r);
@@ -839,7 +839,7 @@ gnm_go_data_vector_get_value (GODataVector *dat, unsigned i)
        if (vec->val == NULL)
                gnm_go_data_vector_load_len (dat);
 
-       if (vec->val->type == VALUE_ARRAY) {
+       if (VALUE_IS_ARRAY (vec->val)) {
                if ((dat->base.flags & GO_DATA_CACHE_IS_VALID) == 0)
                        gnm_go_data_vector_load_values (dat);
                return dat->values[i];
@@ -892,7 +892,7 @@ gnm_go_data_vector_get_str (GODataVector *dat, unsigned i)
        g_return_val_if_fail (vec->val != NULL, NULL);
 
        eval_pos_init_dep (&ep, &vec->dep);
-       if (vec->val->type == VALUE_ARRAY) {
+       if (VALUE_IS_ARRAY (vec->val)) {
                /* we need to cache the strings if needed */
                int len = vec->val->v_array.y * vec->val->v_array.x;
                int x = 0, y = vec->val->v_array.y;
@@ -904,7 +904,7 @@ gnm_go_data_vector_get_str (GODataVector *dat, unsigned i)
                        x--;
                        v = vec->val->v_array.vals [x][y];
 
-                       if (v->type == VALUE_CELLRANGE) {
+                       if (VALUE_IS_CELLRANGE (v)) {
                                /* actually we only need to cache in that case */
                                Sheet *start_sheet, *end_sheet;
                                GnmRange r;
@@ -978,7 +978,7 @@ gnm_go_data_vector_get_markup (GODataVector *dat, unsigned i)
                        return NULL;
                vec->markup = g_ptr_array_new_with_free_func
                        ((GDestroyNotify)cond_pango_attr_list_unref);
-               switch (vec->val->type) {
+               switch (vec->val->v_any.type) {
                case VALUE_CELLRANGE:
                        gnm_rangeref_normalize (&vec->val->v_range.cell,
                                eval_pos_init_dep (&ep, &vec->dep),
@@ -1006,7 +1006,7 @@ gnm_go_data_vector_get_markup (GODataVector *dat, unsigned i)
                                        ? vec->val->v_array.vals [0][len]
                                        : vec->val->v_array.vals [len][0];
 
-                               if (v->type == VALUE_CELLRANGE) {
+                               if (VALUE_IS_CELLRANGE (v)) {
                                        gnm_rangeref_normalize (&v->v_range.cell,
                                                eval_pos_init_dep (&ep, &vec->dep),
                                                &start_sheet, &end_sheet, &r);
@@ -1139,7 +1139,7 @@ gnm_go_data_matrix_load_size (GODataMatrix *dat)
        }
 
        if (mat->val != NULL) {
-               switch (mat->val->type) {
+               switch (mat->val->v_any.type) {
                case VALUE_CELLRANGE:
                        gnm_rangeref_normalize (&mat->val->v_range.cell, &ep,
                                &start_sheet, &end_sheet, &r);
@@ -1273,7 +1273,7 @@ gnm_go_data_matrix_load_values (GODataMatrix *dat)
        if (dat->values == NULL)
                dat->values = g_new (double, size.rows * size.columns);
        vals = dat->values;
-       switch (mat->val->type) {
+       switch (mat->val->v_any.type) {
        case VALUE_CELLRANGE:
                gnm_rangeref_normalize (&mat->val->v_range.cell,
                        eval_pos_init_dep (&ep, &mat->dep),
diff --git a/src/mstyle.c b/src/mstyle.c
index bfbd2f2..ad8c7e0 100644
--- a/src/mstyle.c
+++ b/src/mstyle.c
@@ -1898,7 +1898,7 @@ static gboolean
 cond_expr_harmless (GnmExpr const *expr)
 {
        GnmValue const *v = gnm_expr_get_constant (expr);
-       if (v && v->type != VALUE_CELLRANGE)
+       if (v && !VALUE_IS_CELLRANGE (v))
                return TRUE;
 
        return FALSE;
diff --git a/src/ranges.c b/src/ranges.c
index 56e958a..d469b22 100644
--- a/src/ranges.c
+++ b/src/ranges.c
@@ -90,8 +90,8 @@ range_init_rangeref (GnmRange *range, GnmRangeRef const *rr)
 GnmRange *
 range_init_value (GnmRange *range, GnmValue const *v)
 {
-       g_return_val_if_fail (range != NULL && v != NULL &&
-                             v->type == VALUE_CELLRANGE, NULL);
+       g_return_val_if_fail (range != NULL, NULL);
+       g_return_val_if_fail (v != NULL && VALUE_IS_CELLRANGE (v), NULL);
 
        return range_init_rangeref (range, &v->v_range.cell);
 }
@@ -816,7 +816,7 @@ gnm_sheet_range_dup (GnmSheetRange const *sr)
 gboolean
 gnm_sheet_range_from_value (GnmSheetRange *r, GnmValue const *v)
 {
-       g_return_val_if_fail (v->type == VALUE_CELLRANGE, FALSE);
+       g_return_val_if_fail (VALUE_IS_CELLRANGE (v), FALSE);
 
        r->sheet = v->v_range.cell.a.sheet;
        range_init_value (&r->range, v);
@@ -1110,7 +1110,7 @@ global_range_contained (Sheet const *sheet, GnmValue const *a, GnmValue const *b
        g_return_val_if_fail (a != NULL, FALSE);
        g_return_val_if_fail (b != NULL, FALSE);
 
-       if ((a->type != VALUE_CELLRANGE) || (b->type != VALUE_CELLRANGE))
+       if (!VALUE_IS_CELLRANGE (a) || !VALUE_IS_CELLRANGE (b))
                return FALSE;
 
        target = eval_sheet (a->v_range.cell.a.sheet, sheet);
diff --git a/src/sheet-object-widget.c b/src/sheet-object-widget.c
index 3214909..8b8b8a8 100644
--- a/src/sheet-object-widget.c
+++ b/src/sheet-object-widget.c
@@ -3056,7 +3056,7 @@ sheet_widget_radio_button_write_xml_sax (SheetObject const *so,
 
        gsf_xml_out_add_cstr (output, "Label", swrb->label);
        gsf_xml_out_add_cstr (output, "Value", valstr->str);
-       gsf_xml_out_add_int (output, "ValueType", swrb->value->type);
+       gsf_xml_out_add_int (output, "ValueType", swrb->value->v_any.type);
        gsf_xml_out_add_int (output, "Active", swrb->active);
        sax_write_dep (output, &swrb->dep, "Input", convs);
 
diff --git a/src/sheet.c b/src/sheet.c
index edfbfc5..2135051 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -6454,7 +6454,7 @@ sheet_range_has_heading (Sheet const *sheet, GnmRange const *src,
                        if (!VALUE_IS_NUMBER (b->value))
                                return TRUE;
                        /* check for style differences */
-               } else if (a->value->type != b->value->type)
+               } else if (a->value->v_any.type != b->value->v_any.type)
                        return TRUE;
 
                /* Look for style differences */
diff --git a/src/sort.c b/src/sort.c
index 0a1c1e5..d79c4ac 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -66,8 +66,8 @@ sort_compare_cells (GnmCell const *ca, GnmCell const *cb,
        else
                b = cb->value;
 
-       ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->type;
-       tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->type;
+       ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->v_any.type;
+       tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->v_any.type;
 
        if (ta == VALUE_EMPTY && tb != VALUE_EMPTY) {
                comp = clause->asc ? IS_LESS : IS_GREATER;
diff --git a/src/ssdiff.c b/src/ssdiff.c
index f469378..e194de7 100644
--- a/src/ssdiff.c
+++ b/src/ssdiff.c
@@ -391,7 +391,7 @@ output_cell (GnmDiffState *state, GnmCell const *cell,
        } else {
                GnmValue const *v = cell->value;
                value_get_as_gstring (v, str, state->convs);
-               gsf_xml_out_add_int (state->xml, valtag, v->type);
+               gsf_xml_out_add_int (state->xml, valtag, v->v_any.type);
                if (VALUE_FMT (v))
                        gsf_xml_out_add_cstr (state->xml, fmttag, go_format_as_XL (VALUE_FMT (v)));
        }
diff --git a/src/stf-export.c b/src/stf-export.c
index 0652447..b0f7474 100644
--- a/src/stf-export.c
+++ b/src/stf-export.c
@@ -152,7 +152,7 @@ try_auto_float (GnmValue *value, const GOFormat *format,
        gboolean is_date;
        int is_time;
 
-       if (value->type != VALUE_FLOAT)
+       if (!VALUE_IS_FLOAT (value))
                return NULL;
 
        format = gnm_format_specialize (format, value);
diff --git a/src/style.c b/src/style.c
index 33c2ca8..d6f1c75 100644
--- a/src/style.c
+++ b/src/style.c
@@ -593,7 +593,7 @@ gnm_style_default_halign (GnmStyle const *style, GnmCell const *c)
                return GNM_HALIGN_LEFT;
 
        for (v = c->value; v != NULL ; )
-               switch (v->type) {
+               switch (v->v_any.type) {
                case VALUE_BOOLEAN:
                case VALUE_ERROR:
                        return GNM_HALIGN_CENTER;
diff --git a/src/tools/analysis-frequency.c b/src/tools/analysis-frequency.c
index 7f04c55..ec175be 100644
--- a/src/tools/analysis-frequency.c
+++ b/src/tools/analysis-frequency.c
@@ -252,7 +252,7 @@ static gint
 calc_length (GnmValue   *bin)
 {
        g_return_val_if_fail (bin != NULL, 0);
-       g_return_val_if_fail (bin->type == VALUE_CELLRANGE, 0);
+       g_return_val_if_fail (VALUE_IS_CELLRANGE (bin), 0);
 
        return ((bin->v_range.cell.b.col - bin->v_range.cell.a.col + 1) *
                (bin->v_range.cell.b.row - bin->v_range.cell.a.row + 1));
diff --git a/src/tools/analysis-histogram.c b/src/tools/analysis-histogram.c
index 2e6ef32..626e2c6 100644
--- a/src/tools/analysis-histogram.c
+++ b/src/tools/analysis-histogram.c
@@ -427,7 +427,7 @@ static gint
 calc_length (GnmValue   *bin)
 {
        g_return_val_if_fail (bin != NULL, 0);
-       g_return_val_if_fail (bin->type == VALUE_CELLRANGE, 0);
+       g_return_val_if_fail (VALUE_IS_CELLRANGE (bin), 0);
 
        return ((bin->v_range.cell.b.col - bin->v_range.cell.a.col + 1) *
                (bin->v_range.cell.b.row - bin->v_range.cell.a.row + 1));
diff --git a/src/tools/analysis-tools.c b/src/tools/analysis-tools.c
index 4853e20..bb39cad 100644
--- a/src/tools/analysis-tools.c
+++ b/src/tools/analysis-tools.c
@@ -114,7 +114,7 @@ cb_adjust_areas (gpointer data, G_GNUC_UNUSED gpointer user_data)
 {
        GnmValue *range = (GnmValue *)data;
 
-       if (range == NULL || (range->type != VALUE_CELLRANGE)) {
+       if (range == NULL || !VALUE_IS_CELLRANGE (range)) {
                return;
        }
 
@@ -293,7 +293,7 @@ cb_cut_into_cols (gpointer data, gpointer user_data)
        if (range == NULL) {
                return;
        }
-       if ((range->type != VALUE_CELLRANGE) ||
+       if (!VALUE_IS_CELLRANGE (range) ||
            (range->v_range.cell.b.sheet != NULL &&
             range->v_range.cell.b.sheet != range->v_range.cell.a.sheet)) {
                value_release (range);
@@ -334,7 +334,7 @@ cb_cut_into_rows (gpointer data, gpointer user_data)
        if (range == NULL) {
                return;
        }
-       if ((range->type != VALUE_CELLRANGE) ||
+       if (!VALUE_IS_CELLRANGE (range) ||
            (range->v_range.cell.b.sheet != NULL &&
             range->v_range.cell.b.sheet != range->v_range.cell.a.sheet)) {
                value_release (range);
@@ -408,7 +408,7 @@ cb_check_hom (gpointer data, gpointer user_data)
        homogeneity_check_t *state = (homogeneity_check_t *) user_data;
        gint this_size;
 
-       if (range->type != VALUE_CELLRANGE) {
+       if (!VALUE_IS_CELLRANGE (range)) {
                state->hom = FALSE;
                return;
        }
diff --git a/src/tools/analysis-wilcoxon-mann-whitney.c b/src/tools/analysis-wilcoxon-mann-whitney.c
index 7455568..9cbbd2c 100644
--- a/src/tools/analysis-wilcoxon-mann-whitney.c
+++ b/src/tools/analysis-wilcoxon-mann-whitney.c
@@ -40,7 +40,7 @@ GnmExpr const *analysis_tool_combine_area (GnmValue *val_1, GnmValue *val_2, Wor
        GnmFunc *fd_array;
        GnmExpr const *expr;
 
-       if (val_1->type == VALUE_CELLRANGE && val_2->type == VALUE_CELLRANGE &&
+       if (VALUE_IS_CELLRANGE (val_1) && VALUE_IS_CELLRANGE (val_2) &&
            val_1->v_range.cell.a.sheet == val_2->v_range.cell.a.sheet) {
                GnmRange r_1, r_2;
                gboolean combined = FALSE;
diff --git a/src/tools/dao.c b/src/tools/dao.c
index 7a096de..7381be9 100644
--- a/src/tools/dao.c
+++ b/src/tools/dao.c
@@ -123,8 +123,7 @@ dao_load_from_value (data_analysis_output_t *dao,
                     GnmValue *output_range)
 {
        g_return_val_if_fail (output_range != NULL, dao);
-       g_return_val_if_fail
-               (output_range->type == VALUE_CELLRANGE, dao);
+       g_return_val_if_fail (VALUE_IS_CELLRANGE (output_range), dao);
 
        dao->start_col = output_range->v_range.cell.a.col;
        dao->start_row = output_range->v_range.cell.a.row;
diff --git a/src/tools/filter.c b/src/tools/filter.c
index e1e4153..0effd72 100644
--- a/src/tools/filter.c
+++ b/src/tools/filter.c
@@ -112,7 +112,7 @@ advanced_filter (WorkbookControl        *wbc,
        Sheet *sheet = criteria->v_range.cell.a.sheet;
 
        /* I don't like this -- minimal fix for now.  509427.  */
-       if (criteria->type != VALUE_CELLRANGE)
+       if (!VALUE_IS_CELLRANGE (criteria))
                return analysis_tools_invalid_field;
 
        crit = parse_database_criteria (
diff --git a/src/tools/gnm-solver.c b/src/tools/gnm-solver.c
index d78431d..90c6127 100644
--- a/src/tools/gnm-solver.c
+++ b/src/tools/gnm-solver.c
@@ -193,14 +193,14 @@ gnm_solver_constraint_valid (GnmSolverConstraint const *c,
        g_return_val_if_fail (c != NULL, FALSE);
 
        lhs = gnm_solver_constraint_get_lhs (c);
-       if (lhs == NULL || lhs->type != VALUE_CELLRANGE)
+       if (lhs == NULL || !VALUE_IS_CELLRANGE (lhs))
                return FALSE;
 
        if (gnm_solver_constraint_has_rhs (c)) {
                GnmValue const *rhs = gnm_solver_constraint_get_rhs (c);
                if (rhs == NULL)
                        return FALSE;
-               if (rhs->type == VALUE_CELLRANGE) {
+               if (VALUE_IS_CELLRANGE (rhs)) {
                        GnmSheetRange srl, srr;
 
                        gnm_sheet_range_from_value (&srl, lhs);
diff --git a/src/tools/scenarios.c b/src/tools/scenarios.c
index 7ee8350..40cc7d5 100644
--- a/src/tools/scenarios.c
+++ b/src/tools/scenarios.c
@@ -111,7 +111,7 @@ gnm_scenario_item_valid (const GnmScenarioItem *sci, GnmSheetRange *sr)
                return FALSE;
 
        vr = gnm_expr_top_get_constant (texpr);
-       if (!vr || vr->type != VALUE_CELLRANGE)
+       if (!vr || !VALUE_IS_CELLRANGE (vr))
                return FALSE;
 
        if (sr)
diff --git a/src/validation.c b/src/validation.c
index 9909863..8f0797e 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -518,7 +518,7 @@ gnm_validation_eval (WorkbookControl *wbc, GnmStyle const *mstyle,
        }
 
        val = cell->value;
-       switch (val->type) {
+       switch (val->v_any.type) {
        case VALUE_ERROR:
                if (typeinfo[v->type].errors_not_allowed)
                        BARF (g_strdup_printf (_("Cell %s is not permitted to contain error values"),
diff --git a/src/value-sheet.c b/src/value-sheet.c
index 9592b3c..b2536a4 100644
--- a/src/value-sheet.c
+++ b/src/value-sheet.c
@@ -23,7 +23,7 @@
 void
 value_dump (GnmValue const *value)
 {
-       switch (value->type){
+       switch (value->v_any.type){
        case VALUE_EMPTY:
                g_print ("EMPTY\n");
                break;
@@ -90,7 +90,7 @@ value_area_get_width (GnmValue const *v, GnmEvalPos const *ep)
 {
        g_return_val_if_fail (v, 0);
 
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmRangeRef const *r = &v->v_range.cell;
                int ans = r->b.col - r->a.col;
 
@@ -102,7 +102,7 @@ value_area_get_width (GnmValue const *v, GnmEvalPos const *ep)
                if (ans < 0)
                        ans = -ans;
                return ans + 1;
-       } else if (v->type == VALUE_ARRAY)
+       } else if (VALUE_IS_ARRAY (v))
                return v->v_array.x;
        return 1;
 }
@@ -112,7 +112,7 @@ value_area_get_height (GnmValue const *v, GnmEvalPos const *ep)
 {
        g_return_val_if_fail (v, 0);
 
-       if (v->type == VALUE_CELLRANGE) {
+       if (VALUE_IS_CELLRANGE (v)) {
                GnmRangeRef const *r = &v->v_range.cell;
                int ans = r->b.row - r->a.row;
 
@@ -125,7 +125,7 @@ value_area_get_height (GnmValue const *v, GnmEvalPos const *ep)
                if (ans < 0)
                        ans = -ans;
                return ans + 1;
-       } else if (v->type == VALUE_ARRAY)
+       } else if (VALUE_IS_ARRAY (v))
                return v->v_array.y;
        return 1;
 }
@@ -169,12 +169,12 @@ value_area_get_x_y (GnmValue const *v, int x, int y, GnmEvalPos const *ep)
 {
        g_return_val_if_fail (v, NULL);
 
-       if (v->type == VALUE_ARRAY){
+       if (VALUE_IS_ARRAY (v)){
                g_return_val_if_fail (x < v->v_array.x &&
                                      y < v->v_array.y,
                                      NULL);
                return v->v_array.vals [x][y];
-       } else if (v->type == VALUE_CELLRANGE) {
+       } else if (VALUE_IS_CELLRANGE (v)) {
                GnmCellRef const * const a = &v->v_range.cell.a;
                GnmCellRef const * const b = &v->v_range.cell.b;
                int a_col = a->col;
@@ -286,7 +286,7 @@ value_area_foreach (GnmValue const *v, GnmEvalPos const *ep,
 
        g_return_val_if_fail (func != NULL, NULL);
 
-        if (v->type == VALUE_CELLRANGE) {
+        if (VALUE_IS_CELLRANGE (v)) {
                WrapperClosure wrap;
                GnmRange  r;
                Sheet *start_sheet, *end_sheet;
@@ -308,7 +308,7 @@ value_area_foreach (GnmValue const *v, GnmEvalPos const *ep,
        v_iter.cell_iter = NULL;
 
        /* If not an array, apply func to singleton */
-        if (v->type != VALUE_ARRAY) {
+        if (!VALUE_IS_ARRAY (v)) {
                v_iter.x = v_iter.y = 0;
                v_iter.v = v;
                return (*func) (&v_iter, user_data);
diff --git a/src/value.c b/src/value.c
index 3704d4b..eea95f5 100644
--- a/src/value.c
+++ b/src/value.c
@@ -200,7 +200,7 @@ GnmValue *
 value_error_set_pos (GnmValueErr *err, G_GNUC_UNUSED GnmEvalPos const *pos)
 {
     g_return_val_if_fail (err != NULL, NULL);
-    g_return_val_if_fail (VALUE_IS_ERROR (err), NULL);
+    g_return_val_if_fail (VALUE_IS_ERROR ((GnmValue *)err), NULL);
 
     /* err->src = *pos; */
     return (GnmValue *)err;
@@ -540,7 +540,7 @@ value_release (GnmValue *value)
        if (VALUE_FMT (value) != NULL)
                go_format_unref (VALUE_FMT (value));
 
-       switch (value->type) {
+       switch (value->v_any.type) {
        case VALUE_EMPTY:
        case VALUE_BOOLEAN:
                /* We did not allocate anything, there is nothing to free */
@@ -610,7 +610,7 @@ value_dup (GnmValue const *src)
        if (src == NULL)
                return NULL;
 
-       switch (src->type){
+       switch (src->v_any.type){
        case VALUE_EMPTY:
                res = value_new_empty ();
                break;
@@ -685,7 +685,7 @@ value_cmp (void const *ptr_a, void const *ptr_b)
        default :
                break;
        }
-       return a->type - b->type;
+       return a->v_any.type - b->v_any.type;
 }
 
 int
@@ -697,10 +697,10 @@ value_cmp_reverse (void const *ptr_a, void const *ptr_b)
 gboolean
 value_equal (GnmValue const *a, GnmValue const *b)
 {
-       if (a->type != b->type)
+       if (a->v_any.type != b->v_any.type)
                return FALSE;
 
-       switch (a->type) {
+       switch (a->v_any.type) {
        case VALUE_BOOLEAN:
                return a->v_bool.val == b->v_bool.val;
 
@@ -744,7 +744,7 @@ value_equal (GnmValue const *a, GnmValue const *b)
 guint
 value_hash (GnmValue const *v)
 {
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_BOOLEAN:
                return v->v_bool.val ? 0x555aaaa : 0xaaa5555;
 
@@ -802,7 +802,7 @@ value_get_as_bool (GnmValue const *v, gboolean *err)
        if (v == NULL)
                return FALSE;
 
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_EMPTY:
                return FALSE;
 
@@ -866,7 +866,7 @@ value_get_as_gstring (GnmValue const *v, GString *target,
        if (v == NULL)
                return;
 
-       switch (v->type){
+       switch (v->v_any.type){
        case VALUE_EMPTY:
                return;
 
@@ -1009,7 +1009,7 @@ value_get_as_int (GnmValue const *v)
 {
        if (v == NULL)
                return 0;
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_EMPTY:
                return 0;
 
@@ -1033,7 +1033,7 @@ value_get_as_int (GnmValue const *v)
                return 0;
 
        default:
-               g_warning ("value_get_as_int unknown type 0x%x (%d).", v->type, v->type);
+               g_warning ("value_get_as_int unknown type 0x%x (%d).", v->v_any.type, v->v_any.type);
                return 0;
        }
        return 0;
@@ -1048,7 +1048,7 @@ value_get_as_float (GnmValue const *v)
        if (v == NULL)
                return 0.;
 
-       switch (v->type) {
+       switch (v->v_any.type) {
        case VALUE_EMPTY:
                return 0.;
 
@@ -1087,7 +1087,7 @@ value_is_zero (GnmValue const *v)
 GnmRangeRef const *
 value_get_rangeref (GnmValue const *v)
 {
-       g_return_val_if_fail (v->type == VALUE_CELLRANGE, NULL);
+       g_return_val_if_fail (VALUE_IS_CELLRANGE (v), NULL);
        return &v->v_range.cell;
 }
 
@@ -1129,7 +1129,7 @@ void
 value_array_set (GnmValue *array, int col, int row, GnmValue *v)
 {
        g_return_if_fail (v);
-       g_return_if_fail (array->type == VALUE_ARRAY);
+       g_return_if_fail (VALUE_IS_ARRAY (array));
        g_return_if_fail (col>=0);
        g_return_if_fail (row>=0);
        g_return_if_fail (array->v_array.y > row);
@@ -1181,8 +1181,8 @@ value_diff (GnmValue const *a, GnmValue const *b)
        if (a == b)
                return 0.;
 
-       ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->type;
-       tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->type;
+       ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->v_any.type;
+       tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->v_any.type;
 
        /* string > empty */
        if (ta == VALUE_STRING) {
@@ -1291,8 +1291,8 @@ value_compare_real (GnmValue const *a, GnmValue const *b,
        if (a == b)
                return IS_EQUAL;
 
-       ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->type;
-       tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->type;
+       ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->v_any.type;
+       tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->v_any.type;
 
        /* string > empty */
        if (ta == VALUE_STRING) {
@@ -1390,7 +1390,7 @@ value_set_fmt (GnmValue *v, GOFormat const *fmt)
 {
        if (fmt == VALUE_FMT (v))
                return;
-       g_return_if_fail (v->type != VALUE_EMPTY && v->type != VALUE_BOOLEAN);
+       g_return_if_fail (!VALUE_IS_EMPTY (v) && !VALUE_IS_BOOLEAN (v));
        if (fmt != NULL)
                go_format_ref (fmt);
        if (VALUE_FMT (v) != NULL)
@@ -1412,7 +1412,7 @@ criteria_inspect_values (GnmValue const *x, gnm_float *xr, gnm_float *yr,
        if (x == NULL || y == NULL)
                return CRIT_NULL;
 
-       switch (y->type) {
+       switch (y->v_any.type) {
        case VALUE_BOOLEAN:
                /* If we're searching for a bool -- even one that is
                   from a string search value -- we match only bools.  */
@@ -1818,7 +1818,7 @@ parse_database_criteria (GnmEvalPos const *ep, GnmValue const *database, GnmValu
        int   b_col, b_row, e_col, e_row;
        int   *field_ind;
 
-       g_return_val_if_fail (criteria->type == VALUE_CELLRANGE, NULL);
+       g_return_val_if_fail (VALUE_IS_CELLRANGE (criteria), NULL);
 
        sheet = eval_sheet (criteria->v_range.cell.a.sheet, ep->sheet);
        b_col = criteria->v_range.cell.a.col;
diff --git a/src/value.h b/src/value.h
index 9cf6210..ed05a44 100644
--- a/src/value.h
+++ b/src/value.h
@@ -69,7 +69,6 @@ struct _GnmValueArray {
 };
 
 union _GnmValue {
-       GnmValueType const type;
        GnmValueAny     v_any;
        GnmValueBool    v_bool;
        GnmValueFloat   v_float;
@@ -80,14 +79,16 @@ union _GnmValue {
 };
 
 #define        VALUE_FMT(v)                    ((v)->v_any.fmt)
-#define VALUE_IS_EMPTY(v)              (((v) == NULL) || ((v)->type == VALUE_EMPTY))
-#define VALUE_IS_EMPTY_OR_ERROR(v)     (VALUE_IS_EMPTY(v) || (v)->type == VALUE_ERROR)
-#define VALUE_IS_STRING(v)             ((v)->type == VALUE_STRING)
-#define VALUE_IS_BOOLEAN(v)            ((v)->type == VALUE_BOOLEAN)
-#define VALUE_IS_ERROR(v)              ((v)->type == VALUE_ERROR)
-#define VALUE_IS_NUMBER(v)             (((v)->type == VALUE_FLOAT) || \
-                                        ((v)->type == VALUE_BOOLEAN))
-#define VALUE_IS_FLOAT(v)              ((v)->type == VALUE_FLOAT)
+#define VALUE_IS_EMPTY(v)              (((v) == NULL) || ((v)->v_any.type == VALUE_EMPTY))
+#define VALUE_IS_EMPTY_OR_ERROR(v)     (VALUE_IS_EMPTY(v) || (v)->v_any.type == VALUE_ERROR)
+#define VALUE_IS_STRING(v)             ((v)->v_any.type == VALUE_STRING)
+#define VALUE_IS_BOOLEAN(v)            ((v)->v_any.type == VALUE_BOOLEAN)
+#define VALUE_IS_ERROR(v)              ((v)->v_any.type == VALUE_ERROR)
+#define VALUE_IS_NUMBER(v)             (((v)->v_any.type == VALUE_FLOAT) || \
+                                        ((v)->v_any.type == VALUE_BOOLEAN))
+#define VALUE_IS_FLOAT(v)              ((v)->v_any.type == VALUE_FLOAT)
+#define VALUE_IS_ARRAY(v)              ((v)->v_any.type == VALUE_ARRAY)
+#define VALUE_IS_CELLRANGE(v)          ((v)->v_any.type == VALUE_CELLRANGE)
 
 typedef enum {
        IS_EQUAL,
diff --git a/src/widgets/gnumeric-expr-entry.c b/src/widgets/gnumeric-expr-entry.c
index 893f952..347127f 100644
--- a/src/widgets/gnumeric-expr-entry.c
+++ b/src/widgets/gnumeric-expr-entry.c
@@ -2772,7 +2772,7 @@ gnm_expr_entry_is_cell_ref (GnmExprEntry *gee, Sheet *sheet,
         if (val == NULL)
                return FALSE;
 
-       res = ((val->type == VALUE_CELLRANGE) &&
+       res = ((VALUE_IS_CELLRANGE (val)) &&
               (allow_multiple_cell ||
                ((val->v_range.cell.a.col == val->v_range.cell.b.col) &&
                 (val->v_range.cell.a.row == val->v_range.cell.b.row))));
@@ -2814,7 +2814,7 @@ gnm_expr_entry_global_range_name (GnmExprEntry *gee, Sheet *sheet)
 
        val = gnm_expr_entry_parse_as_value (gee, sheet);
        if (val != NULL) {
-               if (val->type == VALUE_CELLRANGE)
+               if (VALUE_IS_CELLRANGE (val))
                        text = value_get_as_string (val);
                value_release (val);
        }
diff --git a/src/workbook.c b/src/workbook.c
index 3b804c3..272761a 100644
--- a/src/workbook.c
+++ b/src/workbook.c
@@ -548,7 +548,7 @@ workbook_foreach_cell_in_range (GnmEvalPos const *pos,
 
        g_return_val_if_fail (pos != NULL, NULL);
        g_return_val_if_fail (cell_range != NULL, NULL);
-       g_return_val_if_fail (cell_range->type == VALUE_CELLRANGE, NULL);
+       g_return_val_if_fail (VALUE_IS_CELLRANGE (cell_range), NULL);
 
        gnm_rangeref_normalize (&cell_range->v_range.cell, pos,
                &start_sheet, &end_sheet, &r);
diff --git a/src/xml-sax-write.c b/src/xml-sax-write.c
index 50ec4fa..c361ef7 100644
--- a/src/xml-sax-write.c
+++ b/src/xml-sax-write.c
@@ -868,7 +868,7 @@ xml_write_cell_and_position (GnmOutputXML *state,
 
                if (!texpr) {
                        if (val != NULL) {
-                               gsf_xml_out_add_int (state->output, "ValueType", val->type);
+                               gsf_xml_out_add_int (state->output, "ValueType", val->v_any.type);
                                if (VALUE_FMT (val) != NULL) {
                                        const char *fmt = go_format_as_XL (VALUE_FMT (val));
                                        gsf_xml_out_add_cstr (state->output, "ValueFormat", fmt);
@@ -965,7 +965,7 @@ xml_write_filter_expr (GnmOutputXML *state,
        gsf_xml_out_add_cstr_unchecked (state->output,
                filter_expr_attrs[i].op, filter_cond_name [cond->op[i]]);
        gsf_xml_out_add_int (state->output,
-               filter_expr_attrs[i].valtype, cond->value[i]->type);
+               filter_expr_attrs[i].valtype, cond->value[i]->v_any.type);
        gsf_xml_out_add_cstr (state->output,
                filter_expr_attrs[i].val, text->str);
        g_string_free (text, TRUE);
@@ -1153,7 +1153,7 @@ xml_write_scenario (GnmOutputXML *state, GnmScenario const *sc)
                if (val) {
                        gsf_xml_out_add_int (state->output,
                                             "ValueType",
-                                            val->type);
+                                            val->v_any.type);
                        if (VALUE_FMT (val) != NULL) {
                                const char *fmt = go_format_as_XL (VALUE_FMT (val));
                                gsf_xml_out_add_cstr (state->output, "ValueFormat", fmt);


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