diff options
author | Nathan Sidwell <nathan@acm.org> | 2021-01-20 09:21:02 -0800 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2021-01-20 11:41:51 -0800 |
commit | 911f797a9be2dc8ef59f5d5bd6d68baf650b8822 (patch) | |
tree | 79b22640e9966fdc154351b77c8273674f2986c1 /gcc | |
parent | e140f5fd3e235c5a37dc99b79f37a5ad4dc59064 (diff) | |
download | gcc-911f797a9be2dc8ef59f5d5bd6d68baf650b8822.zip gcc-911f797a9be2dc8ef59f5d5bd6d68baf650b8822.tar.gz gcc-911f797a9be2dc8ef59f5d5bd6d68baf650b8822.tar.bz2 |
c++: Avoid UB in signed shift [PR 98625]
I'd forgotten that left shifting a negative value is UB until C++20.
Insert some casts to do unsigned shifts.
PT c++/98625
gcc/cp/
* module.cc (bytes_in::i, bytes_in::wi): Avoid left shift of
signed type.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/module.cc | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 3b40c7e..7f88e3f 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -878,9 +878,12 @@ bytes_in::i () v &= 0xf; if (v & 0x8) v |= -1 ^ 0x7; + /* unsigned necessary due to left shifts of -ve values. */ + unsigned uv = unsigned (v); if ((ptr = read (++bytes))) while (bytes--) - v = (v << 8) | (*ptr++ & 0xff); + uv = (uv << 8) | (*ptr++ & 0xff); + v = int (uv); } else if (v & 0x40) v |= -1 ^ 0x3f; @@ -969,9 +972,12 @@ bytes_in::wi () v &= 0xf; if (v & 0x8) v |= -1 ^ 0x7; + /* unsigned necessary due to left shifts of -ve values. */ + unsigned HOST_WIDE_INT uv = (unsigned HOST_WIDE_INT) v; if ((ptr = read (++bytes))) while (bytes--) - v = (v << 8) | (*ptr++ & 0xff); + uv = (uv << 8) | (*ptr++ & 0xff); + v = (HOST_WIDE_INT) uv; } else if (v & 0x40) v |= -1 ^ 0x3f; |