# HG changeset patch # User Mario de Sousa # Date 1340032260 -3600 # Node ID f5d4e9f9151343eddb1d0230f02317903e8ce4e4 # Parent 60f3edcf6a8f81f206b63979e28dac300f1ff588 determine const value of hex, octal and bin literals correctly. diff -r 60f3edcf6a8f -r f5d4e9f91513 stage3/constant_folding.cc --- a/stage3/constant_folding.cc Mon Jun 18 15:52:09 2012 +0100 +++ b/stage3/constant_folding.cc Mon Jun 18 16:11:00 2012 +0100 @@ -255,7 +255,7 @@ /* extract the value of an integer from an integer_c object !! */ /* NOTE: it must ignore underscores! */ -int64_t extract_int64_value(symbol_c *sym, bool *overflow) { +int64_t extract_int64_value(symbol_c *sym, int base, bool *overflow) { std::string str = ""; integer_c *integer; char *endptr; @@ -266,19 +266,18 @@ if (integer->value[i] != '_') str += integer->value[i]; errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! - ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10); + ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, base); if (overflow != NULL) *overflow = (errno == ERANGE); - if ((errno != 0) && (errno != ERANGE)) + if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0')) ERROR; return ret; } -uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) { +uint64_t extract_uint64_value(symbol_c *sym, int base, bool *overflow) { std::string str = ""; integer_c *integer; - neg_integer_c * neg_integer; char *endptr; uint64_t ret; @@ -287,10 +286,10 @@ if (integer->value[i] != '_') str += integer->value[i]; errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! - ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10); + ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, base); if (overflow != NULL) *overflow = (errno == ERANGE); - if ((errno != 0) && (errno != ERANGE)) + if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0')) ERROR; return ret; @@ -298,26 +297,6 @@ -/* extract the value of an hex integer from an hex_integer_c object !! */ -/* NOTE: it must ignore underscores! */ -uint64_t extract_hex_value(symbol_c *sym) { - std::string str = ""; - char *endptr; - hex_integer_c * hex_integer; - uint64_t ret; - - if ((hex_integer = dynamic_cast(sym)) == NULL) ERROR; - for(unsigned int i = 3; i < strlen(hex_integer->value); i++) - if (hex_integer->value[i] != '_') str += hex_integer->value[i]; - - errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! - ret = strtoull(str.c_str(), &endptr, 16); - if (errno != 0) ERROR; - - return ret; -} - - /* extract the value of a real from an real_c object !! */ /* NOTE: it must ignore underscores! */ /* From iec_bison.yy @@ -336,7 +315,8 @@ */ real64_t extract_real_value(symbol_c *sym, bool *overflow) { std::string str = ""; - real_c * real_sym; + real_c *real_sym; + char *endptr; real64_t ret; if ((real_sym = dynamic_cast(sym)) == NULL) ERROR; @@ -345,17 +325,17 @@ errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! #if (real64_t == float) - ret = strtof(str.c_str(), NULL); + ret = strtof(str.c_str(), &endptr); #elif (real64_t == double) - ret = strtod(str.c_str(), NULL); + ret = strtod(str.c_str(), &endptr); #elif (real64_t == long_double) - ret = strtold(str.c_str(), NULL); + ret = strtold(str.c_str(), &endptr); #else #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting! #endif if (overflow != NULL) *overflow = (errno == ERANGE); - if ((errno != 0) && (errno != ERANGE)) + if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0')) ERROR; return ret; @@ -593,9 +573,9 @@ void *constant_folding_c::visit(integer_c *symbol) { bool overflow; - NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value(symbol, &overflow)); + NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 10, &overflow)); if (overflow) SET_OVFLOW(int64, symbol); - NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); + NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 10, &overflow)); if (overflow) SET_OVFLOW(uint64, symbol); return NULL; } @@ -618,7 +598,7 @@ * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue. */ // if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement - if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) { + if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) { // How do we stop the compiler from complaining about a comparison between int and unsigned int? NEW_CVALUE(int64, symbol); // in principle, if the above condition is true, then no new cvalue was created by DO_UNARY_OPER(). Not that it would be a problem to create a new one! SET_CVALUE(int64, symbol, INT64_MIN); } @@ -627,18 +607,31 @@ void *constant_folding_c::visit(binary_integer_c *symbol) { + bool overflow; + NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 2, &overflow)); + if (overflow) SET_OVFLOW(int64, symbol); + NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 2, &overflow)); + if (overflow) SET_OVFLOW(uint64, symbol); return NULL; } void *constant_folding_c::visit(octal_integer_c *symbol) { + bool overflow; + NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 8, &overflow)); + if (overflow) SET_OVFLOW(int64, symbol); + NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 8, &overflow)); + if (overflow) SET_OVFLOW(uint64, symbol); return NULL; } void *constant_folding_c::visit(hex_integer_c *symbol) { - NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_hex_value(symbol)); - NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_hex_value(symbol)); + bool overflow; + NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 16, &overflow)); + if (overflow) SET_OVFLOW(int64, symbol); + NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 16, &overflow)); + if (overflow) SET_OVFLOW(uint64, symbol); return NULL; }