Skip to content

Commit

Permalink
Fix crash with subtype indication in case range choice. Fixes #655
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Mar 20, 2023
1 parent 642634b commit 4b9474a
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 7 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
and when printing to the terminal.
- The new `configure` option `--disable-default-paths` disables the
default library search paths.
- Subtype indications used as case range choices no longer crash during
analysis (#655).

## Version 1.8.2 - 2023-02-14
- Fixed "failed to suspend thread" crash on macOS.
Expand Down
28 changes: 21 additions & 7 deletions src/sem.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2011-2022 Nick Gasson
// Copyright (C) 2011-2023 Nick Gasson
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -4847,12 +4847,26 @@ static bool sem_check_case(tree_t t, nametab_t *tab)
if (!sem_check_discrete_range(r, type, tab))
return false;

if (!(*static_fn)(tree_left(r)))
sem_error(tree_left(r), "left index of case choice range is "
"not %s static", static_str);
else if (!(*static_fn)(tree_right(r)))
sem_error(tree_right(r), "right index of case choice range "
"is not %s static", static_str);
switch (tree_subkind(r)) {
case RANGE_TO:
case RANGE_DOWNTO:
if (!(*static_fn)(tree_left(r)))
sem_error(tree_left(r), "left index of case choice "
"range is not %s static", static_str);
else if (!(*static_fn)(tree_right(r)))
sem_error(tree_right(r), "right index of case choice "
"range is not %s static", static_str);
break;

case RANGE_EXPR:
if (!(*static_fn)(tree_value(r)))
sem_error(tree_value(r), "range expression is not %s "
"static", static_str);
break;

default:
return false;
}
}
break;
}
Expand Down
88 changes: 88 additions & 0 deletions test/regress/issue655.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
library ieee ;
use ieee.numeric_std.all ;

entity saturate is
port (
x : in signed(31 downto 0) ;
y : out signed(15 downto 0)
) ;
end entity ;

architecture ifarch of saturate is

constant sat_high : signed := to_signed(2**(y'length-1) - 1, y'length) ;
constant sat_low : signed := to_signed(-(2**(y'length-1)), y'length) ;

constant too_high : integer := to_integer(sat_high) ;
constant too_low : integer := to_integer(sat_low) ;

begin

process(all)
begin
if( x >= too_high ) then
y <= sat_high ;
elsif( x <= sat_low ) then
y <= sat_low ;
else
y <= resize(x, y'length) ;
end if ;
end process ;

end architecture ;

architecture casearch of saturate is

subtype too_high is integer range 2**(y'length-1)-1 to integer'high ;
subtype too_low is integer range integer'low to -(2**(y'length-1)) ;

constant sat_high : signed := to_signed(2**y'length - 1, y'length) ;
constant sat_low : signed := to_signed(0, y'length) - sat_high - to_signed(1, y'length) ;

begin

process(all)
begin
case to_integer(x) is
when too_high => y <= sat_high ;
when too_low => y <= sat_low ;
when others => y <= resize(x, y'length) ;
end case ;
end process ;

end architecture ;

entity issue655 is
end entity;

library ieee ;
use ieee.numeric_std.all ;
use ieee.std_logic_1164.all ;

architecture test of issue655 is
signal x : signed(31 downto 0) := X"00000000";
signal y1, y2 : signed(15 downto 0);
begin

u1: entity work.saturate(ifarch) port map (x, y1);

u2: entity work.saturate(ifarch) port map (x, y2);

p1: process is
begin
x <= to_signed(-(2 ** 30), 32);
wait for 1 ns;
assert y1 = X"8000" report to_hstring(y1);
assert y2 = X"8000" report to_hstring(y2);
x <= to_signed(55, 32);
wait for 1 ns;
assert y1 = X"0037" report to_hstring(y1);
assert y2 = X"0037" report to_hstring(y2);
x <= to_signed(2 ** 24, 32);
wait for 1 ns;
assert y1 = X"7fff" report to_hstring(y1);
assert y2 = X"7fff" report to_hstring(y2);
wait;
end process;

end architecture;
1 change: 1 addition & 0 deletions test/regress/testlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -745,3 +745,4 @@ cond4 normal,2019,define=USER_DIRECTIVE=VALID_VALUE
issue646 normal,relaxed
array16 normal,2008
stdenv4 normal,2019
issue655 normal,2008
21 changes: 21 additions & 0 deletions test/sem/issue655.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
entity issue655 is
end entity ;

architecture casearch of issue655 is

subtype too_high is integer range 500 to integer'high ;
subtype too_low is integer range integer'low to -500;

begin

process is
variable x : integer;
begin
case x is
when too_high => null ;
when too_low => null ;
when others => null ;
end case ;
end process ;

end architecture ;

0 comments on commit 4b9474a

Please sign in to comment.