GCC更新后出现意外的CONSTRAINT_ERROR

时间:2017-03-15 19:19:02

标签: gcc ada gnat

我们最近更新了GCC版本(4.8.2到5.3.0)并开始在某些Ada应用程序中收到意外的约束错误。我把它简化为以下内容:

-- moo.adb
with text_io;
procedure moo is
   type thing_type is (something1,something2,something3,something4,something5,something6);
   for thing_type use (something1 => 1,something2 => 2,something3 => 
      3,something4 => 4,something5 => 5,something6 => 6);
   for thing_type'size use 32;
   type thing_array_t is array (0 .. 5) of thing_type;
   thing_array : thing_array_t := (others => something1);
begin
   text_io.put_line("item 0 = " & thing_type'image(thing_array(0)));
end moo;

这个程序将在GCC版本上编译得很好(只需使用“gnatmake moo.adb”编译。)当使用4.8.2构建时,输出符合预期:

item 0 = SOMETHING1

使用5.0.3构建时,我们会收到

raised CONSTRAINT_ERROR : moo.adb:13 invalid data

有趣的是,编译为32位和64位时结果完全相同。可以使用5.3.0更改许多内容以使程序正常工作:删除thing_type'size子句,向枚举器添加或删除值,更改数组中的项数,使用不同的值初始化数组等这段代码有没有明显的问题可以解释这种行为?

2 个答案:

答案 0 :(得分:6)

此错误仍存在于GCC 7.0.1中。在调试器下运行,输出略有编辑,

(gdb) catch exception
Catchpoint 2: all Ada exceptions
(gdb) run
Starting program: /Users/simon/tmp/so/moo 
[New Thread 0x1703 of process 75511]

Catchpoint 2, CONSTRAINT_ERROR (moo.adb:10 invalid data) at 0x0000000100001abe in _ada_moo () at moo.adb:10
10     text_io.put_line("item 0 = " & thing_type'image(thing_array(0)));
(gdb) p thing_array
$5 = (0 => 16843009, 16843009, 16843009, 16843009, 16843009, 16843009)
(gdb) p/x thing_array
$6 = (0 => 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101, 0x1010101)

因此GNAT错误地将thing_array个元素的每个字节设置为16#01#,而不是整个元素。

如果将something1设置为2(同样地增加后来的值),也会发生同样的情况。

我能找到的唯一有用的是宣布,例如,

type base_thing_type is (invalid, something1,something2,something3,something4,something5,something6);
for base_thing_type use (invalid => 0, something1 => 1,something2 => 2,something3 =>
                      3,something4 => 4,something5 => 5,something6 => 6);
for base_thing_type'size use 32;
type thing_type is new base_thing_type range something1 .. something6;

答案 1 :(得分:4)

它看起来像是GCC / GNAT中的一个错误。 我可以在标准兼容模式(-gnato -fstack-check -gnat12)中使用GNAT-GPL-2016复制不正确的行为。关键部分似乎是Something1表示为1而不是更典型的0。 我建议您向GCC开发人员报告该错误。