How do I handle uninitialized data in a dynamic predicate in Ada? - ada

This is some simplified code I haven't tested as is (so it may contain errors) that demonstrates the problem I'm experiencing:
type Space is private;
--Depending on members of Space, determines whether Outer fully contains Inner
function Contains(Outer : Space; Inner : Space);
--Outer should fully contain Inner
type Nested_Space is
record
Inner : Space;
Outer : Space;
end record
with Dynamic_Predicate => Contains(Outer, Inner);
I haven't been able to find a convenient way to initialize a Nested_Space without failing the assert defined by the predicate. If I try to set the members of Inner first, the members of Outer are still wherever they defaulted. But if I try to set the members out Outer first, the members of Inner are still wherever they defaulted. Even if I tried forcing a default on either type, there's still no way to pick a default that will certainly be within the bounds of any arbitrary Nested_Space.
Even trying to initialize with something like
declare
My_Inner : Space := (...);
My_Outer : Space := (...);
My_NS : Nested_Space := (Inner => My_Inner, Outer => My_Outer);
begin
....
end;
I can't seem to keep it from failing the assert. I can come up with some pretty clunky ideas (such as adding an Initialized : Boolean to Nested_Space specifically to check in the predicate, or alternatively setting members of the two different Spaces) but I was hoping there might be a solution that doesn't affect the structure of the record for something not required for the use case.
GNAT solutions are welcome if there's no solution in the ARM.
Thanks in advance!

I haven't been able to find a convenient way to initialize a Nested_Space without failing the assert defined by the predicate. If I try to set the members of Inner first, the members of Outer are still wherever they defaulted. But if I try to set the members out Outer first, the members of Inner are still wherever they defaulted.
ARM 3.2.4 (35/3) says, "A Static_Predicate, like a constraint, always remains True for all objects of the subtype, except in the case of uninitialized variables and other invalid values. A Dynamic_Predicate, on the other hand, is checked as specified above, but can become False at other times. For example, the predicate of a record subtype is not checked when a subcomponent is modified." You seem to be saying that this is not followed, and the record predicate is checked when you assign to a record component. If so, then you have found a compiler error. That it fails for an aggregate seems to support this idea.
However, unless you post a compilable example that demonstrates your problem, we cannot be sure that this is a compiler error.

Related

How is the `'Old` attribute in a **Post** contract handled for access types that might got deallocated inside the function or procedure?

