widl: Fix the calculation of casted integer constant expressions.

This commit is contained in:
Rob Shearman 2010-03-23 13:33:46 +00:00 committed by Alexandre Julliard
parent 979bdf28b6
commit b544014b8e
1 changed files with 98 additions and 43 deletions

View File

@ -35,8 +35,76 @@
#include "typetree.h" #include "typetree.h"
#include "typegen.h" #include "typegen.h"
static int is_integer_type(const type_t *type); static int is_integer_type(const type_t *type)
static int is_float_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) 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 */ /* check for cast of constant expression */
if (type == EXPR_CAST && expr->is_const) if (type == EXPR_CAST && expr->is_const)
{ {
e->is_const = TRUE; if (is_integer_type(tref))
e->cval = expr->cval; {
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); free(var);
return e; return e;
@ -308,45 +402,6 @@ struct expression_type
type_t *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, static void check_scalar_type(const struct expr_loc *expr_loc,
const type_t *cont_type, const type_t *type) const type_t *cont_type, const type_t *type)
{ {