alex
alex

Reputation: 1287

How to make size of generic type explicit in Ada?

I am trying to compile this code: https://github.com/RanaExMachina/ada-fuse

Unfortunately when building I get this error:

fuse-system.ads:147:04: size clause not allowed for variable length type

This seems to be a problem because in the code it tries to set the size of a record which has a generic type as an entry. This seems to be a new error as the developer didn't had that problem back when he wrote that 2.5 years ago. Unfortunately he isn't able to help me on short notice but I have to get that library going. I am a bit helpless in fixing this issue however.

Basically it seems to me that I have to somehow tell gnat how big that type is going to be, which - contrary to gnat's believe - is a priori knowable: it is an access type. Either in the record or the generic type definition.

The relevant parts are:

fuse-main.ads:
  package Fuse.Main is
    package IO is
      new Ada.Direct_IO (Element_Type);
    type File_Access is access IO.File_Type;

fuse-system.ads:
  generic
    type File_Access is private;
  package Fuse.System is
  ...
    type File_Info_Type is record
      Flags       : Flags_Type;
      Fh_Old      : Interfaces.C.unsigned_long;
      Writepage   : Interfaces.C.int;
      Direct_IO   : Boolean := True;
      Keep_Cache  : Boolean := True;
      Flush       : Boolean := True;
      Nonseekable : Boolean := True;
      Fh          : File_Access;
      Lock_Owner  : Interfaces.Unsigned_64;
    end record;
  type File_Info_Access is access File_Info_Type;
  pragma Convention (C, File_Info_Type);
  for File_Info_Type'Size use 32*8;

My gnat version is: 4.9.2-1 (debian jessie)

Upvotes: 2

Views: 253

Answers (1)

Simon Wright
Simon Wright

Reputation: 25491

You know that File_Access is an access type, but within Fuse.System the compiler doesn’t; all it knows is that it’s definite and supports assignment and equality. The actual could be hundreds of bytes.

To tell the compiler that it is an access type, try something like this (I compressed it into one package for my convenience, on Mac OS X, hence the 64-bit pointer size; it compiles OK):

with Ada.Text_IO;
package Fuse_Tests is

   generic
      type File_Type is limited private;
      type File_Access is access File_Type;
   package Fuse_System is
      type File_Info_Type is record
         Fh : File_Access;
      end record;
      for File_Info_Type'Size use 64;
   end Fuse_System;

   type File_Access is access Ada.Text_IO.File_Type;

   package My_Fuse_System is new Fuse_System
     (File_Type   => Ada.Text_IO.File_Type,
      File_Access => File_Access);

end Fuse_Tests;

Or, an alternative suggested in the comments:

with Ada.Text_IO;
package Fuse_Tests is

   generic
      type File_Type;
   package Fuse_System is
      type File_Access is access File_Type;
      type File_Info_Type is record
         Fh : File_Access;
      end record;
      for File_Info_Type'Size use 64;
   end Fuse_System;

   package My_Fuse_System is new Fuse_System
     (File_Type => Ada.Text_IO.File_Type);

   --  if needed ...
   subtype File_Access is My_Fuse_System.File_Access;

end Fuse_Tests;

Upvotes: 7

Related Questions