6.5 Return Statements
1/2
Syntax
2/2
2.1/2
2.2/2
Name Resolution Rules
3/2
{
AI95-00318-02}
{result subtype
(of a function)} The 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.{expected
type (expression of simple_ [partial]} {return
expression} The expression,
if any, of a return_statement
is called the return expression. {result
subtype (of a function)} The result
subtype of a function is the subtype denoted by the subtype_mark
after the reserved word return in the profile of the function.{expected
type (return expression) [partial]} The
expected type for
the expression,
if any, of a simple_return_statement a
return expression is the result type of the corresponding function.
{expected type (expression of extended_return_statement)
[partial]} The expected type for the expression
of an extended_return_statement
is that of the return_subtype_indication.
3.a
To be honest: The same applies to generic
functions.
Legality Rules
4/2
{
AI95-00318-02}
{apply (to a callable
construct by a return statement)} {apply
(to a callable construct by a return_statement)} A
return statement return_statement
shall be within a callable construct, and it
applies to the innermost
callable construct or extended_return_statement
that contains it one. A
return
statement return_statement
shall not be within a body that is within the construct to which the
return statement return_statement
applies.
5/2
5.a/2
Reason: {
AI95-00318-02}
The requirement that a function body has to have at least one
return
statement return_statement
is a “helpful” restriction. There
has was
been some interest in lifting this restriction, or allowing a raise statement
to substitute for the
return statement return_statement.
However, there was enough interest in leaving it as is that we decided
not to change it.
5.b/2
5.1/2
5.2/2
5.3/2
5.4/2
{
AI95-00318-02}
For any return statement that applies to a function
body:
5.5/2
- {AI95-00318-02}
If the result subtype of the function is limited,
then the expression
of the return statement (if any) shall be an aggregate,
a function call (or equivalent use of an operator), or a qualified_expression
or parenthesized expression whose operand is one of these.
5.c/2
Discussion: In
other words, if limited, the expression
must produce a “new” object, rather than being the name of
a preexisting object (which would imply copying).
5.6/2
- {AI95-00416-01}
If the result subtype of the function is class-wide,
the accessibility level of the type of the expression
of the return statement shall not be statically deeper than that of the
master that elaborated the function body. If the result subtype has one
or more unconstrained access discriminants, the accessibility level of
the anonymous access type of each access discriminant, as determined
by the expression
of the simple_return_statement
or the return_subtype_indication,
shall not be statically deeper than that of the master that elaborated
the function body.
5.d/2
Discussion: We
know that if the result type is class wide, then there must be an expression
of the return statement. Similarly, if the result subtype is unconstrained,
then either the return_subtype_indication
(if any) is constrained, or there must be an expression.
Static Semantics
5.7/2
Dynamic Semantics
5.8/2
{
AI95-00318-02}
{
AI95-00416-01}
{execution (extended_return_statement)
[partial]} For 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 might raise
Constraint_Error — see 4.6{implicit
subtype conversion (function return) [partial]} );
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.{creation (of a
return object) [partial]}
5.e/2
Ramification: If
the result type is controlled or has a controlled part, appropriate calls
on Initialize or Adjust are performed prior to executing the handled_sequence_of_statements,
except when the initial expression is an aggregate
(which requires build-in-place with no call on Adjust).
5.f/2
6/2
{
AI95-00318-02}
{execution (simple_
[partial]} {execution
(return_statement) [partial]} For
the execution of a
simple_return_statement return_statement,
the
expression
(if any) is first evaluated
, and converted to the result subtype
, and
then is assigned to the anonymous return object. {return
object (simple_ [partial]} .
{implicit subtype conversion (function
return) [partial]}
6.a
Ramification: The conversion might raise
Constraint_Error — (see
4.6).
7/2
{
AI95-00318-02}
{
AI95-00416-01}
[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 is class-wide, then the tag of the result is the tag
of the value of the expression.
7.a/2
Proof: This is
specified by the rules in 9.2.
7.b/2
Reason: Only the
caller can know when task activations should take place, as it depends
on the context of the call. If the function is being used to initialize
the component of some larger object, then that entire object must be
initialized before any task activations. Even after the outer object
is fully initialized, task activations are still postponed until the
begin at the end of the declarative part if the function is being
used to initialize part of a declared object.
8/2
{
AI95-00318-02}
{
AI95-00344-01}
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. A check is made that the accessibility level of the type
identified by the tag of the result is not deeper than that of the master
that elaborated the function body. If this check fails, Program_Error
is raised.{Program_Error (raised by failure
of run-time check)} {Accessibility_Check
[partial]} {check,
language-defined (Accessibility_Check)} :
8.a/2
Ramification: {
AI95-00318-02}
The first sentence is true even if the tag of the
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 aggregates
and function calls (and no conversions), the tag will already match.
8.b/2
Reason: {
AI95-00318-02}
The first rule ensures that a function whose result
type is a specific tagged type always returns an object whose tag is
that of the result type. This is important for dispatching on controlling
result, and allows the caller to allocate the appropriate amount of space
to hold the value being returned (assuming there are no discriminants).
8.c/2
The check prevents the
returned object from outliving its type. Note that this check cannot
fail for a specific tagged type, as the tag represents the function's
type, which necessarily must be declared outside of the function.
Paragraphs
9 through 20 were deleted.
9/2
- {AI95-00318-02}
{Tag_Check
[partial]} {check,
language-defined (Tag_Check)} If it is
limited, then a check is made that the tag of the value of the return
expression identifies the result type. {Constraint_Error
(raised by failure of run-time check)} Constraint_Error
is raised if this check fails.
10/2
- {AI95-00318-02}
If it is nonlimited, then the tag of the result
is that of the result type.
10.a/2
Ramification: {
AI95-00318-02}
This is true even if the tag of the return expression
is different.
10.b/2
Reason: {
AI95-00318-02}
These rules ensure that a function whose result
type is a specific tagged type always returns an object whose tag is
that of the result type. This is important for dispatching on controlling
result, and, if nonlimited, allows the caller to allocate the appropriate
amount of space to hold the value being returned (assuming there are
no discriminants).
11/2
{
AI95-00318-02}
{return-by-reference
type} A type is a return-by-reference
type if it is a descendant of one of the following:
12/2
13/2
14/2
- {AI95-00318-02}
a nonprivate type with the reserved word limited
in its declaration;
15/2
- {AI95-00318-02}
a composite type with a subcomponent of a return-by-reference
type;
16/2
- {AI95-00318-02}
a private type whose full type is a return-by-reference
type.
16.a/2
Ramification: The
above rules are such that there are no "Ada 83" types other
than those containing tasks that are return-by-reference. This helps
to minimize upward incompatibilities relating to return-by-reference.
17/2
{
AI95-00318-02}
{Accessibility_Check
[partial]} {check,
language-defined (Accessibility_Check)} If
the result type is a return-by-reference type, then a check is made that
the return expression is one of the following:
18/2
- {AI95-00318-02}
a name
that denotes an object view whose accessibility level is not deeper than
that of the master that elaborated the function body; or
18.a/2
Discussion: {
AI95-00316-01}
This rule was unnecessarily confusing, and the
parenthetical remark "(or a value with an associated object, see
6.2)" was added — and then the entire concept was deleted.
19/2
20/2
{
AI95-00318-02}
{Program_Error
(raised by failure of run-time check)} The
exception Program_Error is raised if this check fails.
20.a/2
Discussion: Compare
the definition of return-by-reference with that of by-reference.
20.b/2
The return-by-reference
types are all limited types except those that are limited only because
of a limited private type with a nonlimited untagged full type.
20.c/2
Reason: {generic
contract issue [partial]} This check can often
be performed at compile time. It is defined to be a run-time check to
avoid generic contract model problems. In a future version of the standard,
we anticipate that function return of a local variable will be illegal
for all limited types, eliminating the need for the run-time check except
for dereferences of an access parameter.
21/2
{
AI95-00318-02}
{
AI95-00402-01}
{
AI95-00416-01}
If the result subtype of a function has one or
more unconstrained access discriminants, 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 function, is not deeper than that of the master that elaborated
the function body. If this check fails, Program_Error is raised. {Program_Error
(raised by failure of run-time check)} {Accessibility_Check
[partial]} {check,
language-defined (Accessibility_Check)} For
a function with a return-by-reference result type the result is returned
by reference; that is, the function call denotes a constant view of the
object associated with the value of the return expression. {assignment
operation (during execution of a return_statement)} For
any other function, the result is returned by copy; that is, the converted
value is assigned into an anonymous constant created at the point of
the return_statement,
and the function call denotes that object.
21.a/2
21.b/2
Reason: The check
prevents the returned object (for a nonlimited type) from outliving the
object designated by one of its discriminants. The check is made on the
values of the discriminants, which may come from the return_subtype_indication
(if constrained), or the expression,
but it is never necessary to check both.
22/2
23/2
Implementation Permissions
24/2
{
AI95-00416-01}
If the result subtype of a function is unconstrained,
and a call on the function is used to provide the initial value of an
object with a constrained nominal subtype, Constraint_Error may be raised
at the point of the call (after abandoning the execution of the function
body) if, while elaborating the return_subtype_indication
or evaluating the expression
of a return statement that applies to the function body, it is determined
that the value of the result will violate the constraint of the subtype
of this object.
24.a/2
Reason: Without
such a permission, it would be very difficult to implement “build-in-place”
semantics. Such an exception is not handleable within the function, because
in the return-by-copy case, the constraint check to verify that the result
satisfies the constraints of the object being initialized happens after
the function returns, and we want the semantics to change as little as
possible when switching between return-by-copy and build-in-place. This
implies further that upon detecting such a situation, the implementation
may need to simulate a goto to a point outside any local exception handlers
prior to raising the exception.
24.b/2
Examples
25
Examples of return
statements:
26/2
27
return Key_Value(Last_Index); -- in a function body
28/2
{
AI95-00318-02}
return 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
28.a/2
{
AI95-00318-02}
{
incompatibilities with Ada 83}
In Ada 95,
if the result type of a function has a part that is a task, then an attempt
to return a local variable will raise Program_Error.
This
is illegal in Ada 2005, see below. In Ada 83, if a function returns
a local variable containing a task, execution is erroneous according
to AI83-00867. However, there are other situations where functions that
return tasks (or that return a variant record only one of whose variants
includes a task) are correct in Ada 83 but will raise Program_Error according
to the new rules.
28.b
The rule change was made because there will
be more types (protected types, limited controlled types) in Ada 95 for
which it will be meaningless to return a local variable, and making all
of these erroneous is unacceptable. The current rule was felt to be the
simplest that kept upward incompatibilities to situations involving returning
tasks, which are quite rare.
Wording Changes from Ada 83
28.c
This clause has been moved here from chapter
5, since it has mainly to do with subprograms.
28.d
A function now creates an anonymous object.
This is necessary so that controlled types will work.
28.e/2
28.f/2
{
AI95-00318-02}
There is no need to mention generics in the rules about where a
return
statement return_statement
can appear and what it applies to; the phrase “body of a subprogram
or generic subprogram” is syntactic, and refers exactly to “
subprogram_body”.
Incompatibilities With Ada 95
28.g/2
{
AI95-00318-02}
{incompatibilities with Ada 95}
The entire business about return-by-reference types has been dropped.
Instead, the 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.
28.h/2
We changed these rules
so that functions, combined with the new rules for limited types (7.5),
can be used as build-in-place constructors for limited types. This reduces
the differences between limited and nonlimited types, which will make
limited types useful in more circumstances.
Extensions to Ada 95
28.i/2
{
AI95-00318-02}
{extensions to Ada 95} The
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
28.j/2
{
AI95-00318-02}
The wording was updated to support anonymous access
return subtypes.
28.k/2
28.l/2
{
AI95-00344-01}
{
AI95-00416-01}
Added accessibility checks to class-wide return
statements. These checks could not fail in Ada 95 (as all of the types
had to be declared at the same level, so the tagged type would necessarily
have been at the same level as the type of the object).
28.m/2
{
AI95-00402-01}
{
AI95-00416-01}
Added accessibility checks to return statements
for types with access discriminants. Since such types have to be limited
in Ada 95, the expression
of a return statement would have been illegal in order for this check
to fail.
28.n/2
{
AI95-00416-01}
Added an Implementation Permission allowing early
raising of Constraint_Error if the result cannot fit in the ultimate
object. This gives implementations more flexibility to do built-in-place
returns, and is essential for limited types (which cannot be built in
a temporary).