Zero-extend unsized signed based literal numbers when < integer_width bits.
Whilst the wording in the IEEE standards is ambiguous, discussions on the standards committee mailing lists clarify that an unsized literal is supposed to be the same size as an integer (as shown in IEEE 1364-2005 table 5-22). The token following the base format character is specified to be an unsized number. So to maintain compatibility with the standards and with other tools, if the unsigned number part of an unsized signed based literal can be represented in less than integer_width bits and the MSB is a '1', we need to add a leading zero to ensure it is zero-extended when used in an expression. This fixes issue #1082.
This commit is contained in:
parent
8ee1d56e1a
commit
f31d0dcbc5
20
lexor.lex
20
lexor.lex
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2023 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -971,7 +971,8 @@ verinum*make_unsized_binary(const char*txt)
|
|||
if ((based_size > 0) && (size > based_size)) VLwarn(yylloc,
|
||||
"warning: Extra digits given for sized binary constant.");
|
||||
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
// Allocate one extra bit in case we need to zero-extend.
|
||||
verinum::V*bits = new verinum::V[size+1];
|
||||
|
||||
unsigned idx = size;
|
||||
while (*ptr) {
|
||||
|
|
@ -1000,6 +1001,9 @@ verinum*make_unsized_binary(const char*txt)
|
|||
if (gn_strict_expr_width_flag && (based_size == 0))
|
||||
size = truncate_to_integer_width(bits, size);
|
||||
|
||||
if (sign_flag && (size < integer_width) && (bits[size-1] == verinum::V1))
|
||||
bits[size++] = verinum::V0;
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
out->is_single(single_flag);
|
||||
|
|
@ -1037,7 +1041,8 @@ verinum*make_unsized_octal(const char*txt)
|
|||
"warning: Extra digits given for sized octal constant.");
|
||||
}
|
||||
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
// Allocate one extra bit in case we need to zero-extend.
|
||||
verinum::V*bits = new verinum::V[size+1];
|
||||
|
||||
unsigned idx = size;
|
||||
while (*ptr) {
|
||||
|
|
@ -1071,6 +1076,9 @@ verinum*make_unsized_octal(const char*txt)
|
|||
if (gn_strict_expr_width_flag && (based_size == 0))
|
||||
size = truncate_to_integer_width(bits, size);
|
||||
|
||||
if (sign_flag && (size < integer_width) && (bits[size-1] == verinum::V1))
|
||||
bits[size++] = verinum::V0;
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
|
|
@ -1106,7 +1114,8 @@ verinum*make_unsized_hex(const char*txt)
|
|||
"warning: Extra digits given for sized hex constant.");
|
||||
}
|
||||
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
// Allocate one extra bit in case we need to zero-extend.
|
||||
verinum::V*bits = new verinum::V[size+1];
|
||||
|
||||
unsigned idx = size;
|
||||
while (*ptr) {
|
||||
|
|
@ -1151,6 +1160,9 @@ verinum*make_unsized_hex(const char*txt)
|
|||
if (gn_strict_expr_width_flag && (based_size == 0))
|
||||
size = truncate_to_integer_width(bits, size);
|
||||
|
||||
if (sign_flag && (size < integer_width) && (bits[size-1] == verinum::V1))
|
||||
bits[size++] = verinum::V0;
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
|
|
|
|||
Loading…
Reference in New Issue