From Jason Turner

[basic.start]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpm64rz_bj/{from.md → to.md} +179 -127
tmp/tmpm64rz_bj/{from.md → to.md} RENAMED
@@ -1,22 +1,27 @@
1
  ## Start and termination <a id="basic.start">[[basic.start]]</a>
2
 
3
- ### Main function <a id="basic.start.main">[[basic.start.main]]</a>
4
 
5
- A program shall contain a global function called `main`, which is the
6
- designated start of the program. It is *implementation-defined* whether
7
- a program in a freestanding environment is required to define a `main`
8
- function. In a freestanding environment, start-up and termination is
 
 
 
 
 
9
  *implementation-defined*; start-up contains the execution of
10
  constructors for objects of namespace scope with static storage
11
  duration; termination contains the execution of destructors for objects
12
- with static storage duration.
13
 
14
  An implementation shall not predefine the `main` function. This function
15
- shall not be overloaded. It shall have a declared return type of type
16
- `int`, but otherwise its type is *implementation-defined*. An
17
- implementation shall allow both
18
 
19
  - a function of `()` returning `int` and
20
  - a function of `(int`, pointer to pointer to `char)` returning `int`
21
 
22
  as the type of `main` ([[dcl.fct]]). In the latter form, for purposes
@@ -27,107 +32,85 @@ the program is run. If `argc` is nonzero these arguments shall be
27
  supplied in `argv[0]` through `argv[argc-1]` as pointers to the initial
28
  characters of null-terminated multibyte strings (NTMBS s) (
29
  [[multibyte.strings]]) and `argv[0]` shall be the pointer to the initial
30
  character of a NTMBSthat represents the name used to invoke the program
31
  or `""`. The value of `argc` shall be non-negative. The value of
32
- `argv[argc]` shall be 0. It is recommended that any further (optional)
33
- parameters be added after `argv`.
 
 
34
 
35
  The function `main` shall not be used within a program. The linkage (
36
  [[basic.link]]) of `main` is *implementation-defined*. A program that
37
  defines `main` as deleted or that declares `main` to be `inline`,
38
- `static`, or `constexpr` is ill-formed. The name `main` is not otherwise
39
- reserved. member functions, classes, and enumerations can be called
40
- `main`, as can entities in other namespaces.
 
 
 
 
 
41
 
42
  Terminating the program without leaving the current block (e.g., by
43
  calling the function `std::exit(int)` ([[support.start.term]])) does
44
  not destroy any objects with automatic storage duration (
45
  [[class.dtor]]). If `std::exit` is called to end a program during the
46
  destruction of an object with static or thread storage duration, the
47
  program has undefined behavior.
48
 
49
  A return statement in `main` has the effect of leaving the main function
50
  (destroying any objects with automatic storage duration) and calling
51
- `std::exit` with the return value as the argument. If control reaches
52
- the end of `main` without encountering a `return` statement, the effect
53
- is that of executing
54
 
55
- ``` cpp
56
- return 0;
57
- ```
58
 
59
- ### Initialization of non-local variables <a id="basic.start.init">[[basic.start.init]]</a>
60
-
61
- There are two broad classes of named non-local variables: those with
62
- static storage duration ([[basic.stc.static]]) and those with thread
63
- storage duration ([[basic.stc.thread]]). Non-local variables with
64
- static storage duration are initialized as a consequence of program
65
- initiation. Non-local variables with thread storage duration are
66
  initialized as a consequence of thread execution. Within each of these
67
  phases of initiation, initialization occurs as follows.
68
 
69
- Variables with static storage duration ([[basic.stc.static]]) or thread
70
- storage duration ([[basic.stc.thread]]) shall be zero-initialized (
71
- [[dcl.init]]) before any other initialization takes place. A *constant
72
- initializer* for an object `o` is an expression that is a constant
73
- expression, except that it may also invoke `constexpr` constructors for
74
- `o` and its subobjects even if those objects are of non-literal class
75
- types such a class may have a non-trivial destructor . *Constant
76
- initialization* is performed:
77
 
