X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=parser.cpp;h=518a06da1919a22933031ef15f71652af95f118a;hp=fd29f008f8f78876dc2382b9cbedeb0ed2bc6911;hb=69fa4f8dbd018c092a1e53671f6ce5d4248aac5c;hpb=45236a644fb45ac9f61c3ef38bcab17b5004b095 diff --git a/parser.cpp b/parser.cpp index fd29f00..518a06d 100644 --- a/parser.cpp +++ b/parser.cpp @@ -2523,8 +2523,7 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou parseerror(parser, "expected for-loop condition"); goto onerr; } - } - else if (!parser_next(parser)) { + } else if (!parser_next(parser)) { parseerror(parser, "expected for-loop condition"); goto onerr; } @@ -2535,7 +2534,6 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou if (!cond) goto onerr; } - /* move on to incrementor */ if (parser->tok != ';') { parseerror(parser, "expected semicolon after for-loop initializer"); @@ -3122,6 +3120,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"); @@ -6215,12 +6259,12 @@ bool parser_finish(parser_t *parser, const char *output) ast_expression *subtype; field->m_hasvalue = true; subtype = field->m_next; - ifld = ir_builder_create_field(ir, field->m_name, subtype->m_vtype); + ifld = ir->createField(field->m_name, subtype->m_vtype); if (subtype->m_vtype == TYPE_FIELD) ifld->m_fieldtype = subtype->m_next->m_vtype; else if (subtype->m_vtype == TYPE_FUNCTION) ifld->m_outtype = subtype->m_next->m_vtype; - (void)!ir_value_set_field(field->m_ir_v, ifld); + (void)!field->m_ir_v->setField(ifld); } } for (auto &it : parser->globals) { @@ -6228,7 +6272,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_uses && 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); } @@ -6316,7 +6360,7 @@ bool parser_finish(parser_t *parser, const char *output) generate_checksum(parser, ir); if (OPTS_OPTION_BOOL(OPTION_DUMP)) - ir_builder_dump(ir, con_out); + ir->dump(con_out); for (auto &it : parser->functions) { if (!ir_function_finalize(it->m_ir_func)) { con_out("failed to finalize function %s\n", it->m_name.c_str()); @@ -6326,21 +6370,28 @@ bool parser_finish(parser_t *parser, const char *output) } parser_remove_ast(parser); - 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)) - ir_builder_dump(ir, con_out); + ir->dump(con_out); - if (!ir_builder_generate(ir, output)) { + if (!ir->generate(output)) { con_out("*** failed to generate output file\n"); delete ir; return false; } + + // ir->generate can generate compiler warnings + fnCheckWErrors(); } delete ir; return retval;