From 53fd019780bc33c28c7d41aa046c4b74ed65b01f Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Sat, 1 Dec 2012 13:42:16 +0100 Subject: [PATCH] -fcorrect-ternary; by default -std=fteqcc now uses fteqcc's wrong ternary precedence parsing --- lexer.h | 16 +++++++--------- main.c | 26 ++++++++++++++++++++++++++ opts.def | 1 + 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/lexer.h b/lexer.h index 2d61f8b..e3ba96f 100644 --- a/lexer.h +++ b/lexer.h @@ -150,7 +150,7 @@ typedef struct { unsigned int operands; unsigned int id; unsigned int assoc; - unsigned int prec; + signed int prec; unsigned int flags; } oper_info; @@ -204,7 +204,6 @@ static const oper_info c_operators[] = { { "||", 2, opid2('|','|'), ASSOC_LEFT, 4, 0 }, { "?", 3, opid2('?',':'), ASSOC_RIGHT, 3, 0 }, - { ":", 3, opid2(':','?'), ASSOC_RIGHT, 3, 0 }, { "=", 2, opid1('='), ASSOC_RIGHT, 2, 0 }, { "+=", 2, opid2('+','='), ASSOC_RIGHT, 2, 0 }, @@ -218,7 +217,9 @@ static const oper_info c_operators[] = { { "^=", 2, opid2('^','='), ASSOC_RIGHT, 2, 0 }, { "|=", 2, opid2('|','='), ASSOC_RIGHT, 2, 0 }, - { ",", 2, opid1(','), ASSOC_LEFT, 1, 0 } + { ":", 3, opid2(':','?'), ASSOC_RIGHT, 1, 0 }, + + { ",", 2, opid1(','), ASSOC_LEFT, 0, 0 } }; static const size_t c_operator_count = (sizeof(c_operators) / sizeof(c_operators[0])); @@ -267,9 +268,9 @@ static const oper_info fte_operators[] = { { "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0 }, { "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0 }, - { ":", 0, opid2(':','?'), ASSOC_RIGHT, 3, 0 }, - - { ",", 2, opid1(','), ASSOC_LEFT, 2, 0 } + /* Leave precedence 3 for : with -fcorrect-ternary */ + { ",", 2, opid1(','), ASSOC_LEFT, 2, 0 }, + { ":", 0, opid2(':','?'), ASSOC_RIGHT, 1, 0 } }; static const size_t fte_operator_count = (sizeof(fte_operators) / sizeof(fte_operators[0])); @@ -312,9 +313,6 @@ static const oper_info qcc_operators[] = { { "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0 }, { ",", 2, opid1(','), ASSOC_LEFT, 2, 0 }, - - { "?", 3, opid2('?',':'), ASSOC_RIGHT, 1, 0 }, - { ":", 3, opid2(':','?'), ASSOC_RIGHT, 1, 0 } }; static const size_t qcc_operator_count = (sizeof(qcc_operators) / sizeof(qcc_operators[0])); diff --git a/main.c b/main.c index 57e7a30..220a2e3 100644 --- a/main.c +++ b/main.c @@ -221,6 +221,8 @@ static bool options_parse(int argc, char **argv) { options_set(opts_flags, TRANSLATABLE_STRINGS, true); options_set(opts_flags, ADJUST_VECTOR_FIELDS, false); options_set(opts_flags, ASSIGN_FUNCTION_TYPES, true); + options_set(opts_warn, WARN_TERNARY_PRECEDENCE, true); + options_set(opts_flags, CORRECT_TERNARY, false); opts_standard = COMPILER_FTEQCC; } else if (!strcmp(argarg, "qccx")) { options_set(opts_flags, ADJUST_VECTOR_FIELDS, false); @@ -489,6 +491,7 @@ int main(int argc, char **argv) { size_t itr; int retval = 0; bool opts_output_free = false; + bool operators_free = false; bool progs_src = false; FILE *outfile = NULL; @@ -519,6 +522,7 @@ int main(int argc, char **argv) { options_set(opts_flags, ADJUST_VECTOR_FIELDS, true); options_set(opts_flags, FTEPP, false); + options_set(opts_flags, CORRECT_TERNARY, true); if (!options_parse(argc, argv)) { return usage(); @@ -536,6 +540,26 @@ int main(int argc, char **argv) { operator_count = qcc_operator_count; } + if (operators == fte_operators) { + /* fix ternary? */ + if (OPTS_FLAG(CORRECT_TERNARY)) { + oper_info *newops; + if (operators[operator_count-2].id != opid1(',') || + operators[operator_count-1].id != opid2(':','?')) + { + con_err("internal error: operator precedence table wasn't updated correctly!\n"); + exit(1); + } + operators_free = true; + newops = mem_a(sizeof(operators[0]) * operator_count); + memcpy(newops, operators, sizeof(operators[0]) * operator_count); + memcpy(&newops[operator_count-2], &operators[operator_count-1], sizeof(newops[0])); + memcpy(&newops[operator_count-1], &operators[operator_count-2], sizeof(newops[0])); + newops[operator_count-2].prec = newops[operator_count-1].prec+1; + operators = newops; + } + } + if (opts_dump) { for (itr = 0; itr < COUNT_FLAGS; ++itr) { con_out("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr)); @@ -706,6 +730,8 @@ cleanup: parser_cleanup(); if (opts_output_free) mem_d((char*)opts_output); + if (operators_free) + mem_d((void*)operators); lex_cleanup(); util_meminfo(); diff --git a/opts.def b/opts.def index 8502d43..64de111 100644 --- a/opts.def +++ b/opts.def @@ -39,6 +39,7 @@ GMQCC_DEFINE_FLAG(INITIALIZED_NONCONSTANTS) GMQCC_DEFINE_FLAG(ASSIGN_FUNCTION_TYPES) GMQCC_DEFINE_FLAG(LNO) + GMQCC_DEFINE_FLAG(CORRECT_TERNARY) #endif /* warning flags */ -- 2.39.2