Ada.Containers.Vectors not working with GNAT GPL 2017 - ada

I am trying to compile this code:
with Ada.Containers.Vectors;
procedure Test is
type My_Type is range -1 .. Integer'Last;
package My_Vectors is new Ada.Containers.Vectors (Positive, My_Type);
Vector : My_Vectors.Vector;
begin
Vector.Append (-1);
end Test;
gnatmake test.adb gives this output:
gcc -c test.adb
a-convec.adb:1553:33: missing operand
gnatmake: "test.adb" compilation error
The error message leads to this procedure in the stdlib's implementation:
procedure Insert
(Container : in out Vector;
Before : Extended_Index;
Count : Count_Type := 1)
is
New_Item : Element_Type := <>; -- << here
pragma Warnings (Off, New_Item);
begin
Insert (Container, Before, New_Item, Count);
end Insert;
It looks fine. I don't understand the error message, what's wrong here? Is it a bug in the stdlib?

Looks like this file has been tampered with…
Summarizing the evidence,
Multiple comments report no problem with GNAT versions going back as far as 4.9.1.
The initialization marked << here is a compile-time error, as the compound delimiter <>, named box, is not valid in an expression used in assignment.
Based on How gnatmake Works, a-convec.adb would only be recompiled if it were modified after the corresponding .ali file.
Going forward, you might
Check the modification dates of a-convec.adb and a-convec.ali, found in the adainclude and adalib directories, respectively.
Reinstall the compiler.
Notify upstream maintainers if warranted.

Related

Ada complaining that I've added a volatile object in a function call to generic type when not volatile

So I've got the following declaration:
record
String1 : String (1 .. 64);
String2 : String (1 .. 64);
Timestamp : Time;
Int1 : Long_Long_Integer;
String3 : Unbounded_String;
end record;
And it's used in
package My_Vectors is new Vectors (Index_Type => Positive, Element_Type => Object);
which yields the compilation error:
volatile object cannot act as actual in a call (SPARK RM 7.1.3(10))
Now, Clock is volatile which is used. However I've removed the call to Clock and I still get the same result.
Also, I've tried replacing the Object type with a type of Integer and I don't have any complaints from the Ada compiler. Could someone explain this as I can't see how this is putting a volatile object into an actual anywhere please.
Just tried using the following record and I get the same result:
type My_Record is
record
A: Integer;
B: Integer;
C: String(1 .. 64);
end record;
The standard Ada containers are not supported in SPARK (see SPARK RM 14.8).
Use the SPARK compatible container Ada.Containers.Formal_Vectors instead (see also here and here).
Regarding the compiler error: the current implementation of Ada.Containers.Vector uses atomic operations to improve performance (see here and here). These atomic operations operate (in this case) on variables of type System.Atomic_Counters.Atomic_Unsigned (see here). This type is declared as Atomic and therefore volatile (see RM 8(3)).

Constraint_Error raised when using modular types not divisble by 8

