diff mbox

[Ada] Implementation of AI05-0161 restriction No_Default_Stream_Attributes

Message ID 20110804152435.GA8822@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Aug. 4, 2011, 3:24 p.m. UTC
This new restriction is intended to prevent the use of the predefined stream
attributes for elementary types. A consequence of this restriction is that
the default implementation of stream attributes for composite types cannot
be created if any of its elementary components lacks user-defined Read and
Write attributes. 

Given the following configuration file:

    pragma Restrictions (No_Default_Stream_Attributes);

Then the following must compile quietly:
---
   with Stdarg;
   procedure Main is
   begin
      null;
   end Main;
---
and the following must execute quietly:

   with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
   procedure Stream_Test is
      --  Check that when restriction No_Default_Stream_Attributes is active,
      --  stream operations on composite types are usable if the type of their
      --  elementary components have user-defined stream operations.

      type Count is new Integer;
      procedure Dump_It
        (S : not null access Ada.Streams.Root_Stream_Type'Class; It : Count);
      for Count'Write use Dump_It;

      procedure Grab_It
       (S : not null access Ada.Streams.Root_Stream_Type'Class; It : out Count);
      for Count'Read use Grab_It;
   
      type Rec is record
         Value : Count;
      end record;

      procedure Dump_It
        (S : not null access Ada.Streams.Root_Stream_Type'Class; It : Count) is
      begin
         String'Output (S, Count'Image (It));
      end;

      procedure Grab_It
        (S : not null access Ada.Streams.Root_Stream_Type'Class; It : out Count)
      is
      begin
         It := Count'Value (String'Input (S));
      end Grab_It;

      Rec_File : File_Type;
      S : Stream_Access;
      Obj : Rec := (Value => -1234);
      Recovered : Rec;
   begin
      Create (Rec_File, Name => "temp");
      S := Stream (Rec_File);
      Rec'Output (S, Obj);
      Close (Rec_File);

      Open (Rec_File, Name => "temp",  Mode => In_File);
      Recovered := Rec'Input (S);

      if Obj /= Recovered then
         raise Program_Error;
      end if;
   end;
---
After commenting out any of the attribute definitions above, compilation of
stream_test.adb must yield: 

    stream_test.adb:39:07:
       violation of restriction "No_Default_Stream_Attributes" at gnat.adc:1

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-08-04  Ed Schonberg  <schonberg@adacore.com>

	* exp_ch3.adb (Stream_Operation_Ok): new predicate
	Needs_Elementary_Stream_Operation, to determine whether user-defined
	Read and Write attributes are available for the elementary components
	of the given type. If only the predefined attributes are available,
	then when restriction No_Default_Stream_Attributes is active the
	predefined stream attributes for the composite type cannot be created.
diff mbox

Patch

Index: exp_ch3.adb
===================================================================
--- exp_ch3.adb	(revision 177387)
+++ exp_ch3.adb	(working copy)
@@ -8964,7 +8964,60 @@ 
    is
       Has_Predefined_Or_Specified_Stream_Attribute : Boolean := False;
 
+      function Needs_Elementary_Stream_Operation
+        (T : Entity_Id) return Boolean;
+      --  AI05-0161 : if the restriction No_Default_Stream_Attributes is active
+      --  then we can generate stream subprograms for records that have scalar
+      --  subcomponents only if those subcomponents have user-defined stream
+      --  subprograms. For elementary types only 'Read and 'Write are needed.
+
+      ---------------------------------------
+      -- Needs_Elementary_Stream_Operation --
+      ---------------------------------------
+
+      function Needs_Elementary_Stream_Operation
+        (T : Entity_Id) return Boolean
+      is
+      begin
+         if not Restriction_Active (No_Default_Stream_Attributes) then
+            return False;
+
+         elsif Is_Elementary_Type (T) then
+            return No (TSS (T, TSS_Stream_Read))
+              or else No (TSS (T, TSS_Stream_Write));
+
+         elsif Is_Array_Type (T) then
+            return Needs_Elementary_Stream_Operation (Component_Type (T));
+
+         elsif Is_Record_Type (T) then
+            declare
+               Comp : Entity_Id;
+
+            begin
+               Comp := First_Component (T);
+               while Present (Comp) loop
+                  if Needs_Elementary_Stream_Operation (Etype (Comp)) then
+                     return True;
+                  end if;
+                  Next_Component (Comp);
+               end loop;
+               return False;
+            end;
+
+         elsif Is_Private_Type (T)
+           and then Present (Full_View (T))
+         then
+            return Needs_Elementary_Stream_Operation (Full_View (T));
+
+         else
+            return False;
+         end if;
+      end Needs_Elementary_Stream_Operation;
+
+   --  Start processing for Stream_Operation_OK
+
    begin
+
       --  Special case of a limited type extension: a default implementation
       --  of the stream attributes Read or Write exists if that attribute
       --  has been specified or is available for an ancestor type; a default
@@ -9057,6 +9110,7 @@ 
         and then not Restriction_Active (No_Dispatch)
         and then not No_Run_Time_Mode
         and then RTE_Available (RE_Tag)
+        and then not Needs_Elementary_Stream_Operation (Typ)
         and then RTE_Available (RE_Root_Stream_Type)
         and then not Is_RTE (Typ, RE_Finalization_Collection);
    end Stream_Operation_OK;