Skip to content

Commit 53c38a5

Browse files
authored
Merge 2018-06 CWG Motion 10
Fixes #2122
2 parents 6844810 + a8b8e53 commit 53c38a5

File tree

4 files changed

+109
-41
lines changed

4 files changed

+109
-41
lines changed

source/basic.tex

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3360,36 +3360,47 @@
33603360
declared in a namespace scope other than global scope or declared static
33613361
in global scope.
33623362

3363+
\pnum
3364+
A deallocation function
3365+
is a \defn{destroying operator delete}
3366+
if it has at least two parameters
3367+
and its second parameter
3368+
is of type \tcode{std::destroying_delete_t}.
3369+
A destroying operator delete
3370+
shall be a class member function named \tcode{operator delete}.
3371+
\begin{note}
3372+
Array deletion cannot use a destroying operator delete.
3373+
\end{note}
3374+
33633375
\pnum
33643376
\indextext{\idxcode{delete}!overloading and}%
3365-
Each deallocation function shall return \tcode{void} and its first
3377+
Each deallocation function shall return \tcode{void}.
3378+
If the function is a destroying operator delete
3379+
declared in class type \tcode{C},
3380+
the type of its first parameter shall be \tcode{C*};
3381+
otherwise, the type of its first
33663382
parameter shall be \tcode{void*}. A deallocation function may have more
33673383
than one parameter.
33683384
\indextext{deallocation function!usual}%
3369-
A \defn{usual deallocation function} is a deallocation function that has:
3385+
A \defn{usual deallocation function} is a deallocation function
3386+
whose parameters after the first are
33703387
\begin{itemize}
33713388
\item
3372-
exactly one parameter; or
3389+
optionally, a parameter of type \tcode{std::destroying_delete_t}, then
33733390
\item
3374-
exactly two parameters,
3375-
the type of the second being either
3376-
\tcode{std::align_val_t} or
3377-
\tcode{std::size_t}%
3391+
optionally, a parameter of type \tcode{std::size_t}%
33783392
\footnote{The global \tcode{operator delete(void*, std::size_t)}
33793393
precludes use of an
33803394
allocation function \tcode{void operator new(std::size_t, std::size_t)} as a placement
3381-
allocation function~(\ref{diff.cpp11.basic}).}; or
3395+
allocation function~(\ref{diff.cpp11.basic}).}, then
33823396
\item
3383-
exactly three parameters,
3384-
the type of the second being \tcode{std::size_t}
3385-
and
3386-
the type of the third being \tcode{std::align_val_t}.
3397+
optionally, a parameter of type \tcode{std::align_val_t}.
33873398
\end{itemize}
3399+
A destroying operator delete shall be a usual deallocation function.
33883400
A deallocation function may be an instance of a function
33893401
template. Neither the first parameter nor the return type shall depend
3390-
on a template parameter. \begin{note} That is, a deallocation function
3391-
template shall have a first parameter of type \tcode{void*} and a return
3392-
type of \tcode{void} (as specified above). \end{note} A deallocation
3402+
on a template parameter.
3403+
A deallocation
33933404
function template shall have two or more function parameters. A template
33943405
instance is never a usual deallocation function, regardless of its
33953406
signature.

