Patchwork [Ada] Conditional and case expressions are legal return values

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 13, 2011, 10:35 a.m.
Message ID <20111013103502.GA28871@adacore.com>
Download mbox | patch
Permalink /patch/119407/
State New
Headers show

Comments

Arnaud Charlet - Oct. 13, 2011, 10:35 a.m.
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  <schonberg@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.

Patch

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;