78
- - if each full-expression (including implicit conversions) that appears
79
- in the initializer of a reference with static or thread storage
80
- duration is a constant expression ([[expr.const]]) and the reference
81
- is bound to an lvalue designating an object with static storage
82
- duration, to a temporary (see  [[class.temporary]]), or to a function;
83
- - if an object with static or thread storage duration is initialized by
84
- a constructor call, and if the initialization full-expression is a
85
- constant initializer for the object;
86
- - if an object with static or thread storage duration is not initialized
87
- by a constructor call and if either the object is value-initialized or
88
- every full-expression that appears in its initializer is a constant
89
- expression.
90
 
91
- Together, zero-initialization and constant initialization are called
92
- *static initialization*; all other initialization is *dynamic
93
- initialization*. Static initialization shall be performed before any
94
- dynamic initialization takes place. Dynamic initialization of a
95
- non-local variable with static storage duration is either ordered or
96
- unordered. Definitions of explicitly specialized class template static
97
- data members have ordered initialization. Other class template static
98
- data members (i.e., implicitly or explicitly instantiated
99
- specializations) have unordered initialization. Other non-local
100
- variables with static storage duration have ordered initialization.
101
- Variables with ordered initialization defined within a single
102
- translation unit shall be initialized in the order of their definitions
103
- in the translation unit. If a program starts a thread (
104
- [[thread.threads]]), the subsequent initialization of a variable is
105
- unsequenced with respect to the initialization of a variable defined in
106
- a different translation unit. Otherwise, the initialization of a
107
- variable is indeterminately sequenced with respect to the initialization
108
- of a variable defined in a different translation unit. If a program
109
- starts a thread, the subsequent unordered initialization of a variable
110
- is unsequenced with respect to every other dynamic initialization.
111
- Otherwise, the unordered initialization of a variable is indeterminately
112
- sequenced with respect to every other dynamic initialization. This
113
- definition permits initialization of a sequence of ordered variables
114
- concurrently with another sequence. The initialization of local static
115
- variables is described in  [[stmt.dcl]].
116
 
117
  An implementation is permitted to perform the initialization of a
118
- non-local variable with static storage duration as a static
119
  initialization even if such initialization is not required to be done
120
  statically, provided that
121
 
122
  - the dynamic version of the initialization does not change the value of
123
- any other object of namespace scope prior to its initialization, and
 
124
  - the static version of the initialization produces the same value in
125
  the initialized variable as would be produced by the dynamic
126
  initialization if all variables not required to be initialized
127
  statically were initialized dynamically.
128
 
 
 
129
  As a consequence, if the initialization of an object `obj1` refers to an
130
  object `obj2` of namespace scope potentially requiring dynamic
131
  initialization and defined later in the same translation unit, it is
132
  unspecified whether the value of `obj2` used will be the value of the
133
  fully initialized `obj2` (because `obj2` was statically initialized) or
@@ -141,16 +124,65 @@ double d2 = d1; // unspecified:
141
  // dynamically initialized to 0.0 if d1 is
142
  // dynamically initialized, or 1.0 otherwise
143
  double d1 = fd(); // may be initialized statically or dynamically to 1.0
144
  ```
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  It is *implementation-defined* whether the dynamic initialization of a
147
- non-local variable with static storage duration is done before the first
148
- statement of `main`. If the initialization is deferred to some point in
149
- time after the first statement of `main`, it shall occur before the
150
- first odr-use ([[basic.def.odr]]) of any function or variable defined
151
- in the same translation unit as the variable to be initialized.[^11]
 
 
 
 
 
 
 
152
 
153
  ``` cpp
154
  // - File 1 -
155
  #include "a.h"
156
  #include "b.h"
@@ -173,91 +205,111 @@ int main() {
173
  a.Use();
174
  b.Use();
175
  }
