0

I have an object oriented design as follows (Ada 2012). The question is not about the design itself, but its consequences with a particular runtime profile.

-- several packages ommitted here, ads/adb mixed together
type Interface_A is interface;
type Interface_A_Class_Access is access all Interface_A'Class;

type Interface_B is interface and Interface_A;
type Interface_B_Class_Access is access all Interface_B'Class;

type Interface_C is interface and Interface_B
type Interface_C_Class_Access is access all Interface_C'Class;

type B_Impl is abstract tagged ...;
type B_Impl_Access is access all B_Impl;
type C_Impl is new B_Impl and Interface_C ...;
type C_Impl_Access is access all C_Impl;

function Create_C return C_Impl_Access is begin
   return new C_Impl'(...);
end Create;

I have a factory to instantiate objects of Interface_A, Interface_B or Interface_C.

package body My_Factory is
   procedure Create_A return Interface_A_Class_Access is begin
      return Create_A_Impl; -- error: dynamic interface conversion not supported by configuration
   end Create_B;

   procedure Create_B return Interface_B_Class_Access is begin
      return Create_C_Impl; -- error: dynamic interface conversion not supported by configuration
   end Create_B;

   procedure Create_C return Interface_C_Class_Access is begin
      return Create_C_Impl; -- error: dynamic interface conversion not supported by configuration
   end Create_C;
end package My_Factory;

With my switches, I'm getting the following error for both factory create functions :

error: dynamic interface conversion not supported by configuration

Environment:

  • GNAT 17.2
  • ZFP MPC8641
  • GPRBUILD Pro 18+

What I tried so far :

  1. Change factory implementation with explicit cast or explicit temp variable allocation:

Sample:

package body My_Factory is
   ...
   procedure Create_B return Interface_B_Class_Access is begin
      return Interface_B_Class_Access(Create_C); -- error: dynamic interface conversion not supported by configuration
   end Create_B;

   procedure Create_C return Interface_C_Class_Access is
      tmp : Interface_C_Class_Access;
   begin
      tmp := Create_C; -- error: dynamic interface conversion not supported by configuration
      return tmp;
   end Create_C;
end package My_Factory;

Same problem.

  1. Add explicit constructor methods (affectation of the 'new' into a class access variable)

Sample:

function Create_C return Interface_A_Class_Access is begin
   return new C_Impl'(...); -- error: dynamic interface conversion not supported by configuration
end Create;

function Create_C return Interface_B_Class_Access is
   tmp : Interface_B_Class_Access;
begin
   tmp := new C_Impl'(...); -- works fine
   return tmp;
end Create;

function Create_C return Interface_C_Class_Access is
   tmp : Interface_B_Class_Access;
begin
   tmp := new C_Impl'(...); -- works fine
   return tmp;
end Create;

This second option works fine.

  1. With the standard profile the problem does not arise. I faced the issue while (naively) porting into a specific profile. As far as I get it, this is legit object oriented design, but some constructions are not handled in the same way.

My questions:

  1. Is my second option acceptable ? Why does it work ?

  2. Am I missing something ? I understand that this is somewhat related to dispatch tables management by compiler generated code, but I don't really get the deep mechanics/reasons.

LoneWanderer
  • 3,058
  • 1
  • 23
  • 41

1 Answers1

2

The "not supported by configuration" message hints that this is a limitation of the runtime. And you are using a zero-footprint (ZFP) runtime, which has severe limitations when it comes to, for example, indefinite types (like class-wide types and unconstrained arrays).

The runtime documentation should provide more information about these restrictions/limitations.

egilhh
  • 6,464
  • 1
  • 18
  • 19
  • 1
    The answer might be in the ZFP `a-tags.ads` comments.`-- Displace, IW_Membership, Offset_To_Top, Set_Dynamic_Offset_To_Top, Base_Address, Register_Interface_Offset: They are used with extended support for interface types that is not part of the zfp runtime (membership test applied to interfaces, tagged types with variable size components covering interfaces, explicit dereference through access to interfaces, and unchecked deallocation through access to interfaces).` – LoneWanderer Jun 12 '18 at 13:50
  • Maybe it will help, if you can convert your interfaces to abstract tagged records. – Jacob Sparre Andersen Jun 12 '18 at 16:13
  • 1
    I found this error message (in GCC 8.1.0) at exp_disp.adb:1387, and it’s Displace that’s missing; something to do with displacing the pointer to the secondary stack table. Why your code changes (assignment to a tmp) worked - have no idea, sorry. – Simon Wright Jun 12 '18 at 19:33
  • @JacobSparreAndersen That won't allow me to do multiple inheritance, which is the prupose of `interface`keyword and object design. Rosen trick is not supposed to be necessary anymore in Ada 2012. – LoneWanderer Jun 17 '18 at 13:42
  • @egilhh I'm not sure either to mark tour answer as valid or re post my comment concerning the ZFP definition. I feel the Displace mechanism usage limitation in ZFP is not yet clear enough for me. – LoneWanderer Jun 18 '18 at 12:16