From edb38ce70e86acde9530af5861cfcf8f396b5e75 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Sat, 24 May 2014 19:13:49 +0200 Subject: [PATCH] local compile-time const values are now created as globals, thus they're now subject to constant-folding --- parser.c | 40 +++++++++++++++++++++++++++++++++++----- tests/inexact-local.qc | 7 +++++++ tests/inexact-local.tmpl | 4 ++++ 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 tests/inexact-local.qc create mode 100644 tests/inexact-local.tmpl diff --git a/parser.c b/parser.c index 5666a82..fc02cac 100644 --- a/parser.c +++ b/parser.c @@ -5146,6 +5146,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield bool wasarray = false; ast_member *me[3] = { NULL, NULL, NULL }; + ast_member *last_me[3] = { NULL, NULL, NULL }; if (!localblock && is_static) parseerror(parser, "`static` qualifier is not supported in global scope"); @@ -5609,6 +5610,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield } } } + memcpy(last_me, me, sizeof(me)); me[0] = me[1] = me[2] = NULL; cleanvar = false; /* Part 2.2 @@ -5816,15 +5818,44 @@ skipvar: } else { ast_expression *cexp; ast_value *cval; + bool folded_const = false; cexp = parse_expression_leave(parser, true, false, false); if (!cexp) break; + cval = ast_istype(cexp, ast_value) ? (ast_value*)cexp : NULL; - if (!localblock || is_static) { - cval = (ast_value*)cexp; + /* deal with foldable constants: */ + if (localblock && + var->cvq == CV_CONST && cval && cval->hasvalue && cval->cvq == CV_CONST && !cval->isfield) + { + /* remove it from the current locals */ + if (isvector) { + for (i = 0; i < 3; ++i) { + vec_pop(parser->_locals); + vec_pop(localblock->collect); + } + } + /* do sanity checking, this function really needs refactoring */ + if (vec_last(parser->_locals) != (ast_expression*)var) + parseerror(parser, "internal error: unexpected change in local variable handling"); + else + vec_pop(parser->_locals); + if (vec_last(localblock->locals) != var) + parseerror(parser, "internal error: unexpected change in local variable handling (2)"); + else + vec_pop(localblock->locals); + /* push it to the to-be-generated globals */ + vec_push(parser->globals, (ast_expression*)var); + if (isvector) + for (i = 0; i < 3; ++i) + vec_push(parser->globals, (ast_expression*)last_me[i]); + folded_const = true; + } + + if (folded_const || !localblock || is_static) { if (cval != parser->nil && - (!ast_istype(cval, ast_value) || ((!cval->hasvalue || cval->cvq != CV_CONST) && !cval->isfield)) + (!cval || ((!cval->hasvalue || cval->cvq != CV_CONST) && !cval->isfield)) ) { parseerror(parser, "initializer is non constant"); @@ -5876,8 +5907,7 @@ skipvar: * const float x = ; should propagate the inexact flag */ if (var->cvq == CV_CONST && var->expression.vtype == TYPE_FLOAT) { - cval = (ast_value*)cexp; - if (ast_istype(cexp, ast_value) && cval->hasvalue && cval->cvq == CV_CONST) + if (cval && cval->hasvalue && cval->cvq == CV_CONST) var->inexact = cval->inexact; } } diff --git a/tests/inexact-local.qc b/tests/inexact-local.qc new file mode 100644 index 0000000..a17cccd --- /dev/null +++ b/tests/inexact-local.qc @@ -0,0 +1,7 @@ +void main() { + const float a = 1.0 / 3.0; + const float b = 0.33333333333; + if (a == b) { + // Should trigger warning + } +} diff --git a/tests/inexact-local.tmpl b/tests/inexact-local.tmpl new file mode 100644 index 0000000..3917a90 --- /dev/null +++ b/tests/inexact-local.tmpl @@ -0,0 +1,4 @@ +I: inexact-local.qc +D: inexact comparisons +T: -fail +C: -std=gmqcc -Winexact-compares -Wall -Werror -- 2.39.2