source/expressions.tex

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4310,7 +4310,10 @@
43104310
\pnum
43114311
\indextext{\idxcode{delete}!undefined}%
43124312
In a single-object delete expression, if the static type of the object to be
4313-
deleted is different from its dynamic type, the static type shall be a base
4313+
deleted is different from its dynamic type
4314+
and the selected deallocation function (see below)
4315+
is not a destroying operator delete,
4316+
the static type shall be a base
43144317
class of the dynamic type of the object to be deleted and the static type shall
43154318
have a virtual destructor or the behavior is undefined. In an array delete
43164319
expression, if the dynamic type of the object to be deleted differs from its
@@ -4329,7 +4332,10 @@
43294332
\pnum
43304333
\indextext{\idxcode{delete}!destructor and}%
43314334
If the value of the operand of the \grammarterm{delete-expression} is not a
4332-
null pointer value, the \grammarterm{delete-expression} will invoke the
4335+
null pointer value
4336+
and the selected deallocation function (see below)
4337+
is not a destroying operator delete,
4338+
the \grammarterm{delete-expression} will invoke the
43334339
destructor (if any) for the object or the elements of the array being
43344340
deleted. In the case of an array, the elements will be destroyed in
43354341
order of decreasing address (that is, in reverse order of the completion
@@ -4395,19 +4401,25 @@
43954401
the function to be called is selected as follows:
43964402
\begin{itemize}
43974403
\item
4404+
If any of the deallocation functions is a destroying operator delete,
4405+
all deallocation functions that are not destroying operator deletes
4406+
are eliminated from further consideration.
4407+
\item
43984408
If the type has new-extended alignment,
43994409
a function with a parameter of type \tcode{std::align_val_t} is preferred;
44004410
otherwise a function without such a parameter is preferred.
4401-
If exactly one preferred function is found,
4402-
that function is selected and the selection process terminates.
4403-
If more than one preferred function is found,
4411+
If any preferred functions are found,
44044412
all non-preferred functions are eliminated from further consideration.
44054413
\item
4414+
If exactly one function remains,
4415+
that function is selected and the selection process terminates.
4416+
\item
44064417
If the deallocation functions have class scope,
44074418
the one without a parameter of type \tcode{std::size_t} is selected.
44084419
\item
4409-
If the type is complete and if, for the second alternative (delete
4410-
array) only, the operand is a pointer to a class type with a
4420+
If the type is complete
4421+
and if, for an array delete expression only,
4422+
the operand is a pointer to a class type with a
44114423
non-trivial destructor or a (possibly multi-dimensional) array thereof,
44124424
the function with a parameter of type \tcode{std::size_t} is selected.
44134425
\item
@@ -4417,31 +4429,54 @@
44174429
\end{itemize}
44184430

44194431
\pnum
4432+
For a single-object delete expression,
4433+
the deleted object is
4434+
the object denoted by the operand
4435+
if its static type does not have a virtual destructor,
4436+
and its most-derived object otherwise.
4437+
\begin{note}
4438+
If the deallocation function is not a destroying operator delete
4439+
and the deleted object is not the most derived object in the former case,
4440+
the behavior is undefined,
4441+
as stated above.
4442+
\end{note}
4443+
For an array delete expression,
4444+
the deleted object is
4445+
the array object.
44204446
When a \grammarterm{delete-expression}
44214447
is executed, the selected deallocation function shall be called with
4422-
the address of the most-derived object in a single-object delete expression, or
4423-
the address of the object suitably adjusted for the array allocation
4448+
the address of the deleted object
4449+
in a single-object delete expression, or
4450+
the address of the deleted object
4451+
suitably adjusted for the array allocation
44244452
overhead\iref{expr.new} in an array delete expression,
44254453
as its first argument.
4454+
\begin{note}
4455+
Any cv-qualifiers in the type of the deleted object
4456+
are ignored when forming this argument.
4457+
\end{note}
4458+
If a destroying operator delete is used,
4459+
an unspecified value
4460+
is passed as the argument
4461+
corresponding to the parameter of type \tcode{std::destroying_delete_t}.
44264462
If a deallocation function
44274463
with a parameter of type \tcode{std::align_val_t}
44284464
is used,
4429-
the alignment of the type of the object to be deleted
4465+
the alignment of the type of the deleted object
44304466
is passed as the corresponding argument.
44314467
If a deallocation function
44324468
with a parameter of type \tcode{std::size_t} is used,
4433-
the size
4434-
of the most-derived type, or
4435-
of the array plus allocation overhead, respectively,
4436-
is passed as the corresponding argument.%
4437-
\footnote{If the static type of the object to be deleted is complete
4438-
and is different from the dynamic type, and the destructor is not virtual, the size might
4439-
be incorrect, but that case is already undefined, as stated above.}
4469+
the size of the deleted object
4470+
in a single-object delete expression, or
4471+
of the array plus allocation overhead
4472+
in an array delete expression,
4473+
is passed as the corresponding argument.
44404474
\begin{note}
4441-
If this results in a call to a usual deallocation function, and either
4475+
If this results in a call to a replaceable deallocation function,
4476+
and either
44424477
the first argument was not the result of
4443-
a prior call to a usual allocation function or
4444-
the second argument was not the corresponding argument in said call,
4478+
a prior call to a replaceable allocation function or
4479+
the second or third argument was not the corresponding argument in said call,
44454480
the behavior is undefined~(\ref{new.delete.single}, \ref{new.delete.array}).
44464481
\end{note}
44474482

source/special.tex

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,7 +1186,7 @@
11861186
\indextext{\idxcode{delete}!destructor and}%
11871187
\indextext{destructor!explicit call}%
11881188
In each case, the context of the invocation is the context of the construction of
1189-
the object. A destructor is also invoked implicitly through use of a
1189+
the object. A destructor may also be invoked implicitly through use of a
11901190
\grammarterm{delete-expression}\iref{expr.delete} for a constructed object allocated
11911191
by a \grammarterm{new-expression}\iref{expr.new}; the context of the invocation is the
11921192
\grammarterm{delete-expression}.
@@ -1370,8 +1370,8 @@
13701370
\grammarterm{delete-expression}
13711371
is used to deallocate an object of class
13721372
\tcode{T}
1373-
or array thereof, the static and dynamic types of the object shall be
1374-
identical and the deallocation function's name is looked up in the scope of
1373+
or array thereof,
1374+
the deallocation function's name is looked up in the scope of
13751375
\tcode{T}.
13761376
If this lookup fails to find the name, general deallocation function
13771377
lookup\iref{expr.delete} continues.
@@ -1409,8 +1409,8 @@
14091409
\grammarterm{delete-expression}
14101410
refers to an object of class type,
14111411
because the deallocation function actually called is looked up in the scope of
1412-
the class that is the dynamic type of the object,
1413-
if the destructor is virtual, the effect is the same.
1412+
the class that is the dynamic type of the object
1413+
if the destructor is virtual, the effect is the same in that case.
14141414
For example,
14151415
\begin{codeblock}
14161416
struct B {
@@ -1422,15 +1422,30 @@
14221422
void operator delete(void*);
14231423
};
14241424

1425+
struct E : B {
1426+
void log_deletion();
1427+
void operator delete(E *p, std::destroying_delete_t) {
1428+
p->log_deletion();
1429+
p->~E();
1430+
::operator delete(p);
1431+
}
1432+
};
1433+
14251434
void f() {
14261435
B* bp = new D;
14271436
delete bp; // 1: uses \tcode{D::operator delete(void*)}
1437+
bp = new E;
1438+
delete bp; // 2: uses \tcode{E::operator delete(E*, std::destroying_delete_t)}
14281439
}
14291440
\end{codeblock}
1430-
Here, storage for the non-array object of class
1441+
Here, storage for the object of class
14311442
\tcode{D}
14321443
is deallocated by
14331444
\tcode{D::operator delete()},
1445+
and
1446+
the object of class \tcode{E} is destroyed
1447+
and its storage is deallocated
1448+
by \tcode{E::operator delete()},
14341449
due to the virtual destructor.
14351450
\end{note}
14361451
\begin{note}

source/support.tex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,13 +1822,20 @@
18221822
\rSec2[new.syn]{Header \tcode{<new>} synopsis}
18231823
\indexhdr{new}%
18241824
\indexlibrary{\idxcode{align_val_t}}%
1825+
\indexlibrary{\idxcode{destroying_delete_t}}%
1826+
\indexlibrary{\idxcode{destroying_delete}}%
18251827
\indexlibrary{\idxcode{nothrow_t}}%
18261828
\indexlibrary{\idxcode{nothrow}}%
18271829
\begin{codeblock}
18281830
namespace std {
18291831
class bad_alloc;
18301832
class bad_array_new_length;
18311833

1834+
struct destroying_delete_t {
1835+
explicit destroying_delete_t() = default;
1836+
};
1837+
inline constexpr destroying_delete_t destroying_delete{};
1838+
18321839
enum class align_val_t : size_t {};
18331840

18341841
struct nothrow_t { explicit nothrow_t() = default; };

0 commit comments

Comments
 (0)