X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=parser.cpp;h=ddde65469ec77e7cb596e58451dc88096c5ad8f1;hp=7bb2a10f8f2401f783feebed27da3fb12fac980f;hb=d9127bf28ad5c1f7626487bbc5f29e72e9912d67;hpb=8538658e830e2860799ef25f81983ef60a422cc6;ds=sidebyside diff --git a/parser.cpp b/parser.cpp index 7bb2a10..ddde654 100644 --- a/parser.cpp +++ b/parser.cpp @@ -139,7 +139,7 @@ static ast_expression* parser_find_local(parser_t *parser, const char *name, siz 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; @@ -171,7 +171,7 @@ static ast_value* parser_find_typedef(parser_t *parser, const char *name, size_t 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; @@ -293,6 +293,23 @@ static bool rotate_entfield_array_index_nodes(ast_expression **out) 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)) { @@ -728,6 +745,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) case opid2('|','|'): generated_op += 1; /* INSTR_OR */ + [[fallthrough]]; case opid2('&','&'): generated_op += INSTR_AND; if (!(out = parser->m_fold.op(op, exprs))) { @@ -857,10 +875,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) 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)) { @@ -896,14 +917,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) 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)); @@ -921,15 +935,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } 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)); @@ -1024,10 +1030,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) 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, @@ -1059,10 +1062,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) 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, @@ -1103,10 +1103,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) 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), @@ -1128,10 +1125,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) 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 @@ -1263,14 +1257,14 @@ static bool parser_close_call(parser_t *parser, shunt *sy) * 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 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; } @@ -1280,7 +1274,6 @@ static bool parser_close_call(parser_t *parser, shunt *sy) */ sy->out[fid] = syexp(foldval->m_context, foldval); sy->out.erase(sy->out.end() - paramcount, sy->out.end()); - vec_free(exprs); return true; } @@ -1668,13 +1661,16 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) } 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)); @@ -1993,11 +1989,11 @@ static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool 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) @@ -2005,48 +2001,37 @@ 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); @@ -2634,6 +2619,7 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou 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)) { @@ -3120,6 +3106,52 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * 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"); @@ -3581,9 +3613,9 @@ static bool parse_enum(parser_t *parser) bool flag = false; bool reverse = false; qcfloat_t num = 0; - ast_value **values = nullptr; ast_value *var = nullptr; ast_value *asvalue; + std::vector values; ast_expression *old; @@ -3625,7 +3657,7 @@ static bool parse_enum(parser_t *parser) break; } parseerror(parser, "expected identifier or `}`"); - goto onerror; + return false; } old = parser_find_field(parser, parser_tokval(parser)); @@ -3634,11 +3666,11 @@ static bool parse_enum(parser_t *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; @@ -3648,7 +3680,7 @@ static bool parse_enum(parser_t *parser) if (!parser_next(parser)) { parseerror(parser, "expected `=`, `}` or comma after identifier"); - goto onerror; + return false; } if (parser->tok == ',') @@ -3657,12 +3689,12 @@ static bool parse_enum(parser_t *parser) 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! */ @@ -3670,7 +3702,7 @@ static bool parse_enum(parser_t *parser) 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; @@ -3678,38 +3710,33 @@ static bool parse_enum(parser_t *parser) 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) @@ -4128,7 +4155,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) 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; } @@ -4947,15 +4974,15 @@ static bool parse_typedef(parser_t *parser) 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"); @@ -5187,12 +5214,12 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield /* 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; } @@ -5322,7 +5349,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } 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); @@ -5352,9 +5379,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } } - /* 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. @@ -5450,7 +5476,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield 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); @@ -5480,8 +5506,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield 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]); } } @@ -5718,15 +5744,15 @@ skipvar: /* 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 @@ -5755,7 +5781,10 @@ skipvar: 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; @@ -5977,21 +6006,72 @@ static void generate_checksum(parser_t *parser, ir_builder *ir) 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 = ""; + 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, "", TYPE_NOEXPR); + const_vec[1] = new ast_value(empty_ctx, "", TYPE_NOEXPR); + const_vec[2] = new ast_value(empty_ctx, "", 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; @@ -6000,43 +6080,10 @@ parser_t *parser_create() } 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 = ""; - 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, "", TYPE_NOEXPR); - parser->const_vec[1] = new ast_value(empty_ctx, "", TYPE_NOEXPR); - parser->const_vec[2] = new ast_value(empty_ctx, "", 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; } @@ -6092,54 +6139,42 @@ bool parser_compile_string(parser_t *parser, const char *name, const char *str, 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) { @@ -6227,7 +6262,7 @@ bool parser_finish(parser_t *parser, const char *output) 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); } @@ -6323,13 +6358,17 @@ bool parser_finish(parser_t *parser, const char *output) 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)) @@ -6340,6 +6379,9 @@ bool parser_finish(parser_t *parser, const char *output) delete ir; return false; } + + // ir->generate can generate compiler warnings + fnCheckWErrors(); } delete ir; return retval;