6.5 Return Statements
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
A simple_return_statement
or extended_return_statement
(collectively called a return statement) is used to complete the execution of the innermost enclosing subprogram_body
, entry_body
, or accept_statement
.
Syntax
2/2simple_return_statement
::=
return [expression
];
2.1/5extended_return_object_declaration
::=
defining_identifier
: [aliased][constant] return_subtype_indication
[:= expression
]
[aspect_specification
]
2.2/3extended_return_statement
::=
return extended_return_object_declaration
[do
handled_sequence_of_statements
end return];
2.3/2return_subtype_indication
::=
subtype_indication
| access_definition
Name Resolution Rules
3/5The result subtype of a function is the subtype denoted by the subtype_mark
, or defined by the access_definition
, after the reserved word return in the profile of the function. The expected type for the expression
, if any, of a simple_return_statement
is the result type of the corresponding function. The expected type for the expression
of an extended_return_object_declaration
is that of the return_subtype_indication
.
Legality Rules
4/2A return statement shall be within a callable construct, and it applies to the innermost callable construct or extended_return_statement
that contains it. A return statement shall not be within a body that is within the construct to which the return statement applies.
A function body shall contain at least one return statement that applies to the function body, unless the function contains code_statement
s. A simple_return_statement
shall include an expression
if and only if it applies to a function body. An extended_return_statement
shall apply to a function body. An extended_return_object_declaration
with the reserved word constant shall include an expression
.
raise_expression
can be given in any function body (the raise_expression
will match any type), so there is much less need to eliminate this rule. extended_return_statement
, so a simple_return_statement
without an expression
can be given in one. However, neither simple_return_statement
with an expression
nor an extended_return_statement
can be given inside an extended_return_statement
, as they must apply (directly) to a function body.The expression
of an extended_return_statement
is the expression
(if any) of the extended_return_object_declaration
of the extended_return_statement
.
expression
of a return statement is either the expression
of a simple_return_statement
or the expression
of an extended_return_statement
as defined above. For an extended_return_statement
that applies to a function body:
- If the result subtype of the function is defined by a
subtype_mark
, thereturn_subtype_indication
shall be asubtype_indication
. The type of thesubtype_indication
shall be covered by the result type of the function. The subtype defined by thesubtype_indication
shall be statically compatible with the result subtype of the function; if the result type of the function is elementary, the two subtypes shall statically match. If the result subtype of the function is indefinite, then the subtype defined by thesubtype_indication
shall be a definite subtype, or there shall be anexpression
. 5.4/5 - If the result subtype of the function is defined by an
access_definition
, thereturn_subtype_indication
shall be anaccess_definition
. The subtype defined by theaccess_definition
shall statically match the result subtype of the function. [The accessibility level of this anonymous access subtype is that of the result subtype.]
- If the result subtype of the function is class-wide, the accessibility level of the type of the subtype defined by the
return_subtype_indication
shall not be statically deeper than that of the master that elaborated the function body.
return_subtype_indication
could be a specific type initialized by default; in that case there is no expression
to check. For any return statement that applies to a function body:
- [If the result subtype of the function is limited, then the
expression
of the return statement (if any) shall meet the restrictions described in 7.5.]
- If the result subtype of the function is class-wide, the accessibility level of the type of the
expression
(if any) of the return statement shall not be statically deeper than that of the master that elaborated the function body.
expression
of the return statement unless this is an extended_return_statement
whose return_subtype_indication
is a specific type. We have a separate rule to cover that case. Note that if an extended_return_statement
has an expression
, then both this rule and the next one must be satisfied. - If the subtype determined by the
expression
of thesimple_return_statement
or by thereturn_subtype_indication
has one or more access discriminants, the accessibility level of the anonymous access type of each access discriminant shall not be statically deeper than that of the master that elaborated the function body.
If the reserved word aliased is present in an extended_return_object_declaration
, the type of the extended return object shall be immutably limited.
Static Semantics
5.11/5Within an extended_return_statement
, the return object is declared with the given defining_identifier
, with the nominal subtype defined by the return_subtype_indication
. An extended_return_statement
with the reserved word constant is a full constant declaration that declares the return object to be a constant object.
Dynamic Semantics
5.12/5For the execution of an extended_return_statement
, the subtype_indication
or access_definition
is elaborated. This creates the nominal subtype of the return object. If there is an expression
, it is evaluated and converted to the nominal subtype (which can raise Constraint_Error — see 4.6); the return object is created and the converted value is assigned to the return object. Otherwise, the return object is created and initialized by default as for a stand-alone object of its nominal subtype (see 3.3.1). If the nominal subtype is indefinite, the return object is constrained by its initial value. A check is made that the value of the return object belongs to the function result subtype. Constraint_Error is raised if this check fails.
handled_sequence_of_statements
, except when the initial expression is an aggregate
(which requires build-in-place with no call on Adjust).expression
or the handled_sequence_of_statements
, or a goto out of the handled_sequence_of_statements
), if the return object has been created, it is finalized prior to leaving the return statement. If it has not been created when the return statement is left, it is not created or finalized.For the execution of a simple_return_statement
, the expression
(if any) is first evaluated, converted to the result subtype, and then is assigned to the anonymous return object.
[If the return object has any parts that are tasks, the activation of those tasks does not occur until after the function returns (see 9.2).]
If the result type of a function is a specific tagged type, the tag of the return object is that of the result type. If the result type is class-wide, the tag of the return object is that of the value of the expression
of the return statement, unless the return object is defined by an extended_return_object_declaration
with a subtype_indication
that is specific, in which case it is that of the type of the subtype_indication
. A check is made that the master of the type identified by the tag of the result includes the elaboration of the master that elaborated the function body. If this check fails, Program_Error is raised.
expression
is different, which could happen if the expression
were a view conversion or a dereference of an access value. Note that for a limited type, because of the restriction to aggregate
s and function calls (and no conversions), the tag will already match. For the execution of an extended_return_statement
, the handled_sequence_of_statements
is executed. Within this handled_sequence_of_statements
, the execution of a simple_return_statement
that applies to the extended_return_statement
causes a transfer of control that completes the extended_return_statement
. Upon completion of a return statement that applies to a callable construct by the normal completion of a simple_return_statement
or by reaching the end return of an extended_return_statement
, a transfer of control is performed which completes the execution of the callable construct, and returns to the caller.
extended_return_statement
(such as an exit or goto) does not cause a return to the caller unless it is caused by simple_return_statement
(that is, triggers the second sentence of this paragraph). The return to the caller occurs for the simple_return_statement
that applies to an extended_return_statement
because the last sentence says “the normal completion of a simple_return_statement
”, which includes the one nested in the extended_return_statement
.sequence_of_statements
); the checks which follow occur after the execution of any sequence_of_statements
. This is implicit in the order of definition of these Dynamic Semantics. If the result subtype of the function is defined by an access_definition
designating a specific tagged type T, a check is made that the result value is null or the tag of the object designated by the result value identifies T. Constraint_Error is raised if this check fails.
Paragraphs 9 through 20 were deleted.
If any part of the specific type of the return object of a function (or coextension thereof) has one or more access discriminants whose value is not constrained by the result subtype of the function, a check is made that the accessibility level of the anonymous access type of each access discriminant, as determined by the expression
or the return_subtype_indication
of the return statement, is not deeper than the level of the master of the call (see 3.10.2). If this check fails, Program_Error is raised.
return_subtype_indication
(if constrained), or the expression
, but it is never necessary to check both. expression
or return_subtype_indication
of a return statement).type Global is access T'Class;
function F (Ptr : Global) return T'Class is
begin
return Ptr.all;
end F;
function F return T'Class is
Local : T'Class := ... ;
begin
return Local;
end F;
X : aliased Integer;
21.n/3type Component_Type (Discrim : access Integer := X'Access)
is limited null record;
21.o/3type Undiscriminated is record
Fld : Component_Type;
end record;
21.p/3function F return Undiscriminated is
Local : aliased Integer;
begin
return X : Undiscriminated := (Fld => (Discrim => Local'Access)) do
Foo;
end return;
-- raises Program_Error after calling Foo.
end F;
A check is performed that the return value satisfies the predicates of the return subtype. If this check fails, the effect is as defined in subclause 3.2.4, “Subtype Predicates”.
simple_return_statement
performs this same check. The permissions of 11.4.2 ensure that duplicate evaluation of a predicate at a single point is not required (other than pathological, not portable cases), so a single evaluation of the predicate is enough in this case. In the case of a function, the function_call
denotes a constant view of the return object.
Implementation Permissions
24/3For a function call used to initialize a composite object with a constrained nominal subtype or used to initialize a return object that is built in place into such an object:
- If the result subtype of the function is constrained, and conversion of an object of this subtype to the subtype of the object being initialized would raise Constraint_Error, then Constraint_Error may be raised before calling the function.
- If the result subtype of the function is unconstrained, and a return statement is executed such that the return object is known to be constrained, and conversion of the return object to the subtype of the object being initialized would raise Constraint_Error, then Constraint_Error may be raised at the point of the call (after abandoning the execution of the function body).
Examples
25Examples of return statements:
return; -- in a procedure body, entry_body,
-- accept_statement, or extended_return_statement
27return Key_Value(Last_Index); -- in a function body
28/2return Node : Cell do -- in a function body, see 3.10.1 for Cell
Node.Value := Result;
Node.Succ := Next_Node;
end return;
Incompatibilities With Ada 83
Wording Changes from Ada 83
subprogram_body
”. Inconsistencies With Ada 95
Incompatibilities With Ada 95
expression
of a return statement of a limited type can only be an aggregate
or function_call
(see 7.5). This means that returning a global object or type_conversion
, legal in Ada 95, is now illegal. Such functions can be converted to use anonymous access return types by adding access in the function definition and return statement, adding .all in uses, and adding aliased in the object declarations. This has the advantage of making the reference return semantics much clearer to the casual reader.Extensions to Ada 95
extended_return_statement
is new. This provides a name for the object being returned, which reduces the copying needed to return complex objects (including no copying at all for limited objects). It also allows component-by-component construction of the return object. Wording Changes from Ada 95
expression
of an extended_return_statement
.expression
of a return statement would have been illegal in order for this check to fail. Inconsistencies With Ada 2005
Incompatibilities With Ada 2005
allocator
if necessary, and still must be given there even if given on the return object) or wrong (null exclusions – null could be returned from a function declared to be null excluding), so we expect them to be extremely rare in practice. Extensions to Ada 2005
extended_return_statement
can be declared constant; this works similarly to a constant object declaration.return_subtype_indication
to have a specific type if the return subtype of the function is class-wide. Specifying the (specific) type of the return object is awkward without this change, and this is consistent with the way allocator
s work. Wording Changes from Ada 2005
extended_return_statement
s, since leaving by an exit or goto is considered “normal” completion of the statement.extended_return_object_declaration
to make other rules easier to write and eliminate the problem described in AI05-0205-1. Inconsistencies With Ada 2012
sequence_of_statements
of an extended_return_statement
, and to add an additional predicate check on the returned value. This latter check can fail if the value to be returned is changed in the statements of an extended return. Thus, the following function now raises Assertion_Error, while no exception would be raised in Ada 2012: type Rec is record
Count, Max : Natural;
end record with Dynamic_Predicate => Rec.Count <= Rec.Max;
28.z/5function Foo return Rec is
begin
return Result : Rec := (Count => 5, Max => 10) do
Result.Max := 0;
end return;
end Foo;
Extensions to Ada 2012
aspect_specification
, allowing the specification of (implementation-defined) aspects for return objects. Wording Changes from Ada 2012
subtype_indication
to provide the tag in the case of a simple_return_statement
), such a reading would be so unlike the rest of the language that we do not believe anyone would ever have thought it was intended. As such, we do not believe any implementation ever did this wrong (at least because of the old wording), and thus do not document this as a possible inconsistency.expression
of an extended_return_statement
. That wording was commonly used before the extended_return_object_declaration
was split into a separate syntax production, leaving the extended_return_statement
without any expression
of its own. Moreover, the wording often just uses “expression
of a return statement” to cover both kinds of return statement. Changing the wording in more than a dozen places was unappealing, and some of the changes would be awkward to read, so we defined the term and left the majority of the wording unchanged. 6.5.1 Nonreturning Subprograms
1/5Specifying aspect No_Return to have the value True indicates that a subprogram cannot return normally[; it may, for example, propagate an exception or loop forever].
Paragraphs 2 and 3 were moved to Annex J, “Obsolescent Features”.
Static Semantics
3.1/5For a subprogram or generic subprogram , the following language-defined representation aspect may be specified:
No_Return
- The type of aspect No_Return is Boolean. When aspect No_Return is True for an entity, the entity is said to be nonreturning.
- If directly specified, the
aspect_definition
shall be a static expression. When not directly specified, if the subprogram is a primitive subprogram inherited by a derived type, then the aspect is True if any corresponding subprogram of the parent or progenitor types is nonreturning. Otherwise , the aspect is False.
If a generic subprogram is nonreturning, then so are its instances. If a subprogram declared within a generic unit is nonreturning, then so are the corresponding copies of that subprogram in instances.
Legality Rules
4/3Aspect No_Return shall not be specified for a null procedure nor an instance of a generic unit.
A return statement shall not apply to a nonreturning procedure or generic procedure.
Any return statement that applies to a nonreturning function or generic function shall be a simple_return_statement
with an expression
that is a raise_expression
, a call on a nonreturning function, or a parenthesized expression
of one of these.
A subprogram shall be nonreturning if it overrides a dispatching nonreturning subprogram . In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
If a renaming-as-body completes a nonreturning subprogram declaration, then the renamed subprogram shall be nonreturning.
Paragraph 8 was deleted.
Dynamic Semantics
9/2If the body of a nonreturning procedure completes normally, Program_Error is raised at the point of the call.
Examples
10/5Example of a specification of a No_Return aspect:
procedure Fail(Msg : String) -- raises Fatal_Error exception
with No_Return;
-- Inform compiler and reader that procedure never returns normally