hash = util_hthash(parser->htglobals, name);
*isparam = false;
- for (i = vec_size(parser->variables); i > upto;) {
+ for (i = parser->variables.size(); i > upto;) {
--i;
if ( (e = (ast_expression*)util_htgeth(parser->variables[i], name, hash)) )
return e;
ast_value *e;
hash = util_hthash(parser->typedefs[0], name);
- for (i = vec_size(parser->typedefs); i > upto;) {
+ for (i = parser->typedefs.size(); i > upto;) {
--i;
if ( (e = (ast_value*)util_htgeth(parser->typedefs[i], name, hash)) )
return e;
return true;
}
+static int store_op_for(ast_expression* expr)
+{
+ if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) && expr->m_vtype == TYPE_FIELD && expr->m_next->m_vtype == TYPE_VECTOR) {
+ return type_storep_instr[TYPE_VECTOR];
+ }
+
+ if (ast_istype(expr, ast_member) && ast_istype(((ast_member*)expr)->m_owner, ast_entfield)) {
+ return type_storep_instr[expr->m_vtype];
+ }
+
+ if (ast_istype(expr, ast_entfield)) {
+ return type_storep_instr[expr->m_vtype];
+ }
+
+ return type_store_instr[expr->m_vtype];
+}
+
static bool check_write_to(lex_ctx_t ctx, ast_expression *expr)
{
if (ast_istype(expr, ast_value)) {
case opid2('|','|'):
generated_op += 1; /* INSTR_OR */
+ [[fallthrough]];
case opid2('&','&'):
generated_op += INSTR_AND;
if (!(out = parser->m_fold.op(op, exprs))) {
case opid1('>'):
generated_op += 1; /* INSTR_GT */
+ [[fallthrough]];
case opid1('<'):
generated_op += 1; /* INSTR_LT */
+ [[fallthrough]];
case opid2('>', '='):
generated_op += 1; /* INSTR_GE */
+ [[fallthrough]];
case opid2('<', '='):
generated_op += INSTR_LE;
if (NotSameType(TYPE_FLOAT)) {
case opid1('='):
if (ast_istype(exprs[0], ast_entfield)) {
ast_expression *field = ((ast_entfield*)exprs[0])->m_field;
- if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
- exprs[0]->m_vtype == TYPE_FIELD &&
- exprs[0]->m_next->m_vtype == TYPE_VECTOR)
- {
- assignop = type_storep_instr[TYPE_VECTOR];
- }
- else
- assignop = type_storep_instr[exprs[0]->m_vtype];
+ assignop = store_op_for(exprs[0]);
if (assignop == VINSTR_END || !field->m_next->compareType(*exprs[1]))
{
ast_type_to_string(field->m_next, ty1, sizeof(ty1));
}
else
{
- if (OPTS_FLAG(ADJUST_VECTOR_FIELDS) &&
- exprs[0]->m_vtype == TYPE_FIELD &&
- exprs[0]->m_next->m_vtype == TYPE_VECTOR)
- {
- assignop = type_store_instr[TYPE_VECTOR];
- }
- else {
- assignop = type_store_instr[exprs[0]->m_vtype];
- }
+ assignop = store_op_for(exprs[0]);
if (assignop == VINSTR_END) {
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
return false;
}
(void)check_write_to(ctx, exprs[0]);
- if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->m_vtype];
- else
- assignop = type_store_instr[exprs[0]->m_vtype];
+ assignop = store_op_for(exprs[0]);
switch (exprs[0]->m_vtype) {
case TYPE_FLOAT:
out = new ast_binstore(ctx, assignop,
return false;
}
(void)check_write_to(ctx, exprs[0]);
- if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->m_vtype];
- else
- assignop = type_store_instr[exprs[0]->m_vtype];
+ assignop = store_op_for(exprs[0]);
switch (exprs[0]->m_vtype) {
case TYPE_FLOAT:
out = new ast_binstore(ctx, assignop,
return false;
}
(void)check_write_to(ctx, exprs[0]);
- if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->m_vtype];
- else
- assignop = type_store_instr[exprs[0]->m_vtype];
+ assignop = store_op_for(exprs[0]);
if (exprs[0]->m_vtype == TYPE_FLOAT)
out = new ast_binstore(ctx, assignop,
(op->id == opid2('^','=') ? VINSTR_BITXOR : op->id == opid2('&','=') ? INSTR_BITAND : INSTR_BITOR),
ty1, ty2);
return false;
}
- if (ast_istype(exprs[0], ast_entfield))
- assignop = type_storep_instr[exprs[0]->m_vtype];
- else
- assignop = type_store_instr[exprs[0]->m_vtype];
+ assignop = store_op_for(exprs[0]);
if (exprs[0]->m_vtype == TYPE_FLOAT)
out = fold::binary(ctx, INSTR_BITAND, exprs[0], exprs[1]);
else
* intrinsic call and just evaluate it i.e constant fold it.
*/
if (fold && ast_istype(fun, ast_value) && ((ast_value*)fun)->m_intrinsic) {
- ast_expression **exprs = nullptr;
+ std::vector<ast_expression*> exprs;
ast_expression *foldval = nullptr;
+ exprs.reserve(paramcount);
for (i = 0; i < paramcount; i++)
- vec_push(exprs, sy->out[fid+1 + i].out);
+ exprs.push_back(sy->out[fid+1 + i].out);
- if (!(foldval = parser->m_intrin.do_fold((ast_value*)fun, exprs))) {
- vec_free(exprs);
+ if (!(foldval = parser->m_intrin.do_fold((ast_value*)fun, exprs.data()))) {
goto fold_leave;
}
*/
sy->out[fid] = syexp(foldval->m_context, foldval);
sy->out.erase(sy->out.end() - paramcount, sy->out.end());
- vec_free(exprs);
return true;
}
}
else
{
- if (ast_istype(var, ast_value)) {
- ((ast_value*)var)->m_uses++;
+ // promote these to norefs
+ if (ast_istype(var, ast_value))
+ {
+ ((ast_value *)var)->m_flags |= AST_FLAG_NOREF;
}
- else if (ast_istype(var, ast_member)) {
- ast_member *mem = (ast_member*)var;
+ else if (ast_istype(var, ast_member))
+ {
+ ast_member *mem = (ast_member *)var;
if (ast_istype(mem->m_owner, ast_value))
- ((ast_value*)(mem->m_owner))->m_uses++;
+ ((ast_value *)mem->m_owner)->m_flags |= AST_FLAG_NOREF;
}
}
sy->out.push_back(syexp(parser_ctx(parser), var));
static void parser_enterblock(parser_t *parser)
{
- vec_push(parser->variables, util_htnew(PARSER_HT_SIZE));
- vec_push(parser->_blocklocals, vec_size(parser->_locals));
- vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
- vec_push(parser->_blocktypedefs, vec_size(parser->_typedefs));
- vec_push(parser->_block_ctx, parser_ctx(parser));
+ parser->variables.push_back(util_htnew(PARSER_HT_SIZE));
+ parser->_blocklocals.push_back(parser->_locals.size());
+ parser->typedefs.push_back(util_htnew(TYPEDEF_HT_SIZE));
+ parser->_blocktypedefs.push_back(parser->_typedefs.size());
+ parser->_block_ctx.push_back(parser_ctx(parser));
}
static bool parser_leaveblock(parser_t *parser)
bool rv = true;
size_t locals, typedefs;
- if (vec_size(parser->variables) <= PARSER_HT_LOCALS) {
+ if (parser->variables.size() <= PARSER_HT_LOCALS) {
parseerror(parser, "internal error: parser_leaveblock with no block");
return false;
}
- util_htdel(vec_last(parser->variables));
+ util_htdel(parser->variables.back());
- vec_pop(parser->variables);
- if (!vec_size(parser->_blocklocals)) {
+ parser->variables.pop_back();
+ if (!parser->_blocklocals.size()) {
parseerror(parser, "internal error: parser_leaveblock with no block (2)");
return false;
}
- locals = vec_last(parser->_blocklocals);
- vec_pop(parser->_blocklocals);
- while (vec_size(parser->_locals) != locals) {
- ast_expression *e = vec_last(parser->_locals);
- ast_value *v = (ast_value*)e;
- vec_pop(parser->_locals);
- if (ast_istype(e, ast_value) && !v->m_uses) {
- if (compile_warning(v->m_context, WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->m_name))
- rv = false;
- }
- }
+ locals = parser->_blocklocals.back();
+ parser->_blocklocals.pop_back();
+ parser->_locals.resize(locals);
- typedefs = vec_last(parser->_blocktypedefs);
- while (vec_size(parser->_typedefs) != typedefs) {
- delete vec_last(parser->_typedefs);
- vec_pop(parser->_typedefs);
- }
- util_htdel(vec_last(parser->typedefs));
- vec_pop(parser->typedefs);
+ typedefs = parser->_blocktypedefs.back();
+ parser->_typedefs.resize(typedefs);
+ util_htdel(parser->typedefs.back());
+ parser->typedefs.pop_back();
- vec_pop(parser->_block_ctx);
+ parser->_block_ctx.pop_back();
return rv;
}
static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e)
{
- vec_push(parser->_locals, e);
- util_htset(vec_last(parser->variables), name, (void*)e);
+ parser->_locals.push_back(e);
+ util_htset(parser->variables.back(), name, (void*)e);
}
static void parser_addlocal(parser_t *parser, const std::string &name, ast_expression *e) {
return parser_addlocal(parser, name.c_str(), e);
retval = new ast_value(ctx, "#LOCAL_RETURN", TYPE_VOID);
retval->adoptType(*expected->m_next);
parser->function->m_return_value = retval;
+ parser->function->m_return_value->m_flags |= AST_FLAG_NOREF;
}
if (!exp->compareType(*retval)) {
return false;
}
swcase.m_value = parse_expression_leave(parser, false, false, false);
+
+ if (!operand->compareType(*swcase.m_value)) {
+ char ty1[1024];
+ char ty2[1024];
+
+ ast_type_to_string(swcase.m_value, ty1, sizeof ty1);
+ ast_type_to_string(operand, ty2, sizeof ty2);
+
+ auto fnLiteral = [](ast_expression *expression) -> char* {
+ if (!ast_istype(expression, ast_value))
+ return nullptr;
+ ast_value *value = (ast_value *)expression;
+ if (!value->m_hasvalue)
+ return nullptr;
+ char *string = nullptr;
+ basic_value_t *constval = &value->m_constval;
+ switch (value->m_vtype)
+ {
+ case TYPE_FLOAT:
+ util_asprintf(&string, "%.2f", constval->vfloat);
+ return string;
+ case TYPE_VECTOR:
+ util_asprintf(&string, "'%.2f %.2f %.2f'",
+ constval->vvec.x,
+ constval->vvec.y,
+ constval->vvec.z);
+ return string;
+ case TYPE_STRING:
+ util_asprintf(&string, "\"%s\"", constval->vstring);
+ return string;
+ default:
+ break;
+ }
+ return nullptr;
+ };
+
+ char *literal = fnLiteral(swcase.m_value);
+ if (literal)
+ compile_error(parser_ctx(parser), "incompatible type `%s` for switch case `%s` expected `%s`", ty1, literal, ty2);
+ else
+ compile_error(parser_ctx(parser), "incompatible type `%s` for switch case expected `%s`", ty1, ty2);
+ mem_d(literal);
+ delete switchnode;
+ return false;
+ }
+
if (!swcase.m_value) {
delete switchnode;
parseerror(parser, "expected expression for case");
bool flag = false;
bool reverse = false;
qcfloat_t num = 0;
- ast_value **values = nullptr;
ast_value *var = nullptr;
ast_value *asvalue;
+ std::vector<ast_value*> values;
ast_expression *old;
break;
}
parseerror(parser, "expected identifier or `}`");
- goto onerror;
+ return false;
}
old = parser_find_field(parser, parser_tokval(parser));
if (old) {
parseerror(parser, "value `%s` has already been declared here: %s:%i",
parser_tokval(parser), old->m_context.file, old->m_context.line);
- goto onerror;
+ return false;
}
var = new ast_value(parser_ctx(parser), parser_tokval(parser), TYPE_FLOAT);
- vec_push(values, var);
+ values.push_back(var);
var->m_cvq = CV_CONST;
var->m_hasvalue = true;
if (!parser_next(parser)) {
parseerror(parser, "expected `=`, `}` or comma after identifier");
- goto onerror;
+ return false;
}
if (parser->tok == ',')
break;
if (parser->tok != '=') {
parseerror(parser, "expected `=`, `}` or comma after identifier");
- goto onerror;
+ return false;
}
if (!parser_next(parser)) {
parseerror(parser, "expected expression after `=`");
- goto onerror;
+ return false;
}
/* We got a value! */
asvalue = (ast_value*)old;
if (!ast_istype(old, ast_value) || asvalue->m_cvq != CV_CONST || !asvalue->m_hasvalue) {
compile_error(var->m_context, "constant value or expression expected");
- goto onerror;
+ return false;
}
num = (var->m_constval.vfloat = asvalue->m_constval.vfloat) + 1;
break;
if (parser->tok != ',') {
parseerror(parser, "expected `}` or comma after expression");
- goto onerror;
+ return false;
}
}
/* patch them all (for reversed attribute) */
if (reverse) {
size_t i;
- for (i = 0; i < vec_size(values); i++)
- values[i]->m_constval.vfloat = vec_size(values) - i - 1;
+ for (i = 0; i < values.size(); i++)
+ values[i]->m_constval.vfloat = values.size() - i - 1;
}
if (parser->tok != '}') {
parseerror(parser, "internal error: breaking without `}`");
- goto onerror;
+ return false;
}
if (!parser_next(parser) || parser->tok != ';') {
parseerror(parser, "expected semicolon after enumeration");
- goto onerror;
+ return false;
}
if (!parser_next(parser)) {
parseerror(parser, "parse error after enumeration");
- goto onerror;
+ return false;
}
- vec_free(values);
return true;
-
-onerror:
- vec_free(values);
- return false;
}
static bool parse_block_into(parser_t *parser, ast_block *block)
parser->function = old;
if (!parser_leaveblock(parser))
retval = false;
- if (vec_size(parser->variables) != PARSER_HT_LOCALS) {
+ if (parser->variables.size() != PARSER_HT_LOCALS) {
parseerror(parser, "internal error: local scopes left");
retval = false;
}
return false;
}
- if ( (oldtype = parser_find_typedef(parser, typevar->m_name, vec_last(parser->_blocktypedefs))) ) {
+ if ( (oldtype = parser_find_typedef(parser, typevar->m_name, parser->_blocktypedefs.back())) ) {
parseerror(parser, "type `%s` has already been declared here: %s:%i",
typevar->m_name, oldtype->m_context.file, oldtype->m_context.line);
delete typevar;
return false;
}
- vec_push(parser->_typedefs, typevar);
- util_htset(vec_last(parser->typedefs), typevar->m_name.c_str(), typevar);
+ parser->_typedefs.emplace_back(typevar);
+ util_htset(parser->typedefs.back(), typevar->m_name.c_str(), typevar);
if (parser->tok != ';') {
parseerror(parser, "expected semicolon after typedef");
/* Deal with end_sys_ vars */
was_end = false;
if (var->m_name == "end_sys_globals") {
- var->m_uses++;
+ var->m_flags |= AST_FLAG_NOREF;
parser->crc_globals = parser->globals.size();
was_end = true;
}
else if (var->m_name == "end_sys_fields") {
- var->m_uses++;
+ var->m_flags |= AST_FLAG_NOREF;
parser->crc_fields = parser->fields.size();
was_end = true;
}
}
else /* it's not a global */
{
- old = parser_find_local(parser, var->m_name, vec_size(parser->variables)-1, &isparam);
+ old = parser_find_local(parser, var->m_name, parser->variables.size()-1, &isparam);
if (old && !isparam) {
parseerror(parser, "local `%s` already declared here: %s:%i",
var->m_name, old->m_context.file, (int)old->m_context.line);
}
}
- /* in a noref section we simply bump the usecount */
if (noref || parser->noref)
- var->m_uses++;
+ var->m_flags |= AST_FLAG_NOREF;
/* Part 2:
* Create the global/local, and deal with vector types.
prefix_len = defname.length();
// Add it to the local scope
- util_htset(vec_last(parser->variables), var->m_name.c_str(), (void*)var);
+ util_htset(parser->variables.back(), var->m_name.c_str(), (void*)var);
// now rename the global
defname.append(var->m_name);
if (isvector) {
defname.erase(prefix_len);
for (i = 0; i < 3; ++i) {
- util_htset(vec_last(parser->variables), me[i]->m_name.c_str(), (void*)(me[i]));
- me[i]->m_name = move(defname + me[i]->m_name);
+ util_htset(parser->variables.back(), me[i]->m_name.c_str(), (void*)(me[i]));
+ me[i]->m_name = defname + me[i]->m_name;
parser->globals.push_back(me[i]);
}
}
/* remove it from the current locals */
if (isvector) {
for (i = 0; i < 3; ++i) {
- vec_pop(parser->_locals);
+ parser->_locals.pop_back();
localblock->m_collect.pop_back();
}
}
/* do sanity checking, this function really needs refactoring */
- if (vec_last(parser->_locals) != var)
+ if (parser->_locals.back() != var)
parseerror(parser, "internal error: unexpected change in local variable handling");
else
- vec_pop(parser->_locals);
+ parser->_locals.pop_back();
if (localblock->m_locals.back() != var)
parseerror(parser, "internal error: unexpected change in local variable handling (2)");
else
var->m_cvq = CV_CONST;
}
if (cval == parser->nil)
+ {
var->m_flags |= AST_FLAG_INITIALIZED;
+ var->m_flags |= AST_FLAG_NOREF;
+ }
else
{
var->m_hasvalue = true;
ir->m_code->crc = crc;
}
+parser_t::parser_t()
+ : lex(nullptr)
+ , tok(0)
+ , ast_cleaned(false)
+ , translated(0)
+ , crc_globals(0)
+ , crc_fields(0)
+ , function(nullptr)
+ , aliases(util_htnew(PARSER_HT_SIZE))
+ , htfields(util_htnew(PARSER_HT_SIZE))
+ , htglobals(util_htnew(PARSER_HT_SIZE))
+ , assign_op(nullptr)
+ , noref(false)
+ , max_param_count(1)
+ // finish initializing the rest of the parser before initializing
+ // m_fold and m_intrin with the parser passed along
+ , m_fold()
+ , m_intrin()
+{
+ variables.push_back(htfields);
+ variables.push_back(htglobals);
+ typedefs.push_back(util_htnew(TYPEDEF_HT_SIZE));
+ _blocktypedefs.push_back(0);
+
+ lex_ctx_t empty_ctx;
+ empty_ctx.file = "<internal>";
+ empty_ctx.line = 0;
+ empty_ctx.column = 0;
+ nil = new ast_value(empty_ctx, "nil", TYPE_NIL);
+ nil->m_cvq = CV_CONST;
+ if (OPTS_FLAG(UNTYPED_NIL))
+ util_htset(htglobals, "nil", (void*)nil);
+
+ const_vec[0] = new ast_value(empty_ctx, "<vector.x>", TYPE_NOEXPR);
+ const_vec[1] = new ast_value(empty_ctx, "<vector.y>", TYPE_NOEXPR);
+ const_vec[2] = new ast_value(empty_ctx, "<vector.z>", TYPE_NOEXPR);
+
+ if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) {
+ reserved_version = new ast_value(empty_ctx, "reserved:version", TYPE_STRING);
+ reserved_version->m_cvq = CV_CONST;
+ reserved_version->m_hasvalue = true;
+ reserved_version->m_flags |= AST_FLAG_INCLUDE_DEF;
+ reserved_version->m_flags |= AST_FLAG_NOREF;
+ reserved_version->m_constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
+ } else {
+ reserved_version = nullptr;
+ }
+
+ m_fold = fold(this);
+ m_intrin = intrin(this);
+}
+
+parser_t::~parser_t()
+{
+ remove_ast();
+}
+
parser_t *parser_create()
{
parser_t *parser;
- lex_ctx_t empty_ctx;
size_t i;
- parser = (parser_t*)mem_a(sizeof(parser_t));
+ parser = new parser_t;
if (!parser)
return nullptr;
- memset(parser, 0, sizeof(*parser));
-
- // TODO: remove
- new (parser) parser_t();
-
for (i = 0; i < operator_count; ++i) {
if (operators[i].id == opid1('=')) {
parser->assign_op = operators+i;
}
if (!parser->assign_op) {
con_err("internal error: initializing parser: failed to find assign operator\n");
- mem_d(parser);
+ delete parser;
return nullptr;
}
- vec_push(parser->variables, parser->htfields = util_htnew(PARSER_HT_SIZE));
- vec_push(parser->variables, parser->htglobals = util_htnew(PARSER_HT_SIZE));
- vec_push(parser->typedefs, util_htnew(TYPEDEF_HT_SIZE));
- vec_push(parser->_blocktypedefs, 0);
-
- parser->aliases = util_htnew(PARSER_HT_SIZE);
-
- empty_ctx.file = "<internal>";
- empty_ctx.line = 0;
- empty_ctx.column = 0;
- parser->nil = new ast_value(empty_ctx, "nil", TYPE_NIL);
- parser->nil->m_cvq = CV_CONST;
- if (OPTS_FLAG(UNTYPED_NIL))
- util_htset(parser->htglobals, "nil", (void*)parser->nil);
-
- parser->max_param_count = 1;
-
- parser->const_vec[0] = new ast_value(empty_ctx, "<vector.x>", TYPE_NOEXPR);
- parser->const_vec[1] = new ast_value(empty_ctx, "<vector.y>", TYPE_NOEXPR);
- parser->const_vec[2] = new ast_value(empty_ctx, "<vector.z>", TYPE_NOEXPR);
-
- if (OPTS_OPTION_BOOL(OPTION_ADD_INFO)) {
- parser->reserved_version = new ast_value(empty_ctx, "reserved:version", TYPE_STRING);
- parser->reserved_version->m_cvq = CV_CONST;
- parser->reserved_version->m_hasvalue = true;
- parser->reserved_version->m_flags |= AST_FLAG_INCLUDE_DEF;
- parser->reserved_version->m_constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
- } else {
- parser->reserved_version = nullptr;
- }
-
- parser->m_fold = fold(parser);
- parser->m_intrin = intrin(parser);
return parser;
}
return parser_compile(parser);
}
-static void parser_remove_ast(parser_t *parser)
+void parser_t::remove_ast()
{
- size_t i;
- if (parser->ast_cleaned)
+ if (ast_cleaned)
return;
- parser->ast_cleaned = true;
- for (auto &it : parser->accessors) {
+ ast_cleaned = true;
+ for (auto &it : accessors) {
delete it->m_constval.vfunc;
it->m_constval.vfunc = nullptr;
delete it;
}
- for (auto &it : parser->functions) delete it;
- for (auto &it : parser->globals) delete it;
- for (auto &it : parser->fields) delete it;
-
- for (i = 0; i < vec_size(parser->variables); ++i)
- util_htdel(parser->variables[i]);
- vec_free(parser->variables);
- vec_free(parser->_blocklocals);
- vec_free(parser->_locals);
+ for (auto &it : functions) delete it;
+ for (auto &it : globals) delete it;
+ for (auto &it : fields) delete it;
- for (i = 0; i < vec_size(parser->_typedefs); ++i)
- delete parser->_typedefs[i];
- vec_free(parser->_typedefs);
- for (i = 0; i < vec_size(parser->typedefs); ++i)
- util_htdel(parser->typedefs[i]);
- vec_free(parser->typedefs);
- vec_free(parser->_blocktypedefs);
+ for (auto &it : variables) util_htdel(it);
+ variables.clear();
+ _blocklocals.clear();
+ _locals.clear();
- vec_free(parser->_block_ctx);
+ _typedefs.clear();
+ for (auto &it : typedefs) util_htdel(it);
+ typedefs.clear();
+ _blocktypedefs.clear();
- delete parser->nil;
+ _block_ctx.clear();
- delete parser->const_vec[0];
- delete parser->const_vec[1];
- delete parser->const_vec[2];
+ delete nil;
- if (parser->reserved_version)
- delete parser->reserved_version;
+ delete const_vec[0];
+ delete const_vec[1];
+ delete const_vec[2];
- util_htdel(parser->aliases);
-}
+ if (reserved_version)
+ delete reserved_version;
-void parser_cleanup(parser_t *parser)
-{
- parser_remove_ast(parser);
- parser->~parser_t();
- mem_d(parser);
+ util_htdel(aliases);
}
static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) {
if (!ast_istype(it, ast_value))
continue;
asvalue = (ast_value*)it;
- if (!asvalue->m_uses && !asvalue->m_hasvalue && asvalue->m_vtype != TYPE_FUNCTION) {
+ if (!(asvalue->m_flags & AST_FLAG_NOREF) && asvalue->m_cvq != CV_CONST && asvalue->m_vtype != TYPE_FUNCTION) {
retval = retval && !compile_warning(asvalue->m_context, WARN_UNUSED_VARIABLE,
"unused global: `%s`", asvalue->m_name);
}
return false;
}
}
- parser_remove_ast(parser);
+ parser->remove_ast();
- if (compile_Werrors) {
- con_out("*** there were warnings treated as errors\n");
- compile_show_werrors();
- retval = false;
- }
+ auto fnCheckWErrors = [&retval]() {
+ if (compile_Werrors) {
+ con_out("*** there were warnings treated as errors\n");
+ compile_show_werrors();
+ retval = false;
+ }
+ };
+
+ fnCheckWErrors();
if (retval) {
if (OPTS_OPTION_BOOL(OPTION_DUMPFIN))
delete ir;
return false;
}
+
+ // ir->generate can generate compiler warnings
+ fnCheckWErrors();
}
delete ir;
return retval;