[intro.execution] (original) (raw)

6 Basics [basic]

6.9 Program execution [basic.exec]

6.9.1 Sequential execution [intro.execution]

Such an object exists and retains its last-stored value during the execution of the block and while the block is suspended (by a call of a function, suspension of a coroutine ([expr.await]), or receipt of a signal).

[ Example

:

struct A { int x; }; struct B { int y; struct A a; }; B b = { 5, { 1+1 } };

The constituent expressions of the initializerused for the initialization of b are 5 and 1+1.

end example

]

The immediate subexpressions of an expression E are

A subexpression of an expression E is an immediate subexpression of E or a subexpression of an immediate subexpression of E.

A full-expression is

If a language construct is defined to produce an implicit call of a function, a use of the language construct is considered to be an expression for the purposes of this definition.

Conversions applied to the result of an expression in order to satisfy the requirements of the language construct in which the expression appears are also considered to be part of the full-expression.

For an initializer, performing the initialization of the entity (including evaluating default member initializers of an aggregate) is also considered part of the full-expression.

[ Example

:

struct S { S(int i): I(i) { }
int& v() { return I; } ~S() noexcept(false) { } private: int I; };

S s1(1);
void f() { S s2 = 2;
if (S(3).v())

{ } bool b = noexcept(S());

} struct B { B(S = S(0)); }; B b[2] = { B(), B() };

end example

]

[ Note

:

The evaluation of a full-expression can include the evaluation of subexpressions that are not lexically part of the full-expression.

For example, subexpressions involved in evaluating default arguments ([dcl.fct.default]) are considered to be created in the expression that calls the function, not the expression that defines the default argument.

end note

]

Reading an object designated by a volatileglvalue ([basic.lval]), modifying an object, calling a library I/O function, or calling a function that does any of those operations are allside effects, which are changes in the state of the execution environment.

Evaluation of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and initiation of side effects.

When a call to a library I/O function returns or an access through a volatile glvalue is evaluated the side effect is considered complete, even though some external actions implied by the call (such as the I/O itself) or by the volatile access may not have completed yet.

Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread ([intro.multithread]), which induces a partial order among those evaluations.

Given any two evaluations A andB, if A is sequenced before B(or, equivalently, B is sequenced after A), then the execution ofA shall precede the execution of B.

If A is not sequenced before B and B is not sequenced before A, then A andB are unsequenced.

[ Note

:

The execution of unsequenced evaluations can overlap.

end note

]

Evaluations A and B areindeterminately sequenced when either A is sequenced beforeB or B is sequenced before A, but it is unspecified which.

[ Note

:

Indeterminately sequenced evaluations cannot overlap, but either could be executed first.

end note

]

An expression Xis said to be sequenced before an expression Y if every value computation and every side effect associated with the expression Xis sequenced before every value computation and every side effect associated with the expression Y.

Everyvalue computation andside effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.44

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.

[ Note

:

In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations.

end note

]

The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.

If aside effect on a memory location ([intro.memory]) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent ([intro.multithread]), the behavior is undefined.

[ Note

:

The next subclause imposes similar, but more complex restrictions on potentially concurrent computations.

end note

]

[ Example

:

void g(int i) { i = 7, i++, i++;

i = i++ + 1;
i = i++ + i;
i = i + 1;
}

end example

]

When calling a function (whether or not the function is inline), everyvalue computation andside effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.

For each function invocation F, for every evaluation A that occurs within F and every evaluation B that does not occur within F but is evaluated on the same thread and as part of the same signal handler (if any), either A is sequenced before B orB is sequenced before A.45

[ Note

:

If A and B would not otherwise be sequenced then they are indeterminately sequenced.

end note

]

Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit.

[ Example

:

Evaluation of a new-expression invokes one or more allocation and constructor functions; see [expr.new].

For another example, invocation of a conversion function ([class.conv.fct]) can arise in contexts in which no function call syntax appears.

end example

]

The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be.

If a signal handler is executed as a result of a call to the std​::​raisefunction, then the execution of the handler is sequenced after the invocation of the std​::​raise function and before its return.

[ Note

:

When a signal is received for another reason, the execution of the signal handler is usually unsequenced with respect to the rest of the program.

end note

]