Это ошибка в GNAT, о которой я должен сообщить
Когда я определяю свой собственный тип с диапазоном, оканчивающимся на 127, компилятор не выполняет проверку верхних границ, что позволяет переменной обернуться и стать отрицательным ниже определенного предела. Если я определяю диапазон как 126, тогда выбрасывается правильное исключение. Я включил программы и их вывод ниже.
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure GoodType is
type GOOD_TYPE is range -1..126;
package GOOD_TYPE_IO is new Ada.Text_IO.Integer_IO(GOOD_TYPE);
use GOOD_TYPE_IO;
On_Both1 : GOOD_TYPE := 120;
Index : INTEGER := 0;
begin
for Index in 120..130 loop
On_Both1 := On_Both1 + 1;
Put(Index);
Put(": ");
Put(On_Both1);
New_line;
end loop;
end GoodType;
Выход:
gnatmake -f goodtype.adb && ./goodtype
120: 121
121: 122
122: 123
123: 124
124: 125
125: 126
raised CONSTRAINT_ERROR : goodtype.adb:16 range check failed
,
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure BadType is
type BAD_TYPE is range -1..127;
package BAD_TYPE_IO is new Ada.Text_IO.Integer_IO(BAD_TYPE);
use BAD_TYPE_IO;
On_Both1 : BAD_TYPE := 120;
Index : INTEGER := 0;
begin
for Index in 120..130 loop
On_Both1 := On_Both1 + 1;
Put(Index);
Put(": ");
Put(On_Both1);
New_line;
end loop;
end BadType;
Выход:
gnatmake -f badtype.adb && ./badtype
120: 121
121: 122
122: 123
123: 124
124: 125
125: 126
126: 127
127: -128
128: -127
129: -126
130: -125
1 ответ
GNAT в настоящее время отключает проверку переполнения по умолчанию (хотя это поведение изменится в будущих выпусках).
Пытаться:
gnatmake -gnato -f badtype.adb && ./badtype
Разница в поведении между 126
а также 127
очевидно, потому что первая реализована как проверка диапазона (которая включена по умолчанию), а вторая - как проверка переполнения (которая по умолчанию отключена). Это можно увидеть в разных сообщениях об ошибках, напечатанных в двух случаях (при компиляции с -gnato
:
raised CONSTRAINT_ERROR : goodtype.adb:16 range check failed
против
raised CONSTRAINT_ERROR : badtype.adb:16 overflow check failed