-fcorrect-ternary; by default -std=fteqcc now uses fteqcc's wrong ternary precedence...
authorWolfgang (Blub) Bumiller <blub@speed.at>
Sat, 1 Dec 2012 12:42:16 +0000 (13:42 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Sat, 1 Dec 2012 12:42:16 +0000 (13:42 +0100)
lexer.h
main.c
opts.def

diff --git a/lexer.h b/lexer.h
index 2d61f8bf2bc6364608a31362673d782fb002b9d4..e3ba96f1ff8f91ef2af20310720d2e42036d7878 100644 (file)
--- 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 57e7a3065836f7d7ce59e031d4503068fc0b0f54..220a2e390b85803daed1c2efcbbdd3e96e347598 100644 (file)
--- 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();
index 8502d43a11ef2fac7ea9cf12cd649bc16d146ebf..64de1117bfdc9da9a1b7b482fc947a0997ede01e 100644 (file)
--- 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 */