This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

93
cppdraft/stmt/ambig.md Normal file
View File

@@ -0,0 +1,93 @@
[stmt.ambig]
# 8 Statements [[stmt]](./#stmt)
## 8.11 Ambiguity resolution [stmt.ambig]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1367)
There is an ambiguity in the grammar involving[*expression-statement*](stmt.expr#nt:expression-statement "8.3Expression statement[stmt.expr]")*s* and [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]")*s*: An[*expression-statement*](stmt.expr#nt:expression-statement "8.3Expression statement[stmt.expr]") with a [function-style explicit type
conversion](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)[expr.type.conv]") as its leftmost subexpression can be
indistinguishable from a [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") where the first[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") starts with a ([.](#1.sentence-1)
In those cases the[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") is considered a [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]"),
except as specified below[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1377)
[*Note [1](#note-1)*:
If the [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") cannot syntactically be a[*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]"), there is no ambiguity,
so this rule does not apply[.](#2.sentence-1)
In some cases, the whole [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") needs to be examined
to determine whether this is the case[.](#2.sentence-2)
This resolves the meaning
of many examples[.](#2.sentence-3)
[*Example [1](#example-1)*:
Assuming T is a[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers")),
T(a)->m = 7; // expression-statement T(a)++; // expression-statement T(a,5)<<c; // expression-statement T(*d)(int); // declaration T(e)[5]; // declaration T(f) = { 1, 2 }; // declaration T(*g)(double(3)); // declaration
In the last example above, g, which is a pointer to T,
is initialized to double(3)[.](#2.sentence-5)
This is of course ill-formed for
semantic reasons, but that does not affect the syntactic analysis[.](#2.sentence-6)
— *end example*]
The remaining cases are [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]")*s*[.](#2.sentence-7)
[*Example [2](#example-2)*: class T {// ...public: T();
T(int);
T(int, int);};
T(a); // declaration T(*b)(); // declaration T(c)=7; // declaration T(d),e,f=3; // declarationextern int h;
T(g)(h,2); // declaration — *end example*]
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1425)
The disambiguation is purely syntactic; that is, the meaning of the
names occurring in such a statement, beyond whether they are[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")*s* or not, is not generally used in or changed by the
disambiguation[.](#3.sentence-1)
Class templates are instantiated as necessary to
determine if a qualified name is a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")[.](#3.sentence-2)
Disambiguation
precedes parsing, and a statement disambiguated as a declaration may be
an ill-formed declaration[.](#3.sentence-3)
If, during parsing, lookup finds
that a name in a template argument is bound to
(part of) the declaration being parsed,
the program is ill-formed[.](#3.sentence-4)
No diagnostic is required[.](#3.sentence-5)
[*Example [3](#example-3)*: struct T1 { T1 operator()(int x) { return T1(x); }int operator=(int x) { return x; } T1(int) { }};struct T2 { T2(int) { } };int a, (*(*b)(T2))(int), c, d;
void f() {// disambiguation requires this to be parsed as a declaration: T1(a) = 3,
T2(4), // T2 will be declared as a variable of type T1, but this will not(*(*b)(T2(c)))(int(d)); // allow the last part of the declaration to parse properly,// since it depends on T2 being a type-name} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1458)
A syntactically ambiguous statement that can syntactically be
a [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") with an outermost [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") is considered a [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") only if it starts with auto[.](#4.sentence-1)
[*Example [4](#example-4)*: struct M;struct S { S* operator()(); int N; int M; void mem(S s) {auto(s)()->M; // expression, S::M hides ::M}};
void f(S s) {{auto(s)()->N; // expressionauto(s)()->M; // function declaration}{ S(s)()->N; // expression S(s)()->M; // expression}} — *end example*]

35
cppdraft/stmt/block.md Normal file
View File

@@ -0,0 +1,35 @@
[stmt.block]
# 8 Statements [[stmt]](./#stmt)
## 8.4 Compound statement or block [stmt.block]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L243)
A [*compound statement*](#def:statement,compound "8.4Compound statement or block[stmt.block]") (also known as a block) groups a
sequence of statements into a single statement[.](#1.sentence-1)
[compound-statement:](#nt:compound-statement "8.4Compound statement or block[stmt.block]")
{ [*statement-seq*](#nt:statement-seq "8.4Compound statement or block[stmt.block]")opt [*label-seq*](#nt:label-seq "8.4Compound statement or block[stmt.block]")opt }
[statement-seq:](#nt:statement-seq "8.4Compound statement or block[stmt.block]")
[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") [*statement-seq*](#nt:statement-seq "8.4Compound statement or block[stmt.block]")opt
[label-seq:](#nt:label-seq "8.4Compound statement or block[stmt.block]")
[*label*](stmt.label#nt:label "8.2Label[stmt.label]") [*label-seq*](#nt:label-seq "8.4Compound statement or block[stmt.block]")opt
A label at the end of a [*compound-statement*](#nt:compound-statement "8.4Compound statement or block[stmt.block]") is treated as if it were followed by a null statement[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L265)
[*Note [1](#note-1)*:
A compound statement defines a block scope ([[basic.scope]](basic.scope "6.4Scope"))[.](#2.sentence-1)
A declaration is a [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") ([[stmt.dcl]](stmt.dcl "8.10Declaration statement"))[.](#2.sentence-2)
— *end note*]

20
cppdraft/stmt/break.md Normal file
View File

@@ -0,0 +1,20 @@
[stmt.break]
# 8 Statements [[stmt]](./#stmt)
## 8.8 Jump statements [[stmt.jump]](stmt.jump#stmt.break)
### 8.8.2 The break statement [stmt.break]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1031)
A break statement shall be enclosed by ([[stmt.pre]](stmt.pre "8.1Preamble"))an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]") ([[stmt.iter]](stmt.iter "8.6Iteration statements")),
an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]") ([[stmt.expand]](stmt.expand "8.7Expansion statements")), or
a switch statement ([[stmt.switch]](stmt.switch "8.5.3The switch statement"))[.](#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[.](#1.sentence-2)

19
cppdraft/stmt/cont.md Normal file
View File

@@ -0,0 +1,19 @@
[stmt.cont]
# 8 Statements [[stmt]](./#stmt)
## 8.8 Jump statements [[stmt.jump]](stmt.jump#stmt.cont)
### 8.8.3 The continue statement [stmt.cont]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1046)
A continue statement shall be enclosed by ([[stmt.pre]](stmt.pre "8.1Preamble"))an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]") or an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]")[.](#1.sentence-1)
If the innermost enclosing such statement X is an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]") ([[stmt.iter]](stmt.iter "8.6Iteration statements")),
the continue statement
causes control to pass to the end of the [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") or [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of X[.](#1.sentence-2)
Otherwise, control passes to the end of the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of the current Si ([[stmt.expand]](stmt.expand "8.7Expansion statements"))[.](#1.sentence-3)

View File

@@ -0,0 +1,39 @@
[stmt.contract.assert]
# 8 Statements [[stmt]](./#stmt)
## 8.9 Assertion statement [stmt.contract.assert]
[assertion-statement:](#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]")
contract_assert [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") ) ;
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1224)
An [*assertion-statement*](#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]") introduces a contract assertion ([[basic.contract]](basic.contract "6.11Contract assertions"))[.](#1.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the introduced contract assertion[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1232)
The predicate ([[basic.contract.general]](basic.contract.general "6.11.1General"))
of an [*assertion-statement*](#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]") is its [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") contextually converted to bool[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1238)
The evaluation of consecutive [*assertion-statement*](#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]")*s* is an evaluation in sequence ([[basic.contract.eval]](basic.contract.eval "6.11.2Evaluation")) of
the contract assertions introduced
by those [*assertion-statement*](#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]")*s*[.](#3.sentence-1)
[*Note [1](#note-1)*:
A sequence of [*assertion-statement*](#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]")*s* can thus be repeatedly evaluated as a group[.](#3.sentence-2)
[*Example [1](#example-1)*: int f(int i){contract_assert(i == 0); // #1contract_assert(i >= 0); // #2return 0;}int g = f(0); // can evaluate #1, #2, #1, #2 — *end example*]
— *end note*]

99
cppdraft/stmt/dcl.md Normal file
View File

@@ -0,0 +1,99 @@
[stmt.dcl]
# 8 Statements [[stmt]](./#stmt)
## 8.10 Declaration statement [stmt.dcl]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1262)
A declaration statement introduces one or more new names into a
block; it has the form
[declaration-statement:](#nt:declaration-statement "8.10Declaration statement[stmt.dcl]")
[*block-declaration*](dcl.pre#nt:block-declaration "9.1Preamble[dcl.pre]")
[*Note [1](#note-1)*:
If an identifier introduced by a declaration was previously declared in
an outer block,the outer declaration is hidden
for the remainder of the block ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3Unqualified name lookup")),
after which it resumes its force[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1280)
A block variable with automatic storage duration ([[basic.stc.auto]](basic.stc.auto "6.8.6.4Automatic storage duration"))
is [*active*](#def:variable,active "8.10Declaration statement[stmt.dcl]") everywhere in the scope to which it belongs
after its [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]")[.](#2.sentence-1)
Upon each transfer of control (including sequential execution of statements)
within a function from point P to point Q,
all block variables with automatic storage duration
that are active at P and not at Q are destroyed in the reverse order of their construction[.](#2.sentence-2)
Then, all block variables with automatic storage duration
that are active at Q but not at P are initialized in declaration order;
unless all such variables have vacuous initialization ([[basic.life]](basic.life "6.8.4Lifetime")),
the transfer of control shall not be a jump[.](#2.sentence-3)[73](#footnote-73 "The transfer from the condition of a switch statement to a case label is considered a jump in this respect.")
When a [*declaration-statement*](#nt:declaration-statement "8.10Declaration statement[stmt.dcl]") is executed,P and Q are the points immediately before and after it;
when a function returns, Q is after its body[.](#2.sentence-4)
[*Example [1](#example-1)*: void f() {// ...goto lx; // error: jump into scope of a// ... ly: X a = 1; // ... lx:goto ly; // OK, jump implies destructor call for a followed by// construction again immediately following label ly} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1320)
Dynamic initialization of a block variable with[static storage duration](basic.stc.static "6.8.6.2Static storage duration[basic.stc.static]") or[thread storage duration](basic.stc.thread "6.8.6.3Thread storage duration[basic.stc.thread]") is performed
the first time control passes through its declaration; such a variable is
considered initialized upon the completion of its initialization[.](#3.sentence-1)
If the
initialization exits by throwing an exception, the initialization is not
complete, so it will be tried again the next time control enters the
declaration[.](#3.sentence-2)
If control enters the declaration concurrently while the variable is
being initialized, the concurrent execution shall wait for completion
of the initialization[.](#3.sentence-3)
[*Note [2](#note-2)*:
A conforming implementation cannot introduce
any deadlock around execution of the initializer[.](#3.sentence-4)
Deadlocks might still be caused by the program logic;
the implementation need only avoid deadlocks
due to its own synchronization operations[.](#3.sentence-5)
— *end note*]
If control
re-enters the declaration recursively while
the variable is being initialized, the behavior is undefined[.](#3.sentence-6)
[*Example [2](#example-2)*: int foo(int i) {static int s = foo(2*i); // undefined behavior: recursive callreturn i+1;} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1355)
An object associated with
a block variable with static or thread storage duration
will be destroyed if and only if it was constructed[.](#4.sentence-1)
[*Note [3](#note-3)*:
[[basic.start.term]](basic.start.term "6.10.3.4Termination") describes the order in which such objects are destroyed[.](#4.sentence-2)
— *end note*]
[73)](#footnote-73)[73)](#footnoteref-73)
The transfer from the condition of a switch statement to acase label is considered a jump in this respect[.](#footnote-73.sentence-1)

24
cppdraft/stmt/do.md Normal file
View File

@@ -0,0 +1,24 @@
[stmt.do]
# 8 Statements [[stmt]](./#stmt)
## 8.6 Iteration statements [[stmt.iter]](stmt.iter#stmt.do)
### 8.6.3 The do statement [stmt.do]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L651)
The expression is [contextually converted to bool](conv#def:conversion,contextual_to_bool "7.3Standard conversions[conv]");
if that conversion is ill-formed, the program is ill-formed[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L655)
In the do statement, the substatement is executed repeatedly
until the value of the expression becomes false[.](#2.sentence-1)
The test takes
place after each execution of the statement[.](#2.sentence-2)

108
cppdraft/stmt/expand.md Normal file
View File

@@ -0,0 +1,108 @@
[stmt.expand]
# 8 Statements [[stmt]](./#stmt)
## 8.7 Expansion statements [stmt.expand]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L790)
Expansion statements specify repeated instantiations ([[temp.decls.general]](temp.decls.general "13.7.1General"))
of their substatement[.](#1.sentence-1)
[expansion-statement:](#nt:expansion-statement "8.7Expansion statements[stmt.expand]")
template for ([*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") :[*expansion-initializer*](#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") ) [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[expansion-initializer:](#nt:expansion-initializer "8.7Expansion statements[stmt.expand]")
[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")
[*expansion-init-list*](#nt:expansion-init-list "8.7Expansion statements[stmt.expand]")
[expansion-init-list:](#nt:expansion-init-list "8.7Expansion statements[stmt.expand]")
{ [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt }
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L812)
The [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of an [*expansion-statement*](#nt:expansion-statement "8.7Expansion statements[stmt.expand]") is a control-flow-limited statement ([[stmt.label]](stmt.label "8.2Label"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L816)
For an expression E, let the expressions*begin-expr* and *end-expr* be determined as specified in [[stmt.ranged]](stmt.ranged "8.6.5The range-based for statement")[.](#3.sentence-1)
An expression is [*expansion-iterable*](#def:expansion-iterable "8.7Expansion statements[stmt.expand]") if it does not have array type and either
- [(3.1)](#3.1)
*begin-expr* and *end-expr* are of the formE.begin() and E.end(), or
- [(3.2)](#3.2)
argument-dependent lookups for begin(E) and for end(E) each find at least one function or function template[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L829)
An expansion statement is
- [(4.1)](#4.1)
an [*enumerating expansion statement*](#def:expansion_statement,enumerating "8.7Expansion statements[stmt.expand]") if its [*expansion-initializer*](#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") is of the form [*expansion-init-list*](#nt:expansion-init-list "8.7Expansion statements[stmt.expand]");
- [(4.2)](#4.2)
otherwise, an [*iterating expansion statement*](#def:expansion_statement,iterating "8.7Expansion statements[stmt.expand]") if its [*expansion-initializer*](#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") is an expansion-iterable expression;
- [(4.3)](#4.3)
otherwise, a [*destructuring expansion statement*](#def:expansion_statement,destructuring "8.7Expansion statements[stmt.expand]")[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L842)
An expansion statement S is equivalent to a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") containing instantiations of the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") (including its implied initialization),
together with the compound-statement of S, as follows:
- [(5.1)](#5.1)
If S is an enumerating expansion statement, S is equivalent to:{[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")S0 ⋮ SN−1} where N is the number of elements in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),Si is{[*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") = Ei; [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")} and Ei is the ith element of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]").
- [(5.2)](#5.2)
Otherwise, if S is an iterating expansion statement, S is equivalent to:{[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")static constexpr auto&& *range* = [*expansion-initializer*](#nt:expansion-initializer "8.7Expansion statements[stmt.expand]"); static constexpr auto *begin* = *begin-expr*; // see [[stmt.ranged]](stmt.ranged "8.6.5The range-based for statement")static constexpr auto *end* = *end-expr*; // see [[stmt.ranged]](stmt.ranged "8.6.5The range-based for statement")S0 ⋮ SN−1} where N is the result of evaluating the expression[] consteval { std::ptrdiff_t result = 0; for (auto i = *begin*; i != *end*; ++i, ++result); return result; // distance from *begin* to *end*}() and Si is{static constexpr auto *iter* = *begin* + i; [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") = **iter*; [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")}
The variables *range*, *begin*, *end*, and *iter* are defined for exposition only[.](#5.2.sentence-2)
[*Note [1](#note-1)*:
The instantiation is ill-formed if *range* is not a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#5.2.sentence-3)
— *end note*]
- [(5.3)](#5.3)
Otherwise, S is a destructuring expansion statement and S is equivalent to:{[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")constexpropt auto&& [u0, u1, …, uN−1] = [*expansion-initializer*](#nt:expansion-initializer "8.7Expansion statements[stmt.expand]"); S0 ⋮ SN−1} where N is the structured binding size of the type
of the [*expansion-initializer*](#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") and Si is{[*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") = ui; [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")}
The keyword constexpr is present in the declaration
of u0,u1,…,uN−1 if and only ifconstexpr is one of the [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]")[.](#5.3.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L931)
[*Example [1](#example-1)*: consteval int f(auto const&... Containers) {int result = 0; template for (auto const& c : {Containers...}) { // OK, enumerating expansion statement result += c[0]; }return result;}constexpr int c1[] = {1, 2, 3};constexpr int c2[] = {4, 3, 2, 1};static_assert(f(c1, c2) == 5); — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L947)
[*Example [2](#example-2)*: consteval int f() {constexpr std::array<int, 3> arr {1, 2, 3}; int result = 0; template for (constexpr int s : arr) { // OK, iterating expansion statement result += sizeof(char[s]); }return result;}static_assert(f() == 6); — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L962)
[*Example [3](#example-3)*: struct S {int i; short s;};
consteval long f(S s) {long result = 0; template for (auto x : s) { // OK, destructuring expansion statement result += sizeof(x); }return result;}static_assert(f(S{}) == sizeof(int) + sizeof(short)); — *end example*]

33
cppdraft/stmt/expr.md Normal file
View File

@@ -0,0 +1,33 @@
[stmt.expr]
# 8 Statements [[stmt]](./#stmt)
## 8.3 Expression statement [stmt.expr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L217)
Expression statements have the form
[expression-statement:](#nt:expression-statement "8.3Expression statement[stmt.expr]")
[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ;
The expression is
a [discarded-value expression](expr.context#def:discarded-value_expression "7.2.3Context dependence[expr.context]")[.](#1.sentence-2)
Allside effects from an expression statement
are completed before the next statement is executed[.](#1.sentence-3)
An expression statement with the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") missing is called
a [*null statement*](#def:statement,null "8.3Expression statement[stmt.expr]")[.](#1.sentence-4)
[*Note [1](#note-1)*:
Most statements are expression statements — usually assignments or
function calls[.](#1.sentence-5)
A null statement is useful to supply a null body to an
iteration statement such as a while statement ([[stmt.while]](stmt.while "8.6.2The while statement"))[.](#1.sentence-6)
— *end note*]

49
cppdraft/stmt/for.md Normal file
View File

@@ -0,0 +1,49 @@
[stmt.for]
# 8 Statements [[stmt]](./#stmt)
## 8.6 Iteration statements [[stmt.iter]](stmt.iter#stmt.for)
### 8.6.4 The for statement [stmt.for]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L663)
The for statement
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")opt ; [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
while ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) {
[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ;
}
}
except that the [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") is
in the same scope as the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]"), and
except that acontinue in [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") (not enclosed in another
iteration statement) will execute [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") before
re-evaluating [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")[.](#1.sentence-1)
[*Note [1](#note-1)*:
Thus the first statement specifies initialization for the loop; the
condition ([[stmt.pre]](stmt.pre "8.1Preamble")) specifies a test, sequenced before each
iteration, such that the loop is exited when the condition becomesfalse; the expression often specifies incrementing that is
sequenced after each iteration[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L693)
Either or both of the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") and the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") can be omitted[.](#2.sentence-1)
A missing [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") makes the implied while clause
equivalent to while (true)[.](#2.sentence-2)

16
cppdraft/stmt/goto.md Normal file
View File

@@ -0,0 +1,16 @@
[stmt.goto]
# 8 Statements [[stmt]](./#stmt)
## 8.8 Jump statements [[stmt.jump]](stmt.jump#stmt.goto)
### 8.8.6 The goto statement [stmt.goto]
[1](#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[.](#1.sentence-1)
The identifier shall be a[label](stmt.label "8.2Label[stmt.label]") located in the current function[.](#1.sentence-2)

146
cppdraft/stmt/if.md Normal file
View File

@@ -0,0 +1,146 @@
[stmt.if]
# 8 Statements [[stmt]](./#stmt)
## 8.5 Selection statements [[stmt.select]](stmt.select#stmt.if)
### 8.5.2 The if statement [stmt.if]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L307)
If the condition ([[stmt.pre]](stmt.pre "8.1Preamble")) yields true, the first
substatement is executed[.](#1.sentence-1)
If the else part of the selection
statement is present and the condition yields false, the second
substatement is executed[.](#1.sentence-2)
If the first substatement is reached via a
label, the condition is not evaluated and the second substatement is
not executed[.](#1.sentence-3)
In the second form of if statement
(the one including else), if the first substatement is also anif statement then that inner if statement shall contain
an else part[.](#1.sentence-4)[72](#footnote-72 "In other words, the else is associated with the nearest un-elsed if.")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L322)
If the if statement is of the form if constexpr,
the value of the condition
is contextually converted to bool and
the converted expression shall be a constant expression ([[expr.const]](expr.const "7.7Constant expressions"));
this
form is called a [*constexpr if*](#def:constexpr_if "8.5.2The if statement[stmt.if]") statement[.](#2.sentence-1)
If the value of the
converted condition is false, the first substatement is a[*discarded statement*](#def:discarded_statement "8.5.2The if statement[stmt.if]"), otherwise the second substatement, if
present, is a discarded statement[.](#2.sentence-2)
During the instantiation of an
enclosing templated entity ([[temp.pre]](temp.pre "13.1Preamble")), if the condition is
not value-dependent after its instantiation, the discarded substatement
(if any) is not instantiated[.](#2.sentence-3)
Each substatement of a constexpr if statement is a control-flow-limited
statement ([[stmt.label]](stmt.label "8.2Label"))[.](#2.sentence-4)
[*Example [1](#example-1)*: if constexpr (sizeof(int[2])) {} // OK, narrowing allowed — *end example*]
[*Note [1](#note-1)*:
Odr-uses ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in a discarded statement do not require
an entity to be defined[.](#2.sentence-5)
— *end note*]
[*Example [2](#example-2)*: template<typename T, typename ... Rest> void g(T&& p, Rest&& ...rs) {// ... handle pif constexpr (sizeof...(rs) > 0) g(rs...); // never instantiated with an empty argument list}extern int x; // no definition of x requiredint f() {if constexpr (true)return 0; else if (x)return x; elsereturn -x;} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L368)
An if statement of the form
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
if constexpropt ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
and an if statement of the form
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
if constexpropt ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
except that the [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") is
in the same scope as the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L394)
An if statement of the form if consteval is called a [*consteval if statement*](#def:statement,consteval_if "8.5.2The if statement[stmt.if]")[.](#4.sentence-1)
The [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]"), if any, in a consteval if statement
shall be a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")[.](#4.sentence-2)
[*Example [3](#example-3)*: constexpr void f(bool b) {if (true)if consteval { }else ; // error: not a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]"); else not associated with outer if} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L409)
If a consteval if statement is evaluated in a context
that is manifestly constant-evaluated ([[expr.const]](expr.const "7.7Constant expressions")),
the first substatement is executed[.](#5.sentence-1)
[*Note [2](#note-2)*:
The first substatement is an immediate function context[.](#5.sentence-2)
— *end note*]
Otherwise, if the else part of the selection statement is present,
then the second substatement is executed[.](#5.sentence-3)
Each substatement of a consteval if statement is a control-flow-limited
statement ([[stmt.label]](stmt.label "8.2Label"))[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L421)
An if statement of the form
if ! consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
is not itself a consteval if statement,
but is equivalent to the consteval if statement
if consteval { } else [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
An if statement of the form
if ! consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")1 else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")2
is not itself a consteval if statement,
but is equivalent to the consteval if statement
if consteval [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")2 else [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")1
[72)](#footnote-72)[72)](#footnoteref-72)
In other words, the else is associated with the nearest un-elsedif[.](#footnote-72.sentence-1)

285
cppdraft/stmt/iter.md Normal file
View File

@@ -0,0 +1,285 @@
[stmt.iter]
# 8 Statements [[stmt]](./#stmt)
## 8.6 Iteration statements [stmt.iter]
### [8.6.1](#general) General [[stmt.iter.general]](stmt.iter.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L531)
Iteration statements specify looping[.](#general-1.sentence-1)
[iteration-statement:](#nt:iteration-statement "8.6.1General[stmt.iter.general]")
while ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
do [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")opt ; [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") : [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
[*Note [1](#general-note-1)*:
An [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") ends with a semicolon[.](#general-1.sentence-2)
— *end note*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L550)
The substatement in an [*iteration-statement*](#nt:iteration-statement "8.6.1General[stmt.iter.general]") implicitly defines
a block [scope](basic.scope "6.4Scope[basic.scope]") which is entered and exited each time
through the loop[.](#general-2.sentence-1)
If the substatement in an [*iteration-statement*](#nt:iteration-statement "8.6.1General[stmt.iter.general]") is
a single statement and not a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]"),
it is as if it was rewritten to be
a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") containing the original statement[.](#general-2.sentence-2)
[*Example [1](#general-example-1)*:
while (--x >= 0)int i; can be equivalently rewritten aswhile (--x >= 0) {int i;}
Thus after the while statement, i is no longer in scope[.](#general-2.sentence-4)
— *end example*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L573)
A [*trivially empty iteration statement*](#def:iteration_statement,trivially_empty "8.6.1General[stmt.iter.general]") is
an iteration statement matching one of the following forms:
- [(3.1)](#general-3.1)
while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
- [(3.2)](#general-3.2)
while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) { }
- [(3.3)](#general-3.3)
do ; while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
- [(3.4)](#general-3.4)
do { } while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
- [(3.5)](#general-3.5)
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ; ) ;
- [(3.6)](#general-3.6)
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ; ) { }
The [*controlling expression*](#def:expression,controlling "8.6.1General[stmt.iter.general]") of a trivially empty iteration statement
is the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") of
a while, do, or for statement
(or true, if the for statement has no [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]"))[.](#general-3.sentence-1)
A [*trivial infinite loop*](#def:loop,trivial_infinite "8.6.1General[stmt.iter.general]") is a trivially empty iteration statement
for which the converted controlling expression is a constant expression,
when interpreted as a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ([[expr.const]](expr.const "7.7Constant expressions")), and
evaluates to true[.](#general-3.sentence-2)
The [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") of a trivial infinite loop is replaced with
a call to the function std::this_thread::yield ([[thread.thread.this]](thread.thread.this "32.4.5Namespace this_­thread"));
it is implementation-defined
whether this replacement occurs on freestanding implementations[.](#general-3.sentence-3)
[*Note [2](#general-note-2)*:
In a freestanding environment,
concurrent forward progress is not guaranteed;
such systems therefore require explicit cooperation[.](#general-3.sentence-4)
A call to yield can add implicit cooperation where none is otherwise intended[.](#general-3.sentence-5)
— *end note*]
### [8.6.2](#stmt.while) The while statement [[stmt.while]](stmt.while)
[1](#stmt.while-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L607)
In the while statement, the substatement is executed repeatedly
until the value of the condition ([[stmt.pre]](stmt.pre "8.1Preamble")) becomesfalse[.](#stmt.while-1.sentence-1)
The test takes place before each execution of the
substatement[.](#stmt.while-1.sentence-2)
[2](#stmt.while-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L613)
A while statement is equivalent to
*label* :
{
if ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) {
[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
goto *label* ;
}
}
[*Note [1](#stmt.while-note-1)*:
The variable created in the condition is destroyed and created with each
iteration of the loop[.](#stmt.while-2.sentence-1)
[*Example [1](#stmt.while-example-1)*: struct A {int val;
A(int i) : val(i) { }~A() { }operator bool() { return val != 0; }};int i = 1;while (A a = i) {// ... i = 0;}
In the while-loop, the constructor and destructor are each called twice,
once for the condition that succeeds and once for the condition that
fails[.](#stmt.while-2.sentence-2)
— *end example*]
— *end note*]
### [8.6.3](#stmt.do) The do statement [[stmt.do]](stmt.do)
[1](#stmt.do-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L651)
The expression is [contextually converted to bool](conv#def:conversion,contextual_to_bool "7.3Standard conversions[conv]");
if that conversion is ill-formed, the program is ill-formed[.](#stmt.do-1.sentence-1)
[2](#stmt.do-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L655)
In the do statement, the substatement is executed repeatedly
until the value of the expression becomes false[.](#stmt.do-2.sentence-1)
The test takes
place after each execution of the statement[.](#stmt.do-2.sentence-2)
### [8.6.4](#stmt.for) The for statement [[stmt.for]](stmt.for)
[1](#stmt.for-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L663)
The for statement
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")opt ; [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
while ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) {
[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ;
}
}
except that the [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") is
in the same scope as the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]"), and
except that acontinue in [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") (not enclosed in another
iteration statement) will execute [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") before
re-evaluating [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")[.](#stmt.for-1.sentence-1)
[*Note [1](#stmt.for-note-1)*:
Thus the first statement specifies initialization for the loop; the
condition ([[stmt.pre]](stmt.pre "8.1Preamble")) specifies a test, sequenced before each
iteration, such that the loop is exited when the condition becomesfalse; the expression often specifies incrementing that is
sequenced after each iteration[.](#stmt.for-1.sentence-2)
— *end note*]
[2](#stmt.for-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L693)
Either or both of the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") and the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") can be omitted[.](#stmt.for-2.sentence-1)
A missing [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") makes the implied while clause
equivalent to while (true)[.](#stmt.for-2.sentence-2)
### [8.6.5](#stmt.ranged) The range-based for statement [[stmt.ranged]](stmt.ranged)
[1](#stmt.ranged-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L703)
The range-based for statement
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") : [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt
auto &&*range* = [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") ;
auto *begin* = *begin-expr* ;
auto *end* = *end-expr* ;
for ( ; *begin* != *end*; ++*begin* ) {
[*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") = * *begin* ;
[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
}
where
- [(1.1)](#stmt.ranged-1.1)
if the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") is an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]"),
it is regarded as if it were surrounded by parentheses (so that a comma operator
cannot be reinterpreted as delimiting two [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]")*s*);
- [(1.2)](#stmt.ranged-1.2)
*range*, *begin*, and *end* are variables defined for
exposition only; and
- [(1.3)](#stmt.ranged-1.3)
*begin-expr* and *end-expr* are determined as follows:
* [(1.3.1)](#stmt.ranged-1.3.1)
if the type of *range* is a reference to an
array type R, *begin-expr* and *end-expr* are*range* and *range* + N, respectively,
where N is
the array bound[.](#stmt.ranged-1.3.1.sentence-1)
If R is an array of unknown bound or an array of
incomplete type, the program is ill-formed;
* [(1.3.2)](#stmt.ranged-1.3.2)
if the type of *range* is a reference to a
class type C, and
searches in the scope of C ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))
for the names begin and end each find at least one declaration,*begin-expr* and *end-expr* are*range*.begin() and *range*.end(),
respectively;
* [(1.3.3)](#stmt.ranged-1.3.3)
otherwise, *begin-expr* and *end-expr* arebegin(*range*) and end(*range*), respectively,
where begin and end undergo
argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4Argument-dependent name lookup"))[.](#stmt.ranged-1.3.3.sentence-1)
[*Note [1](#stmt.ranged-note-1)*:
Ordinary unqualified lookup ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3Unqualified name lookup")) is not
performed[.](#stmt.ranged-1.3.3.sentence-2)
— *end note*]
[*Example [1](#stmt.ranged-example-1)*: int array[5] = { 1, 2, 3, 4, 5 };for (int& x : array) x *= 2; — *end example*]
[*Note [2](#stmt.ranged-note-2)*:
The lifetime of some temporaries in the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") is extended to cover the entire loop ([[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#stmt.ranged-1.sentence-2)
— *end note*]
[*Example [2](#stmt.ranged-example-2)*: using T = std::list<int>;const T& f1(const T& t) { return t; }const T& f2(T t) { return t; } T g();
void foo() {for (auto e : f1(g())) {} // OK, lifetime of return value of g() extendedfor (auto e : f2(g())) {} // undefined behavior} — *end example*]

View File

@@ -0,0 +1,102 @@
[stmt.iter.general]
# 8 Statements [[stmt]](./#stmt)
## 8.6 Iteration statements [[stmt.iter]](stmt.iter#general)
### 8.6.1 General [stmt.iter.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L531)
Iteration statements specify looping[.](#1.sentence-1)
[iteration-statement:](#nt:iteration-statement "8.6.1General[stmt.iter.general]")
while ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
do [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")opt ; [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") : [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
[*Note [1](#note-1)*:
An [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") ends with a semicolon[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L550)
The substatement in an [*iteration-statement*](#nt:iteration-statement "8.6.1General[stmt.iter.general]") implicitly defines
a block [scope](basic.scope "6.4Scope[basic.scope]") which is entered and exited each time
through the loop[.](#2.sentence-1)
If the substatement in an [*iteration-statement*](#nt:iteration-statement "8.6.1General[stmt.iter.general]") is
a single statement and not a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]"),
it is as if it was rewritten to be
a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") containing the original statement[.](#2.sentence-2)
[*Example [1](#example-1)*:
while (--x >= 0)int i; can be equivalently rewritten aswhile (--x >= 0) {int i;}
Thus after the while statement, i is no longer in scope[.](#2.sentence-4)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L573)
A [*trivially empty iteration statement*](#def:iteration_statement,trivially_empty "8.6.1General[stmt.iter.general]") is
an iteration statement matching one of the following forms:
- [(3.1)](#3.1)
while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
- [(3.2)](#3.2)
while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) { }
- [(3.3)](#3.3)
do ; while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
- [(3.4)](#3.4)
do { } while ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ) ;
- [(3.5)](#3.5)
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ; ) ;
- [(3.6)](#3.6)
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ; ) { }
The [*controlling expression*](#def:expression,controlling "8.6.1General[stmt.iter.general]") of a trivially empty iteration statement
is the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") of
a while, do, or for statement
(or true, if the for statement has no [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]"))[.](#3.sentence-1)
A [*trivial infinite loop*](#def:loop,trivial_infinite "8.6.1General[stmt.iter.general]") is a trivially empty iteration statement
for which the converted controlling expression is a constant expression,
when interpreted as a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ([[expr.const]](expr.const "7.7Constant expressions")), and
evaluates to true[.](#3.sentence-2)
The [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") of a trivial infinite loop is replaced with
a call to the function std::this_thread::yield ([[thread.thread.this]](thread.thread.this "32.4.5Namespace this_­thread"));
it is implementation-defined
whether this replacement occurs on freestanding implementations[.](#3.sentence-3)
[*Note [2](#note-2)*:
In a freestanding environment,
concurrent forward progress is not guaranteed;
such systems therefore require explicit cooperation[.](#3.sentence-4)
A call to yield can add implicit cooperation where none is otherwise intended[.](#3.sentence-5)
— *end note*]

243
cppdraft/stmt/jump.md Normal file
View File

@@ -0,0 +1,243 @@
[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.1General[stmt.jump.general]")
break ;
continue ;
return [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1General[dcl.init.general]")opt ;
[*coroutine-return-statement*](#nt:coroutine-return-statement "8.8.5The co_­return statement[stmt.return.coroutine]")
goto [*identifier*](lex.name#nt:identifier "5.11Identifiers[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.4Automatic 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.10Declaration statement"))[.](#general-2.sentence-1)
For temporaries, see [[class.temporary]](class.temporary "6.8.7Temporary objects")[.](#general-2.sentence-2)
However, the program can be terminated (by callingstd::exit() orstd::abort() ([[support.start.term]](support.start.term "17.5Startup 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.4Await")) 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.1Preamble"))an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]") ([[stmt.iter]](stmt.iter "8.6Iteration statements")),
an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]") ([[stmt.expand]](stmt.expand "8.7Expansion statements")), or
a switch statement ([[stmt.switch]](stmt.switch "8.5.3The 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.1Preamble"))an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]") or an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion 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.1General[stmt.iter.general]") ([[stmt.iter]](stmt.iter "8.6Iteration statements")),
the continue statement
causes control to pass to the end of the [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") or [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound 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.4Compound statement or block[stmt.block]") of the current Si ([[stmt.expand]](stmt.expand "8.7Expansion 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.1General[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.5Constructors")), or a
destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#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.5Initializers[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.6Copy/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.7Destructors"), [[except.ctor]](except.ctor "14.3Stack 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.1main function")) nor a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine 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.10Declaration statement")),
which, in turn,
is sequenced before the evaluation of
postcondition assertions of the function ([[dcl.contract.func]](dcl.contract.func "9.4.1General")),
which, in turn,
is sequenced before the destruction of function parameters ([[expr.call]](expr.call "7.6.1.3Function 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.8Relationships between types")),
a return statement that binds the returned reference to
a temporary expression ([[class.temporary]](class.temporary "6.8.7Temporary 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.5The co_­return statement[stmt.return.coroutine]")
co_return [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1General[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.4Coroutine definitions"))[.](#stmt.return.coroutine-1.sentence-1)
A coroutine shall not enclose
a return statement ([[stmt.return]](#stmt.return "8.8.4The 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.2The 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.1General[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.4Coroutine 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.4Coroutine 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.1General[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.1General[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.4Compound statement or block[stmt.block]") { [*expression*](expr.comma#nt:expression "7.6.20Comma 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.1General[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.1General[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.2Label[stmt.label]") located in the current function[.](#stmt.goto-1.sentence-2)

View File

@@ -0,0 +1,43 @@
[stmt.jump.general]
# 8 Statements [[stmt]](./#stmt)
## 8.8 Jump statements [[stmt.jump]](stmt.jump#general)
### 8.8.1 General [stmt.jump.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L988)
Jump statements unconditionally transfer control[.](#1.sentence-1)
[jump-statement:](#nt:jump-statement "8.8.1General[stmt.jump.general]")
break ;
continue ;
return [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1General[dcl.init.general]")opt ;
[*coroutine-return-statement*](stmt.return.coroutine#nt:coroutine-return-statement "8.8.5The co_­return statement[stmt.return.coroutine]")
goto [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ;
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1007)
[*Note [1](#note-1)*:
On exit from a scope (however accomplished), objects with [automatic storage
duration](basic.stc.auto "6.8.6.4Automatic 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.10Declaration statement"))[.](#2.sentence-1)
For temporaries, see [[class.temporary]](class.temporary "6.8.7Temporary objects")[.](#2.sentence-2)
However, the program can be terminated (by callingstd::exit() orstd::abort() ([[support.start.term]](support.start.term "17.5Startup and termination")), for example) without
destroying objects with automatic storage duration[.](#2.sentence-3)
— *end note*]
[*Note [2](#note-2)*:
A suspension of a coroutine ([[expr.await]](expr.await "7.6.2.4Await")) is not considered to be an exit from a scope[.](#2.sentence-4)
— *end note*]

60
cppdraft/stmt/label.md Normal file
View File

@@ -0,0 +1,60 @@
[stmt.label]
# 8 Statements [[stmt]](./#stmt)
## 8.2 Label [stmt.label]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L163)
A label can be added to a statement or
used anywhere in a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")[.](#1.sentence-1)
[label:](#nt:label "8.2Label[stmt.label]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") :
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt case [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") :
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt default :
[labeled-statement:](#nt:labeled-statement "8.2Label[stmt.label]")
[*label*](#nt:label "8.2Label[stmt.label]") [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the label[.](#1.sentence-2)
The only use of a label with an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is
as the target of a goto[.](#1.sentence-3)
No two labels in a function shall have the same [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")[.](#1.sentence-4)
A label can be used in a goto statement
before its introduction[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L190)
A [*labeled-statement*](#nt:labeled-statement "8.2Label[stmt.label]") whose [*label*](#nt:label "8.2Label[stmt.label]") is a case or default label
shall be enclosed by ([[stmt.pre]](stmt.pre "8.1Preamble")) a switch statement ([[stmt.switch]](stmt.switch "8.5.3The switch statement"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L198)
A [*control-flow-limited statement*](#def:statement,control-flow-limited "8.2Label[stmt.label]") is a statement S for which:
- [(3.1)](#3.1)
a case or default label appearing within S shall
be associated with a switch statement ([[stmt.switch]](stmt.switch "8.5.3The switch statement")) within S, and
- [(3.2)](#3.2)
a label declared in S shall only be referred to by a
statement ([[stmt.goto]](stmt.goto "8.8.6The goto statement")) in S[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L210)
An identifier label shall not be enclosed
by an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]") ([[stmt.expand]](stmt.expand "8.7Expansion statements"))[.](#4.sentence-1)

177
cppdraft/stmt/pre.md Normal file
View File

@@ -0,0 +1,177 @@
[stmt.pre]
# 8 Statements [[stmt]](./#stmt)
## 8.1 Preamble [stmt.pre]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L11)
Except as indicated, statements are executed in sequence ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#1.sentence-1)
[statement:](#nt:statement "8.1Preamble[stmt.pre]")
[*labeled-statement*](stmt.label#nt:labeled-statement "8.2Label[stmt.label]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*expression-statement*](stmt.expr#nt:expression-statement "8.3Expression statement[stmt.expr]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*selection-statement*](stmt.select.general#nt:selection-statement "8.5.1General[stmt.select.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*jump-statement*](stmt.jump.general#nt:jump-statement "8.8.1General[stmt.jump.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]")
[*declaration-statement*](stmt.dcl#nt:declaration-statement "8.10Declaration statement[stmt.dcl]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*try-block*](except.pre#nt:try-block "14.1Preamble[except.pre]")
[init-statement:](#nt:init-statement "8.1Preamble[stmt.pre]")
[*expression-statement*](stmt.expr#nt:expression-statement "8.3Expression statement[stmt.expr]")
[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1Preamble[dcl.pre]")
[*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]")
[condition:](#nt:condition "8.1Preamble[stmt.pre]")
[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")
[*structured-binding-declaration*](dcl.pre#nt:structured-binding-declaration "9.1Preamble[dcl.pre]") [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")
[for-range-declaration:](#nt:for-range-declaration "8.1Preamble[stmt.pre]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")
[*structured-binding-declaration*](dcl.pre#nt:structured-binding-declaration "9.1Preamble[dcl.pre]")
[for-range-initializer:](#nt:for-range-initializer "8.1Preamble[stmt.pre]")
[*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1General[dcl.init.general]")
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the respective statement[.](#1.sentence-2)
See [[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators") for the optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a[*for-range-declaration*](#nt:for-range-declaration "8.1Preamble[stmt.pre]")[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L57)
A [*substatement*](#def:substatement "8.1Preamble[stmt.pre]") of a [*statement*](#nt:statement "8.1Preamble[stmt.pre]") is one of the following:
- [(2.1)](#2.1)
for a [*labeled-statement*](stmt.label#nt:labeled-statement "8.2Label[stmt.label]"), its [*statement*](#nt:statement "8.1Preamble[stmt.pre]"),
- [(2.2)](#2.2)
for a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]"), any [*statement*](#nt:statement "8.1Preamble[stmt.pre]") of its [*statement-seq*](stmt.block#nt:statement-seq "8.4Compound statement or block[stmt.block]"),
- [(2.3)](#2.3)
for a [*selection-statement*](stmt.select.general#nt:selection-statement "8.5.1General[stmt.select.general]"), any of its [*statement*](#nt:statement "8.1Preamble[stmt.pre]")*s* or [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")*s* (but not its [*init-statement*](#nt:init-statement "8.1Preamble[stmt.pre]")),
- [(2.4)](#2.4)
for an [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]"), its [*statement*](#nt:statement "8.1Preamble[stmt.pre]") (but not an [*init-statement*](#nt:init-statement "8.1Preamble[stmt.pre]")), or
- [(2.5)](#2.5)
for an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]"), its [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") (but not an [*init-statement*](#nt:init-statement "8.1Preamble[stmt.pre]"))[.](#2.sentence-1)
[*Note [1](#note-1)*:
The [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") is not a substatement of the [*statement*](#nt:statement "8.1Preamble[stmt.pre]") (if any)
in which the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") lexically appears[.](#2.sentence-2)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L78)
A [*statement*](#nt:statement "8.1Preamble[stmt.pre]") S1 [*encloses*](#def:enclosing_statement "8.1Preamble[stmt.pre]") a [*statement*](#nt:statement "8.1Preamble[stmt.pre]") S2 if
- [(3.1)](#3.1)
S2 is a substatement of S1,
- [(3.2)](#3.2)
S1 is a [*selection-statement*](stmt.select.general#nt:selection-statement "8.5.1General[stmt.select.general]"), [*iteration-statement*](stmt.iter.general#nt:iteration-statement "8.6.1General[stmt.iter.general]"), or [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]"),
and S2 is the [*init-statement*](#nt:init-statement "8.1Preamble[stmt.pre]") of S1,
- [(3.3)](#3.3)
S1 is a [*try-block*](except.pre#nt:try-block "14.1Preamble[except.pre]") and S2 is its [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") or
any of the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")*s* of
its [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]")*s*, or
- [(3.4)](#3.4)
S1 encloses a statement S3 and S3 encloses S2[.](#3.sentence-1)
A statement S1 is[*enclosed by*](#def:enclosed_by_statement "8.1Preamble[stmt.pre]") a statement S2 ifS2 encloses S1[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L104)
The rules for [*condition*](#nt:condition "8.1Preamble[stmt.pre]")*s* apply both
to [*selection-statement*](stmt.select.general#nt:selection-statement "8.5.1General[stmt.select.general]")*s* ([[stmt.select]](stmt.select "8.5Selection statements")) and
to the for and while statements ([[stmt.iter]](stmt.iter "8.6Iteration statements"))[.](#4.sentence-1)
If a [*structured-binding-declaration*](dcl.pre#nt:structured-binding-declaration "9.1Preamble[dcl.pre]") appears in a [*condition*](#nt:condition "8.1Preamble[stmt.pre]"),
the [*condition*](#nt:condition "8.1Preamble[stmt.pre]") is a structured binding declaration ([[dcl.pre]](dcl.pre "9.1Preamble"))[.](#4.sentence-2)
A [*condition*](#nt:condition "8.1Preamble[stmt.pre]") that is
neither an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") nor a structured binding declaration
is a declaration ([[dcl]](dcl "9Declarations"))[.](#4.sentence-3)
The [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall not
specify a function or an array[.](#4.sentence-4)
The [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall not
define a class or enumeration[.](#4.sentence-5)
If the auto [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") appears in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"),
the type of the identifier being declared is deduced from the initializer as described in [[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")[.](#4.sentence-6)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L121)
The [*decision variable*](#def:variable,decision "8.1Preamble[stmt.pre]") of a [*condition*](#nt:condition "8.1Preamble[stmt.pre]") that is neither an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") nor a structured binding declaration
is the declared variable[.](#5.sentence-1)
The decision variable of a [*condition*](#nt:condition "8.1Preamble[stmt.pre]") that is a structured binding declaration is specified in [[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations")[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L128)
The value of a [*condition*](#nt:condition "8.1Preamble[stmt.pre]") that is not an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") in a statement other than a switch statement is the value of the
decision variable
contextually converted to bool ([[conv]](conv "7.3Standard conversions"))[.](#6.sentence-1)
If that
conversion is ill-formed, the program is ill-formed[.](#6.sentence-2)
The value of a[*condition*](#nt:condition "8.1Preamble[stmt.pre]") that is an expression is the value of the
expression, contextually converted to bool for statements other
than switch;
if that conversion is ill-formed, the program is
ill-formed[.](#6.sentence-3)
The value of the condition will be referred to as simply
“the condition” where the usage is unambiguous[.](#6.sentence-4)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L144)
If a [*condition*](#nt:condition "8.1Preamble[stmt.pre]") can be syntactically resolved
as either an expression or a declaration,
it is interpreted as the latter[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L149)
In the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a [*condition*](#nt:condition "8.1Preamble[stmt.pre]") or of a [*for-range-declaration*](#nt:for-range-declaration "8.1Preamble[stmt.pre]"),
including that of any [*structured-binding-declaration*](dcl.pre#nt:structured-binding-declaration "9.1Preamble[dcl.pre]") of
the [*condition*](#nt:condition "8.1Preamble[stmt.pre]"),
each[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") shall be either a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") or constexpr[.](#8.sentence-1)
The [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a [*for-range-declaration*](#nt:for-range-declaration "8.1Preamble[stmt.pre]") shall not define a class or enumeration[.](#8.sentence-2)

83
cppdraft/stmt/ranged.md Normal file
View File

@@ -0,0 +1,83 @@
[stmt.ranged]
# 8 Statements [[stmt]](./#stmt)
## 8.6 Iteration statements [[stmt.iter]](stmt.iter#stmt.ranged)
### 8.6.5 The range-based for statement [stmt.ranged]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L703)
The range-based for statement
for ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") : [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt
auto &&*range* = [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") ;
auto *begin* = *begin-expr* ;
auto *end* = *end-expr* ;
for ( ; *begin* != *end*; ++*begin* ) {
[*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") = * *begin* ;
[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
}
where
- [(1.1)](#1.1)
if the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") is an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]"),
it is regarded as if it were surrounded by parentheses (so that a comma operator
cannot be reinterpreted as delimiting two [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]")*s*);
- [(1.2)](#1.2)
*range*, *begin*, and *end* are variables defined for
exposition only; and
- [(1.3)](#1.3)
*begin-expr* and *end-expr* are determined as follows:
* [(1.3.1)](#1.3.1)
if the type of *range* is a reference to an
array type R, *begin-expr* and *end-expr* are*range* and *range* + N, respectively,
where N is
the array bound[.](#1.3.1.sentence-1)
If R is an array of unknown bound or an array of
incomplete type, the program is ill-formed;
* [(1.3.2)](#1.3.2)
if the type of *range* is a reference to a
class type C, and
searches in the scope of C ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))
for the names begin and end each find at least one declaration,*begin-expr* and *end-expr* are*range*.begin() and *range*.end(),
respectively;
* [(1.3.3)](#1.3.3)
otherwise, *begin-expr* and *end-expr* arebegin(*range*) and end(*range*), respectively,
where begin and end undergo
argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4Argument-dependent name lookup"))[.](#1.3.3.sentence-1)
[*Note [1](#note-1)*:
Ordinary unqualified lookup ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3Unqualified name lookup")) is not
performed[.](#1.3.3.sentence-2)
— *end note*]
[*Example [1](#example-1)*: int array[5] = { 1, 2, 3, 4, 5 };for (int& x : array) x *= 2; — *end example*]
[*Note [2](#note-2)*:
The lifetime of some temporaries in the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") is extended to cover the entire loop ([[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#1.sentence-2)
— *end note*]
[*Example [2](#example-2)*: using T = std::list<int>;const T& f1(const T& t) { return t; }const T& f2(T t) { return t; } T g();
void foo() {for (auto e : f1(g())) {} // OK, lifetime of return value of g() extendedfor (auto e : f2(g())) {} // undefined behavior} — *end example*]

107
cppdraft/stmt/return.md Normal file
View File

@@ -0,0 +1,107 @@
[stmt.return]
# 8 Statements [[stmt]](./#stmt)
## 8.8 Jump statements [[stmt.jump]](stmt.jump#stmt.return)
### 8.8.4 The return statement [stmt.return]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L1063)
A function returns control to its caller by the return statement[.](#1.sentence-1)
[2](#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.1General[dcl.init.general]") of a return statement is called its operand[.](#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.5Constructors")), or a
destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#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[.](#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.5Initializers[dcl.init]") from the operand[.](#2.sentence-4)
[*Note [1](#note-1)*:
A constructor or destructor does not have a return type[.](#2.sentence-5)
— *end note*]
[*Note [2](#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[.](#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.6Copy/move elision"))[.](#2.sentence-7)
— *end note*]
[3](#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.7Destructors"), [[except.ctor]](except.ctor "14.3Stack unwinding"))[.](#3.sentence-1)
[*Example [1](#example-1)*: class A {~A() {}};
A f() { return A(); } // error: destructor of A is private (even though it is never invoked) — *end example*]
[4](#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[.](#4.sentence-1)
Otherwise, flowing off the end of a function
that is neither main ([[basic.start.main]](basic.start.main "6.10.3.1main function")) nor a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))
results in undefined behavior[.](#4.sentence-2)
[5](#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]](stmt.jump "8.8Jump statements")) of the block
enclosing the return statement[.](#5.sentence-1)
[*Note [3](#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.10Declaration statement")),
which, in turn,
is sequenced before the evaluation of
postcondition assertions of the function ([[dcl.contract.func]](dcl.contract.func "9.4.1General")),
which, in turn,
is sequenced before the destruction of function parameters ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#5.sentence-2)
— *end note*]
[6](#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.8Relationships between types")),
a return statement that binds the returned reference to
a temporary expression ([[class.temporary]](class.temporary "6.8.7Temporary objects")) is ill-formed[.](#6.sentence-1)
[*Example [2](#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*]

View File

@@ -0,0 +1,63 @@
[stmt.return.coroutine]
# 8 Statements [[stmt]](./#stmt)
## 8.8 Jump statements [[stmt.jump]](stmt.jump#stmt.return.coroutine)
### 8.8.5 The co_return statement [stmt.return.coroutine]
[coroutine-return-statement:](#nt:coroutine-return-statement "8.8.5The co_­return statement[stmt.return.coroutine]")
co_return [*expr-or-braced-init-list*](dcl.init.general#nt:expr-or-braced-init-list "9.5.1General[dcl.init.general]")opt ;
[1](#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.4Coroutine definitions"))[.](#1.sentence-1)
A coroutine shall not enclose
a return statement ([[stmt.return]](stmt.return "8.8.4The return statement"))[.](#1.sentence-2)
[*Note [1](#note-1)*:
For this determination, it is irrelevant whether the return statement
is enclosed by a discarded statement ([[stmt.if]](stmt.if "8.5.2The if statement"))[.](#1.sentence-3)
— *end note*]
[2](#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.1General[dcl.init.general]") of a co_return statement is
called its operand[.](#2.sentence-1)
Let *p* be an lvalue naming the coroutine
promise object ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))[.](#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.4Coroutine definitions") and *S* is defined as follows:
- [(2.1)](#2.1)
If the operand is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[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.1General[dcl.init.general]"))[.](#2.1.sentence-1)
The expression *S* shall be a prvalue of type void[.](#2.1.sentence-2)
- [(2.2)](#2.2)
Otherwise,*S* is the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") { [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")opt ; *p*.return_void(); }[.](#2.2.sentence-1)
The expression *p*.return_void() shall be a prvalue of type void[.](#2.2.sentence-2)
[3](#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.1General[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.1General[dcl.fct.def.general]") results in undefined behavior[.](#3.sentence-1)

289
cppdraft/stmt/select.md Normal file
View File

@@ -0,0 +1,289 @@
[stmt.select]
# 8 Statements [[stmt]](./#stmt)
## 8.5 Selection statements [stmt.select]
### [8.5.1](#general) General [[stmt.select.general]](stmt.select.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L276)
Selection statements choose one of several flows of control[.](#general-1.sentence-1)
[selection-statement:](#nt:selection-statement "8.5.1General[stmt.select.general]")
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
if !opt consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
if !opt consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
switch ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
See [[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators") for the optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a condition[.](#general-1.sentence-2)
[*Note [1](#general-note-1)*:
An [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") ends with a semicolon[.](#general-1.sentence-3)
— *end note*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L296)
[*Note [2](#general-note-2)*:
Each [*selection-statement*](#nt:selection-statement "8.5.1General[stmt.select.general]") and
each substatement of a [*selection-statement*](#nt:selection-statement "8.5.1General[stmt.select.general]") has a block scope ([[basic.scope.block]](basic.scope.block "6.4.3Block scope"))[.](#general-2.sentence-1)
— *end note*]
### [8.5.2](#stmt.if) The if statement [[stmt.if]](stmt.if)
[1](#stmt.if-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L307)
If the condition ([[stmt.pre]](stmt.pre "8.1Preamble")) yields true, the first
substatement is executed[.](#stmt.if-1.sentence-1)
If the else part of the selection
statement is present and the condition yields false, the second
substatement is executed[.](#stmt.if-1.sentence-2)
If the first substatement is reached via a
label, the condition is not evaluated and the second substatement is
not executed[.](#stmt.if-1.sentence-3)
In the second form of if statement
(the one including else), if the first substatement is also anif statement then that inner if statement shall contain
an else part[.](#stmt.if-1.sentence-4)[72](#footnote-72 "In other words, the else is associated with the nearest un-elsed if.")
[2](#stmt.if-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L322)
If the if statement is of the form if constexpr,
the value of the condition
is contextually converted to bool and
the converted expression shall be a constant expression ([[expr.const]](expr.const "7.7Constant expressions"));
this
form is called a [*constexpr if*](#def:constexpr_if "8.5.2The if statement[stmt.if]") statement[.](#stmt.if-2.sentence-1)
If the value of the
converted condition is false, the first substatement is a[*discarded statement*](#def:discarded_statement "8.5.2The if statement[stmt.if]"), otherwise the second substatement, if
present, is a discarded statement[.](#stmt.if-2.sentence-2)
During the instantiation of an
enclosing templated entity ([[temp.pre]](temp.pre "13.1Preamble")), if the condition is
not value-dependent after its instantiation, the discarded substatement
(if any) is not instantiated[.](#stmt.if-2.sentence-3)
Each substatement of a constexpr if statement is a control-flow-limited
statement ([[stmt.label]](stmt.label "8.2Label"))[.](#stmt.if-2.sentence-4)
[*Example [1](#stmt.if-example-1)*: if constexpr (sizeof(int[2])) {} // OK, narrowing allowed — *end example*]
[*Note [1](#stmt.if-note-1)*:
Odr-uses ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in a discarded statement do not require
an entity to be defined[.](#stmt.if-2.sentence-5)
— *end note*]
[*Example [2](#stmt.if-example-2)*: template<typename T, typename ... Rest> void g(T&& p, Rest&& ...rs) {// ... handle pif constexpr (sizeof...(rs) > 0) g(rs...); // never instantiated with an empty argument list}extern int x; // no definition of x requiredint f() {if constexpr (true)return 0; else if (x)return x; elsereturn -x;} — *end example*]
[3](#stmt.if-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L368)
An if statement of the form
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
if constexpropt ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
and an if statement of the form
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
if constexpropt ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
except that the [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") is
in the same scope as the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")[.](#stmt.if-3.sentence-1)
[4](#stmt.if-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L394)
An if statement of the form if consteval is called a [*consteval if statement*](#def:statement,consteval_if "8.5.2The if statement[stmt.if]")[.](#stmt.if-4.sentence-1)
The [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]"), if any, in a consteval if statement
shall be a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")[.](#stmt.if-4.sentence-2)
[*Example [3](#stmt.if-example-3)*: constexpr void f(bool b) {if (true)if consteval { }else ; // error: not a [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]"); else not associated with outer if} — *end example*]
[5](#stmt.if-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L409)
If a consteval if statement is evaluated in a context
that is manifestly constant-evaluated ([[expr.const]](expr.const "7.7Constant expressions")),
the first substatement is executed[.](#stmt.if-5.sentence-1)
[*Note [2](#stmt.if-note-2)*:
The first substatement is an immediate function context[.](#stmt.if-5.sentence-2)
— *end note*]
Otherwise, if the else part of the selection statement is present,
then the second substatement is executed[.](#stmt.if-5.sentence-3)
Each substatement of a consteval if statement is a control-flow-limited
statement ([[stmt.label]](stmt.label "8.2Label"))[.](#stmt.if-5.sentence-4)
[6](#stmt.if-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L421)
An if statement of the form
if ! consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
is not itself a consteval if statement,
but is equivalent to the consteval if statement
if consteval { } else [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
An if statement of the form
if ! consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")1 else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")2
is not itself a consteval if statement,
but is equivalent to the consteval if statement
if consteval [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")2 else [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")1
[72)](#footnote-72)[72)](#footnoteref-72)
In other words, the else is associated with the nearest un-elsedif[.](#footnote-72.sentence-1)
### [8.5.3](#stmt.switch) The switch statement [[stmt.switch]](stmt.switch)
[1](#stmt.switch-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L444)
The switch statement causes control to be transferred to one of
several statements depending on the value of a condition[.](#stmt.switch-1.sentence-1)
[2](#stmt.switch-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L448)
If the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") is an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]"),
the value of the condition is the value of the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]");
otherwise, it is the value of the decision variable[.](#stmt.switch-2.sentence-1)
The value of the condition shall be of integral type, enumeration type, or class
type[.](#stmt.switch-2.sentence-2)
If of class type, the
condition is [contextually implicitly converted](conv#def:contextually_implicitly_converted "7.3Standard conversions[conv]") to
an integral or enumeration type[.](#stmt.switch-2.sentence-3)
If the (possibly converted) type is subject to [integral
promotions](conv.prom "7.3.7Integral promotions[conv.prom]"), the condition is converted
to the promoted type[.](#stmt.switch-2.sentence-4)
Any
statement within the switch statement can be labeled with one or
more case labels as follows:
case [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") :
where the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be
a converted [constant expression](expr.const "7.7Constant expressions[expr.const]") of the
adjusted type of the switch condition[.](#stmt.switch-2.sentence-5)
No two of the case constants in
the same switch shall have the same value after conversion[.](#stmt.switch-2.sentence-6)
[3](#stmt.switch-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L471)
There shall be at most one label of the formdefault : within a switch statement[.](#stmt.switch-3.sentence-1)
[4](#stmt.switch-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L479)
Switch statements can be nested; a case or default label
is associated with the smallest switch enclosing it[.](#stmt.switch-4.sentence-1)
[5](#stmt.switch-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L483)
When the switch statement is executed, its condition is
evaluated[.](#stmt.switch-5.sentence-1)
If one of the case constants has the same value as the condition,
control is passed to the statement following the matched case label[.](#stmt.switch-5.sentence-2)
If
no case constant matches the condition, and if there is adefault label, control passes to the statement labeled by the
default label[.](#stmt.switch-5.sentence-3)
If no case matches and if there is no default then none of the statements in the switch is executed[.](#stmt.switch-5.sentence-4)
[6](#stmt.switch-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L495)
case and default labels in themselves do not alter the
flow of control, which continues unimpeded across such labels[.](#stmt.switch-6.sentence-1)
To exit
from a switch, see break, [[stmt.break]](stmt.break "8.8.2The break statement")[.](#stmt.switch-6.sentence-2)
[*Note [1](#stmt.switch-note-1)*:
Usually, the substatement that is the subject of a switch is compound
and case and default labels appear on the top-level
statements contained within the (compound) substatement, but this is not
required[.](#stmt.switch-6.sentence-3)
Declarations can appear in the substatement of aswitch statement[.](#stmt.switch-6.sentence-4)
— *end note*]
[7](#stmt.switch-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L509)
A switch statement of the form
switch ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
switch ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
except that the [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") is in
the same scope as the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")[.](#stmt.switch-7.sentence-1)

View File

@@ -0,0 +1,39 @@
[stmt.select.general]
# 8 Statements [[stmt]](./#stmt)
## 8.5 Selection statements [[stmt.select]](stmt.select#general)
### 8.5.1 General [stmt.select.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L276)
Selection statements choose one of several flows of control[.](#1.sentence-1)
[selection-statement:](#nt:selection-statement "8.5.1General[stmt.select.general]")
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
if constexpropt ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
if !opt consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
if !opt consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") else [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
switch ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")opt [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
See [[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators") for the optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a condition[.](#1.sentence-2)
[*Note [1](#note-1)*:
An [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") ends with a semicolon[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L296)
[*Note [2](#note-2)*:
Each [*selection-statement*](#nt:selection-statement "8.5.1General[stmt.select.general]") and
each substatement of a [*selection-statement*](#nt:selection-statement "8.5.1General[stmt.select.general]") has a block scope ([[basic.scope.block]](basic.scope.block "6.4.3Block scope"))[.](#2.sentence-1)
— *end note*]

114
cppdraft/stmt/switch.md Normal file
View File

@@ -0,0 +1,114 @@
[stmt.switch]
# 8 Statements [[stmt]](./#stmt)
## 8.5 Selection statements [[stmt.select]](stmt.select#stmt.switch)
### 8.5.3 The switch statement [stmt.switch]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L444)
The switch statement causes control to be transferred to one of
several statements depending on the value of a condition[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L448)
If the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") is an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]"),
the value of the condition is the value of the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]");
otherwise, it is the value of the decision variable[.](#2.sentence-1)
The value of the condition shall be of integral type, enumeration type, or class
type[.](#2.sentence-2)
If of class type, the
condition is [contextually implicitly converted](conv#def:contextually_implicitly_converted "7.3Standard conversions[conv]") to
an integral or enumeration type[.](#2.sentence-3)
If the (possibly converted) type is subject to [integral
promotions](conv.prom "7.3.7Integral promotions[conv.prom]"), the condition is converted
to the promoted type[.](#2.sentence-4)
Any
statement within the switch statement can be labeled with one or
more case labels as follows:
case [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") :
where the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be
a converted [constant expression](expr.const "7.7Constant expressions[expr.const]") of the
adjusted type of the switch condition[.](#2.sentence-5)
No two of the case constants in
the same switch shall have the same value after conversion[.](#2.sentence-6)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L471)
There shall be at most one label of the formdefault : within a switch statement[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L479)
Switch statements can be nested; a case or default label
is associated with the smallest switch enclosing it[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L483)
When the switch statement is executed, its condition is
evaluated[.](#5.sentence-1)
If one of the case constants has the same value as the condition,
control is passed to the statement following the matched case label[.](#5.sentence-2)
If
no case constant matches the condition, and if there is adefault label, control passes to the statement labeled by the
default label[.](#5.sentence-3)
If no case matches and if there is no default then none of the statements in the switch is executed[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L495)
case and default labels in themselves do not alter the
flow of control, which continues unimpeded across such labels[.](#6.sentence-1)
To exit
from a switch, see break, [[stmt.break]](stmt.break "8.8.2The break statement")[.](#6.sentence-2)
[*Note [1](#note-1)*:
Usually, the substatement that is the subject of a switch is compound
and case and default labels appear on the top-level
statements contained within the (compound) substatement, but this is not
required[.](#6.sentence-3)
Declarations can appear in the substatement of aswitch statement[.](#6.sentence-4)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L509)
A switch statement of the form
switch ( [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
is equivalent to
{
[*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]")
switch ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) [*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
}
except that the [*init-statement*](stmt.pre#nt:init-statement "8.1Preamble[stmt.pre]") is in
the same scope as the [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")[.](#7.sentence-1)

47
cppdraft/stmt/while.md Normal file
View File

@@ -0,0 +1,47 @@
[stmt.while]
# 8 Statements [[stmt]](./#stmt)
## 8.6 Iteration statements [[stmt.iter]](stmt.iter#stmt.while)
### 8.6.2 The while statement [stmt.while]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L607)
In the while statement, the substatement is executed repeatedly
until the value of the condition ([[stmt.pre]](stmt.pre "8.1Preamble")) becomesfalse[.](#1.sentence-1)
The test takes place before each execution of the
substatement[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/statements.tex#L613)
A while statement is equivalent to
*label* :
{
if ( [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ) {
[*statement*](stmt.pre#nt:statement "8.1Preamble[stmt.pre]")
goto *label* ;
}
}
[*Note [1](#note-1)*:
The variable created in the condition is destroyed and created with each
iteration of the loop[.](#2.sentence-1)
[*Example [1](#example-1)*: struct A {int val;
A(int i) : val(i) { }~A() { }operator bool() { return val != 0; }};int i = 1;while (A a = i) {// ... i = 0;}
In the while-loop, the constructor and destructor are each called twice,
once for the condition that succeeds and once for the condition that
fails[.](#2.sentence-2)
— *end example*]
— *end note*]