Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ada CONSTRAINT_ERROR not being raised when it "should"

I've been looking through this Ada 95 tutorial. I was reading that it is possible to define a type that has a range that is different than the standard range, and if the program tries to go outside this range it will throw an error. While working on my own program I noticed that if the end of the range in the definition falls on the boundary for of its underlying type then the program will not raise the CONSTRAINT_ERROR when assigning values out of that range. Instead it will happily keep going and then wrap around. I wrote a program to explicitly show this.

Does anyone know of an Ada rule that explains this behavior?

-Kirk

Here is the output from my terminal, the source code is below that.

me@acheron:~/Dropbox/programs/ada$ gnatmake constraints.adb -f
gcc-4.6 -c constraints.adb
gnatbind -x constraints.ali
gnatlink constraints.ali
me@acheron:~/Dropbox/programs/ada$ ./constraints

Type ON has size:           7
It has a min/max of:           0        127
It's base has a min/max of:        -128        127

Type UNDER has size:           7
It has a min/max of:           0        126
It's base has a min/max of:        -128        127
The value of No_Error is:         245

raised CONSTRAINT_ERROR : constraints.adb:58 range check failed
me@acheron:~/Dropbox/programs/ada$

Source Code:

with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;

Procedure Constraints is

    type UNDER is range 0..126;
    type ON is range 0..127;
    type OVER is range 0..128;    

    Error : UNDER := 0;
    No_Error : ON := 0;

    Index : INTEGER := 0;

begin
    New_Line;
    Put("Type ON has size: ");
    Put(INTEGER(ON'SIZE));
    New_Line;
    Put("It has a min/max of: ");
    Put(INTEGER(ON'FIRST));
    Put(INTEGER(ON'LAST));
    New_Line;
    Put("It's base has a min/max of: ");
    Put(INTEGER(ON'BASE'FIRST));
    Put(INTEGER(ON'BASE'LAST));

    New_Line;
    New_Line;

    Put("Type UNDER has size: ");
    Put(INTEGER(UNDER'SIZE));
    New_Line;
    Put("It has a min/max of: ");
    Put(INTEGER(UNDER'FIRST));
    Put(INTEGER(UNDER'LAST));
    New_Line;
    Put("It's base has a min/max of: ");
    Put(INTEGER(UNDER'BASE'FIRST));
    Put(INTEGER(UNDER'BASE'LAST));

    Safe_Loop:
    loop
        No_Error := No_Error + 1;
        Index := Index + 1;
        --Put(INTEGER(No_Error));
        exit Safe_Loop when Index = 245;  
    end loop Safe_Loop;

    New_Line;
    Put("The value of No_Error is: ");
    Put(INTEGER(No_Error));

    Index := 0;

    Crash_Loop:
    loop
        Error := Error + 1;
        Index := Index + 1;
        exit Crash_Loop when Index = 245;
    end loop Crash_Loop;


end Constraints;
like image 298
chew socks Avatar asked Oct 23 '22 07:10

chew socks


1 Answers

According to the documentation:

Note again that -gnato is off by default, so overflow checking is not performed in default mode. This means that out of the box, with the default settings, GNAT does not do all the checks expected from the language description in the Ada Reference Manual. If you want all constraint checks to be performed, as described in this Manual, then you must explicitly use the -gnato switch either on the gnatmake or gcc command.

That said, the documentation also claims that:

Basically the rule is that in the default mode (-gnato not used), the generated code assures that all integer variables stay within their declared ranges, or within the base range if there is no declared range. This prevents any serious problems like indexes out of range for array operations. ¶ What is not checked in default mode is an overflow that results in an in-range, but incorrect value.

which seems to be wrong in the case you describe, since No_Error really does end up completely outside its range. So this seems to go beyond "not […] expected from the language description" and into the realm of "compiler bug"; but at least you should be able to fix it by adding the -gnato flag.

like image 182
ruakh Avatar answered Nov 30 '22 22:11

ruakh