mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
[qfcc] Treat { } as nil for initializing compound types
This commit is contained in:
parent
7c9072aebf
commit
b4aebc120e
6 changed files with 93 additions and 8 deletions
|
@ -614,7 +614,7 @@ void convert_int (expr_t *e);
|
|||
void convert_short (expr_t *e);
|
||||
void convert_short_int (expr_t *e);
|
||||
void convert_double (expr_t *e);
|
||||
void convert_nil (expr_t *e, struct type_s *t);
|
||||
expr_t *convert_nil (expr_t *e, struct type_s *t);
|
||||
|
||||
expr_t *test_expr (expr_t *e);
|
||||
void backpatch (ex_list_t *list, expr_t *label);
|
||||
|
|
|
@ -287,6 +287,21 @@ def_to_ddef (def_t *def, ddef_t *ddef, int aux)
|
|||
ddef->s_name = ReuseString (def->name);
|
||||
}
|
||||
|
||||
static int
|
||||
zero_memory (expr_t *local_expr, def_t *def, type_t *zero_type,
|
||||
int init_size, int init_offset)
|
||||
{
|
||||
int zero_size = type_size (zero_type);
|
||||
expr_t *zero = convert_nil (new_nil_expr (), zero_type);
|
||||
expr_t *dst;
|
||||
|
||||
for (; init_offset < init_size + 1 - zero_size; init_offset += zero_size) {
|
||||
dst = new_pointer_expr (init_offset, zero_type, def);
|
||||
append_expr (local_expr, assign_expr (unary_expr ('.', dst), zero));
|
||||
}
|
||||
return init_offset;
|
||||
}
|
||||
|
||||
static void
|
||||
init_elements (struct def_s *def, expr_t *eles)
|
||||
{
|
||||
|
@ -298,6 +313,39 @@ init_elements (struct def_s *def, expr_t *eles)
|
|||
base_offset = def->offset;
|
||||
if (def->local && local_expr)
|
||||
base_offset = 0;
|
||||
if (eles->type == ex_nil) {
|
||||
if (def->local && local_expr) {
|
||||
// memset to 0
|
||||
int init_size = type_size (def->type);
|
||||
int init_offset = 0;
|
||||
|
||||
if (options.code.progsversion != PROG_ID_VERSION) {
|
||||
init_offset = zero_memory (local_expr, def, &type_zero,
|
||||
init_size, init_offset);
|
||||
}
|
||||
// probably won't happen any time soon, but who knows...
|
||||
if (options.code.progsversion != PROG_ID_VERSION
|
||||
&& init_size - init_offset >= type_size (&type_quaternion)) {
|
||||
init_offset = zero_memory (local_expr, def, &type_quaternion,
|
||||
init_size, init_offset);
|
||||
}
|
||||
if (init_size - init_offset >= type_size (&type_vector)) {
|
||||
init_offset = zero_memory (local_expr, def, &type_vector,
|
||||
init_size, init_offset);
|
||||
}
|
||||
if (options.code.progsversion != PROG_ID_VERSION
|
||||
&& init_size - init_offset >= type_size (&type_double)) {
|
||||
init_offset = zero_memory (local_expr, def, &type_double,
|
||||
init_size, init_offset);
|
||||
}
|
||||
if (init_size - init_offset >= type_size (type_default)) {
|
||||
zero_memory (local_expr, def, type_default,
|
||||
init_size, init_offset);
|
||||
}
|
||||
}
|
||||
// it's a global, so already initialized to 0
|
||||
return;
|
||||
}
|
||||
if (is_array (def->type)) {
|
||||
type_t *array_type = def->type->t.array.type;
|
||||
int array_size = def->type->t.array.size;
|
||||
|
@ -334,8 +382,11 @@ init_elements (struct def_s *def, expr_t *eles)
|
|||
}
|
||||
for (count = 0, e = eles->e.block.head; e; count++, e = e->next) {
|
||||
convert_name (e);
|
||||
if (e->type == ex_nil && count < num_elements)
|
||||
if (e->type == ex_nil && count < num_elements
|
||||
&& !(is_array (elements[count].type)
|
||||
|| is_struct (elements[count].type))) {
|
||||
convert_nil (e, elements[count].type);
|
||||
}
|
||||
if (e->type == ex_error) {
|
||||
free (elements);
|
||||
return;
|
||||
|
@ -349,7 +400,8 @@ init_elements (struct def_s *def, expr_t *eles)
|
|||
for (i = 0, e = eles->e.block.head; i < count; i++, e = e->next) {
|
||||
g = D_POINTER (pr_type_t, &elements[i]);
|
||||
c = constant_expr (e);
|
||||
if (c->type == ex_block) {
|
||||
// nil will not survive as nil to this point if array or struct
|
||||
if (c->type == ex_block || c->type == ex_nil) {
|
||||
if (!is_array (elements[i].type)
|
||||
&& !is_struct (elements[i].type)) {
|
||||
error (e, "type mismatch in initializer");
|
||||
|
@ -567,15 +619,18 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
|
|||
convert_name (init);
|
||||
if (init->type == ex_error)
|
||||
return;
|
||||
if (init->type == ex_nil)
|
||||
convert_nil (init, sym->type);
|
||||
if ((is_array (sym->type) || is_struct (sym->type)
|
||||
|| sym->type == &type_vector || sym->type == &type_quaternion)
|
||||
&& init->type == ex_block && !init->e.block.result) {
|
||||
&& ((init->type == ex_block && !init->e.block.result)
|
||||
|| init->type == ex_nil)) {
|
||||
init_elements (sym->s.def, init);
|
||||
sym->s.def->initialized = 1;
|
||||
} else {
|
||||
type_t *init_type = get_type (init);
|
||||
type_t *init_type;
|
||||
if (init->type == ex_nil) {
|
||||
convert_nil (init, sym->type);
|
||||
}
|
||||
init_type = get_type (init);
|
||||
if (!type_assignable (sym->type, init_type)) {
|
||||
error (init, "type mismatch in initializer");
|
||||
return;
|
||||
|
|
|
@ -1325,11 +1325,12 @@ convert_double (expr_t *e)
|
|||
e->e.value = new_float_val (float_val);
|
||||
}
|
||||
|
||||
void
|
||||
expr_t *
|
||||
convert_nil (expr_t *e, type_t *t)
|
||||
{
|
||||
e->type = ex_value;
|
||||
e->e.value = new_nil_val (t);
|
||||
return e;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -1065,6 +1065,13 @@ opt_initializer
|
|||
var_initializer
|
||||
: '=' expr { $$ = $2; }
|
||||
| '=' '{' element_list optional_comma '}' { $$ = $3; }
|
||||
| '=' '{' '}'
|
||||
{
|
||||
if (is_scalar ($<spec>-1.type)) {
|
||||
error (0, "empty scalar initializer");
|
||||
}
|
||||
$$ = new_nil_expr ();
|
||||
}
|
||||
;
|
||||
|
||||
optional_state_expr
|
||||
|
|
|
@ -48,6 +48,7 @@ test_progs_dat=\
|
|||
return-ivar.dat \
|
||||
sendv.dat \
|
||||
state.dat \
|
||||
struct-nil-init.dat \
|
||||
structarray.dat \
|
||||
structlive.dat \
|
||||
structptr.dat \
|
||||
|
@ -301,6 +302,15 @@ state.run: Makefile build-run
|
|||
include ./$(DEPDIR)/state.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/state.Qo
|
||||
|
||||
struct_nil_init_dat_SOURCES=struct-nil-init.r
|
||||
struct_nil_init_obj=$(struct_nil_init_dat_SOURCES:.r=.qfo)
|
||||
struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP)
|
||||
$(QFCC) $(QCFLAGS) -o $@ $(struct_nil_init_obj)
|
||||
struct-nil-init.run: Makefile build-run
|
||||
@$(srcdir)/build-run $@
|
||||
include ./$(DEPDIR)/struct-nil-init.Qo # am--include-marker
|
||||
r_depfiles_remade += ./$(DEPDIR)/struct-nil-init.Qo
|
||||
|
||||
structarray_dat_SOURCES=structarray.r
|
||||
structarray_obj=$(structarray_dat_SOURCES:.r=.qfo)
|
||||
structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP)
|
||||
|
|
12
tools/qfcc/test/struct-nil-init.r
Normal file
12
tools/qfcc/test/struct-nil-init.r
Normal file
|
@ -0,0 +1,12 @@
|
|||
#pragma bug die
|
||||
|
||||
struct foo {
|
||||
quaternion x;
|
||||
double y;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
struct foo bar = { };
|
||||
return bar.y; // to survive and prevail
|
||||
}
|
Loading…
Reference in a new issue