Hi folks,
I am writing an Ada package (an option processing package) that requires
to pass an anonymous access to function type to a procedure, which will
then store it in an array to be called later.
I have stumbled into a strange behaviour of the GNAT compiler (gnat
--version: GNAT 12.2.0, Copyright (C) 1996-2022, Free Software
Foundation, Inc.; installed using 'alr install
--prefix=~/install/gnat-alire/gnat-alire-12.2' with alr 2.0-dev on
Ubuntu-20.04):
1) when I compile the code (the 'process_options.adb' main procedure
that uses the 'Get_Options' package) with the 'Is_Present' and other
fields explicitly initialised ('Is_Present => False' at
get_options.adb:24), everything compiles and runs as expected;
2) when I instead change to default initialisation ('Is_Present =><>' at
get_options.adb:24, or remove the line altogether to rely on the 'others
=> <>' statement), I get the following error message from the compiler:
gcc -c -Iprograms/ -Isrc -gnata -I- -o
/home/saulius/tests/ada/ada-pass-access-function/.obj/get_options.o
/home/saulius/tests/ada/ada-pass-access-function/src/get_options.adb
get_options.adb:20:29: error: illegal attempt to store anonymous
access to subprogram
get_options.adb:20:29: error: value has deeper accessibility than any
master (RM 3.10.2 (13))
get_options.adb:20:29: error: use named access type for "Processor"
instead of access parameter
gnatmake:
"/home/saulius/tests/ada/ada-pass-access-function/src/get_options.adb"
compilation error
Is the behaviour of the GNAT compiler correct in both cases?
If yes, why the legality of the anonymous access procedure type
assignment depends on the initialisation code of /other/ fields?
If not, which case is correct and will be retained in the future? (I
have a bad feeling that the behaviour in (2) is correct and (1) is a
compiler bug, although the behaviour in (1) fits neatly my purpose and
seems to be totally safe in this particular case :) ...).
I attach what I see as a minimal working example abstracted from my code.
I will be grateful for any explanations, or any hint as to where to seek
information (the mailing lists mentioned at
http://sigada.org/resources.html#Google%20Groups are unfortunately
mostly filled with spam and/or advertisements, seem to be unmoderated
and unused).
Sincerely yours,
Saulius
--
Dr. Saulius Gražulis
Vilnius University Institute of Biotechnology, Saulėtekio al. 7
LT-10257 Vilnius, Lietuva (Lithuania)
fax: (+370-5)-2234367 / phone (office): (+370-5)-2234353
mobile: (+370-684)-49802, (+370-614)-36366
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
with Text_IO; use Text_IO;
package body Get_Options is
procedure Help (Option_String : String; Pos : Positive) is
begin
Put_Line ("This is a help from the package ...");
end;
function Option
(
Short_Option : String;
Processor : access procedure
(Option_String : String; Position : Positive)
) return Option_Type is
begin
return
(
Short_Option => Short_Option (Short_Option'First + 1),
Value_Processor => Processor,
-- Fails to compile if the folowing line, 'Is_Present =>
-- False,', is commented out or changed to use the default
-- initialisation ('Is_Present => <>'):
Is_Present => <>,
others => <>
);
end;
end Get_Options;
package Get_Options is
type Option_Processor_Type is access procedure
(Option_String : String; Position : Positive);
type Option_Type is record
Short_Option : Character;
Value_Processor : Option_Processor_Type;
Is_Present : Boolean := False;
end record;
type Option_Array is array (Positive range <>) of Option_Type;
procedure Help (Option_String : String; Pos : Positive);
function Option
(
Short_Option : String;
Processor : access procedure
(Option_String : String; Position : Positive)
) return Option_Type;
end Get_Options;
pragma Ada_2022;
with Text_IO; use Text_IO;
with Get_Options; use Get_Options;
procedure Process_Options is
procedure Help (Option_String : String; Pos : Positive) is
begin
Put_Line ("This is a help from the main program ...");
end;
Options : Option_Array :=
(
Option ("-h", Help'Access),
Option ("-H", Get_Options.Help'Access)
);
begin
-- Options (1).Value_Processor := Get_Options.Help'Access; -- compiles and works
-- Options (1).Value_Processor := Help'Access; -- fails at compile time
for O of Options loop
Put_Line (O.Short_Option'Image);
Put_Line (O.Is_Present'Image);
Put_Line (O.Value_Processor'Image);
if O.Value_Processor /= null then
O.Value_Processor ("--one", 1);
end if;
end loop;
end;