244 lines
13 KiB
Markdown
244 lines
13 KiB
Markdown
[stmt.jump]
|
||
|
||
# 8 Statements [[stmt]](./#stmt)
|
||
|
||
## 8.8 Jump statements [stmt.jump]
|
||
|
||
### [8.8.1](#general) General [[stmt.jump.general]](stmt.jump.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L988)
|
||
|
||
Jump statements unconditionally transfer control[.](#general-1.sentence-1)
|
||
|
||
[jump-statement:](#nt:jump-statement "8.8.1 General [stmt.jump.general]")
|
||
break ;
|
||
continue ;
|
||
return [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]")opt ;
|
||
[*coroutine-return-statement*](#nt:coroutine-return-statement "8.8.5 The co_return statement [stmt.return.coroutine]")
|
||
goto [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ;
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1007)
|
||
|
||
[*Note [1](#general-note-1)*:
|
||
|
||
On exit from a scope (however accomplished), objects with [automatic storage
|
||
duration](basic.stc.auto "6.8.6.4 Automatic storage duration [basic.stc.auto]") that have been constructed in that scope are destroyed
|
||
in the reverse order of their construction ([[stmt.dcl]](stmt.dcl "8.10 Declaration statement"))[.](#general-2.sentence-1)
|
||
|
||
For temporaries, see [[class.temporary]](class.temporary "6.8.7 Temporary objects")[.](#general-2.sentence-2)
|
||
|
||
However, the program can be terminated (by callingstd::exit() orstd::abort() ([[support.start.term]](support.start.term "17.5 Startup and termination")), for example) without
|
||
destroying objects with automatic storage duration[.](#general-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#general-note-2)*:
|
||
|
||
A suspension of a coroutine ([[expr.await]](expr.await "7.6.2.4 Await")) is not considered to be an exit from a scope[.](#general-2.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
### [8.8.2](#stmt.break) The break statement [[stmt.break]](stmt.break)
|
||
|
||
[1](#stmt.break-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1031)
|
||
|
||
A break statement shall be enclosed by ([[stmt.pre]](stmt.pre "8.1 Preamble"))an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1 General [stmt.iter.general]") ([[stmt.iter]](stmt.iter "8.6 Iteration statements")),
|
||
an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7 Expansion statements [stmt.expand]") ([[stmt.expand]](stmt.expand "8.7 Expansion statements")), or
|
||
a switch statement ([[stmt.switch]](stmt.switch "8.5.3 The switch statement"))[.](#stmt.break-1.sentence-1)
|
||
|
||
The break statement causes
|
||
termination of the innermost such enclosing statement;
|
||
control passes to the statement following the
|
||
terminated statement, if any[.](#stmt.break-1.sentence-2)
|
||
|
||
### [8.8.3](#stmt.cont) The continue statement [[stmt.cont]](stmt.cont)
|
||
|
||
[1](#stmt.cont-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1046)
|
||
|
||
A continue statement shall be enclosed by ([[stmt.pre]](stmt.pre "8.1 Preamble"))an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1 General [stmt.iter.general]") or an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7 Expansion statements [stmt.expand]")[.](#stmt.cont-1.sentence-1)
|
||
|
||
If the innermost enclosing such statement X is an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1 General [stmt.iter.general]") ([[stmt.iter]](stmt.iter "8.6 Iteration statements")),
|
||
the continue statement
|
||
causes control to pass to the end of the [*statement*](stmt.pre#nt:statement "8.1 Preamble [stmt.pre]") or [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of X[.](#stmt.cont-1.sentence-2)
|
||
|
||
Otherwise, control passes to the end of the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of the current Si ([[stmt.expand]](stmt.expand "8.7 Expansion statements"))[.](#stmt.cont-1.sentence-3)
|
||
|
||
### [8.8.4](#stmt.return) The return statement [[stmt.return]](stmt.return)
|
||
|
||
[1](#stmt.return-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1063)
|
||
|
||
A function returns control to its caller by the return statement[.](#stmt.return-1.sentence-1)
|
||
|
||
[2](#stmt.return-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1066)
|
||
|
||
The [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]") of a return statement is called its operand[.](#stmt.return-2.sentence-1)
|
||
|
||
A return statement with
|
||
no operand shall be used only in a function whose return type iscv void, a constructor ([[class.ctor]](class.ctor "11.4.5 Constructors")), or a
|
||
destructor ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#stmt.return-2.sentence-2)
|
||
|
||
A return statement with an operand of type void shall be used only
|
||
in a function that has a cv void return type[.](#stmt.return-2.sentence-3)
|
||
|
||
A return statement with any other operand shall be used only
|
||
in a function that has a return type other than cv void;the return statement initializes the
|
||
returned reference or prvalue result object
|
||
of the (explicit or implicit) function call
|
||
by [copy-initialization](dcl.init#def:copy-initialization "9.5 Initializers [dcl.init]") from the operand[.](#stmt.return-2.sentence-4)
|
||
|
||
[*Note [1](#stmt.return-note-1)*:
|
||
|
||
A constructor or destructor does not have a return type[.](#stmt.return-2.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#stmt.return-note-2)*:
|
||
|
||
A return statement can involve
|
||
an invocation of a constructor to perform a copy or move of the operand
|
||
if it is not a prvalue or if its type differs from the return type of the function[.](#stmt.return-2.sentence-6)
|
||
|
||
A copy operation associated with a return statement can be elided or
|
||
converted to a move operation if an automatic storage duration variable is returned ([[class.copy.elision]](class.copy.elision "11.9.6 Copy/move elision"))[.](#stmt.return-2.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[3](#stmt.return-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1094)
|
||
|
||
The destructor for the result object
|
||
is potentially invoked ([[class.dtor]](class.dtor "11.4.7 Destructors"), [[except.ctor]](except.ctor "14.3 Stack unwinding"))[.](#stmt.return-3.sentence-1)
|
||
|
||
[*Example [1](#stmt.return-example-1)*: class A {~A() {}};
|
||
A f() { return A(); } // error: destructor of A is private (even though it is never invoked) â *end example*]
|
||
|
||
[4](#stmt.return-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1106)
|
||
|
||
Flowing off the end of
|
||
a constructor,
|
||
a destructor, or
|
||
a non-coroutine function with a cv void return type is
|
||
equivalent to a return with no operand[.](#stmt.return-4.sentence-1)
|
||
|
||
Otherwise, flowing off the end of a function
|
||
that is neither main ([[basic.start.main]](basic.start.main "6.10.3.1 main function")) nor a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))
|
||
results in undefined behavior[.](#stmt.return-4.sentence-2)
|
||
|
||
[5](#stmt.return-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1116)
|
||
|
||
The copy-initialization of the result of the call is sequenced before the
|
||
destruction of temporaries at the end of the full-expression established
|
||
by the operand of the return statement, which, in turn, is sequenced
|
||
before the destruction of local variables ([stmt.jump]) of the block
|
||
enclosing the return statement[.](#stmt.return-5.sentence-1)
|
||
|
||
[*Note [3](#stmt.return-note-3)*:
|
||
|
||
These operations
|
||
are sequenced before the destruction of local variables
|
||
in each remaining enclosing block of the function ([[stmt.dcl]](stmt.dcl "8.10 Declaration statement")),
|
||
which, in turn,
|
||
is sequenced before the evaluation of
|
||
postcondition assertions of the function ([[dcl.contract.func]](dcl.contract.func "9.4.1 General")),
|
||
which, in turn,
|
||
is sequenced before the destruction of function parameters ([[expr.call]](expr.call "7.6.1.3 Function call"))[.](#stmt.return-5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[6](#stmt.return-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1133)
|
||
|
||
In a function whose return type is a reference,
|
||
other than an invented function for std::is_convertible ([[meta.rel]](meta.rel "21.3.8 Relationships between types")),
|
||
a return statement that binds the returned reference to
|
||
a temporary expression ([[class.temporary]](class.temporary "6.8.7 Temporary objects")) is ill-formed[.](#stmt.return-6.sentence-1)
|
||
|
||
[*Example [2](#stmt.return-example-2)*: auto&& f1() {return 42; // ill-formed}const double& f2() {static int x = 42; return x; // ill-formed}auto&& id(auto&& r) {return static_cast<decltype(r)&&>(r);}auto&& f3() {return id(42); // OK, but probably a bug} â *end example*]
|
||
|
||
### [8.8.5](#stmt.return.coroutine) The co_return statement [[stmt.return.coroutine]](stmt.return.coroutine)
|
||
|
||
[coroutine-return-statement:](#nt:coroutine-return-statement "8.8.5 The co_return statement [stmt.return.coroutine]")
|
||
co_return [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]")opt ;
|
||
|
||
[1](#stmt.return.coroutine-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1165)
|
||
|
||
A co_return statement transfers control to
|
||
the caller or resumer of a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#stmt.return.coroutine-1.sentence-1)
|
||
|
||
A coroutine shall not enclose
|
||
a return statement ([[stmt.return]](#stmt.return "8.8.4 The return statement"))[.](#stmt.return.coroutine-1.sentence-2)
|
||
|
||
[*Note [1](#stmt.return.coroutine-note-1)*:
|
||
|
||
For this determination, it is irrelevant whether the return statement
|
||
is enclosed by a discarded statement ([[stmt.if]](stmt.if "8.5.2 The if statement"))[.](#stmt.return.coroutine-1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[2](#stmt.return.coroutine-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1175)
|
||
|
||
The [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]") of a co_return statement is
|
||
called its operand[.](#stmt.return.coroutine-2.sentence-1)
|
||
|
||
Let *p* be an lvalue naming the coroutine
|
||
promise object ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#stmt.return.coroutine-2.sentence-2)
|
||
|
||
A co_return statement is equivalent to:
|
||
|
||
{ S; goto *final-suspend*; }
|
||
|
||
where *final-suspend* is the exposition-only label
|
||
defined in [[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions") and *S* is defined as follows:
|
||
|
||
- [(2.1)](#stmt.return.coroutine-2.1)
|
||
|
||
If the operand is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") or an expression of non-void type,*S* is *p*.return_value([*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]"))[.](#stmt.return.coroutine-2.1.sentence-1)
|
||
The expression *S* shall be a prvalue of type void[.](#stmt.return.coroutine-2.1.sentence-2)
|
||
|
||
- [(2.2)](#stmt.return.coroutine-2.2)
|
||
|
||
Otherwise,*S* is the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") { [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")opt ; *p*.return_void(); }[.](#stmt.return.coroutine-2.2.sentence-1)
|
||
The expression *p*.return_void() shall be a prvalue of type void[.](#stmt.return.coroutine-2.2.sentence-2)
|
||
|
||
[3](#stmt.return.coroutine-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1200)
|
||
|
||
If a search for the name return_void in the scope of the promise type
|
||
finds any declarations,
|
||
flowing off the end of a coroutine's [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") is equivalent to a co_return with no operand;
|
||
otherwise flowing off the end of a coroutine's [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") results in undefined behavior[.](#stmt.return.coroutine-3.sentence-1)
|
||
|
||
### [8.8.6](#stmt.goto) The goto statement [[stmt.goto]](stmt.goto)
|
||
|
||
[1](#stmt.goto-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1211)
|
||
|
||
The goto statement unconditionally transfers control to the
|
||
statement labeled by the identifier[.](#stmt.goto-1.sentence-1)
|
||
|
||
The identifier shall be a[label](stmt.label "8.2 Label [stmt.label]") located in the current function[.](#stmt.goto-1.sentence-2)
|