-1- Except as indicated, statements are executed in sequence.
statement: labeled-statement expression-statement compound-statement selection-statement iteration-statement jump-statement declaration-statement try-block
-1- A statement can be labeled.
An identifier label declares the identifier. The only use of an identifier label is as the target of a goto. The scope of a label is the function in which it appears. Labels shall not be redeclared within a function. A label can be used in a goto statement before its definition. Labels have their own name space and do not interfere with other identifiers.labeled-statement: identifier : statement case constant-expression : statement default : statement
-2-
Case labels and default labels shall occur only in switch statements.
6.2 - Expression statement [stmt.expr]
-1- Expression statements have the form
The expression is evaluated and its value is discarded. The lvalue-to-rvalue (conv.lval), array-to-pointer (conv.array), and function-to-pointer (conv.func) standard conversions are not applied to the expression. All side effects from an expression statement are completed before the next statement is executed. An expression statement with the expression missing is called a null statement. [Note: Most statements are expression statements --- usually assignments or function calls. A null statement is useful to carry a label just before the } of a compound statement and to supply a null body to an iteration statement such as a while statement (stmt.while). ]expression-statement: expressionopt ;
-1- So that several statements can be used where one is expected, the compound statement (also, and equivalently, called ``block'') is provided.
compound-statement: { statement-seqopt }
A compound statement defines a local scope (basic.scope). [Note: a declaration is a statement (stmt.dcl). ]statement-seq: statement statement-seq statement
-1- Selection statements choose one of several flows of control.
selection-statement: if ( condition ) statement if ( condition ) statement else statement switch ( condition ) statement
In clause stmt.stmt, the term substatement refers to the contained statement or statements that appear in the syntax notation. The substatement in a selection-statement (both substatements, in the else form of the if statement) implicitly defines a local scope (basic.scope). If the substatement in a selection-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original substatement. [Example:condition: expression type-specifier-seq declarator = assignment-expression
can be equivalently rewritten asif (x) int i;
Thus after the if statement, i is no longer in scope. ]if (x) { int i; }
-2- The rules for conditions apply both to selection-statements and to the for and while statements (stmt.iter). The declarator shall not specify a function or an array. The type-specifier-seq shall not contain typedef and shall not declare a new class or enumeration.
-3- A name introduced by a declaration in a condition (either introduced by the type-specifier-seq or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition. If the name is re-declared in the outermost block of a substatement controlled by the condition, the declaration that re-declares the name is ill-formed. [Example:
if (int x = f()) { int x; //ill-formed, redeclaration of x } else { int x; // ill-formed, redeclaration of x }
-4- The value of a condition that is an initialized declaration in a statement other than a switch statement is the value of the declared variable implicitly converted to type bool. If that conversion is ill-formed, the program is ill-formed. The value of a condition that is an initialized declaration in a switch statement is the value of the declared variable if it has integral or enumeration type, or of that variable implicitly converted to integral or enumeration type otherwise. The value of a condition that is an expression is the value of the expression, implicitly converted to bool for statements other than switch; if that conversion is ill-formed, the program is ill-formed. The value of the condition will be referred to as simply ``the condition'' where the usage is unambiguous.
-5-
If a
condition
can be syntactically resolved as either an expression or the
declaration of a local name, it is interpreted as a declaration.
6.4.1 - The if statement [stmt.if]
-1- If the condition (stmt.select) yields true the first substatement is executed. If the else part of the selection statement is present and the condition yields false, the second substatement is executed. In the second form of if statement (the one including else), if the first substatement is also an if statement then that inner if statement shall contain an else part.*
[Footnote: In other words, the else is associated with the nearest un-elsed if. --- end foonote]
-1- The switch statement causes control to be transferred to one of several statements depending on the value of a condition.
-2- The condition shall be of integral type, enumeration type, or of a class type for which a single conversion function to integral or enumeration type exists (class.conv). If the condition is of class type, the condition is converted by calling that conversion function, and the result of the conversion is used in place of the original condition for the remainder of this section. Integral promotions are performed. Any statement within the switch statement can be labeled with one or more case labels as follows:
where the constant-expression shall be an integral constant-expression. The integral constant-expression (expr.const) is implicitly converted to the promoted type of the switch condition. No two of the case constants in the same switch shall have the same value after conversion to the promoted type of the switch condition.caseconstant-expression :
-3- There shall be at most one label of the form
within a switch statement.default :
-4- Switch statements can be nested; a case or default label is associated with the smallest switch enclosing it.
-5- When the switch statement is executed, its condition is evaluated and compared with each case constant. If one of the case constants is equal to the value of the condition, control is passed to the statement following the matched case label. If no case constant matches the condition, and if there is a default label, control passes to the statement labeled by the default label. If no case matches and if there is no default then none of the statements in the switch is executed.
-6-
case
and
default
labels in themselves do not alter the flow of control,
which continues unimpeded across such labels.
To exit from a switch, see
break,
stmt.break.
[Note:
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.
Declarations can appear in the
substatement
of a
switch-statement.
]
6.5 - Iteration statements [stmt.iter]
-1- Iteration statements specify looping.
iteration-statement: while ( condition ) statement do statement while ( expression ) ; for ( for-init-statement conditionopt ; expressionopt ) statement
[Note: a for-init-statement ends with a semicolon. ]for-init-statement: expression-statement simple-declaration
-2- The substatement in an iteration-statement implicitly defines a local scope (basic.scope) which is entered and exited each time through the loop.
-3- If the substatement in an iteration-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original statement. [Example:
can be equivalently rewritten aswhile (--x >= 0) int i;
Thus after the while statement, i is no longer in scope. ]while (--x >= 0) { int i; }
-4-
[Note:
The requirements on
conditions
in iteration statements are described in stmt.select.
--- end note]
6.5.1 - The while statement [stmt.while]
-1- In the while statement the substatement is executed repeatedly until the value of the condition (stmt.select) becomes false. The test takes place before each execution of the substatement.
-2- When the condition of a while statement is a declaration, the scope of the variable that is declared extends from its point of declaration (basic.scope.pdecl) to the end of the while statement. A while statement of the form
is equivalent towhile (T t = x)statement
The object created in a condition is destroyed and created with each iteration of the loop. [Example:label: { //start of condition scope T t = x; if (t) { statement goto label; } } // end of condition scope
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. ]struct A { int val; A(int i) : val(i) { } ~A() { } operator bool() { return val != 0; } }; int i = 1; while (A a = i) { //... i = 0; }
-1- The expression is implicitly converted to bool; if that is not possible, the program is ill-formed.
-2-
In the
do
statement the
substatement is executed repeatedly until
the value of the expression becomes
false.
The test takes place after each execution of the
statement.
6.5.3 - The for statement [stmt.for]
-1- The for statement
is equivalent tofor (for-init-statement conditionopt ; expressionopt ) statement
except that names declared in the for-init-statement are in the same declarative-region as those declared in the condition, and except that a continue in statement (not enclosed in another iteration statement) will execute expression before re-evaluating condition. [Note: Thus the first statement specifies initialization for the loop; the condition (stmt.select) specifies a test, made before each iteration, such that the loop is exited when the condition becomes false; the expression often specifies incrementing that is done after each iteration. ]{for-init-statement while ( condition ) { statement expression ; } }
-2- Either or both of the condition and the expression can be omitted. A missing condition makes the implied while clause equivalent to while(true).
-3- If the for-init-statement is a declaration, the scope of the name(s) declared extends to the end of the for-statement. [Example:
int i = 42; int a[10]; for (int i = 0; i < 10; i++) a[i] = i; int j = i; //j = 42
-1- Jump statements unconditionally transfer control.
jump-statement: break ; continue ; return expressionopt ; goto identifier ;
-2-
On exit from a scope (however accomplished), destructors (class.dtor)
are called for all
constructed
objects with automatic storage duration (basic.stc.auto)
(named objects or temporaries)
that are declared in that scope,
in the reverse order of their declaration.
Transfer out of a loop, out of a block, or back past an initialized
variable
with automatic storage duration
involves the destruction of
variables with automatic storage duration that are in scope
at the point transferred from but not at the point transferred
to.
(See stmt.dcl for transfers into blocks).
[Note:
However, the program can be terminated (by calling
exit()
or
abort()(lib.support.start.term),
for example) without destroying class objects with automatic storage duration.
]
6.6.1 - The break statement [stmt.break]
-1-
The
break
statement shall occur only in an
iteration-statement
or a
switch
statement and causes termination of the smallest enclosing
iteration-statement
or
switch
statement;
control passes to the
statement following the terminated statement, if any.
6.6.2 - The continue statement [stmt.cont]
-1- The continue statement shall occur only in an iteration-statement and causes control to pass to the loop-continuation portion of the smallest enclosing iteration-statement, that is, to the end of the loop. More precisely, in each of the statements
a continue not contained in an enclosed iteration statement is equivalent to goto contin.[ROFF TAB STOPS SET] [ROFF TAB STOPS SET] while (foo) { do { for (;;) { { { { // ... // ... // ... } } } contin: ; contin: ; contin: ; } } while (foo); }
-1- A function returns to its caller by the return statement.
-2- A return statement without an expression can be used only in functions that do not return a value, that is, a function with the return type void, a constructor (class.ctor), or a destructor (class.dtor). A return statement with an expression of non-void type can be used only in functions returning a value; the value of the expression is returned to the caller of the function. The expression is implicitly converted to the return type of the function in which it appears. A return statement can involve the construction and copy of a temporary object (class.temporary). Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
-3-
A return statement with an expression of type ``cv void'' can be used
only in functions with a return type of
cv
void; the expression is
evaluated just before the function returns to its caller.
6.6.4 - The goto statement [stmt.goto]
-1-
The
goto
statement unconditionally transfers control to the statement labeled by the
identifier.
The identifier shall be a label
(stmt.label)
located in the current function.
6.7 - Declaration statement [stmt.dcl]
-1- A declaration statement introduces one or more new identifiers into a block; it has the form
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, after which it resumes its force.declaration-statement: block-declaration
-2- Variables with automatic storage duration (basic.stc.auto) are initialized each time their declaration-statement is executed. Variables with automatic storage duration declared in the block are destroyed on exit from the block (stmt.jump).
-3- It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps*
[Footnote: The transfer from the condition of a switch statement to a case label is considered a jump in this respect. --- end foonote]from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (basic.types) and is declared without an initializer (dcl.init).
void f() { //... goto lx; // ill-formed: 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 }
-4- The zero-initialization (dcl.init) of all local objects with static storage duration (basic.stc.static) is performed before any other initialization takes place. A local object of POD type (basic.types) with static storage duration initialized with constant-expressions is initialized before its block is first entered. An implementation is permitted to perform early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope (basic.start.init). Otherwise such an object is initialized the first time control passes through its declaration; such an object is considered initialized upon the completion of its initialization. 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. If control re-enters the declaration (recursively) while the object is being initialized, the behavior is undefined. [Example:
int foo(int i) { static int s = foo(2*i); //recursive call - undefined return i+1; }
-5-
The destructor for a local object with static storage duration
will be executed if and only if the variable was constructed.
[Note:
basic.start.term
describes the order in which local objects with static storage duration are
destroyed.
]
6.8 - Ambiguity resolution [stmt.ambig]
-1- There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (expr.type.conv) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration. [Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. This disambiguates many examples. [Example: assuming T is a simple-type-specifier (dcl.type),
T(a)->m = 7; //expression-statement T(a)++; // expression-statement T(a,5)<<c; // expression-statement
In the last example above, g, which is a pointer to T, is initialized to double(3). This is of course ill-formed for semantic reasons, but that does not affect the syntactic analysis.T(*d)(int); //declaration T(e)[5]; // declaration T(f) = { 1, 2 }; // declaration T(*g)(double(3)); // declaration
-2- The remaining cases are declarations. [Example:
class T { //... public: T(); T(int); T(int, int); }; T(a); // declaration T(*b)(); // declaration T(c)=7; // declaration T(d),e,f=3; // declaration extern int h; T(g)(h,2); // declaration
-3- The disambiguation is purely syntactic; that is, the meaning of the names occurring in such a statement, beyond whether they are type-names or not, is not generally used in or changed by the disambiguation. Class templates are instantiated as necessary to determine if a qualified name is a type-name. Disambiguation precedes parsing, and a statement disambiguated as a declaration may be an ill-formed declaration. If, during parsing, a name in a template parameter is bound differently than it would be bound during a trial parse, the program is ill-formed. No diagnostic is required. [Note: This can occur only when the name is declared earlier in the declaration. ] [Example:
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 (*(*b)(T2(c)))(int(d)); // a variable of type T1 // but this will not allow // the last part of the // declaration to parse // properly since it depends // on T2 being a type-name }