Properly support globals initialized to nil

This commit is contained in:
Wolfgang Bumiller 2012-12-29 21:15:59 +01:00
parent 432a29e4d9
commit 755ee5462f
3 changed files with 35 additions and 17 deletions

5
ast.c
View file

@ -209,8 +209,11 @@ bool ast_compare_type(ast_expression *a, ast_expression *b)
return false;
if (vec_size(a->expression.params) != vec_size(b->expression.params))
return false;
if (a->expression.flags != b->expression.flags)
if ((a->expression.flags & AST_FLAG_TYPE_MASK) !=
(b->expression.flags & AST_FLAG_TYPE_MASK) )
{
return false;
}
if (vec_size(a->expression.params)) {
size_t i;
for (i = 0; i < vec_size(a->expression.params); ++i) {

2
ast.h
View file

@ -143,6 +143,8 @@ typedef struct
#define AST_FLAG_VARIADIC (1<<0)
#define AST_FLAG_NORETURN (1<<1)
#define AST_FLAG_INLINE (1<<2)
#define AST_FLAG_INITIALIZED (1<<3)
#define AST_FLAG_TYPE_MASK (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
/* Value
*

View file

@ -4812,8 +4812,12 @@ skipvar:
if (!localblock) {
cval = (ast_value*)cexp;
if (!ast_istype(cval, ast_value) || ((!cval->hasvalue || cval->cvq != CV_CONST) && !cval->isfield))
if (cval != parser->nil &&
(!ast_istype(cval, ast_value) || ((!cval->hasvalue || cval->cvq != CV_CONST) && !cval->isfield))
)
{
parseerror(parser, "cannot initialize a global constant variable with a non-constant expression");
}
else
{
if (opts.standard != COMPILER_GMQCC &&
@ -4822,14 +4826,19 @@ skipvar:
{
var->cvq = CV_CONST;
}
var->hasvalue = true;
if (cval->expression.vtype == TYPE_STRING)
var->constval.vstring = parser_strdup(cval->constval.vstring);
else if (cval->expression.vtype == TYPE_FIELD)
var->constval.vfield = cval;
if (cval == parser->nil)
var->expression.flags |= AST_FLAG_INITIALIZED;
else
memcpy(&var->constval, &cval->constval, sizeof(var->constval));
ast_unref(cval);
{
var->hasvalue = true;
if (cval->expression.vtype == TYPE_STRING)
var->constval.vstring = parser_strdup(cval->constval.vstring);
else if (cval->expression.vtype == TYPE_FIELD)
var->constval.vfield = cval;
else
memcpy(&var->constval, &cval->constval, sizeof(var->constval));
ast_unref(cval);
}
}
} else {
int cvq;
@ -5064,6 +5073,7 @@ bool parser_init()
empty_ctx.file = "<internal>";
empty_ctx.line = 0;
parser->nil = ast_value_new(empty_ctx, "nil", TYPE_NIL);
parser->nil->cvq = CV_CONST;
if (OPTS_FLAG(UNTYPED_NIL))
util_htset(parser->htglobals, "nil", (void*)parser->nil);
return true;
@ -5263,14 +5273,17 @@ bool parser_finish(const char *output)
if (!ast_istype(parser->globals[i], ast_value))
continue;
asvalue = (ast_value*)(parser->globals[i]);
if (asvalue->cvq == CV_CONST && !asvalue->hasvalue)
(void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_CONSTANT,
"uninitialized constant: `%s`",
asvalue->name);
else if ((asvalue->cvq == CV_NONE || asvalue->cvq == CV_CONST) && !asvalue->hasvalue)
(void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_GLOBAL,
"uninitialized global: `%s`",
asvalue->name);
if (!(asvalue->expression.flags & AST_FLAG_INITIALIZED))
{
if (asvalue->cvq == CV_CONST && !asvalue->hasvalue)
(void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_CONSTANT,
"uninitialized constant: `%s`",
asvalue->name);
else if ((asvalue->cvq == CV_NONE || asvalue->cvq == CV_CONST) && !asvalue->hasvalue)
(void)!compile_warning(ast_ctx(asvalue), WARN_UNINITIALIZED_GLOBAL,
"uninitialized global: `%s`",
asvalue->name);
}
if (!ast_generate_accessors(asvalue, ir)) {
ir_builder_delete(ir);
return false;