176
  ```
177
 
178
- It is implementation-defined whether either `a` or `b` is initialized
179
  before `main` is entered or whether the initializations are delayed
180
  until `a` is first odr-used in `main`. In particular, if `a` is
181
  initialized before `main` is entered, it is not guaranteed that `b` will
182
  be initialized before it is odr-used by the initialization of `a`, that
183
  is, before `A::A` is called. If, however, `a` is initialized at some
184
  point after the first statement of `main`, `b` will be initialized prior
185
  to its use in `A::A`.
186
 
 
 
187
  It is *implementation-defined* whether the dynamic initialization of a
188
- non-local variable with static or thread storage duration is done before
189
- the first statement of the initial function of the thread. If the
190
- initialization is deferred to some point in time after the first
191
- statement of the initial function of the thread, it shall occur before
192
- the first odr-use ([[basic.def.odr]]) of any variable with thread
193
- storage duration defined in the same translation unit as the variable to
194
- be initialized.
 
 
 
 
 
 
 
 
195
 
196
  If the initialization of a non-local variable with static or thread
197
  storage duration exits via an exception, `std::terminate` is called (
198
  [[except.terminate]]).
199
 
200
  ### Termination <a id="basic.start.term">[[basic.start.term]]</a>
201
 
202
  Destructors ([[class.dtor]]) for initialized objects (that is, objects
203
- whose lifetime ([[basic.life]]) has begun) with static storage duration
204
- are called as a result of returning from `main` and as a result of
205
- calling `std::exit` ([[support.start.term]]). Destructors for
206
- initialized objects with thread storage duration within a given thread
207
- are called as a result of returning from the initial function of that
208
- thread and as a result of that thread calling `std::exit`. The
209
- completions of the destructors for all initialized objects with thread
210
- storage duration within that thread are sequenced before the initiation
211
- of the destructors of any object with static storage duration. If the
212
- completion of the constructor or dynamic initialization of an object
213
- with thread storage duration is sequenced before that of another, the
214
- completion of the destructor of the second is sequenced before the
215
- initiation of the destructor of the first. If the completion of the
216
- constructor or dynamic initialization of an object with static storage
217
- duration is sequenced before that of another, the completion of the
218
- destructor of the second is sequenced before the initiation of the
219
- destructor of the first. This definition permits concurrent destruction.
220
- If an object is initialized statically, the object is destroyed in the
221
- same order as if the object was dynamically initialized. For an object
222
- of array or class type, all subobjects of that object are destroyed
223
- before any block-scope object with static storage duration initialized
224
- during the construction of the subobjects is destroyed. If the
225
- destruction of an object with static or thread storage duration exits
226
- via an exception, `std::terminate` is called ([[except.terminate]]).
 
 
 
 
 
 
 
 
227
 
228
  If a function contains a block-scope object of static or thread storage
229
  duration that has been destroyed and the function is called during the
230
  destruction of an object with static or thread storage duration, the
231
  program has undefined behavior if the flow of control passes through the
232
  definition of the previously destroyed block-scope object. Likewise, the
233
  behavior is undefined if the block-scope object is used indirectly
234
  (i.e., through a pointer) after its destruction.
235
 
236
  If the completion of the initialization of an object with static storage
237
- duration is sequenced before a call to `std::atexit` (see `<cstdlib>`, 
238
- [[support.start.term]]), the call to the function passed to
239
- `std::atexit` is sequenced before the call to the destructor for the
240
- object. If a call to `std::atexit` is sequenced before the completion of
241
- the initialization of an object with static storage duration, the call
242
- to the destructor for the object is sequenced before the call to the
243
- function passed to `std::atexit`. If a call to `std::atexit` is
244
- sequenced before another call to `std::atexit`, the call to the function
245
- passed to the second `std::atexit` call is sequenced before the call to
246
- the function passed to the first `std::atexit` call.
 
247
 
248
  If there is a use of a standard library object or function not permitted
249
  within signal handlers ([[support.runtime]]) that does not happen
250
  before ([[intro.multithread]]) completion of destruction of objects
251
  with static storage duration and execution of `std::atexit` registered
252
  functions ([[support.start.term]]), the program has undefined behavior.
253
- If there is a use of an object with static storage duration that does
254
- not happen before the object’s destruction, the program has undefined
255
- behavior. Terminating every thread before a call to `std::exit` or the
256
- exit from `main` is sufficient, but not necessary, to satisfy these
257
- requirements. These requirements permit thread managers as
258
- static-storage-duration objects.
 
259
 
260
  Calling the function `std::abort()` declared in `<cstdlib>` terminates
261
  the program without executing any destructors and without calling the
262
  functions passed to `std::atexit()` or `std::at_quick_exit()`.
263
 
 
1
  ## Start and termination <a id="basic.start">[[basic.start]]</a>
2
 
3
+ ### `main` function <a id="basic.start.main">[[basic.start.main]]</a>
4
 
5
+ A program shall contain a global function called `main`. Executing a
6
+ program starts a main thread of execution ([[intro.multithread]],
7
+ [[thread.threads]]) in which the `main` function is invoked, and in
8
+ which variables of static storage duration might be initialized (
9
+ [[basic.start.static]]) and destroyed ([[basic.start.term]]). It is
10
+ *implementation-defined* whether a program in a freestanding environment
11
+ is required to define a `main` function.
12
+
13
+ [*Note 1*: In a freestanding environment, start-up and termination is
14
  *implementation-defined*; start-up contains the execution of
15
  constructors for objects of namespace scope with static storage
16
  duration; termination contains the execution of destructors for objects
17
+ with static storage duration. — *end note*]
18
 
19
  An implementation shall not predefine the `main` function. This function
20
+ shall not be overloaded. Its type shall have C++language linkage and it
21
+ shall have a declared return type of type `int`, but otherwise its type
22
+ is *implementation-defined*. An implementation shall allow both
23
 
24
  - a function of `()` returning `int` and
25
  - a function of `(int`, pointer to pointer to `char)` returning `int`
26
 
27
  as the type of `main` ([[dcl.fct]]). In the latter form, for purposes
 
32
  supplied in `argv[0]` through `argv[argc-1]` as pointers to the initial
33
  characters of null-terminated multibyte strings (NTMBS s) (
34
  [[multibyte.strings]]) and `argv[0]` shall be the pointer to the initial
35
  character of a NTMBSthat represents the name used to invoke the program
36
  or `""`. The value of `argc` shall be non-negative. The value of
37
+ `argv[argc]` shall be 0.
38
+
39
+ [*Note 2*: It is recommended that any further (optional) parameters be
40
+ added after `argv`. — *end note*]
41
 
42
  The function `main` shall not be used within a program. The linkage (
43
  [[basic.link]]) of `main` is *implementation-defined*. A program that
44
  defines `main` as deleted or that declares `main` to be `inline`,
45
+ `static`, or `constexpr` is ill-formed. The `main` function shall not be
46
+ declared with a *linkage-specification* ([[dcl.link]]). A program that
47
+ declares a variable `main` at global scope or that declares the name
48
+ `main` with C language linkage (in any namespace) is ill-formed. The
49
+ name `main` is not otherwise reserved.
50
+
51
+ [*Example 1*: Member functions, classes, and enumerations can be called
52
+ `main`, as can entities in other namespaces. — *end example*]
53
 
54
  Terminating the program without leaving the current block (e.g., by
55
  calling the function `std::exit(int)` ([[support.start.term]])) does
56
  not destroy any objects with automatic storage duration (
57
  [[class.dtor]]). If `std::exit` is called to end a program during the
58
  destruction of an object with static or thread storage duration, the
59
  program has undefined behavior.
60
 
61
  A return statement in `main` has the effect of leaving the main function
62
  (destroying any objects with automatic storage duration) and calling
63
+ `std::exit` with the return value as the argument. If control flows off
64
+ the end of the *compound-statement* of `main`, the effect is equivalent
65
+ to a `return` with operand `0` (see also [[except.handle]]).
66
 
67
+ ### Static initialization <a id="basic.start.static">[[basic.start.static]]</a>
 
 
68
 
69
+ Variables with static storage duration are initialized as a consequence
70
+ of program initiation. Variables with thread storage duration are
 
 
 
 
 
71
  initialized as a consequence of thread execution. Within each of these
72
  phases of initiation, initialization occurs as follows.
73
 
74
+ A *constant initializer* for a variable or temporary object `o` is an
75
+ initializer whose full-expression is a constant expression, except that
76
+ if `o` is an object, such an initializer may also invoke constexpr
77
+ constructors for `o` and its subobjects even if those objects are of
78
+ non-literal class types.
 
 
 
79
 
80
+ [*Note 1*: Such a class may have a non-trivial
81
+ destructor. *end note*]
 
 
 
 
 
 
 
 
 
 
82
 
83
+ *Constant initialization* is performed if a variable or temporary object
84
+ with static or thread storage duration is initialized by a constant
85
+ initializer for the entity. If constant initialization is not performed,
86
+ a variable with static storage duration ([[basic.stc.static]]) or
87
+ thread storage duration ([[basic.stc.thread]]) is zero-initialized (
88
+ [[dcl.init]]). Together, zero-initialization and constant initialization
89
+ are called *static initialization*; all other initialization is *dynamic
90
+ initialization*. All static initialization strongly happens before (
91
+ [[intro.races]]) any dynamic initialization.
92
+
93
+ [*Note 2*: The dynamic initialization of non-local variables is
94
+ described in  [[basic.start.dynamic]]; that of local static variables is
95
+ described in  [[stmt.dcl]]. *end note*]
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
  An implementation is permitted to perform the initialization of a
98
+ variable with static or thread storage duration as a static
99
  initialization even if such initialization is not required to be done
100
  statically, provided that
101
 
102
  - the dynamic version of the initialization does not change the value of
103
+ any other object of static or thread storage duration prior to its
104
+ initialization, and
105
  - the static version of the initialization produces the same value in
106
  the initialized variable as would be produced by the dynamic
107
  initialization if all variables not required to be initialized
108
  statically were initialized dynamically.
109
 
110
+ [*Note 3*:
111
+
112
  As a consequence, if the initialization of an object `obj1` refers to an
113
  object `obj2` of namespace scope potentially requiring dynamic
114
  initialization and defined later in the same translation unit, it is
115
  unspecified whether the value of `obj2` used will be the value of the
116
  fully initialized `obj2` (because `obj2` was statically initialized) or
 
124
  // dynamically initialized to 0.0 if d1 is
125
  // dynamically initialized, or 1.0 otherwise
126
  double d1 = fd(); // may be initialized statically or dynamically to 1.0
127
  ```
