mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-20 18:32:01 +00:00
-fbail-on-werror option
This commit is contained in:
parent
24f3098418
commit
5cfd97c344
5 changed files with 167 additions and 157 deletions
29
conout.c
29
conout.c
|
@ -384,6 +384,14 @@ void con_cprintmsg (void *ctx, int lvl, const char *msgtype, const char *msg, ..
|
|||
size_t compile_errors = 0;
|
||||
size_t compile_warnings = 0;
|
||||
|
||||
size_t compile_Werrors = 0;
|
||||
static lex_ctx first_werror;
|
||||
|
||||
void compile_show_werrors()
|
||||
{
|
||||
con_cprintmsg((void*)&first_werror, LVL_ERROR, "first warning", "was here");
|
||||
}
|
||||
|
||||
void vcompile_error(lex_ctx ctx, const char *msg, va_list ap)
|
||||
{
|
||||
++compile_errors;
|
||||
|
@ -400,8 +408,9 @@ void compile_error(lex_ctx ctx, const char *msg, ...)
|
|||
|
||||
bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_list ap)
|
||||
{
|
||||
int lvl = LVL_WARNING;
|
||||
char warn_name[1024];
|
||||
const char *msgtype = "warning";
|
||||
int lvl = LVL_WARNING;
|
||||
char warn_name[1024];
|
||||
|
||||
if (!OPTS_WARN(warntype))
|
||||
return false;
|
||||
|
@ -410,16 +419,22 @@ bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_
|
|||
warn_name[1] = 'W';
|
||||
(void)util_strtononcmd(opts_warn_list[warntype].name, warn_name+2, sizeof(warn_name)-2);
|
||||
|
||||
++compile_warnings;
|
||||
if (OPTS_WERROR(warntype)) {
|
||||
++compile_errors;
|
||||
if (!compile_Werrors)
|
||||
first_werror = ctx;
|
||||
++compile_Werrors;
|
||||
msgtype = "Werror";
|
||||
if (OPTS_FLAG(BAIL_ON_WERROR)) {
|
||||
msgtype = "error";
|
||||
++compile_errors;
|
||||
}
|
||||
lvl = LVL_ERROR;
|
||||
}
|
||||
else
|
||||
++compile_warnings;
|
||||
|
||||
con_vprintmsg_c(lvl, ctx.file, ctx.line, ((lvl == LVL_ERROR) ? "error" : "warning"), fmt, ap, warn_name);
|
||||
con_vprintmsg_c(lvl, ctx.file, ctx.line, msgtype, fmt, ap, warn_name);
|
||||
|
||||
return OPTS_WERROR(warntype);
|
||||
return OPTS_WERROR(warntype) && OPTS_FLAG(BAIL_ON_WERROR);
|
||||
}
|
||||
|
||||
bool GMQCC_WARN compile_warning(lex_ctx ctx, int warntype, const char *fmt, ...)
|
||||
|
|
2
gmqcc.h
2
gmqcc.h
|
@ -685,12 +685,14 @@ int con_out (const char *, ...);
|
|||
|
||||
/* error/warning interface */
|
||||
extern size_t compile_errors;
|
||||
extern size_t compile_Werrors;
|
||||
extern size_t compile_warnings;
|
||||
|
||||
void /********/ compile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, ...);
|
||||
void /********/ vcompile_error (lex_ctx ctx, /*LVL_ERROR*/ const char *msg, va_list ap);
|
||||
bool GMQCC_WARN compile_warning (lex_ctx ctx, int warntype, const char *fmt, ...);
|
||||
bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_list ap);
|
||||
void compile_show_werrors();
|
||||
|
||||
/*===================================================================*/
|
||||
/*========================= assembler.c =============================*/
|
||||
|
|
1
opts.c
1
opts.c
|
@ -59,6 +59,7 @@ static void opts_setdefault() {
|
|||
opts_set(opts.flags, FTEPP, false);
|
||||
opts_set(opts.flags, FTEPP_PREDEFS, false);
|
||||
opts_set(opts.flags, CORRECT_TERNARY, true);
|
||||
opts_set(opts.flags, BAIL_ON_WERROR, true);
|
||||
}
|
||||
|
||||
void opts_init(const char *output, int standard, size_t arraysize) {
|
||||
|
|
1
opts.def
1
opts.def
|
@ -45,6 +45,7 @@
|
|||
GMQCC_DEFINE_FLAG(TRUE_EMPTY_STRINGS)
|
||||
GMQCC_DEFINE_FLAG(FALSE_EMPTY_STRINGS)
|
||||
GMQCC_DEFINE_FLAG(UTF8)
|
||||
GMQCC_DEFINE_FLAG(BAIL_ON_WERROR)
|
||||
#endif
|
||||
|
||||
/* warning flags */
|
||||
|
|
291
parser.c
291
parser.c
|
@ -76,8 +76,6 @@ typedef struct {
|
|||
size_t *_blocktypedefs;
|
||||
lex_ctx *_block_ctx;
|
||||
|
||||
size_t errors;
|
||||
|
||||
/* we store the '=' operator info */
|
||||
const oper_info *assign_op;
|
||||
|
||||
|
@ -114,11 +112,8 @@ static ast_expression* parse_expression(parser_t *parser, bool stopatcomma);
|
|||
static void parseerror(parser_t *parser, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
parser->errors++;
|
||||
|
||||
va_start(ap, fmt);
|
||||
con_vprintmsg(LVL_ERROR, parser->lex->tok.ctx.file, parser->lex->tok.ctx.line, "parse error", fmt, ap);
|
||||
vcompile_error(parser->lex->tok.ctx, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
@ -992,11 +987,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
|||
field->expression.next->expression.vtype == TYPE_FUNCTION &&
|
||||
exprs[1]->expression.vtype == TYPE_FUNCTION)
|
||||
{
|
||||
if (parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
|
||||
"invalid types in assignment: cannot assign %s to %s", ty2, ty1))
|
||||
{
|
||||
parser->errors++;
|
||||
}
|
||||
(void)!parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
|
||||
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
||||
}
|
||||
else
|
||||
parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
||||
|
@ -1026,11 +1018,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
|||
exprs[0]->expression.vtype == TYPE_FUNCTION &&
|
||||
exprs[1]->expression.vtype == TYPE_FUNCTION)
|
||||
{
|
||||
if (parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
|
||||
"invalid types in assignment: cannot assign %s to %s", ty2, ty1))
|
||||
{
|
||||
parser->errors++;
|
||||
}
|
||||
(void)!parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
|
||||
"invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
||||
}
|
||||
else
|
||||
parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
||||
|
@ -1306,8 +1295,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
|
|||
params->exprs = NULL;
|
||||
ast_delete(params);
|
||||
}
|
||||
if (!ast_call_check_types(call))
|
||||
parser->errors++;
|
||||
(void)!ast_call_check_types(call);
|
||||
} else {
|
||||
parseerror(parser, "invalid function call");
|
||||
return false;
|
||||
|
@ -1873,10 +1861,8 @@ static bool parser_leaveblock(parser_t *parser)
|
|||
ast_value *v = (ast_value*)e;
|
||||
vec_pop(parser->_locals);
|
||||
if (ast_istype(e, ast_value) && !v->uses) {
|
||||
if (compile_warning(ast_ctx(v), WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name)) {
|
||||
parser->errors++;
|
||||
if (compile_warning(ast_ctx(v), WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->name))
|
||||
rv = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4742,7 +4728,7 @@ bool parser_compile()
|
|||
if (!parser_global_statement(parser)) {
|
||||
if (parser->tok == TOKEN_EOF)
|
||||
parseerror(parser, "unexpected eof");
|
||||
else if (!parser->errors)
|
||||
else if (compile_errors)
|
||||
parseerror(parser, "there have been errors, bailing out");
|
||||
lex_close(parser->lex);
|
||||
parser->lex = NULL;
|
||||
|
@ -4759,7 +4745,7 @@ bool parser_compile()
|
|||
lex_close(parser->lex);
|
||||
parser->lex = NULL;
|
||||
|
||||
return !parser->errors;
|
||||
return !compile_errors;
|
||||
}
|
||||
|
||||
bool parser_compile_file(const char *filename)
|
||||
|
@ -4844,133 +4830,138 @@ bool parser_finish(const char *output)
|
|||
ir_builder *ir;
|
||||
bool retval = true;
|
||||
|
||||
if (!parser->errors)
|
||||
{
|
||||
ir = ir_builder_new("gmqcc_out");
|
||||
if (!ir) {
|
||||
con_out("failed to allocate builder\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < vec_size(parser->fields); ++i) {
|
||||
ast_value *field;
|
||||
bool hasvalue;
|
||||
if (!ast_istype(parser->fields[i], ast_value))
|
||||
continue;
|
||||
field = (ast_value*)parser->fields[i];
|
||||
hasvalue = field->hasvalue;
|
||||
field->hasvalue = false;
|
||||
if (!ast_global_codegen((ast_value*)field, ir, true)) {
|
||||
con_out("failed to generate field %s\n", field->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
if (hasvalue) {
|
||||
ir_value *ifld;
|
||||
ast_expression *subtype;
|
||||
field->hasvalue = true;
|
||||
subtype = field->expression.next;
|
||||
ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
|
||||
if (subtype->expression.vtype == TYPE_FIELD)
|
||||
ifld->fieldtype = subtype->expression.next->expression.vtype;
|
||||
else if (subtype->expression.vtype == TYPE_FUNCTION)
|
||||
ifld->outtype = subtype->expression.next->expression.vtype;
|
||||
(void)!ir_value_set_field(field->ir_v, ifld);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->globals); ++i) {
|
||||
ast_value *asvalue;
|
||||
if (!ast_istype(parser->globals[i], ast_value))
|
||||
continue;
|
||||
asvalue = (ast_value*)(parser->globals[i]);
|
||||
if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) {
|
||||
retval = retval && !genwarning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE,
|
||||
"unused global: `%s`", asvalue->name);
|
||||
}
|
||||
if (!ast_global_codegen(asvalue, ir, false)) {
|
||||
con_out("failed to generate global %s\n", asvalue->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->imm_float); ++i) {
|
||||
if (!ast_global_codegen(parser->imm_float[i], ir, false)) {
|
||||
con_out("failed to generate global %s\n", parser->imm_float[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->imm_string); ++i) {
|
||||
if (!ast_global_codegen(parser->imm_string[i], ir, false)) {
|
||||
con_out("failed to generate global %s\n", parser->imm_string[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->imm_vector); ++i) {
|
||||
if (!ast_global_codegen(parser->imm_vector[i], ir, false)) {
|
||||
con_out("failed to generate global %s\n", parser->imm_vector[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->globals); ++i) {
|
||||
ast_value *asvalue;
|
||||
if (!ast_istype(parser->globals[i], ast_value))
|
||||
continue;
|
||||
asvalue = (ast_value*)(parser->globals[i]);
|
||||
if (!ast_generate_accessors(asvalue, ir)) {
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->fields); ++i) {
|
||||
ast_value *asvalue;
|
||||
asvalue = (ast_value*)(parser->fields[i]->expression.next);
|
||||
|
||||
if (!ast_istype((ast_expression*)asvalue, ast_value))
|
||||
continue;
|
||||
if (asvalue->expression.vtype != TYPE_ARRAY)
|
||||
continue;
|
||||
if (!ast_generate_accessors(asvalue, ir)) {
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->functions); ++i) {
|
||||
if (!ast_function_codegen(parser->functions[i], ir)) {
|
||||
con_out("failed to generate function %s\n", parser->functions[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (opts.dump)
|
||||
ir_builder_dump(ir, con_out);
|
||||
for (i = 0; i < vec_size(parser->functions); ++i) {
|
||||
if (!ir_function_finalize(parser->functions[i]->ir_func)) {
|
||||
con_out("failed to finalize function %s\n", parser->functions[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
if (opts.dumpfin)
|
||||
ir_builder_dump(ir, con_out);
|
||||
|
||||
generate_checksum(parser);
|
||||
|
||||
if (!ir_builder_generate(ir, output)) {
|
||||
con_out("*** failed to generate output file\n");
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ir_builder_delete(ir);
|
||||
return retval;
|
||||
if (compile_errors) {
|
||||
con_out("*** there were compile errors\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
con_out("*** there were compile errors\n");
|
||||
return false;
|
||||
ir = ir_builder_new("gmqcc_out");
|
||||
if (!ir) {
|
||||
con_out("failed to allocate builder\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < vec_size(parser->fields); ++i) {
|
||||
ast_value *field;
|
||||
bool hasvalue;
|
||||
if (!ast_istype(parser->fields[i], ast_value))
|
||||
continue;
|
||||
field = (ast_value*)parser->fields[i];
|
||||
hasvalue = field->hasvalue;
|
||||
field->hasvalue = false;
|
||||
if (!ast_global_codegen((ast_value*)field, ir, true)) {
|
||||
con_out("failed to generate field %s\n", field->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
if (hasvalue) {
|
||||
ir_value *ifld;
|
||||
ast_expression *subtype;
|
||||
field->hasvalue = true;
|
||||
subtype = field->expression.next;
|
||||
ifld = ir_builder_create_field(ir, field->name, subtype->expression.vtype);
|
||||
if (subtype->expression.vtype == TYPE_FIELD)
|
||||
ifld->fieldtype = subtype->expression.next->expression.vtype;
|
||||
else if (subtype->expression.vtype == TYPE_FUNCTION)
|
||||
ifld->outtype = subtype->expression.next->expression.vtype;
|
||||
(void)!ir_value_set_field(field->ir_v, ifld);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->globals); ++i) {
|
||||
ast_value *asvalue;
|
||||
if (!ast_istype(parser->globals[i], ast_value))
|
||||
continue;
|
||||
asvalue = (ast_value*)(parser->globals[i]);
|
||||
if (!asvalue->uses && !asvalue->hasvalue && asvalue->expression.vtype != TYPE_FUNCTION) {
|
||||
retval = retval && !genwarning(ast_ctx(asvalue), WARN_UNUSED_VARIABLE,
|
||||
"unused global: `%s`", asvalue->name);
|
||||
}
|
||||
if (!ast_global_codegen(asvalue, ir, false)) {
|
||||
con_out("failed to generate global %s\n", asvalue->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->imm_float); ++i) {
|
||||
if (!ast_global_codegen(parser->imm_float[i], ir, false)) {
|
||||
con_out("failed to generate global %s\n", parser->imm_float[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->imm_string); ++i) {
|
||||
if (!ast_global_codegen(parser->imm_string[i], ir, false)) {
|
||||
con_out("failed to generate global %s\n", parser->imm_string[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->imm_vector); ++i) {
|
||||
if (!ast_global_codegen(parser->imm_vector[i], ir, false)) {
|
||||
con_out("failed to generate global %s\n", parser->imm_vector[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->globals); ++i) {
|
||||
ast_value *asvalue;
|
||||
if (!ast_istype(parser->globals[i], ast_value))
|
||||
continue;
|
||||
asvalue = (ast_value*)(parser->globals[i]);
|
||||
if (!ast_generate_accessors(asvalue, ir)) {
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->fields); ++i) {
|
||||
ast_value *asvalue;
|
||||
asvalue = (ast_value*)(parser->fields[i]->expression.next);
|
||||
|
||||
if (!ast_istype((ast_expression*)asvalue, ast_value))
|
||||
continue;
|
||||
if (asvalue->expression.vtype != TYPE_ARRAY)
|
||||
continue;
|
||||
if (!ast_generate_accessors(asvalue, ir)) {
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < vec_size(parser->functions); ++i) {
|
||||
if (!ast_function_codegen(parser->functions[i], ir)) {
|
||||
con_out("failed to generate function %s\n", parser->functions[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (opts.dump)
|
||||
ir_builder_dump(ir, con_out);
|
||||
for (i = 0; i < vec_size(parser->functions); ++i) {
|
||||
if (!ir_function_finalize(parser->functions[i]->ir_func)) {
|
||||
con_out("failed to finalize function %s\n", parser->functions[i]->name);
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (compile_Werrors) {
|
||||
con_out("*** there were warnings treated as errors\n");
|
||||
compile_show_werrors();
|
||||
retval = false;
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
if (opts.dumpfin)
|
||||
ir_builder_dump(ir, con_out);
|
||||
|
||||
generate_checksum(parser);
|
||||
|
||||
if (!ir_builder_generate(ir, output)) {
|
||||
con_out("*** failed to generate output file\n");
|
||||
ir_builder_delete(ir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ir_builder_delete(ir);
|
||||
return retval;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue