unsigned int operands;
unsigned int id;
unsigned int assoc;
- unsigned int prec;
+ signed int prec;
unsigned int flags;
} oper_info;
{ "||", 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 },
{ "^=", 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]));
{ "&&", 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]));
{ "||", 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]));
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);
size_t itr;
int retval = 0;
bool opts_output_free = false;
+ bool operators_free = false;
bool progs_src = false;
FILE *outfile = NULL;
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();
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));
parser_cleanup();
if (opts_output_free)
mem_d((char*)opts_output);
+ if (operators_free)
+ mem_d((void*)operators);
lex_cleanup();
util_meminfo();