In Ada 2005, several constructs of a limited type can be built in place, and
as such can be returned by function calls. In Ada 2012, the new expression forms
conditional expressions and case expressions can also be built in place if each
of their dependent expressions can be built in place.

The following must compile and execute quietly:

---
procedure Lim is
   type T is limited record
      Value  : Integer;
   end record;

   function Build (X : integer) return T is
   begin
      return (if X > 10 then (Value => X / 2) else  (Value => 0));
   end;
   THing : T := Build (12);

   function Build2 (X : Integer) return T is
   begin
     return (case X is
               when 1..10  =>  (value => 2 * X),
               when others => (Value => 0));
   end;

  Thing2 : T := Build2 (9);
begin
   if THing.Value /= 6 then
      raise Program_Error;
   end if;

   if THing2.Value /= 18 then
      raise Program_Error;
   end if;
end;

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

2011-10-13  Ed Schonberg  <schonb...@adacore.com>

        * sem_ch3.adb (OK_For_Limited_Init_In_05): Conditional and case
        expressions are legal limited return values if each one of their
        dependent expressions are legal.

Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb (revision 179898)
+++ sem_ch3.adb (working copy)
@@ -16889,6 +16889,38 @@
          when N_Attribute_Reference =>
             return Attribute_Name (Original_Node (Exp)) = Name_Input;
 
+         --  For a conditional expression, all dependent expressions must be
+         --  legal constructs.
+
+         when N_Conditional_Expression =>
+            declare
+               Then_Expr : constant Node_Id :=
+                 Next
+                   (First (Expressions (Original_Node (Exp))));
+               Else_Expr : constant Node_Id := Next (Then_Expr);
+
+            begin
+               return OK_For_Limited_Init_In_05 (Typ, Then_Expr)
+                 and then OK_For_Limited_Init_In_05 (Typ, Else_Expr);
+            end;
+
+         when N_Case_Expression =>
+            declare
+               Alt : Node_Id;
+
+            begin
+               Alt := First (Alternatives (Original_Node (Exp)));
+               while Present (Alt) loop
+                  if not OK_For_Limited_Init_In_05 (Typ, Expression (Alt)) then
+                     return False;
+                  end if;
+
+                  Next (Alt);
+               end loop;
+
+               return True;
+            end;
+
          when others =>
             return False;
       end case;

Reply via email to