I've encountered an issue where using modular types in Ada that are not divisible by the system's Storage_Unit ( as defined in the runtime's system.ads ) will raise a Constraint_Error at runtime when accessed. I originally encountered this issue working on an bare-metal system using a minimal runtime while trying to read 12bit values from a buffer by overlaying the 12bit array over the buffer in memory. Does anyone know why this is occurring?
The following minimal example illustrates the issue I'm encountering. I tested this using AdaCore's GNAT 2019, compiled with the included zfp runtime. Using the standard runtime does not reproduce the issue.
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
----------------------------------------------------------------------------
-- Modular type with standard size divisible by 8.
----------------------------------------------------------------------------
type Type_One is mod 2 ** 16;
type Buffer_Type_One is array (1 .. 128) of Type_One;
----------------------------------------------------------------------------
-- Modular type with non-base 8 size.
----------------------------------------------------------------------------
type Type_Two is mod 2 ** 12;
type Buffer_Type_Two is array (1 .. 128) of Type_Two;
type Buffer is array (1 .. 256) of Character;
----------------------------------------------------------------------------
-- Example buffer.
----------------------------------------------------------------------------
Test_Buffer : Buffer := (others => ' ');
begin
----------------------------------------------------------------------------
-- Will not raise an exception.
----------------------------------------------------------------------------
Test_One :
declare
Buffer_One : Buffer_Type_One
with Import,
Convention => Ada,
Address => Test_Buffer'Address;
begin
Put_Line ("Testing type one");
for I in Natural range 1 .. 16 loop
Put_Line ("Test: " & Buffer_One (I)'Image);
end loop;
end Test_One;
----------------------------------------------------------------------------
-- Will raise a constraint error at runtime.
----------------------------------------------------------------------------
Test_Two :
declare
Buffer_Two : Buffer_Type_Two
with Import,
Convention => Ada,
Address => Test_Buffer'Address;
begin
Put_Line ("Testing type two");
for I in Natural range 1 .. 16 loop
Put_Line ("Test: " & Buffer_Two (I)'Image);
end loop;
exception
when Constraint_Error =>
Put_Line ("Constraint error encountered.");
end Test_Two;
end Main;
Here is the project file I used to compile this example:
project Test is
for Object_Dir use "obj";
for Exec_Dir use "build";
for Create_Missing_Dirs use "True";
for Languages use ("Ada");
package Builder is
for Executable ("main.adb") use "test";
end Builder;
for Main use ("main.adb");
package Compiler is
for Default_Switches ("Ada") use (
"-gnat2012",
"-gnatwadehl",
"-gnatVa",
"-gnaty3abcdefhiklmnoprstux"
);
end Compiler;
for Runtime ("Ada") use "zfp";
end Test;
I can't seem to find anything in the RM that would indicate why this would happen.
EDIT: Simon Wright below has figured out why this is happening. My naive understanding was that an instance of Buffer_Type_Two overlaid at the specified memory address would interpret the memory at this location as a sequence of 12bit values. It appears that this is not the case. It appears as though the compiler is rounding the size of the type up to 16bits, then raising a Constraint_Error when the 16bit value read from the array does not conform to the 12bit type.
If anyone can think of a better way to read a sequence of 12bit values from a location in memory in a sequential way I would greatly appreciate it, thank you.
With recent GNATs, you can achieve the behaviour you want by defining Buffer_Type_Two as
type Buffer_Type_Two is array (1 .. 128) of Type_Two
with Pack;
ARM 13.2(9) warns that this may not do what you want for 13-bit values (recent GNATs do, though).
An alternative would be
type Buffer_Type_Two is array (1 .. 128) of Type_Two
with Component_Size => 12;
The results are
...
Testing type two
Test: 32
Test: 514
Test: 32
Test: 514
...
For 13 bits, with either approach,
...
Testing type two
Test: 32
Test: 257
Test: 2056
Test: 64
Test: 514
Test: 4112
Test: 128
Test: 1028
Test: 32
...
HOWEVER, for an embedded target, you’ll need to use the -full- runtime system; for others, as pointed out by #egilhh above,
ajxs.adb:14:09: packing of 12-bit components not supported by configuration
Considering the compilation warnings, the code didn’t really deserve to work ...
31. Buffer_One : Buffer_Type_One
32. with Import,
33. Convention => Ada,
34. Address => Test_Buffer'Address;
|
>>> warning: specified address for "Buffer_One" may be inconsistent with alignment
>>> warning: program execution may be erroneous (RM 13.3(27))
>>> warning: alignment of "Buffer_One" is 2
>>> warning: alignment of "Test_Buffer" is 1
and
49. Buffer_Two : Buffer_Type_Two
50. with Import,
51. Convention => Ada,
52. Address => Test_Buffer'Address;
|
>>> warning: specified address for "Buffer_Two" may be inconsistent with alignment
>>> warning: program execution may be erroneous (RM 13.3(27))
>>> warning: alignment of "Buffer_Two" is 2
>>> warning: alignment of "Test_Buffer" is 1
but that’s not the problem, as it happens: Type_Two is mod 2**12, i.e. mod 4096, but the value in Buffer_Two(1) is 16#2020# (two space characters), which is 8224 in decimal.
"But why isn’t the stored value automatically masked to the 12 bits I asked for?" you say. For reasons of efficiency, "the size of an object is not necessarily the same as the size of the type of [the] object", GNAT RM 4.43, and GNAT expects the spare 4 bits at the top of the 16-bit word to be zero. On its own, a value of type Type_Two occupies (has ’Object_Size of) 16 bits. You could get the 12-bit size you want by including the Type_Two field in a record and specifying its layout, but that does add complication.
The problem wasn’t detected here without the -gnatVa (turn on all validity checking options).
The physical value of 16#2020# is not in the range of Type_Two so Constraint_Error is expected with -gnatVa.
GNAT CE 2020 raises Constraint_Error.
Uncommenting the exception/when part leads to further information:
raised CONSTRAINT_ERROR : main.adb:51 invalid data

Ada: Pragma List

Can anybody tell me what Pragma List does (specifically, what is "listing of the compilation")? I don't understand the description from the LRM (2.8.25)
A pragma List takes one of the identifiers On or Off as the single argument. This pragma is allowed anywhere a pragma is allowed. It specifies that listing of the compilation is to be continued or suspended until a List pragma with the opposite argument is given within the same compilation. The pragma itself is always listed if the compiler is producing a listing.
A compiler can output, i.e. “list” its input, together with any messages that it will generate, such as error messages. This is useful when you want a clear, verbose view of what a message is about, in context. IDEs will normally link message to code, but even today, considering Jacob's hint at computing history, a list can literally point out. Using a pragma List, the programmer can exclude what does not need to be listed, if he or she knows. Or, exclude what should never be listed, for reasons of secrecy.
Listing first, then the original program text, with pragma List:
Compiling: /some/path/some_proc.adb
Source file time stamp: 2017-01-30 08:30:40
Compiled at: 2017-01-30 09:30:42
1. procedure Some_Proc is
2. procedure Inner;
3. -- Does this and that...
4.
5. pragma List (Off);
10. pragma List (On);
11.
12. begin
13. Inner (42);
|
>>> too many arguments in call to "Inner"
14. end Some_Proc;
14 lines: 1 error
gprbuild: *** compilation phase failed
(If your compiler is GNAT, specify -gnatl among the switches, for listing, and compile:)
procedure Some_Proc is
procedure Inner;
-- Does this and that...
pragma List (Off);
procedure Inner is
begin
null;
end Inner;
pragma List (On);
begin
Inner (42);
end Some_Proc;
You should think back to how compilers worked and were used in the late 1970'ies. I'm pretty sure the meaning is as simple as it is written (substitute "is producing" with "outputs", to get a more modern wording).
with Ada.Text_IO;
-- Now you see me.
pragma List (Off);
-- Now you do not.
private with Some_Secret_Package;
pragma List (On);
package Hello_World is
...

Inconsistent argument passing mode

Consider the following code (which compile with GCC 4.7.4):
procedure Main is
procedure Sub_Proc(N : in out Integer) is
M : Integer;
begin
M := N;
end;
procedure Proc(N : out Integer) is
begin
Sub_Proc(N);
end;
N : Integer;
begin
Proc(N);
end Main;
The procedure Proc is supposed to ensure that the argument N which is an out argument will never be read inside his body. But it passes this argument to a procedure Sub_Proc which takes an in out argument, so potentially the previous argument will be read inside this procedure whereas the calling procedure ensured the opposite.
Is it a GCC bug or an Ada standard specificity ?
You’ll have received a warning on the Sub_Proc(N); call: "N" may be referenced before it has a value. So the compiler was trying to help!
In Ada 83, your program would have been illegal: 6.4.1(3) says "for the mode in out, the variable must not be a formal parameter of mode out”. Indeed, using -gnat83, and after a minor rearrangement of the code to allow it to compile, the equivalent to the above warning is the error (Ada 83) illegal reading of out parameter.
In Ada 95 and Ada 2012 it is OK to read the value of an out parameter after it has been assigned; in ARM95 6.4.1(15) we find that the value starts out uninitialized (as indicated by the warning message noted above), so using it is a Bad Idea.
So the answer is, GNAT’s behaviour conforms with the standard.

Ada Modeless Subprogram Parameters

If a parameter in Ada is left modeless, what happens?
what is the difference between
procedure my_func ( param_1 : in param_type )
and
procedure my_func ( param_1 : param_type )
I am new to ada and have been writing most of my procedures as the latter. The program compiles and runs as expected.
There is no difference - if no parameter mode is given, the compiler assumes "in".
See http://www.ada-auth.org/standards/12rm/html/RM-6-1.html line beginning 18/3.
-- Martin
As suggested by Martin, the default mode is 'in' if not provided.
I would like to add that if possible, you can sometimes experiment with things about which you are doubtful.
like look at the below simple code, I have not given any mode to the arguement 'no_1'.
And as seen I am assigning value of 'no_2' to it.
with Ada.Text_IO; use Ada.Text_IO;
procedure just_testing is
procedure get_value (no_1 : Integer);
procedure get_value (no_1 : Integer) is
no_2 : Integer := 2;
begin
no_1 := no_2;
end get_value;
begin
Put("auto mode");
end just_testing;
And when I compile this code, look what we get as error.
>gnatmake just_testing.adb
gcc -c just_testing.adb
just_testing.adb:10:09: assignment to "in" mode parameter not allowed
gnatmake: "just_testing.adb" compilation error
So, compiler makes it clear that the default mode is 'in', as we can not assign any value to argument with mode in.

Resources