Skip to content

Commit ce857d9

Browse files
committed
Redistribute parts of exception handling as appropriate
1 parent 7bfc96c commit ce857d9

File tree

6 files changed

+599
-623
lines changed

6 files changed

+599
-623
lines changed

Diff for: source/basic.tex

+16-16
Original file line numberDiff line numberDiff line change
@@ -4772,13 +4772,13 @@
47724772
\pnum
47734773
Each of the following is termed a \defnadj{definable}{item}:
47744774
\begin{itemize}
4775-
\item a class type\iref{class},
4776-
\item an enumeration type\iref{dcl.enum},
4777-
\item a function\iref{dcl.fct},
47784775
\item a variable\iref{basic.link},
4779-
\item a templated entity\iref{temp.pre},
4776+
\item a function\iref{dcl.fct},
47804777
\item a default argument for a parameter
47814778
(for a function in a given scope)\iref{dcl.fct.default}, or
4779+
\item an enumeration type\iref{dcl.enum},
4780+
\item a class type\iref{class},
4781+
\item a templated entity\iref{temp.pre},
47824782
\item a default template argument\iref{temp.param}.
47834783
\end{itemize}
47844784

@@ -5059,13 +5059,12 @@
50595059
type \tcode{T} must be complete if
50605060
\begin{itemize}
50615061
\item an object of type \tcode{T} is defined\iref{basic.def}, or
5062-
\item a non-static class data member of type \tcode{T} is
5063-
declared\iref{class.mem}, or
5062+
\item a function with a return type or argument type of type \tcode{T}
5063+
is defined\iref{basic.def} or called\iref{expr.call}, or
5064+
\item the type \tcode{T} is the subject of an
5065+
\keyword{alignof} expression\iref{expr.alignof}, or
50645066
\item \tcode{T} is used as the allocated type or array element type in a
50655067
\grammarterm{new-expression}\iref{expr.new}, or
5066-
\item an lvalue-to-rvalue conversion is applied to
5067-
a glvalue referring
5068-
to an object of type \tcode{T}\iref{conv.lval}, or
50695068
\item an expression is converted (either implicitly or explicitly) to
50705069
type \tcode{T}\iref{conv,expr.type.conv,
50715070
expr.dynamic.cast,expr.static.cast,expr.cast}, or
@@ -5074,20 +5073,21 @@
50745073
or reference to \tcode{T} using a standard conversion\iref{conv},
50755074
a \keyword{dynamic_cast}\iref{expr.dynamic.cast} or
50765075
a \keyword{static_cast}\iref{expr.static.cast}, or
5076+
\item an lvalue-to-rvalue conversion is applied to
5077+
a glvalue referring
5078+
to an object of type \tcode{T}\iref{conv.lval}, or
50775079
\item a class member access operator is applied to an expression of type
50785080
\tcode{T}\iref{expr.ref}, or
50795081
\item the \keyword{typeid} operator\iref{expr.typeid} or the
50805082
\keyword{sizeof} operator\iref{expr.sizeof} is applied to an operand of
50815083
type \tcode{T}, or
5082-
\item a function with a return type or argument type of type \tcode{T}
5083-
is defined\iref{basic.def} or called\iref{expr.call}, or
5084-
\item a class with a base class of type \tcode{T} is
5085-
defined\iref{class.derived}, or
50865084
\item an lvalue of type \tcode{T} is assigned to\iref{expr.ass}, or
5087-
\item the type \tcode{T} is the subject of an
5088-
\keyword{alignof} expression\iref{expr.alignof}, or
50895085
\item an \grammarterm{exception-declaration} has type \tcode{T}, reference to
5090-
\tcode{T}, or pointer to \tcode{T}\iref{except.handle}.
5086+
\tcode{T}, or pointer to \tcode{T}\iref{except.handle}, or
5087+
\item a non-static class data member of type \tcode{T} is
5088+
declared\iref{class.mem}, or
5089+
\item a class with a base class of type \tcode{T} is
5090+
defined\iref{class.derived}.
50915091
\end{itemize}
50925092
\end{note}
50935093

Diff for: source/declarations.tex

+267
Original file line numberDiff line numberDiff line change
@@ -4422,6 +4422,273 @@
44224422
\indextext{declaration!default argument|)}%
44234423
\indextext{declarator!meaning of|)}
44244424

