Consider a trivial example with composition of interfaces:
with Ada.Text_IO;
procedure A is
package Stuff is
type Base_1 is interface;
procedure P_1 (X : in Base_1) is abstract;
type Base_2 is interface;
procedure P_2 (X : in Base_2) is abstract;
type Middle is interface and Base_1 and Base_2;
type Concrete is new Middle with null record;
procedure P_1 (X : in Concrete);
procedure P_2 (X : in Concrete);
function Make_Concrete return Concrete;
end Stuff;
package body Stuff is
procedure P_1 (X : in Concrete) is
begin
Ada.Text_IO.Put_Line ("Concrete.P_1");
end P_1;
procedure P_2 (X : in Concrete) is
begin
Ada.Text_IO.Put_Line ("Concrete.P_2");
end P_2;
function Make_Concrete return Concrete is
C : Concrete;
begin
return C;
end Make_Concrete;
end Stuff;
use Stuff;
B_1 : Base_1'Class := Make_Concrete;
B_2 : Base_2'Class := Make_Concrete;
begin
B_1.P_1;
B_2.P_2;
end;
$ gnatmake a
$ ./a
Concrete.P_1
Concrete.P_1
$
In other words, both calls dispatched to the same procedure.
Some experiments led me to the interesting observation:
Changing this:
type Middle is interface and Base_1 and Base_2;
to this:
type Middle is interface and Base_2 and Base_1;
results in:
$ ./a
Concrete.P_2
Concrete.P_2
Again, both calls dispatched to the same procedure, but now I know
that in both cases the dispatch goes to the *first* progenitor of the
Middle interface. Obviously against 3.9.4-1/b.
Things get particularly funny when the signatures of P_1 and P_2 are
different (say, they have different sets of parameters).
It all looks like the v-table got messed up.
$ gnatmake --version
GNATMAKE 4.4.0 20080314 (experimental) [trunk revision 133226]
It is the newest version I could find for my system.
--
Maciej Sobczak * www.msobczak.com * www.inspirel.com