128
 
129
+ — *end note*]
130
+
131
+ ### Dynamic initialization of non-local variables <a id="basic.start.dynamic">[[basic.start.dynamic]]</a>
132
+
133
+ Dynamic initialization of a non-local variable with static storage
134
+ duration is unordered if the variable is an implicitly or explicitly
135
+ instantiated specialization, is partially-ordered if the variable is an
136
+ inline variable that is not an implicitly or explicitly instantiated
137
+ specialization, and otherwise is ordered.
138
+
139
+ [*Note 1*: An explicitly specialized non-inline static data member or
140
+ variable template specialization has ordered
141
+ initialization. — *end note*]
142
+
143
+ Dynamic initialization of non-local variables `V` and `W` with static
144
+ storage duration are ordered as follows:
145
+
146
+ - If `V` and `W` have ordered initialization and `V` is defined before
147
+ `W` within a single translation unit, the initialization of `V` is
148
+ sequenced before the initialization of `W`.
149
+ - If `V` has partially-ordered initialization, `W` does not have
150
+ unordered initialization, and `V` is defined before `W` in every
151
+ translation unit in which `W` is defined, then
152
+ - if the program starts a thread ([[intro.multithread]]) other than
153
+ the main thread ([[basic.start.main]]), the initialization of `V`
154
+ strongly happens before the initialization of `W`;
155
+ - otherwise, the initialization of `V` is sequenced before the
156
+ initialization of `W`.
157
+ - Otherwise, if the program starts a thread other than the main thread
158
+ before either `V` or `W` is initialized, it is unspecified in which
159
+ threads the initializations of `V` and `W` occur; the initializations
160
+ are unsequenced if they occur in the same thread.
161
+ - Otherwise, the initializations of `V` and `W` are indeterminately
162
+ sequenced.
163
+
164
+ [*Note 2*: This definition permits initialization of a sequence of
165
+ ordered variables concurrently with another sequence. — *end note*]
166
+
167
+ A *non-initialization odr-use* is an odr-use ([[basic.def.odr]]) not
168
+ caused directly or indirectly by the initialization of a non-local
169
+ static or thread storage duration variable.
170
+
171
  It is *implementation-defined* whether the dynamic initialization of a
