Annex F (informative)
Core undefined behavior
[ub]
F.4
[stmt]
: Statements
[ub.stmt]
F.4.1
[ub:stmt.return.flow.off]
Specified in:
[stmt.
return]
1
#
Flowing off the end of a function other than
main
or a coroutine results in undefined behavior if the return type is not
cv
void
.
2
#
[
Example
1
:
int
f
(
int
x
)
{
if
(
x
)
return
1
;
// undefined behavior if
x
is
0
}
void
b
(
)
{
int
x
=
f
(
0
)
;
// undefined behavior, using
0
as an argument will cause
f(...)
to flow
// off the end without a
return
statement
}
—
end example
]
F.4.2
[ub:stmt.return.coroutine.flow.off]
Specified in:
[stmt.
return.
coroutine]
1
#
Flowing off the end of a coroutine function body that does not return
void
has undefined behavior
.
2
#
[
Example
1
:
#include
<
cassert
>
#include
<
coroutine
>
#include
<
iostream
>
#include
<
vector
>
class
resumable
{
public
:
struct
promise_type;
using
coro_handle
=
std
::
coroutine_handle
<
promise_type
>
; resumable
(
coro_handle handle
)
:
handle_
(
handle
)
{
assert
(
handle
)
;
}
resumable
(
resumable
&
)
=
delete
; resumable
(
resumable
&
&
)
=
delete
;
bool
resume
(
)
{
if
(
not handle_
.
done
(
)
)
handle_
.
resume
(
)
;
return
not handle_
.
done
(
)
;
}
~
resumable
(
)
{
handle_
.
destroy
(
)
;
}
const
char
*
return_val
(
)
;
private
:
coro_handle handle_;
}
;
struct
resumable
::
promise_type
{
using
coro_handle
=
std
::
coroutine_handle
<
promise_type
>
;
const
char
*
string_;
auto
get_return_object
(
)
{
return
coro_handle
::
from_promise
(
*
this
)
;
}
auto
initial_suspend
(
)
{
return
std
::
suspend_always
(
)
;
}
auto
final_suspend
(
)
noexcept
{
return
std
::
suspend_always
(
)
;
}
void
unhandled_exception
(
)
{
std
::
terminate
(
)
;
}
void
return_value
(
const
char
*
string
)
{
string_
=
string;
}
}
;
const
char
*
resumable
::
return_val
(
)
{
return
handle_
.
promise
(
)
.
string_;
}
resumable foo
(
)
{
std
::
cout
<
<
"Hello"
<
<
std
::
endl;
co_await
std
::
suspend_always
(
)
;
// undefined behavior, falling off the end of coroutine that does not return
void
}
int
main
(
)
{
resumable res
=
foo
(
)
;
while
(
res
.
resume
(
)
)
; std
::
cout
<
<
res
.
return_val
(
)
<
<
std
::
endl;
}
—
end example
]
F.4.3
[ub:stmt.dcl.local.static.init.recursive]
Specified in:
[stmt.
dcl]
1
#
If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined
.
2
#
[
Example
1
:
int
foo
(
int
i
)
{
static
int
s
=
foo
(
2
*
i
)
;
// undefined behavior, recursive call
return
i
+
1
;
}
—
end example
]