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;