From: Dale Weiler Date: Sun, 26 Nov 2017 22:30:42 +0000 (-0500) Subject: Merge pull request #177 from xonotic/terencehill/warning_removal X-Git-Tag: xonotic-v0.8.5~29^2 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=commitdiff_plain;h=679e3771de1c016b30bb21da2823e2dc832c2e8a;hp=27c0886ffbd1065183f21bc94c95234641fe9932 Merge pull request #177 from xonotic/terencehill/warning_removal Get rid of a warning on Windows --- diff --git a/exec.cpp b/exec.cpp index 9e49ed8..387923f 100644 --- a/exec.cpp +++ b/exec.cpp @@ -113,7 +113,8 @@ qc_program_t* prog_load(const char *filename, bool skipversion) /* spawn the world entity */ prog->entitypool.emplace_back(true); prog->entitydata.resize(prog->entityfields); - memset(prog->entitydata.data(), 0, sizeof(prog->entitydata[0]) * prog->entityfields); + if (prog->entitydata.size()) + memset(prog->entitydata.data(), 0, sizeof(prog->entitydata[0]) * prog->entityfields); prog->entities = 1; /* cache some globals and fields from names */ @@ -517,8 +518,10 @@ static qcint_t prog_leavefunction(qc_program_t *prog) { oldsp = prog->stack[prog->stack.size()-1].localsp; #endif if (prev) { - qcint_t *globals = &prog->globals[0] + prev->firstlocal; - memcpy(globals, &prog->localstack[oldsp], prev->locals * sizeof(prog->localstack[0])); + if (prev->locals) { + qcint_t *globals = &prog->globals[0] + prev->firstlocal; + memcpy(globals, &prog->localstack[oldsp], prev->locals * sizeof(prog->localstack[0])); + } prog->localstack.resize(oldsp); } diff --git a/fold.cpp b/fold.cpp index 7a0df0e..7b13db6 100644 --- a/fold.cpp +++ b/fold.cpp @@ -1392,8 +1392,8 @@ ast_expression *fold::op(const oper_info *info, ast_expression **opexprs) { return nullptr; switch(info->operands) { - case 3: if(!c) return nullptr; - case 2: if(!b) return nullptr; + case 3: if(!c) return nullptr; [[fallthrough]]; + case 2: if(!b) return nullptr; [[fallthrough]]; case 1: if(!a) { compile_error(ctx(), "internal error: fold_op no operands to fold\n"); @@ -1560,6 +1560,7 @@ ast_expression *fold::superfluous(ast_expression *left, ast_expression *right, i case INSTR_DIV_F: if (swapped) return nullptr; + [[fallthrough]]; case INSTR_MUL_F: if (immvalue_float(load) == 1.0f) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; @@ -1572,6 +1573,7 @@ ast_expression *fold::superfluous(ast_expression *left, ast_expression *right, i case INSTR_SUB_F: if (swapped) return nullptr; + [[fallthrough]]; case INSTR_ADD_F: if (immvalue_float(load) == 0.0f) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; @@ -1591,6 +1593,7 @@ ast_expression *fold::superfluous(ast_expression *left, ast_expression *right, i case INSTR_SUB_V: if (swapped) return nullptr; + [[fallthrough]]; case INSTR_ADD_V: if (vec3_cmp(immvalue_vector(load), vec3_create(0, 0, 0))) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; diff --git a/gmqcc.h b/gmqcc.h index 112628e..10b74f5 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -741,7 +741,6 @@ parser_t *parser_create(void); bool parser_compile_file(parser_t *parser, const char *); bool parser_compile_string(parser_t *parser, const char *, const char *, size_t); bool parser_finish(parser_t *parser, const char *); -void parser_cleanup(parser_t *parser); /* ftepp.c */ struct ftepp_t; diff --git a/ir.cpp b/ir.cpp index 7a2583b..facbc33 100644 --- a/ir.cpp +++ b/ir.cpp @@ -1474,6 +1474,7 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, !ir_instr_op(in, 1, func, false)) { delete in; + delete out; return nullptr; } self->m_instr.push_back(in); @@ -3239,7 +3240,7 @@ bool ir_builder::generateGlobalFunctionCode(ir_value *global) return true; } -static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *name) +static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *name, int type) { char *component; size_t len, i; @@ -3247,7 +3248,7 @@ static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *na if (!name || name[0] == '#' || OPTS_FLAG(SINGLE_VECTOR_DEFS)) return; - def.type = TYPE_FLOAT; + def.type = type; len = strlen(name); @@ -3347,9 +3348,9 @@ bool ir_builder::generateGlobal(ir_value *global, bool islocal) def.offset = global->codeAddress(); m_code->defs.push_back(def); if (global->m_vtype == TYPE_VECTOR) - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FLOAT); else if (global->m_vtype == TYPE_FIELD && global->m_fieldtype == TYPE_VECTOR) - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FIELD); return true; } } @@ -3391,7 +3392,7 @@ bool ir_builder::generateGlobal(ir_value *global, bool islocal) if (pushdef) { m_code->defs.push_back(def); if (global->m_fieldtype == TYPE_VECTOR) - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FIELD); } return gen_global_field(m_code.get(), global); case TYPE_ENTITY: @@ -3457,7 +3458,7 @@ bool ir_builder::generateGlobal(ir_value *global, bool islocal) if (pushdef) { m_code->defs.push_back(def); def.type &= ~DEF_SAVEGLOBAL; - gen_vector_defs(m_code.get(), def, global->m_name.c_str()); + gen_vector_defs(m_code.get(), def, global->m_name.c_str(), TYPE_FLOAT); } return global->m_code.globaladdr >= 0; } @@ -3560,7 +3561,7 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) } if (field->m_fieldtype == TYPE_VECTOR) { - gen_vector_defs (self->m_code.get(), def, field->m_name.c_str()); + gen_vector_defs (self->m_code.get(), def, field->m_name.c_str(), TYPE_FIELD); gen_vector_fields(self->m_code.get(), fld, field->m_name.c_str()); } diff --git a/main.cpp b/main.cpp index 449067d..76c1d31 100644 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,7 @@ #include "gmqcc.h" #include "lexer.h" +#include "parser.h" /* TODO: cleanup this whole file .. it's a fuckign mess */ @@ -736,7 +737,7 @@ cleanup: vec_free(ppems); if (!OPTS_OPTION_BOOL(OPTION_PP_ONLY)) - if(parser) parser_cleanup(parser); + delete parser; /* free allocated option strings */ for (itr = 0; itr < OPTION_COUNT; itr++) diff --git a/parser.cpp b/parser.cpp index e365316..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; } @@ -1996,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) @@ -2008,41 +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) - vec_pop(parser->_locals); + 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); @@ -3170,6 +3159,7 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression * } if (!OPTS_FLAG(RELAXED_SWITCH)) { if (!ast_istype(swcase.m_value, ast_value)) { /* || ((ast_value*)swcase.m_value)->m_cvq != CV_CONST) { */ + delete switchnode; parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch"); ast_unref(operand); return false; @@ -3623,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; @@ -3667,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)); @@ -3676,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; @@ -3690,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 == ',') @@ -3699,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! */ @@ -3712,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; @@ -3720,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) @@ -4170,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; } @@ -4989,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"); @@ -5364,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); @@ -5491,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); @@ -5521,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]); } } @@ -5759,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 @@ -6021,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; @@ -6044,44 +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_flags |= AST_FLAG_NOREF; - 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; } @@ -6137,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) { @@ -6368,7 +6358,7 @@ bool parser_finish(parser_t *parser, const char *output) return false; } } - parser_remove_ast(parser); + parser->remove_ast(); auto fnCheckWErrors = [&retval]() { if (compile_Werrors) { diff --git a/parser.h b/parser.h index a09238d..e5361a8 100644 --- a/parser.h +++ b/parser.h @@ -2,7 +2,7 @@ #define GMQCC_PARSER_HDR #include "gmqcc.h" #include "lexer.h" -//#include "ast.h" +#include "ast.h" #include "intrin.h" #include "fold.h" @@ -12,7 +12,10 @@ struct parser_t; #define parser_ctx(p) ((p)->lex->tok.ctx) struct parser_t { - parser_t() { } + parser_t(); + ~parser_t(); + + void remove_ast(); lex_file *lex; int tok; @@ -45,17 +48,17 @@ struct parser_t { std::vector continues; /* A list of hashtables for each scope */ - ht *variables; + std::vector variables; ht htfields; ht htglobals; - ht *typedefs; + std::vector typedefs; /* not to be used directly, we use the hash table */ - ast_expression **_locals; - size_t *_blocklocals; - ast_value **_typedefs; - size_t *_blocktypedefs; - lex_ctx_t *_block_ctx; + std::vector _locals; + std::vector _blocklocals; + std::vector> _typedefs; + std::vector _blocktypedefs; + std::vector _block_ctx; /* we store the '=' operator info */ const oper_info *assign_op; diff --git a/tests/memberbinop.qc b/tests/memberbinop.qc new file mode 100644 index 0000000..55f5aea --- /dev/null +++ b/tests/memberbinop.qc @@ -0,0 +1,15 @@ +.vector k; + +void t(entity e) +{ + e.k = '0 0 0'; + e.k.x += 2; + e.k.y += 4; + e.k.z += 6; +} + +void main() { + entity e = spawn(); + t(e); + print(vtos(e.k)); +} diff --git a/tests/memberbinop.tmpl b/tests/memberbinop.tmpl new file mode 100644 index 0000000..21abd20 --- /dev/null +++ b/tests/memberbinop.tmpl @@ -0,0 +1,6 @@ +I: memberbinop.qc +D: test member bin ops +T: -execute +C: -std=gmqcc +E: $null +M: '2 4 6'