Assume having the following setup:
type My is new Integer;
type My_Acc is access My;
procedure Replace(Self : in out My_Acc; New_Int : Integer)
with Pre => New_Int /= Self.all, Post => Self'Old.all /= Self.all;
Note: Code above might not be fully valid, but I hope the concept is understandable.
Now what happens if Unchecked_Deallocation() is used on Self inside Replace
and a new Integer is allocated and set to Self (This should result in Self'Old pointing to a now invalid memory location)?
Does Ada keep kind of a snapshot where Self'Old points to the previous memory location, but before Unchecked_Deallocation() is executed?
If Self'Old would get invalid for use in the Post contract, how could you still access the previous value? Is it possible to create a manual snapshot in the Pre contract that can then be used in Post? Maybe it can be achieved using Ghost_Code?
I want to make everything in Spark, in case that changes something.
Edit: Fixed Self to in out as mentioned by Simon Wright.
Edit: Fixed type of Self to allow null
It may be that the latest versions of SPARK support access types; it used not to, at all.
First, your Not_Null_My_Acc needs to be a subtype of My_Acc, unless you meant it to be a type in its own right.
Second, you can’t deallocate Self inside Replace and allocate a new value; Self is in-mode, & hence not writable.
Third, you can’t apply ’Old to Self, because
warning: attribute "Old" applied to constant has no effect
What you can say is
Post => Self.all'Old /= Self.all;
In ARM 6.1.1(26ff) it says
Each X'Old in a postcondition expression that is enabled denotes a constant that is implicitly declared at the beginning of the subprogram body, entry body, or accept statement.
The implicitly declared entity denoted by each occurrence of X'Old is declared as follows:
...
X'Old : constant S := X;
... in other words, nothing fancy is expected, just a straight copy of (in this case) Self: not Self.all.
So, if your Replace deallocates Self, then Self’Old is a dangling reference, and erroneous.
I suggested previously that changing the postcondition to
Post => Self.all'Old /= Self.all;
would be safe; why wouldn’t that meet your requirements? is there something going on you haven’t told us about?
Note the subtle difference between Self’Old.all and Self.all’Old. The first one takes a copy of Self as it was before the call, which gets dereferenced after the call (by which time it’s pointing into hyperspace), while the second one dereferences the prior Self and copies the integer value it finds there; on return that’s still valid.

Ada deferred constant finalized using complicated calculation; where to put the code?

I needed the result of a rather complex calculation to define a private type, something like this:
generic
top_m : Positive;
package Mystic is
type T is private;
private
type Table is array (Positive range <>) of Positive;
function reallyComplicatedFunction(x : Positive) return Table;
mytable : constant Table := reallyComplicatedFunction(top_m);
-- I will need mytable for calculations later
type T is array (mytable'Range) of Natural;
-- T is very different from Table, except they share their Range
end Mystic;
I needed the type T to depend on generic parameter top_m in a really complicated way, embodied by reallyComplicatedFunction(.). The function is defined in the body of package Mystic, but it does not use anything else declared by the package.
To my surprise this setup works just fine. Maybe I'm just lucky, because as far as I can tell from decyphering the ARM, this kind of invocation of the function is merely 'legal' but it is not guaranteed not to throw a Program_Error. I interpret this as "it would be too restrictive to forbid this sort of stuff entirely, but the compiler can't be expected to determine its feasibility in all cases either, so we'll just allow you to experiment with it". And then there's the rather significant possibility that I'm completely misreading the reference manual. Anyway, books on Ada give rather stern warnings about this sort of thing, typically around the discussion of pragma Elaborate et al., such that I almost didn't try this solution.
I've also tried to put the function in a private child package of Mystic, but I could not resolve circularities between the child implicitly depending on the parent and the parent specification depending on the child. Anyway, this function is not an extension of Mystic but a necessary code to initialize it.
My question would then be: where is the proper place for such a function?
ETA: at the request of Simon Wright, here's the part of the ARM I struggle with: http://www.ada-auth.org/standards/12rm/html/RM-3-11.html entries 9, 10/1 and 14:
For a construct that attempts to use a body, a check
(Elaboration_Check) is performed, as follows:
For a call to a (non-protected) subprogram that has an explicit body, a check is made that the body is already elaborated. This check
and the evaluations of any actual parameters of the call are done in
an arbitrary order.
...
The exception Program_Error is raised if any of these checks fails.
As far as I understand, the construct mytable : constant Table := etc. tries to use the body of reallyComplicatedFunction, so it must check whether it was elaborated or not. I assume - this is a weak point in my reasoning but this is what I understood - that elaboration of the body of reallyComplicatedFunction only occurs during the elaboration of the body of package Mystic, so my function won't be elaborated at the time it is called from the private part of the package specification. Nonetheless, I don't receive the Program_Error as promised when using (an instance of) the package.
ETA2: following a remark from trashgod, I've tried turning package Mystic into a non-generic one; made top_m into a visible constant and removed the genericity part. The compiler now catches the circularity I was worried about from the beginning and the program exits with Program_Error: access before elaboration. It's as if the body of a generic package was elaborated before the first instantiation, or rather before the elaboration of the specification of said package during instantiation. Since I'd expect Ada to cater to this kind of need (of hiding complex calculations needed to instantiate a package in the body of said package), I'd not be surprised if it worked as per the standard, but I don't recall reading anything like this anywhere and would like to know the exact rules. Something very smart is going on because if I make the body of the function dependent on type T, the compiler warns about 'call to Tt may occur before body is seen' at the point of package instantiation (I guess 'Tt' is some internality of type T), and when the program is run, it throws a Program_Error complaining about access before elaboration, pointing to the first place where an object of type T is instantiated by another function I have called by reallyComplicatedFunction for testing purposes.
Edit, reflecting the comment that explain why reallyComplicatedFunction should not be public.
If I understand correctly, the function does not really not depend on Mystic, but reallyComplicatedFunction should be private. In that case, I'd try putting it elsewhere, and keep the dependency on top_m. I have assumed that Table could also be moved, even though formally it is creating a dependence of reallyComplicatedFunction, Table being in its parameter profile.
To resolve, a new private place is created in a hierarchy, a private sibling gets the declarations and will only be used in the private part of original Mystic. Hence, private with in the latter's context clause.
package Top is end;
private generic
top_m : Positive;
package Top.Outsourced is
type Table is array (Positive range <>) of Positive;
function reallyComplicatedFunction(x : Positive) return Table;
end Top.Outsourced;
private with Top.Outsourced;
generic
Top_M : Positive;
package Top.Mystic is
type T is private;
private
package Initializer is new Top.Outsourced (top_m);
subtype Table is Initializer.Table;
mytable : constant Table := Initializer.reallyComplicatedFunction (top_m);
-- I will need mytable for calculations later
type T is array (mytable'Range) of Natural;
-- T is very different from Table, except they share their Range
end Top.Mystic;
package body Top.Outsourced is
function reallyComplicatedFunction(x : Positive) return Table is
Limit : Positive;
begin
Limit := Positive'Min (top_m, 1) + x/2;
return Result : Table (1 .. Limit);
end reallyComplicatedFunction;
end Top.Outsourced;
Assuming (since you didn't specify it) the array returned from reallyComplicatedFunction has the range 1..top_m, you could define a new subtype and use that as the range for both arrays:
subtype My_Range is Positive range 1..m_top
type Table is array (My_Range) of Positive;
type T is array (My_Range) of Natural;
and move both my_table and reallyComplicatedFunction inside the package body.

Ada Function Parameter as Access Type or Not

I am refactoring some code originally written using access types, but not yet tested. I found access types to be troublesome in Ada because they can only refer to dynamically allocated items, and referring to items defined at compile time is apparently not allowed. (This is Ada83.)
But now I come to a function like this one:
function Get_Next(stateInfo : State_Info_Access_Type) return integer;
I know that I can easily pass parameter "contents" of an access type rather than the access pointer itself, so I am considering writing this as
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
where State_Info_Type is the type that State_Info_Access_Type refers to.
With this refactor, for all intents and purposes I think I'm still really passing what amounts to an implicit pointer back to the contents (using the .all) syntax).
I want to refactor and test starting with the lowest level functions, working my way up the call chains. My goal is to push the access types out of the code as I go.
Am I understanding this correctly or am I missing something?
I think original author(s), and possibly OP are missing a point, that is, how Ada parameter modes work.
To quote #T.E.D
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Ada does this automatically, and leaves the parameter modes as a way of describing the flow of information (Its NOT the C style reference / value conundrum). See the useful wikibook.
What worries me is that the code you have inherited looks like the author has used the explicit access parameter type as a way of getting functions to have side effects (usually considered a bad thing in Ada - World).
My recommendation is to change your functions to:
function Get_Next(State_Info : in State_Info_Type) return Integer;
and see if the compiler tells you if you are trying to modify State_Info. If so, you may need to change your functions to procedures like this:
procedure Get_Next(State_Info : in out State_Info_Type;
Result : out Integer);
This explicitly shows the flow of information without needing to know the register size or the size of State_Info_Type.
As an aside Ada 2012 Will allow you to have functions that have in out parameters.
To quote #T.E.D,
Every Ada compiler I know of under the hood passes objects larger than fit in a machine register by reference. It is the compiler, not the details of your parameter passing mechanisim, that enforces not writing data back out of the routine.
Since this code hasn’t yet been tested, I think you are completely right to rework what looks like code written with a C mindset. But, you oughtn’t to mention pointers at all; you suggested
function Get_Next(stateInfoPtr : State_Info_Type) return integer;
but this would be better as
function Get_Next(stateInfo : State_Info_Type) return integer;
or even (IMO) as
function Get_Next(State_Info : State_Info_Type) return Integer;
to use more standard Ada styling! My editor (Emacs, but GPS can do this too) will change state_info into State_Info on the fly.
As an afterthought, you might be able to get rid of State_Info_Type_Pointer altogether. You mention .all, so I guess you’ve got
SITP : State_Info_Type_Pointer := new State_Info_Type;
... set up components
Next := Get_Next (SITP.all);
but what about
SIT : State_Info_Type;
... set up components
Next := Get_Next (SIT);
I wouldn't recommend this, but you can get pointers to variables in Ada 83 by using 'Address.
You can then use overlays (again this is all Ada83 stuff) to achieve access...
function something(int_address : Address) return integer
is
x : integer;
for x'address use int_address;
begin
-- play with x as you will.

Safety of unrestricted_access

I have a complicated situation so I hope I can explain it properly.
I am using unchecked_access in combination with Ada.Finalization.Controlled types to pass references to vectors to an out of scope protected hashed map type on the Initialize procedure and removing references in the protected map on the finalize procedure. This way I thought I could assure that it would be impossible for any tasks to see out of scope references in the map.
However, the way I have the protected map organized snap shots are taken at each instance that is it used (effectively making it a normal hashed_map) which during the course of it being used vector references could go out of scope and the snap shot would still have the reference and attempt to access it.
I could see this creating 2 problems, either I am creating dangling pointers and trying to reference freed memory or my snapshot of the references is keeping the memory alive and I am leaving garbage around. I made a test to see what would happen and it seems the memory is still alive but is this really the case? Are there any other problems with my organization?
with Ada.Containers; use Ada.Containers;
with Ada.Containers.Vectors;
with Ada.Text_IO; use Ada.Text_IO;
procedure Test is
package V_Integer is new Ada.Containers.Vectors(Positive, Integer);
use V_Integer;
type V_Access is access all Vector;
Bar : V_Access;
begin
declare
Foo : aliased Vector;
begin
Bar := Foo'unrestricted_Access;
Foo.Append(3);
Foo.Append(5);
Put_Line("In scope: " & count_type'image(Length(Bar.all)));
end;
-- Will this reference always exist? Does it need to be freed?
Put_Line("Out of scope: " & count_type'image(Length(Bar.all)));
end Test;
begin
declare
Foo : aliased Vector;
begin
Bar := Foo'unrestricted_Access;
Foo.Append(3);
Foo.Append(5);
Put_Line("In scope: " & count_type'image(Length(Bar.all)));
end;
-- Will this reference always exist? Does it need to be freed?
Put_Line("Out of scope: " & count_type'image(Length(Bar.all)));
end Test;
Foo will be an object of type Vector, and it will probably exist on the stack. This object is itself a relatively small record, maybe about 6 32-bit words in GNAT (give or take a few, I haven't checked). It contains an access component that is used to get at all the vector's elements, and it contains some other housekeeping information. Bar will point to that small 6-word record. Essentially it will contain the address of something on the stack.
Since the small record Foo exists on the stack, when it goes out of scope, the stack space could be used for something else. Whether it will happen in this case, I don't know. But if you have another declare...begin...end block after the one in the example, local variables used by the new block could reuse the same stack space. Or if a procedure is called, that will put different stuff on the stack. In either case, the stack space previously used by Foo will be overwritten. And Bar will still point to the same address, but the area it points to will have been overrun with other data. So the result is likely to be wrong and could be a disaster.
I don't know if this is exactly how the implementation will work, but no matter how it's implemented, this code is potentially disastrous. The main things to keep in mind are: (1) If a variable goes out of scope, the space used for that variable may be reused at will; (2) if you use 'Unchecked_Access (or 'Unrestricted_Access) to set up a pointer to that variable, then after the variable goes out of scope, accessing data pointed to by the pointer could get you garbage or very bad behavior; (3) variables, whether aliased or not, are not (usually) dynamically allocated and the program does not need to (and cannot) explicitly free them, even if you've created a reference to them with 'Unchecked_Access.

Dealing with access type in Ada95

I have a specification of a function that acts like a constructor. The specification of the function is
function Create_Controller return Type_Controller;
Also, in the specification file, I have the Type_Controller type, which is an access. I copy the relevant fragment:
type Type_Controller_Implementation;
type Type_Controller is access Type_Controller_Implementation;
So, this is what I've attempted:
function Create_Controller return Type_Controller
is
My_Controller : aliased Type_Controller_Implementation;
begin
return My_Controller'Access;
end Create_Controller;
I tried to compile the program without the aliased keyword, but then, the compiler says:
prefix of "Access" attribute must be aliased
So, I put the aliased keyword and the compiler now suggests that I should change the specification:
result must be general access type
add "all" to type "Controlador_De_Impresion" defined at controller.ads
The problem is that I'm not allowed to change the specification. I've read the chapter about access types in the Ada Programming Wikibook, but I still don't understand why my code doesn't work. What am I doing wrong?
The implementation of the Create_Controller function body is incorrect. Were it to work as coded, you'd be returning a pointer to a variable local to that function body's scope...which would be immediately lost upon returning from the function, leaving you with an invalid pointer.
No, an instance of the type needs to be allocated and returned. If there's no explicit initialization that needs to occur you can simply do:
return new Type_Controller_Implementation;
If there is some initialization/construction that has to occur, then:
function Create_Controller return Type_Controller
is
My_Controller : Type_Controller := new Type_Controller_Implementation;
begin
-- Set fields of My_Controller
...
return My_Controller;
end Create_Controller;
When you declare an access type as access T, you're saying that "this is a pointer to a T and it must point to objects of type T allocated from a pool". (That is, allocated with a new keyword.) When you declare an access type as access all T, you're saying that it can point either to a T allocated from a pool, or to an aliased variable of type T.
If the type is declared as access T and you can't change it, then all access values of the type have to point to something allocated with new. You can't make it point to a variable (even to a "global" variable that isn't located on the stack).
The reasons for this are historical, I think. The first version of Ada (Ada 83) only had "pool-specific types." You couldn't make an access value point to some other variable at all, without trickery. This meant that a compiler could implement access values as indexes into some storage block, or as some other value, instead of making them the actual address of an object. This could save space (an access value could be smaller than an address) or allow more flexibility in how pool memory was managed. Allowing access values to point directly to objects takes away some of that flexibility. I think that's why they decided to keep the old meaning, for backward compatibility, and require an all keyword to indicate the new kind of access.

Resources