172
+ non-local non-inline variable with static storage duration is sequenced
173
+ before the first statement of `main` or is deferred. If it is deferred,
174
+ it strongly happens before any non-initialization odr-use of any
175
+ non-inline function or non-inline variable defined in the same
176
+ translation unit as the variable to be initialized. [^11] It is
177
+ *implementation-defined* in which threads and at which points in the
178
+ program such deferred dynamic initialization occurs.
179
+
180
+ [*Note 3*: Such points should be chosen in a way that allows the
181
+ programmer to avoid deadlocks. — *end note*]
182
+
183
+ [*Example 1*:
184
 
185
  ``` cpp
186
  // - File 1 -
187
  #include "a.h"
188
  #include "b.h"
 
205
  a.Use();
206
  b.Use();
207
  }
208
  ```
209
 
210
+ It is *implementation-defined* whether either `a` or `b` is initialized
211
  before `main` is entered or whether the initializations are delayed
212
  until `a` is first odr-used in `main`. In particular, if `a` is
213
  initialized before `main` is entered, it is not guaranteed that `b` will
214
  be initialized before it is odr-used by the initialization of `a`, that
215
  is, before `A::A` is called. If, however, `a` is initialized at some
216
  point after the first statement of `main`, `b` will be initialized prior
217
  to its use in `A::A`.
218
 
219
+ — *end example*]
220
+
221
  It is *implementation-defined* whether the dynamic initialization of a
