mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
Nil is a constant, so allow it in global initializers.
This commit is contained in:
parent
b0879ba255
commit
67beaf4487
10 changed files with 38 additions and 25 deletions
|
@ -44,9 +44,9 @@ typedef enum {
|
|||
ex_uexpr, // unary expression
|
||||
ex_def,
|
||||
ex_temp, // temporary variable
|
||||
ex_nil, // umm, nil, null. nuff said
|
||||
ex_name,
|
||||
|
||||
ex_nil, // umm, nil, null. nuff said
|
||||
ex_string,
|
||||
ex_float,
|
||||
ex_vector,
|
||||
|
@ -206,6 +206,7 @@ void convert_uint_int (expr_t *e);
|
|||
void convert_int_uint (expr_t *e);
|
||||
void convert_short_int (expr_t *e);
|
||||
void convert_short_uint (expr_t *e);
|
||||
void convert_nil (expr_t *e, struct type_s *t);
|
||||
|
||||
expr_t *test_expr (expr_t *e, int test);
|
||||
void backpatch (ex_list_t *list, expr_t *label);
|
||||
|
|
|
@ -328,7 +328,7 @@ emit_assign_expr (int oper, expr_t *e)
|
|||
if (e->rvalue && def_b->managed)
|
||||
def_b->users++;
|
||||
if (e1->type == ex_expr && extract_type (e1->e.expr.e1) == ev_pointer
|
||||
&& e1->e.expr.e1->type < ex_string) {
|
||||
&& e1->e.expr.e1->type < ex_nil) {
|
||||
def_a = emit_sub_expr (e1->e.expr.e1, 0);
|
||||
def_c = emit_sub_expr (e1->e.expr.e2, 0);
|
||||
op = opcode_find (operator, def_b->type, def_a->type, def_c->type);
|
||||
|
@ -470,7 +470,7 @@ emit_deref_expr (expr_t *e, def_t *dest)
|
|||
|
||||
if (e->type == ex_expr
|
||||
&& e->e.expr.op == '&'
|
||||
&& e->e.expr.e1->type < ex_string)
|
||||
&& e->e.expr.e1->type < ex_nil)
|
||||
e->e.expr.op = '.';
|
||||
if (e->type == ex_uexpr && e->e.expr.op == '.')
|
||||
d = emit_sub_expr (e, 0);
|
||||
|
|
|
@ -76,9 +76,9 @@ etype_t qc_types[] = {
|
|||
ev_void, // ex_uexpr
|
||||
ev_void, // ex_def
|
||||
ev_void, // ex_temp
|
||||
ev_void, // ex_nil
|
||||
ev_void, // ex_name
|
||||
|
||||
ev_void, // ex_nil
|
||||
ev_string, // ex_string
|
||||
ev_float, // ex_float
|
||||
ev_vector, // ex_vector
|
||||
|
@ -141,6 +141,10 @@ convert_name (expr_t *e)
|
|||
expr_t *new;
|
||||
class_t *class;
|
||||
|
||||
new = get_enum (name);
|
||||
if (new)
|
||||
goto convert;
|
||||
|
||||
class = get_class (name, 0);
|
||||
if (class) {
|
||||
e->type = ex_def;
|
||||
|
@ -159,9 +163,6 @@ convert_name (expr_t *e)
|
|||
return;
|
||||
}
|
||||
new = class_ivar_expr (current_class, name);
|
||||
if (new)
|
||||
goto convert;
|
||||
new = get_enum (name);
|
||||
if (new)
|
||||
goto convert;
|
||||
error (e, "Undeclared variable \"%s\".", name);
|
||||
|
@ -604,7 +605,7 @@ new_short_expr (short short_val)
|
|||
int
|
||||
is_constant (expr_t *e)
|
||||
{
|
||||
if (e->type >= ex_string
|
||||
if (e->type >= ex_nil
|
||||
|| (e->type == ex_def && e->e.def->constant))
|
||||
return 1;
|
||||
return 0;
|
||||
|
@ -615,6 +616,8 @@ constant_expr (expr_t *var)
|
|||
{
|
||||
def_t *def;
|
||||
|
||||
convert_name (var);
|
||||
|
||||
if (var->type != ex_def || !var->e.def->constant)
|
||||
return var;
|
||||
|
||||
|
@ -818,7 +821,7 @@ print_expr (expr_t *e)
|
|||
e->e.temp.users);
|
||||
break;
|
||||
case ex_nil:
|
||||
printf ("NULL");
|
||||
printf ("NIL");
|
||||
break;
|
||||
case ex_string:
|
||||
case ex_name:
|
||||
|
@ -1365,7 +1368,7 @@ convert_short_uint (expr_t *e)
|
|||
e->e.uinteger_val = e->e.short_val;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
convert_nil (expr_t *e, type_t *t)
|
||||
{
|
||||
e->type = expr_types[t->type];
|
||||
|
@ -1696,7 +1699,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
|
|||
{
|
||||
expr_t *tmp1, *tmp2;
|
||||
e = new_block_expr ();
|
||||
if (e2->type < ex_string)
|
||||
if (e2->type < ex_nil)
|
||||
tmp1 = new_temp_def_expr (&type_float);
|
||||
else
|
||||
tmp1 = e2;
|
||||
|
@ -2519,7 +2522,7 @@ assign_expr (expr_t *e1, expr_t *e2)
|
|||
&& POINTER_VAL (e->e.pointer) < 65536)) {
|
||||
if (e->type == ex_expr && e->e.expr.op == '&'
|
||||
&& e->e.expr.type->type == ev_pointer
|
||||
&& e->e.expr.e1->type < ex_string) {
|
||||
&& e->e.expr.e1->type < ex_nil) {
|
||||
e2 = e;
|
||||
e2->e.expr.op = '.';
|
||||
e2->e.expr.type = t2;
|
||||
|
@ -2640,7 +2643,7 @@ init_elements (def_t *def, expr_t *eles)
|
|||
}
|
||||
init_elements (&elements[i], c);
|
||||
continue;
|
||||
} else if (c->type >= ex_string) {
|
||||
} else if (c->type >= ex_nil) {
|
||||
if (c->type == ex_integer
|
||||
&& elements[i].type->type == ev_float)
|
||||
convert_int (c);
|
||||
|
|
|
@ -167,6 +167,8 @@ ReuseConstant (expr_t *expr, def_t *def)
|
|||
clear_immediates ();
|
||||
}
|
||||
cn = 0;
|
||||
if (e.type == ex_nil)
|
||||
convert_nil (&e, def->type);
|
||||
switch (e.type) {
|
||||
case ex_entity:
|
||||
tab = entity_imm_defs;
|
||||
|
|
|
@ -358,9 +358,11 @@ type_or_name (char *token)
|
|||
yylval.typename = typename;
|
||||
return TYPE_NAME;
|
||||
}
|
||||
if ((class = get_class (token, 0))) {
|
||||
yylval.string_val = save_string (token);
|
||||
return CLASS_NAME;
|
||||
if (!get_enum (token)) {
|
||||
if ((class = get_class (token, 0))) {
|
||||
yylval.string_val = save_string (token);
|
||||
return CLASS_NAME;
|
||||
}
|
||||
}
|
||||
yylval.string_val = save_string (token);
|
||||
return NAME;
|
||||
|
|
|
@ -373,7 +373,7 @@ enum
|
|||
{
|
||||
$$ = 0;
|
||||
$3 = constant_expr ($3);
|
||||
if ($3->type < ex_string) {
|
||||
if ($3->type < ex_nil) {
|
||||
error ($3, "non-constant initializer");
|
||||
} else if ($3->type != ex_integer) {
|
||||
error ($3, "invalid initializer type");
|
||||
|
@ -600,15 +600,14 @@ var_initializer
|
|||
def_initialized ($$);
|
||||
} else {
|
||||
$2 = constant_expr ($2);
|
||||
if ($2->type >= ex_string) {
|
||||
if ($$->constant) {
|
||||
if ($2->type >= ex_nil) {
|
||||
if ($2->type != ex_nil
|
||||
&& !type_assignable ($$->type, get_type ($2))) {
|
||||
error ($2, "incompatible types in initialization");
|
||||
} else if ($$->constant) {
|
||||
error ($2, "%s re-initialized", $$->name);
|
||||
} else {
|
||||
if ($$->type->type == ev_func) {
|
||||
PARSE_ERROR;
|
||||
} else {
|
||||
ReuseConstant ($2, $$);
|
||||
}
|
||||
ReuseConstant ($2, $$);
|
||||
}
|
||||
} else {
|
||||
error ($2, "non-constant expression used for initializer");
|
||||
|
|
|
@ -106,7 +106,7 @@ case_label_expr (switch_block_t *switch_block, expr_t *value)
|
|||
convert_name (value);
|
||||
value = constant_expr (value);
|
||||
}
|
||||
if (value && value->type < ex_string) {
|
||||
if (value && value->type < ex_nil) {
|
||||
error (value, "non-constant case value");
|
||||
free (cl);
|
||||
return 0;
|
||||
|
|
2
tools/qfcc/test/enum.r
Normal file
2
tools/qfcc/test/enum.r
Normal file
|
@ -0,0 +1,2 @@
|
|||
typedef enum {x} X;
|
||||
X y = x;
|
3
tools/qfcc/test/imp.r
Normal file
3
tools/qfcc/test/imp.r
Normal file
|
@ -0,0 +1,3 @@
|
|||
void () foo = #0;
|
||||
@static IMP bar = NIL;
|
||||
@static IMP baz = 0;
|
1
tools/qfcc/test/nil.r
Normal file
1
tools/qfcc/test/nil.r
Normal file
|
@ -0,0 +1 @@
|
|||
Class x = NIL;
|
Loading…
Reference in a new issue