Rob Shearman : widl: Fix the calculation of casted integer constant expressions.

Alexandre Julliard julliard at winehq.org
Tue Mar 23 12:12:50 CDT 2010


Module: wine
Branch: master
Commit: b544014b8e1bb1e3e6f89d96edbeead320375afc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b544014b8e1bb1e3e6f89d96edbeead320375afc

Author: Rob Shearman <robertshearman at gmail.com>
Date:   Tue Mar 23 13:33:46 2010 +0000

widl: Fix the calculation of casted integer constant expressions.

---

 tools/widl/expr.c |  141 +++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 98 insertions(+), 43 deletions(-)

diff --git a/tools/widl/expr.c b/tools/widl/expr.c
index bca7c5a..67c5e71 100644
--- a/tools/widl/expr.c
+++ b/tools/widl/expr.c
@@ -35,8 +35,76 @@
 #include "typetree.h"
 #include "typegen.h"
 
-static int is_integer_type(const type_t *type);
-static int is_float_type(const type_t *type);
+static int is_integer_type(const type_t *type)
+{
+    switch (type_get_type(type))
+    {
+    case TYPE_ENUM:
+        return TRUE;
+    case TYPE_BASIC:
+        switch (type_basic_get_type(type))
+        {
+        case TYPE_BASIC_INT8:
+        case TYPE_BASIC_INT16:
+        case TYPE_BASIC_INT32:
+        case TYPE_BASIC_INT64:
+        case TYPE_BASIC_INT:
+        case TYPE_BASIC_INT3264:
+        case TYPE_BASIC_CHAR:
+        case TYPE_BASIC_HYPER:
+        case TYPE_BASIC_BYTE:
+        case TYPE_BASIC_WCHAR:
+        case TYPE_BASIC_ERROR_STATUS_T:
+            return TRUE;
+        case TYPE_BASIC_FLOAT:
+        case TYPE_BASIC_DOUBLE:
+        case TYPE_BASIC_HANDLE:
+            return FALSE;
+        }
+        return FALSE;
+    default:
+        return FALSE;
+    }
+}
+
+static int is_signed_integer_type(const type_t *type)
+{
+    switch (type_get_type(type))
+    {
+    case TYPE_ENUM:
+        return FALSE;
+    case TYPE_BASIC:
+        switch (type_basic_get_type(type))
+        {
+        case TYPE_BASIC_INT8:
+        case TYPE_BASIC_INT16:
+        case TYPE_BASIC_INT32:
+        case TYPE_BASIC_INT64:
+        case TYPE_BASIC_INT:
+        case TYPE_BASIC_INT3264:
+            return type_basic_get_sign(type) < 0;
+        case TYPE_BASIC_CHAR:
+            return TRUE;
+        case TYPE_BASIC_HYPER:
+        case TYPE_BASIC_BYTE:
+        case TYPE_BASIC_WCHAR:
+        case TYPE_BASIC_ERROR_STATUS_T:
+        case TYPE_BASIC_FLOAT:
+        case TYPE_BASIC_DOUBLE:
+        case TYPE_BASIC_HANDLE:
+            return FALSE;
+        }
+    default:
+        return FALSE;
+    }
+}
+
+static int is_float_type(const type_t *type)
+{
+    return (type_get_type(type) == TYPE_BASIC &&
+        (type_basic_get_type(type) == TYPE_BASIC_FLOAT ||
+         type_basic_get_type(type) == TYPE_BASIC_DOUBLE));
+}
 
 expr_t *make_expr(enum expr_type type)
 {
@@ -146,8 +214,34 @@ expr_t *make_exprt(enum expr_type type, var_t *var, expr_t *expr)
     /* check for cast of constant expression */
     if (type == EXPR_CAST && expr->is_const)
     {
-        e->is_const = TRUE;
-        e->cval = expr->cval;
+        if (is_integer_type(tref))
+        {
+            unsigned int align = 0;
+            unsigned int cast_type_bits = type_memsize(tref, &align) * 8;
+            unsigned long cast_mask;
+
+            e->is_const = TRUE;
+            if (is_signed_integer_type(tref))
+            {
+                cast_mask = (1 << (cast_type_bits - 1)) - 1;
+                if (expr->cval & (1 << (cast_type_bits - 1)))
+                    e->cval = -((-expr->cval) & cast_mask);
+                else
+                    e->cval = expr->cval & cast_mask;
+            }
+            else
+            {
+                /* calculate ((1 << cast_type_bits) - 1) avoiding overflow */
+                cast_mask = ((1 << (cast_type_bits - 1)) - 1) |
+                            1 << (cast_type_bits - 1);
+                e->cval = expr->cval & cast_mask;
+            }
+        }
+        else
+        {
+            e->is_const = TRUE;
+            e->cval = expr->cval;
+        }
     }
     free(var);
     return e;
@@ -308,45 +402,6 @@ struct expression_type
     type_t *type;
 };
 
-static int is_integer_type(const type_t *type)
-{
-    switch (type_get_type(type))
-    {
-    case TYPE_ENUM:
-        return TRUE;
-    case TYPE_BASIC:
-        switch (type_basic_get_type(type))
-        {
-        case TYPE_BASIC_INT8:
-        case TYPE_BASIC_INT16:
-        case TYPE_BASIC_INT32:
-        case TYPE_BASIC_INT64:
-        case TYPE_BASIC_INT:
-        case TYPE_BASIC_INT3264:
-        case TYPE_BASIC_CHAR:
-        case TYPE_BASIC_HYPER:
-        case TYPE_BASIC_BYTE:
-        case TYPE_BASIC_WCHAR:
-        case TYPE_BASIC_ERROR_STATUS_T:
-            return TRUE;
-        case TYPE_BASIC_FLOAT:
-        case TYPE_BASIC_DOUBLE:
-        case TYPE_BASIC_HANDLE:
-            return FALSE;
-        }
-        return FALSE;
-    default:
-        return FALSE;
-    }
-}
-
-static int is_float_type(const type_t *type)
-{
-    return (type_get_type(type) == TYPE_BASIC &&
-        (type_basic_get_type(type) == TYPE_BASIC_FLOAT ||
-         type_basic_get_type(type) == TYPE_BASIC_DOUBLE));
-}
-
 static void check_scalar_type(const struct expr_loc *expr_loc,
                               const type_t *cont_type, const type_t *type)
 {




More information about the wine-cvs mailing list