222
+ non-local inline variable with static storage duration is sequenced
223
+ before the first statement of `main` or is deferred. If it is deferred,
224
+ it strongly happens before any non-initialization odr-use of that
225
+ variable. It is *implementation-defined* in which threads and at which
226
+ points in the program such deferred dynamic initialization occurs.
227
+
228
+ It is *implementation-defined* whether the dynamic initialization of a
229
+ non-local non-inline variable with thread storage duration is sequenced
230
+ before the first statement of the initial function of a thread or is
231
+ deferred. If it is deferred, the initialization associated with the
232
+ entity for thread *t* is sequenced before the first non-initialization
233
+ odr-use by *t* of any non-inline variable with thread storage duration
234
+ defined in the same translation unit as the variable to be initialized.
235
+ It is *implementation-defined* in which threads and at which points in
236
+ the program such deferred dynamic initialization occurs.
237
 
238
  If the initialization of a non-local variable with static or thread
239
  storage duration exits via an exception, `std::terminate` is called (
240
  [[except.terminate]]).
241
 
242
  ### Termination <a id="basic.start.term">[[basic.start.term]]</a>
243
 
244
  Destructors ([[class.dtor]]) for initialized objects (that is, objects
245
+ whose lifetime ([[basic.life]]) has begun) with static storage
246
+ duration, and functions registered with `std::atexit`, are called as
247
+ part of a call to `std::exit` ([[support.start.term]]). The call to
248
+ `std::exit` is sequenced before the invocations of the destructors and
249
+ the registered functions.
250
+
251
+ [*Note 1*: Returning from `main` invokes `std::exit` (
252
+ [[basic.start.main]]). *end note*]
253
+
254
+ Destructors for initialized objects with thread storage duration within
255
+ a given thread are called as a result of returning from the initial
256
+ function of that thread and as a result of that thread calling
257
+ `std::exit`. The completions of the destructors for all initialized
258
+ objects with thread storage duration within that thread strongly happen
259
+ before the initiation of the destructors of any object with static
260
+ storage duration.
261
+
262
+ If the completion of the constructor or dynamic initialization of an
263
+ object with static storage duration strongly happens before that of
264
+ another, the completion of the destructor of the second is sequenced
265
+ before the initiation of the destructor of the first. If the completion
266
+ of the constructor or dynamic initialization of an object with thread
267
+ storage duration is sequenced before that of another, the completion of
268
+ the destructor of the second is sequenced before the initiation of the
269
+ destructor of the first. If an object is initialized statically, the
270
+ object is destroyed in the same order as if the object was dynamically
271
+ initialized. For an object of array or class type, all subobjects of
272
+ that object are destroyed before any block-scope object with static
273
+ storage duration initialized during the construction of the subobjects
274
+ is destroyed. If the destruction of an object with static or thread
275
+ storage duration exits via an exception, `std::terminate` is called (
276
+ [[except.terminate]]).
277
 