4425+
\rSec3[except.spec]{Exception specifications}%
4426+
\indextext{exception specification|(}
4427+
4428+
\pnum
4429+
The predicate indicating whether a function cannot exit via an exception
4430+
is called the \defn{exception specification} of the function.
4431+
If the predicate is false,
4432+
the function has a
4433+
\indextext{exception specification!potentially-throwing}%
4434+
\defnx{potentially-throwing exception specification}%
4435+
{potentially-throwing!exception specification},
4436+
otherwise it has a
4437+
\indextext{exception specification!non-throwing}%
4438+
\defn{non-throwing exception specification}.
4439+
The exception specification is either defined implicitly,
4440+
or defined explicitly
4441+
by using a \grammarterm{noexcept-specifier}
4442+
as a suffix of a function declarator\iref{dcl.fct}.
4443+
4444+
\begin{bnf}
4445+
\nontermdef{noexcept-specifier}\br
4446+
\keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br
4447+
\keyword{noexcept}\br
4448+
\end{bnf}
4449+
4450+
\pnum
4451+
\indextext{exception specification!noexcept!constant expression and}%
4452+
In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression},
4453+
if supplied, shall be a contextually converted constant expression
4454+
of type \keyword{bool}\iref{expr.const};
4455+
that constant expression is the exception specification of
4456+
the function type in which the \grammarterm{noexcept-specifier} appears.
4457+
A \tcode{(} token that follows \keyword{noexcept} is part of the
4458+
\grammarterm{noexcept-specifier} and does not commence an
4459+
initializer\iref{dcl.init}.
4460+
The \grammarterm{noexcept-specifier} \keyword{noexcept}
4461+
without a \grammarterm{constant-expression}
4462+
is
4463+
equivalent to the \grammarterm{noexcept-specifier}
4464+
\tcode{\keyword{noexcept}(\keyword{true})}.
4465+
\begin{example}
4466+
\begin{codeblock}
4467+
void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type \keyword{bool}
4468+
void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing
4469+
\end{codeblock}
4470+
\end{example}
4471+
4472+
\pnum
4473+
If a declaration of a function
4474+
does not have a \grammarterm{noexcept-specifier},
4475+
the declaration has a potentially throwing exception specification
4476+
unless it is a destructor or a deallocation function
4477+
or is defaulted on its first declaration,
4478+
in which cases the exception specification
4479+
is as specified below
4480+
and no other declaration for that function
4481+
shall have a \grammarterm{noexcept-specifier}.
4482+
In an explicit instantiation\iref{temp.explicit}
4483+
a \grammarterm{noexcept-specifier} may be specified,
4484+
but is not required.
4485+
If a \grammarterm{noexcept-specifier} is specified
4486+
in an explicit instantiation,
4487+
the exception specification shall be the same as
4488+
the exception specification of all other declarations of that function.
4489+
A diagnostic is required only if the
4490+
exception specifications are not the same
4491+
within a single translation unit.
4492+
4493+
\pnum
4494+
\indextext{exception specification!virtual function and}%
4495+
If a virtual function has a
4496+
non-throwing exception specification,
4497+
all declarations, including the definition, of any function
4498+
that overrides that virtual function in any derived class
4499+
shall have a non-throwing
4500+
exception specification,
4501+
unless the overriding function is defined as deleted.
4502+
\begin{example}
4503+
\begin{codeblock}
4504+
struct B {
4505+
virtual void f() noexcept;
4506+
virtual void g();
4507+
virtual void h() noexcept = delete;
4508+
};
4509+
4510+
struct D: B {
4511+
void f(); // error
4512+
void g() noexcept; // OK
4513+
void h() = delete; // OK
4514+
};
4515+
\end{codeblock}
4516+
4517+
The declaration of
4518+
\tcode{D::f}
4519+
is ill-formed because it
4520+
has a potentially-throwing exception specification,
4521+
whereas
4522+
\tcode{B::f}
4523+
has a non-throwing exception specification.
4524+
\end{example}
4525+
4526+
\pnum
4527+
An expression $E$ is
4528+
\defnx{potentially-throwing}{potentially-throwing!expression} if
4529+
\begin{itemize}
4530+
\item
4531+
$E$ is a \grammarterm{throw-expression}\iref{expr.throw},
4532+
or
4533+
\item
4534+
$E$ implicitly invokes a function
4535+
(such as an overloaded operator,
4536+
an allocation function in a \grammarterm{new-expression},
4537+
a constructor for a function argument,
4538+
or a destructor if $E$ is a full-expression\iref{intro.execution})
4539+
that has a potentially-throwing exception specification,
4540+
or
4541+
\item
4542+
any of the immediate subexpressions\iref{intro.execution}
4543+
of $E$ is potentially-throwing,
4544+
or
4545+
\item
4546+
$E$ is a function call\iref{expr.call}
4547+
whose \grammarterm{postfix-expression}
4548+
has a function type,
4549+
or a pointer-to-function type,
4550+
with a potentially-throwing exception specification,
4551+
or
4552+
\item
4553+
$E$ is a \keyword{dynamic_cast} expression that casts to a reference type and
4554+
requires a runtime check\iref{expr.dynamic.cast},
4555+
or
4556+
\item
4557+
$E$ is a \keyword{typeid} expression applied to a
4558+
(possibly parenthesized) built-in unary \tcode{*} operator
4559+
applied to a pointer to a
4560+
polymorphic class type\iref{expr.typeid}.
4561+
\end{itemize}
4562+
4563+
\pnum
4564+
An implicitly-declared constructor for a class \tcode{X},
4565+
or a constructor without a \grammarterm{noexcept-specifier}
4566+
that is defaulted on its first declaration,
4567+
has a potentially-throwing exception specification
4568+
if and only if
4569+
any of the following constructs is potentially-throwing:
4570+
\begin{itemize}
4571+
\item
4572+
the invocation of a constructor selected by overload resolution
4573+
in the implicit definition of the constructor
4574+
for class \tcode{X}
4575+
to initialize a potentially constructed subobject, or
4576+
\item
4577+
a subexpression of such an initialization,
4578+
such as a default argument expression, or,
4579+
\item
4580+
for a default constructor, a default member initializer.
4581+
\end{itemize}
4582+
\begin{note}
4583+
Even though destructors for fully-constructed subobjects
4584+
are invoked when an exception is thrown
4585+
during the execution of a constructor\iref{except.ctor},
4586+
their exception specifications do not contribute
4587+
to the exception specification of the constructor,
4588+
because an exception thrown from such a destructor
4589+
would call the function \tcode{std::terminate}
4590+
rather than escape the constructor\iref{except.throw,except.terminate}.
4591+
\end{note}
4592+
4593+
\pnum
4594+
The exception specification for an implicitly-declared destructor,
4595+
or a destructor without a \grammarterm{noexcept-specifier},
4596+
is potentially-throwing if and only if
4597+
any of the destructors
4598+
for any of its potentially constructed subobjects
4599+
has a potentially-throwing exception specification or
4600+
the destructor is virtual and the destructor of any virtual base class
4601+
has a potentially-throwing exception specification.
4602+
4603+
\pnum
4604+
The exception specification for an implicitly-declared assignment operator,
4605+
or an assignment-operator without a \grammarterm{noexcept-specifier}
4606+
that is defaulted on its first declaration,
4607+
is potentially-throwing if and only if
4608+
the invocation of any assignment operator
4609+
in the implicit definition is potentially-throwing.
4610+
4611+
\pnum
4612+
A deallocation function\iref{basic.stc.dynamic.deallocation}
4613+
with no explicit \grammarterm{noexcept-specifier}
4614+
has a non-throwing exception specification.
4615+
4616+
\pnum
4617+
The exception specification for a comparison operator function\iref{over.binary}
4618+
without a \grammarterm{noexcept-specifier}
4619+
that is defaulted on its first declaration
4620+
is potentially-throwing if and only if
4621+
any expression
4622+
in the implicit definition is potentially-throwing.
4623+
4624+
\pnum
4625+
\begin{example}
4626+
\begin{codeblock}
4627+
struct A {
4628+
A(int = (A(5), 0)) noexcept;
4629+
A(const A&) noexcept;
4630+
A(A&&) noexcept;
4631+
~A();
4632+
};
4633+
struct B {
4634+
B() noexcept;
4635+
B(const B&) = default; // implicit exception specification is \tcode{\keyword{noexcept}(\keyword{true})}
4636+
B(B&&, int = (throw 42, 0)) noexcept;
4637+
~B() noexcept(false);
4638+
};
4639+
int n = 7;
4640+
struct D : public A, public B {
4641+
int * p = new int[n];
4642+
// \tcode{D::D()} potentially-throwing, as the \keyword{new} operator may throw \tcode{bad_alloc} or \tcode{bad_array_new_length}
4643+
// \tcode{D::D(const D\&)} non-throwing
4644+
// \tcode{D::D(D\&\&)} potentially-throwing, as the default argument for \tcode{B}'s constructor may throw
4645+
// \tcode{D::\~D()} potentially-throwing
4646+
};
4647+
\end{codeblock}
4648+
Furthermore, if
4649+
\tcode{A::\~{}A()}
4650+
were virtual,
4651+
the program would be ill-formed since a function that overrides a virtual
4652+
function from a base class
4653+
shall not have a potentially-throwing exception specification
4654+
if the base class function has a non-throwing exception specification.
4655+
\end{example}
4656+
4657+
\pnum
4658+
An exception specification is considered to be \defnx{needed}{needed!exception specification} when:
4659+
\begin{itemize}
4660+
\item in an expression, the function is selected by
4661+
overload resolution\iref{over.match,over.over};
4662+
4663+
\item the function is odr-used\iref{term.odr.use} or, if it appears in an
4664+
unevaluated operand, would be odr-used if the expression were
4665+
potentially-evaluated;
4666+
4667+
\item the exception specification is compared to that of another
4668+
declaration (e.g., an explicit specialization or an overriding virtual
4669+
function);
4670+
4671+
\item the function is defined; or
4672+
4673+
\item the exception specification is needed for a defaulted
4674+
function that calls the function.
4675+
\begin{note}
4676+
A defaulted declaration does not require the
4677+
exception specification of a base member function to be evaluated
4678+
until the implicit exception specification of the derived
4679+
function is needed, but an explicit \grammarterm{noexcept-specifier} needs
4680+
the implicit exception specification to compare against.
4681+
\end{note}
4682+
\end{itemize}
4683+
The exception specification of a defaulted
4684+
function is evaluated as described above only when needed; similarly, the
4685+
\grammarterm{noexcept-specifier} of a specialization of a function
4686+
template or member function of a class template is instantiated only when
4687+
needed.
4688+
%
4689+
\indextext{exception specification|)}
4690+
\indextext{exception handling|)}
4691+
44254692
\rSec1[dcl.init]{Initializers}%
44264693

44274694
\rSec2[dcl.init.general]{General}%

0 commit comments

Comments
 (0)