}
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));
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;
+ while (vec_size(parser->_locals) != locals)
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;
- }
- }
typedefs = vec_last(parser->_blocktypedefs);
while (vec_size(parser->_typedefs) != typedefs) {
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");
/* 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;
}
}
}
- /* 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.
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;
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;
if (!ast_istype(it, ast_value))
continue;
asvalue = (ast_value*)it;
- if (!asvalue->m_uses && asvalue->m_cvq != CV_CONST && 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);
}
}
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))
delete ir;
return false;
}
+
+ // ir->generate can generate compiler warnings
+ fnCheckWErrors();
}
delete ir;
return retval;