d3dcompiler: Postincrement/decrement expressions are const.

Also check for const expressions used as l-values.
oldstable
Matteo Bruni 2012-09-17 15:32:05 +02:00 committed by Alexandre Julliard
parent 7cce71a0c3
commit 237558f649
3 changed files with 118 additions and 5 deletions

View File

@ -1027,6 +1027,7 @@ BOOL add_func_parameter(struct list *list, struct parse_parameter *param,
struct hlsl_type *new_hlsl_type(const char *name, enum hlsl_type_class type_class,
enum hlsl_base_type base_type, unsigned dimx, unsigned dimy) DECLSPEC_HIDDEN;
struct hlsl_type *new_array_type(struct hlsl_type *basic_type, unsigned int array_size) DECLSPEC_HIDDEN;
struct hlsl_type *clone_hlsl_type(struct hlsl_type *old) DECLSPEC_HIDDEN;
struct hlsl_type *get_type(struct hlsl_scope *scope, const char *name, BOOL recursive) DECLSPEC_HIDDEN;
BOOL find_function(const char *name) DECLSPEC_HIDDEN;
unsigned int components_count_type(struct hlsl_type *type) DECLSPEC_HIDDEN;

View File

@ -1026,20 +1026,38 @@ postfix_expr: primary_expr
struct hlsl_ir_node *operands[3];
struct source_location loc;
set_location(&loc, &@2);
if ($1->data_type->modifiers & HLSL_MODIFIER_CONST)
{
hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
"modifying a const expression");
return 1;
}
operands[0] = $1;
operands[1] = operands[2] = NULL;
set_location(&loc, &@2);
$$ = &new_expr(HLSL_IR_BINOP_POSTINC, operands, &loc)->node;
/* Post increment/decrement expressions are considered const */
$$->data_type = clone_hlsl_type($$->data_type);
$$->data_type->modifiers |= HLSL_MODIFIER_CONST;
}
| postfix_expr OP_DEC
{
struct hlsl_ir_node *operands[3];
struct source_location loc;
set_location(&loc, &@2);
if ($1->data_type->modifiers & HLSL_MODIFIER_CONST)
{
hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
"modifying a const expression");
return 1;
}
operands[0] = $1;
operands[1] = operands[2] = NULL;
set_location(&loc, &@2);
$$ = &new_expr(HLSL_IR_BINOP_POSTDEC, operands, &loc)->node;
/* Post increment/decrement expressions are considered const */
$$->data_type = clone_hlsl_type($$->data_type);
$$->data_type->modifiers |= HLSL_MODIFIER_CONST;
}
| postfix_expr '.' any_identifier
{
@ -1113,9 +1131,15 @@ unary_expr: postfix_expr
struct hlsl_ir_node *operands[3];
struct source_location loc;
set_location(&loc, &@1);
if ($2->data_type->modifiers & HLSL_MODIFIER_CONST)
{
hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
"modifying a const expression");
return 1;
}
operands[0] = $2;
operands[1] = operands[2] = NULL;
set_location(&loc, &@1);
$$ = &new_expr(HLSL_IR_BINOP_PREINC, operands, &loc)->node;
}
| OP_DEC unary_expr
@ -1123,9 +1147,15 @@ unary_expr: postfix_expr
struct hlsl_ir_node *operands[3];
struct source_location loc;
set_location(&loc, &@1);
if ($2->data_type->modifiers & HLSL_MODIFIER_CONST)
{
hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
"modifying a const expression");
return 1;
}
operands[0] = $2;
operands[1] = operands[2] = NULL;
set_location(&loc, &@1);
$$ = &new_expr(HLSL_IR_BINOP_PREDEC, operands, &loc)->node;
}
| unary_op unary_expr
@ -1335,10 +1365,19 @@ assignment_expr: conditional_expr
}
| unary_expr assign_op assignment_expr
{
struct source_location loc;
set_location(&loc, &@2);
if ($1->data_type->modifiers & HLSL_MODIFIER_CONST)
{
hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
"l-value is const");
return 1;
}
$$ = make_assignment($1, $2, BWRITERSP_WRITEMASK_ALL, $3);
if (!$$)
return 1;
set_location(&$$->loc, &@2);
$$->loc = loc;
}
assign_op: '='

View File

@ -947,6 +947,79 @@ static BOOL compare_hlsl_types(const struct hlsl_type *t1, const struct hlsl_typ
return TRUE;
}
struct hlsl_type *clone_hlsl_type(struct hlsl_type *old)
{
struct hlsl_type *type;
struct hlsl_struct_field *old_field, *field;
type = d3dcompiler_alloc(sizeof(*type));
if (!type)
{
ERR("Out of memory\n");
return NULL;
}
if (old->name)
{
type->name = d3dcompiler_strdup(old->name);
if (!type->name)
{
d3dcompiler_free(type);
return NULL;
}
}
type->type = old->type;
type->base_type = old->base_type;
type->dimx = old->dimx;
type->dimy = old->dimy;
type->modifiers = old->modifiers;
type->sampler_dim = old->sampler_dim;
switch (old->type)
{
case HLSL_CLASS_ARRAY:
type->e.array.type = old->e.array.type;
type->e.array.elements_count = old->e.array.elements_count;
break;
case HLSL_CLASS_STRUCT:
type->e.elements = d3dcompiler_alloc(sizeof(*type->e.elements));
if (!type->e.elements)
{
d3dcompiler_free((void *)type->name);
d3dcompiler_free(type);
return NULL;
}
list_init(type->e.elements);
LIST_FOR_EACH_ENTRY(old_field, old->e.elements, struct hlsl_struct_field, entry)
{
field = d3dcompiler_alloc(sizeof(*field));
if (!field)
{
LIST_FOR_EACH_ENTRY_SAFE(field, old_field, type->e.elements, struct hlsl_struct_field, entry)
{
d3dcompiler_free((void *)field->semantic);
d3dcompiler_free((void *)field->name);
d3dcompiler_free(field);
}
d3dcompiler_free(type->e.elements);
d3dcompiler_free((void *)type->name);
d3dcompiler_free(type);
return NULL;
}
field->type = clone_hlsl_type(old_field->type);
field->name = d3dcompiler_strdup(old_field->name);
if (old_field->semantic)
field->semantic = d3dcompiler_strdup(old_field->semantic);
field->modifiers = old_field->modifiers;
list_add_tail(type->e.elements, &field->entry);
}
break;
default:
break;
}
list_add_tail(&hlsl_ctx.types, &type->entry);
return type;
}
static BOOL convertible_data_type(struct hlsl_type *type)
{
return type->type != HLSL_CLASS_OBJECT;