278
  If a function contains a block-scope object of static or thread storage
279
  duration that has been destroyed and the function is called during the
280
  destruction of an object with static or thread storage duration, the
281
  program has undefined behavior if the flow of control passes through the
282
  definition of the previously destroyed block-scope object. Likewise, the
283
  behavior is undefined if the block-scope object is used indirectly
284
  (i.e., through a pointer) after its destruction.
285
 
286
  If the completion of the initialization of an object with static storage
287
+ duration strongly happens before a call to `std::atexit` (see
288
+ `<cstdlib>`,  [[support.start.term]]), the call to the function passed
289
+ to `std::atexit` is sequenced before the call to the destructor for the
290
+ object. If a call to `std::atexit` strongly happens before the
291
+ completion of the initialization of an object with static storage
292
+ duration, the call to the destructor for the object is sequenced before
293
+ the call to the function passed to `std::atexit`. If a call to
294
+ `std::atexit` strongly happens before another call to `std::atexit`, the
295
+ call to the function passed to the second `std::atexit` call is
296
+ sequenced before the call to the function passed to the first
297
+ `std::atexit` call.
298
 
299
  If there is a use of a standard library object or function not permitted
300
  within signal handlers ([[support.runtime]]) that does not happen
301
  before ([[intro.multithread]]) completion of destruction of objects
302
  with static storage duration and execution of `std::atexit` registered
303
  functions ([[support.start.term]]), the program has undefined behavior.
304
+
305
+ [*Note 2*: If there is a use of an object with static storage duration
306
+ that does not happen before the object’s destruction, the program has
307
+ undefined behavior. Terminating every thread before a call to
308
+ `std::exit` or the exit from `main` is sufficient, but not necessary, to
309
+ satisfy these requirements. These requirements permit thread managers as
310
+ static-storage-duration objects. — *end note*]
311
 
312
  Calling the function `std::abort()` declared in `<cstdlib>` terminates
313
  the program without executing any destructors and without calling the
314
  functions passed to `std::atexit()` or `std::at_quick_exit()`.
315